diff --git a/client.c b/client.c index a556a86f..18394c40 100644 --- a/client.c +++ b/client.c @@ -244,6 +244,9 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, char *line = NULL, **caps = NULL, *cause; u_int ncaps = 0; struct args_value *values; +#ifdef TTY_OVER_SOCKET + struct tty* tty = xmalloc(sizeof *tty); +#endif /* Set up the initial command. */ if (shell_command != NULL) { @@ -402,6 +405,10 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags, } else if (msg == MSG_SHELL) proc_send(client_peer, msg, -1, NULL, 0); +#ifdef TTY_OVER_SOCKET + tty_attach_stdin_to_socket(tty, client_peer); +#endif + /* Start main loop. */ proc_loop(client_proc, NULL); @@ -479,12 +486,14 @@ client_send_identify(const char *ttynam, const char *termname, char **caps, caps[i], strlen(caps[i]) + 1); } +#ifndef TTY_OVER_SOCKET if ((fd = dup(STDIN_FILENO)) == -1) fatal("dup failed"); proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0); if ((fd = dup(STDOUT_FILENO)) == -1) fatal("dup failed"); proc_send(client_peer, MSG_IDENTIFY_STDOUT, fd, NULL, 0); +#endif pid = getpid(); proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid); @@ -810,5 +819,10 @@ client_dispatch_attached(struct imsg *imsg) system(data); proc_send(client_peer, MSG_UNLOCK, -1, NULL, 0); break; +#ifdef TTY_OVER_SOCKET + case MSG_TTY_READ: + write(STDOUT_FILENO, data, datalen); + break; +#endif } } diff --git a/compat.h b/compat.h index 93928603..90e9d14e 100644 --- a/compat.h +++ b/compat.h @@ -77,6 +77,11 @@ #define __weak __attribute__ ((__weak__)) #endif +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__) +#define WIN32_PLATFORM +#define TTY_OVER_SOCKET +#endif + #ifndef ECHOPRT #define ECHOPRT 0 #endif diff --git a/server-client.c b/server-client.c index ae2e54f9..4f812493 100644 --- a/server-client.c +++ b/server-client.c @@ -22,6 +22,7 @@ #include <errno.h> #include <fcntl.h> + #include <stdlib.h> #include <string.h> #include <time.h> @@ -3409,6 +3410,11 @@ server_client_dispatch(struct imsg *imsg, void *arg) case MSG_READ_DONE: file_read_done(&c->files, imsg); break; +#ifdef TTY_OVER_SOCKET + case MSG_TTY_WRITE: + write(c->fd, imsg->data, datalen); + break; +#endif } } @@ -3581,6 +3587,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) c->cwd = xstrdup("/"); log_debug("client %p IDENTIFY_CWD %s", c, data); break; +#ifndef TTY_OVER_SOCKET case MSG_IDENTIFY_STDIN: if (datalen != 0) fatalx("bad MSG_IDENTIFY_STDIN size"); @@ -3593,6 +3600,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) c->out_fd = imsg_get_fd(imsg); log_debug("client %p IDENTIFY_STDOUT %d", c, c->out_fd); break; +#endif case MSG_IDENTIFY_ENVIRON: if (datalen == 0 || data[datalen - 1] != '\0') fatalx("bad MSG_IDENTIFY_ENVIRON string"); @@ -3621,8 +3629,8 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) c->name = name; log_debug("client %p name is %s", c, c->name); -#ifdef __CYGWIN__ - c->fd = open(c->ttyname, O_RDWR|O_NOCTTY); +#ifdef TTY_OVER_SOCKET + c->fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); c->out_fd = dup(c->fd); #endif diff --git a/tmux-protocol.h b/tmux-protocol.h index 3cf00c09..443b817d 100644 --- a/tmux-protocol.h +++ b/tmux-protocol.h @@ -68,6 +68,11 @@ enum msgtype { MSG_WRITE_READY, MSG_WRITE_CLOSE, MSG_READ_CANCEL +#ifdef TTY_OVER_SOCKET + , + MSG_TTY_READ, + MSG_TTY_WRITE +#endif }; /* diff --git a/tmux.h b/tmux.h index 0753cb27..0fa6fcc6 100644 --- a/tmux.h +++ b/tmux.h @@ -2542,6 +2542,11 @@ void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *); void tty_cmd_syncstart(struct tty *, const struct tty_ctx *); void tty_default_colours(struct grid_cell *, struct window_pane *); +#ifdef TTY_OVER_SOCKET +int tty_attach_stdin_to_socket(struct tty *, struct tmuxpeer *); +int tty_attach_out_to_socket(struct tty *, struct client *); +#endif + /* tty-term.c */ extern struct tty_terms tty_terms; u_int tty_term_ncodes(void); diff --git a/tty.c b/tty.c index ea2fa941..61f05d6b 100644 --- a/tty.c +++ b/tty.c @@ -250,6 +250,11 @@ tty_write_callback(__unused int fd, __unused short events, void *data) struct client *c = tty->client; size_t size = EVBUFFER_LENGTH(tty->out); int nwrite; +#ifdef TTY_OVER_SOCKET + enum msgtype msg = MSG_TTY_READ; + + proc_send(c->peer, msg, -1, EVBUFFER_DATA(tty->out), size); +#endif nwrite = evbuffer_write(tty->out, c->fd); if (nwrite == -1) @@ -304,6 +309,40 @@ tty_open(struct tty *tty, char **cause) return (0); } +#ifdef TTY_OVER_SOCKET +static struct tmuxpeer *client_peer; + +static void +tty_stdin_socket_callback(int fd, __unused short events, void *data) +{ + struct tty *tty = data; + int nread; + enum msgtype msg = MSG_TTY_WRITE; + + nread = evbuffer_read(tty->in, fd, -1); + if (nread == 0 || nread == -1) { + event_del(&tty->event_in); + return; + } + + proc_send(client_peer, msg, -1, EVBUFFER_DATA(tty->in), nread); +} + +int +tty_attach_stdin_to_socket(struct tty *tty, struct tmuxpeer *peer) +{ + client_peer = peer; + + event_set(&tty->event_in, STDIN_FILENO, EV_PERSIST|EV_READ, + tty_stdin_socket_callback, tty); + tty->in = evbuffer_new(); + if (tty->in == NULL) + fatal("out of memory"); + + return (0); +} +#endif + static void tty_start_timer_callback(__unused int fd, __unused short events, void *data) {