I've found a better way to get tmux working on cygwin.  There's now no need
to modify tty.c to have separate read and write file descriptors.  I've
attached the new patch.



On Wed, May 15, 2013 at 12:59 AM, J Raynor <jxray...@gmail.com> wrote:

> Below is a patch for getting tmux running on cygwin.  I only have access
> to a 32 bit XP system, so I don't know if it works on other versions of
> Windows.  Cygwin doesn't provide a libevent package, so you'll first have
> to install that.  I used libevent-2.0.21-stable.  Also, for tmux I had to
> specify CFLAGS="-I/usr/include/ncurses" to configure or ncurses.h won't be
> found during make.
>
> I didn't solve the general problem of passing file descriptors over a
> socket.  Tmux is using a library to send messages, and it looks like
> there's only 1 message type that needed to pass a descriptor.  So, I added
> the necessary info to msg_identify on the sending side, and the info is
> extracted and put to use before things continue on as normal on the
> receiving side.
>
> Things weren't quite that easy, though.  There are 2 HANDLEs to the pty,
> one for input and one for output.  Cygwin hides this, setting up stuff
> under the hood so that 1 unix file descriptor can do both.  There doesn't
> appear to be a way to set that up on the receiving side, so instead of
> having 1 tty file descriptor that can be used for input/output, I have to
> have 1 for input and 1 for output.  As a result, all the writes in tty.c
> have to be changed to use the write file descriptor.
>
> I don't expect this patch to be integrated into tmux.  I just want to get
> it out there and see if other people are interested in testing it or
> improving it.  I believe I know how to add a function to cygwin to get the
> 2 HANDLEs combined into 1 file descriptor, but I don't know if the cygwin
> folks would accept it.  Plus, having people patch and build tmux and cygwin
> seems to be asking a bit much as this stage.
>
>
>
>
> *** client.c.orig    2013-05-14 17:44:06.535685400 -0500
> --- client.c    2013-05-14 19:43:41.305473500 -0500
> ***************
> *** 63,68 ****
> --- 63,69 ----
>   int        client_dispatch_attached(void);
>   int        client_dispatch_wait(void *);
>   const char     *client_exit_message(void);
> + void        cyg_add_identify_info(struct msg_identify_data *, int);
>
>   /*
>    * Get server create lock. If already held then server start is
> happening in
> ***************
> *** 328,335 ****
>           strlcpy(data.term, term, sizeof data.term) >= sizeof data.term)
>           *data.term = '\0';
>
> !     if ((fd = dup(STDIN_FILENO)) == -1)
> !         fatal("dup failed");
>       imsg_compose(&client_ibuf,
>           MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
>       client_update_event();
> --- 329,335 ----
>           strlcpy(data.term, term, sizeof data.term) >= sizeof data.term)
>           *data.term = '\0';
>
> !     cyg_add_identify_info(&data, STDIN_FILENO);
>       imsg_compose(&client_ibuf,
>           MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
>       client_update_event();
> ***************
> *** 661,663 ****
> --- 661,708 ----
>           imsg_free(&imsg);
>       }
>   }
> +
> +
> + #include <wtypes.h>
> + #define CW_GET_INSTKEY 39   /* see cygwin.h */
> +
> + struct pipe_request {
> +     DWORD pid;
> + };
> +
> + struct pipe_reply {
> +     HANDLE ttyin;
> +     HANDLE ttyout;
> +     DWORD error;
> + };
> +
> + void
> + cyg_add_identify_info(struct msg_identify_data *data, int fd)
> + {
> +
> +     char pipepath[256];
> +     WCHAR instkey[64];
> +     struct pipe_request req;
> +     struct pipe_reply repl;
> +     DWORD len;
> +
> +     req.pid = GetCurrentProcessId();
> +
> +     snprintf(&data->cyg_pty_path, sizeof(data->cyg_pty_path), "%s",
> ttyname(fd));
> +     cygwin_internal(CW_GET_INSTKEY, &instkey);
> +
> +     snprintf(&pipepath, sizeof(pipepath),
> "\\\\.\\pipe\\cygwin-%ls-%s-master-ctl",
> +         &instkey, basename(data->cyg_pty_path));
> +
> +     if(!CallNamedPipe(&pipepath, &req, sizeof req, &repl, sizeof repl,
> &len, 500))
> +         fatal("CallNamedPipe failed");
> +
> +         data->cyg_handle_ttyin = repl.ttyin;
> +         data->cyg_handle_ttyout = repl.ttyout;
> +         data->cyg_pid = req.pid;
> +
> + }
> +
> +
> +
> +
> *** server-client.c.orig    2013-05-14 18:22:54.012432600 -0500
> --- server-client.c    2013-05-14 19:48:16.030508700 -0500
> ***************
> *** 43,48 ****
> --- 43,49 ----
>   void    server_client_msg_identify(
>           struct client *, struct msg_identify_data *, int);
>   void    server_client_msg_shell(struct client *);
> + void    cyg_get_identify_fd(struct msg_identify_data *, struct imsg *);
>
>   /* Create a new client. */
>   void
> ***************
> *** 823,831 ****
>           case MSG_IDENTIFY:
>               if (datalen != sizeof identifydata)
>                   fatalx("bad MSG_IDENTIFY size");
>               if (imsg.fd == -1)
>                   fatalx("MSG_IDENTIFY missing fd");
> -             memcpy(&identifydata, imsg.data, sizeof identifydata);
>
>               server_client_msg_identify(c, &identifydata, imsg.fd);
>               break;
> --- 824,833 ----
>           case MSG_IDENTIFY:
>               if (datalen != sizeof identifydata)
>                   fatalx("bad MSG_IDENTIFY size");
> +             memcpy(&identifydata, imsg.data, sizeof identifydata);
> +             cyg_get_identify_fd(&identifydata, &imsg);
>               if (imsg.fd == -1)
>                   fatalx("MSG_IDENTIFY missing fd");
>
>               server_client_msg_identify(c, &identifydata, imsg.fd);
>               break;
> ***************
> *** 976,981 ****
> --- 978,984 ----
>       }
>       data->term[(sizeof data->term) - 1] = '\0';
>       tty_init(&c->tty, c, fd, data->term);
> +     c->tty.wfd = data->cyg_fd_ttyout;
>       if (data->flags & IDENTIFY_UTF8)
>           c->tty.flags |= TTY_UTF8;
>       if (data->flags & IDENTIFY_256COLOURS)
> ***************
> *** 1006,1008 ****
> --- 1009,1057 ----
>       server_write_client(c, MSG_SHELL, &data, sizeof data);
>       c->flags |= CLIENT_BAD;    /* it will die after exec */
>   }
> +
> +
> + #include <wtypes.h>
> + void
> + cyg_get_identify_fd(struct msg_identify_data *data, struct imsg *imsg)
> + {
> +
> +         HANDLE hSRCproc, hSRCttyin, hSRCttyout, hTGTttyin, hTGTttyout;
> +         DWORD pid;
> +         int x, y;
> +
> +         hSRCttyin = data->cyg_handle_ttyin;
> +         hSRCttyout = data->cyg_handle_ttyout;
> +         pid = data->cyg_pid;
> +
> +         hSRCproc = OpenProcess(PROCESS_DUP_HANDLE, 1, pid);
> +         if(hSRCproc == NULL)
> +                 fatalx("OpenProcess failed");
> +
> +
> +         if(!DuplicateHandle(hSRCproc, hSRCttyin, GetCurrentProcess(),
> +         &hTGTttyin, 0, TRUE,
> DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS))
> +             fatalx("DuplicatHandle failed for ttyin");
> +
> +         if(!DuplicateHandle(hSRCproc, hSRCttyout, GetCurrentProcess(),
> +         &hTGTttyout, 0, TRUE,
> DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS))
> +             fatalx("DuplicatHandle failed for ttyout");
> +
> +
> +
> +     data->cyg_fd_ttyin = cygwin_attach_handle_to_fd(data->cyg_pty_path,
> -1, hTGTttyin, 1, GENERIC_READ|GENERIC_WRITE);
> +     data->cyg_fd_ttyout = cygwin_attach_handle_to_fd("dummy", -1,
> hTGTttyout, 1, GENERIC_READ|GENERIC_WRITE);
> +
> +     if(data->cyg_fd_ttyin < 0)
> +         fatalx("cygwin_attach_handle_to_fd failed for ttyin");
> +
> +     if(data->cyg_fd_ttyout < 0)
> +         fatalx("cygwin_attach_handle_to_fd failed for ttyout");
> +
> +     imsg->fd = data->cyg_fd_ttyin;
> +
> +
> + }
> +
> +
> +
> *** tmux.h.orig    2013-05-14 17:24:47.819533400 -0500
> --- tmux.h    2013-05-14 19:44:57.304755100 -0500
> ***************
> *** 470,480 ****
> --- 470,489 ----
>       char        argv[COMMAND_LENGTH];
>   };
>
> + typedef ulong DWORD;    /* including wtypes.h in tmux.h causes
> compilation problems */
> + typedef void *HANDLE;    /* in some files, so use typedefs here to avoid
> that*/
>   struct msg_identify_data {
>       char        cwd[MAXPATHLEN];
>
>       char        term[TERMINAL_LENGTH];
>
> +     HANDLE        cyg_handle_ttyin;
> +     HANDLE        cyg_handle_ttyout;
> +     DWORD        cyg_pid;
> +     int        cyg_fd_ttyin;
> +     int        cyg_fd_ttyout;
> +     char        cyg_pty_path[16];
> +
>   #define IDENTIFY_UTF8 0x1
>   #define IDENTIFY_256COLOURS 0x2
>   #define IDENTIFY_88COLOURS 0x4
> ***************
> *** 1216,1222 ****
> --- 1225,1234 ----
>       struct tty_term    *term;
>
>       int         fd;
> +     int         wfd;
> +
>       struct bufferevent *event;
> +     struct bufferevent *wevent;
>
>       int         log_fd;
>
> *** tty.c.orig    2013-05-14 17:31:28.525720600 -0500
> --- tty.c    2013-05-14 17:40:35.452162200 -0500
> ***************
> *** 23,35 ****
>
>   #include <errno.h>
>   #include <fcntl.h>
> ! #include <resolv.h>
>   #include <stdlib.h>
>   #include <string.h>
>   #include <termios.h>
>   #include <unistd.h>
>
>   #include "tmux.h"
>
>   void    tty_read_callback(struct bufferevent *, void *);
>   void    tty_error_callback(struct bufferevent *, short, void *);
> --- 23,36 ----
>
>   #include <errno.h>
>   #include <fcntl.h>
> ! //#include <resolv.h>
>   #include <stdlib.h>
>   #include <string.h>
>   #include <termios.h>
>   #include <unistd.h>
>
>   #include "tmux.h"
> + #define ECHOPRT         0x00000020      /* visual erase mode for
> hardcopy */
>
>   void    tty_read_callback(struct bufferevent *, void *);
>   void    tty_error_callback(struct bufferevent *, short, void *);
> ***************
> *** 154,159 ****
> --- 155,163 ----
>       tty->event = bufferevent_new(
>           tty->fd, tty_read_callback, NULL, tty_error_callback, tty);
>
> +     tty->wevent = bufferevent_new(
> +         tty->wfd, NULL, NULL, tty_error_callback, tty);
> +
>       tty_start_tty(tty);
>
>       tty_keys_build(tty);
> ***************
> *** 305,310 ****
> --- 309,315 ----
>
>       if (tty->flags & TTY_OPENED) {
>           bufferevent_free(tty->event);
> +         bufferevent_free(tty->wevent);
>
>           tty_term_free(tty->term);
>           tty_keys_free(tty);
> ***************
> *** 314,320 ****
> --- 319,327 ----
>
>       if (tty->fd != -1) {
>           close(tty->fd);
> +         close(tty->wfd);
>           tty->fd = -1;
> +         tty->wfd = -1;
>       }
>   }
>
> ***************
> *** 338,344 ****
>
>       slen = strlen(s);
>       for (i = 0; i < 5; i++) {
> !         n = write(tty->fd, s, slen);
>           if (n >= 0) {
>               s += n;
>               slen -= n;
> --- 345,351 ----
>
>       slen = strlen(s);
>       for (i = 0; i < 5; i++) {
> !         n = write(tty->wfd, s, slen);
>           if (n >= 0) {
>               s += n;
>               slen -= n;
> ***************
> *** 391,397 ****
>   {
>       if (*s == '\0')
>           return;
> !     bufferevent_write(tty->event, s, strlen(s));
>
>       if (tty->log_fd != -1)
>           write(tty->log_fd, s, strlen(s));
> --- 398,404 ----
>   {
>       if (*s == '\0')
>           return;
> !     bufferevent_write(tty->wevent, s, strlen(s));
>
>       if (tty->log_fd != -1)
>           write(tty->log_fd, s, strlen(s));
> ***************
> *** 406,416 ****
>       if (tty->cell.attr & GRID_ATTR_CHARSET) {
>           acs = tty_acs_get(tty, ch);
>           if (acs != NULL)
> !             bufferevent_write(tty->event, acs, strlen(acs));
>           else
> !             bufferevent_write(tty->event, &ch, 1);
>       } else
> !         bufferevent_write(tty->event, &ch, 1);
>
>       if (ch >= 0x20 && ch != 0x7f) {
>           sx = tty->sx;
> --- 413,423 ----
>       if (tty->cell.attr & GRID_ATTR_CHARSET) {
>           acs = tty_acs_get(tty, ch);
>           if (acs != NULL)
> !             bufferevent_write(tty->wevent, acs, strlen(acs));
>           else
> !             bufferevent_write(tty->wevent, &ch, 1);
>       } else
> !         bufferevent_write(tty->wevent, &ch, 1);
>
>       if (ch >= 0x20 && ch != 0x7f) {
>           sx = tty->sx;
> ***************
> *** 432,438 ****
>   void
>   tty_putn(struct tty *tty, const void *buf, size_t len, u_int width)
>   {
> !     bufferevent_write(tty->event, buf, len);
>       if (tty->log_fd != -1)
>           write(tty->log_fd, buf, len);
>       tty->cx += width;
> --- 439,445 ----
>   void
>   tty_putn(struct tty *tty, const void *buf, size_t len, u_int width)
>   {
> !     bufferevent_write(tty->wevent, buf, len);
>       if (tty->log_fd != -1)
>           write(tty->log_fd, buf, len);
>       tty->cx += width;
>
>
>
>
>
>
>

Attachment: tmux-cygwin.patch
Description: Binary data

------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to