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; > > > > > > >
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