diff options
author | Tiago Cunha <tcunha@gmx.com> | 2010-10-24 01:31:08 +0000 |
---|---|---|
committer | Tiago Cunha <tcunha@gmx.com> | 2010-10-24 01:31:08 +0000 |
commit | bdbd4e28c2c3cbf6c1372bee50a7ea26b32d7041 (patch) | |
tree | 6123779990e9dee74bba3422e23f88ce866493f4 | |
parent | 1276ea36536a5d25e041fb2d50f4743618d07cfd (diff) |
Sync OpenBSD patchset 777:
Merge the before and after attach client code into one in client.c
(instead of two in tmux.c and client.c).
-rw-r--r-- | client.c | 341 | ||||
-rw-r--r-- | server.c | 15 | ||||
-rw-r--r-- | tmux.c | 276 | ||||
-rw-r--r-- | tmux.h | 15 |
4 files changed, 299 insertions, 348 deletions
@@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.98 2010-10-24 00:45:57 tcunha Exp $ */ +/* $Id: client.c,v 1.99 2010-10-24 01:31:08 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -28,7 +28,6 @@ #include <pwd.h> #include <stdlib.h> #include <string.h> -#include <syslog.h> #include <unistd.h> #include "tmux.h" @@ -37,81 +36,171 @@ struct imsgbuf client_ibuf; struct event client_event; const char *client_exitmsg; int client_exitval; +int client_attached; +int client_connect(char *, int); void client_send_identify(int); void client_send_environ(void); void client_write_server(enum msgtype, void *, size_t); void client_update_event(void); void client_signal(int, short, void *); void client_callback(int, short, void *); -int client_dispatch(void); +int client_dispatch_attached(void); +int client_dispatch_wait(void *); -struct imsgbuf * -client_init(char *path, int cmdflags, int flags) +/* Connect client to server. */ +int +client_connect(char *path, int start_server) { struct sockaddr_un sa; size_t size; int fd, mode; -#ifdef HAVE_SETPROCTITLE - char rpathbuf[MAXPATHLEN]; -#endif - -#ifdef HAVE_SETPROCTITLE - if (realpath(path, rpathbuf) == NULL) - strlcpy(rpathbuf, path, sizeof rpathbuf); - setproctitle("client (%s)", rpathbuf); -#endif memset(&sa, 0, sizeof sa); sa.sun_family = AF_UNIX; size = strlcpy(sa.sun_path, path, sizeof sa.sun_path); if (size >= sizeof sa.sun_path) { errno = ENAMETOOLONG; - goto not_found; + return (-1); } if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("socket failed"); if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) { - if (!(cmdflags & CMD_STARTSERVER)) - goto not_found; + if (!start_server) + goto failed; switch (errno) { case ECONNREFUSED: if (unlink(path) != 0) - goto not_found; + goto failed; /* FALLTHROUGH */ case ENOENT: - if ((fd = server_start(path)) == -1) - goto start_failed; - goto server_started; + if ((fd = server_start()) == -1) + goto failed; + break; + default: + goto failed; } - goto not_found; } -server_started: if ((mode = fcntl(fd, F_GETFL)) == -1) fatal("fcntl failed"); if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) fatal("fcntl failed"); + return (fd); + +failed: + close(fd); + return (-1); +} + +/* Client main loop. */ +int +client_main(int argc, char **argv, int flags) +{ + struct cmd *cmd; + struct cmd_list *cmdlist; + struct msg_command_data cmddata; + int cmdflags, fd; + enum msgtype msg; + char *cause; + + /* Set up the initial command. */ + cmdflags = 0; + if (shell_cmd != NULL) { + msg = MSG_SHELL; + cmdflags = CMD_STARTSERVER; + } else if (argc == 0) { + msg = MSG_COMMAND; + cmdflags = CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST; + } else { + msg = MSG_COMMAND; + + /* + * It sucks parsing the command string twice (in client and + * later in server) but it is necessary to get the start server + * flag. + */ + if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { + log_warnx("%s", cause); + return (1); + } + cmdflags &= ~CMD_STARTSERVER; + TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { + if (cmd->entry->flags & CMD_STARTSERVER) + cmdflags |= CMD_STARTSERVER; + if (cmd->entry->flags & CMD_SENDENVIRON) + cmdflags |= CMD_SENDENVIRON; + if (cmd->entry->flags & CMD_CANTNEST) + cmdflags |= CMD_CANTNEST; + } + cmd_list_free(cmdlist); + } + + /* + * Check if this could be a nested session, if the command can't nest: + * if the socket path matches $TMUX, this is probably the same server. + */ + if (shell_cmd == NULL && environ_path != NULL && + cmdflags & CMD_CANTNEST && strcmp(socket_path, environ_path) == 0) { + log_warnx("sessions should be nested with care. " + "unset $TMUX to force."); + return (1); + } + + /* Initialise the client socket and start the server. */ + fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER); + if (fd == -1) { + log_warn("failed to connect to server"); + return (1); + } + + /* Set process title, log and signals now this is the client. */ + setproctitle("client (%s)", socket_path); + logfile("client"); + + /* Create imsg. */ imsg_init(&client_ibuf, fd); - event_set(&client_event, fd, EV_READ, client_callback, NULL); + event_set(&client_event, fd, EV_READ, client_callback, shell_cmd); + /* Establish signal handlers. */ + set_signals(client_signal); + + /* Send initial environment. */ if (cmdflags & CMD_SENDENVIRON) client_send_environ(); client_send_identify(flags); - return (&client_ibuf); + /* Send first command. */ + if (msg == MSG_COMMAND) { + /* Fill in command line arguments. */ + cmddata.pid = environ_pid; + cmddata.idx = environ_idx; + + /* Prepare command for server. */ + cmddata.argc = argc; + if (cmd_pack_argv( + argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) { + log_warnx("command too long"); + return (1); + } + + client_write_server(msg, &cmddata, sizeof cmddata); + } else if (msg == MSG_SHELL) + client_write_server(msg, NULL, 0); -start_failed: - log_warnx("server failed to start"); - return (NULL); + /* Set the event and dispatch. */ + client_update_event(); + event_dispatch(); -not_found: - log_warn("server not found"); - return (NULL); + /* Print the exit message, if any, and exit. */ + if (client_attached && client_exitmsg != NULL && !login_shell) + printf("[%s]\n", client_exitmsg); + return (client_exitval); } +/* Send identify message to server with the file descriptors. */ void client_send_identify(int flags) { @@ -136,13 +225,16 @@ client_send_identify(int flags) if ((fd = dup(STDOUT_FILENO)) == -1) fatal("dup failed"); - imsg_compose(&client_ibuf, MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0); + imsg_compose(&client_ibuf, + MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0); if ((fd = dup(STDERR_FILENO)) == -1) fatal("dup failed"); - imsg_compose(&client_ibuf, MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0); + imsg_compose(&client_ibuf, + MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0); } +/* Forward entire environment to server. */ void client_send_environ(void) { @@ -156,12 +248,14 @@ client_send_environ(void) } } +/* Write a message to the server without a file descriptor. */ void client_write_server(enum msgtype type, void *buf, size_t len) { imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len); } +/* Update client event based on whether it needs to read or read and write. */ void client_update_event(void) { @@ -171,91 +265,74 @@ client_update_event(void) events = EV_READ; if (client_ibuf.w.queued > 0) events |= EV_WRITE; - event_set(&client_event, client_ibuf.fd, events, client_callback, NULL); + event_set( + &client_event, client_ibuf.fd, events, client_callback, shell_cmd); event_add(&client_event, NULL); } -__dead void -client_main(void) -{ - logfile("client"); - - /* Note: event_init() has already been called. */ - - /* Set up signals. */ - set_signals(client_signal); - - /* - * Send a resize message immediately in case the terminal size has - * changed between the identify message to the server and the MSG_READY - * telling us to move into the client code. - */ - client_write_server(MSG_RESIZE, NULL, 0); - - /* - * imsg_read in the first client poll loop (before the terminal has - * been initialised) may have read messages into the buffer after the - * MSG_READY switched to here. Process anything outstanding now to - * avoid hanging waiting for messages that have already arrived. - */ - if (client_dispatch() != 0) - goto out; - - /* Set the event and dispatch. */ - client_update_event(); - event_dispatch(); - -out: - /* Print the exit message, if any, and exit. */ - if (client_exitmsg != NULL && !login_shell) - printf("[%s]\n", client_exitmsg); - exit(client_exitval); -} - +/* Callback to handle signals in the client. */ /* ARGSUSED */ void client_signal(int sig, unused short events, unused void *data) { - struct sigaction sigact; + struct sigaction sigact; + int status; - switch (sig) { - case SIGHUP: - client_exitmsg = "lost tty"; - client_exitval = 1; - client_write_server(MSG_EXITING, NULL, 0); - break; - case SIGTERM: - client_exitmsg = "terminated"; - client_exitval = 1; - client_write_server(MSG_EXITING, NULL, 0); - break; - case SIGWINCH: - client_write_server(MSG_RESIZE, NULL, 0); - break; - case SIGCONT: - memset(&sigact, 0, sizeof sigact); - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = SA_RESTART; - sigact.sa_handler = SIG_IGN; - if (sigaction(SIGTSTP, &sigact, NULL) != 0) - fatal("sigaction failed"); - client_write_server(MSG_WAKEUP, NULL, 0); - break; + if (!client_attached) { + switch (sig) { + case SIGCHLD: + waitpid(WAIT_ANY, &status, WNOHANG); + break; + case SIGTERM: + event_loopexit(NULL); + break; + } + } else { + switch (sig) { + case SIGHUP: + client_exitmsg = "lost tty"; + client_exitval = 1; + client_write_server(MSG_EXITING, NULL, 0); + break; + case SIGTERM: + client_exitmsg = "terminated"; + client_exitval = 1; + client_write_server(MSG_EXITING, NULL, 0); + break; + case SIGWINCH: + client_write_server(MSG_RESIZE, NULL, 0); + break; + case SIGCONT: + memset(&sigact, 0, sizeof sigact); + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = SA_RESTART; + sigact.sa_handler = SIG_IGN; + if (sigaction(SIGTSTP, &sigact, NULL) != 0) + fatal("sigaction failed"); + client_write_server(MSG_WAKEUP, NULL, 0); + break; + } } client_update_event(); } +/* Callback for client imsg read events. */ /* ARGSUSED */ void -client_callback(unused int fd, short events, unused void *data) +client_callback(unused int fd, short events, void *data) { ssize_t n; + int retval; if (events & EV_READ) { if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) goto lost_server; - if (client_dispatch() != 0) { + if (client_attached) + retval = client_dispatch_attached(); + else + retval = client_dispatch_wait(data); + if (retval != 0) { event_loopexit(NULL); return; } @@ -275,8 +352,76 @@ lost_server: event_loopexit(NULL); } +/* Dispatch imsgs when in wait state (before MSG_READY). */ +int +client_dispatch_wait(void *data) +{ + struct imsg imsg; + ssize_t n, datalen; + struct msg_shell_data shelldata; + struct msg_exit_data exitdata; + const char *shellcmd = data; + + if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) + fatalx("imsg_read failed"); + + for (;;) { + if ((n = imsg_get(&client_ibuf, &imsg)) == -1) + fatalx("imsg_get failed"); + if (n == 0) + return (0); + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + + switch (imsg.hdr.type) { + case MSG_EXIT: + case MSG_SHUTDOWN: + if (datalen != sizeof exitdata) { + if (datalen != 0) + fatalx("bad MSG_EXIT size"); + } else { + memcpy(&exitdata, imsg.data, sizeof exitdata); + client_exitval = exitdata.retcode; + } + imsg_free(&imsg); + return (-1); + case MSG_READY: + if (datalen != 0) + fatalx("bad MSG_READY size"); + + client_attached = 1; + break; + case MSG_VERSION: + if (datalen != 0) + fatalx("bad MSG_VERSION size"); + + log_warnx("protocol version mismatch (client %u, " + "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid); + client_exitval = 1; + + imsg_free(&imsg); + return (-1); + case MSG_SHELL: + if (datalen != sizeof shelldata) + fatalx("bad MSG_SHELL size"); + memcpy(&shelldata, imsg.data, sizeof shelldata); + shelldata.shell[(sizeof shelldata.shell) - 1] = '\0'; + + clear_signals(0); + + shell_exec(shelldata.shell, shellcmd); + /* NOTREACHED */ + default: + fatalx("unexpected message"); + } + + imsg_free(&imsg); + } +} + +/* Dispatch imsgs in attached state (after MSG_READY). */ +/* ARGSUSED */ int -client_dispatch(void) +client_dispatch_attached(void) { struct imsg imsg; struct msg_lock_data lockdata; @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.246 2010-10-24 00:45:57 tcunha Exp $ */ +/* $Id: server.c,v 1.247 2010-10-24 01:31:08 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -105,16 +105,13 @@ server_create_socket(void) /* Fork new server. */ int -server_start(char *path) +server_start(void) { struct window_pane *wp; int pair[2]; char *cause; struct timeval tv; u_int i; -#ifdef HAVE_SETPROCTITLE - char rpathbuf[MAXPATHLEN]; -#endif /* The first client is special and gets a socketpair; create it. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) @@ -157,14 +154,8 @@ server_start(char *path) utf8_build(); start_time = time(NULL); - socket_path = path; - -#ifdef HAVE_SETPROCTITLE - if (realpath(socket_path, rpathbuf) == NULL) - strlcpy(rpathbuf, socket_path, sizeof rpathbuf); log_debug("socket path %s", socket_path); - setproctitle("server (%s)", rpathbuf); -#endif + setproctitle("server (%s)", socket_path); server_fd = server_create_socket(); server_client_create(pair[1]); @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.c,v 1.91 2010/10/16 08:42:35 nicm Exp $ */ +/* $Id: tmux.c,v 1.220 2010-10-24 01:31:08 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -18,16 +18,13 @@ #include <sys/types.h> #include <sys/stat.h> -#include <sys/wait.h> #include <errno.h> #include <event.h> #include <fcntl.h> #include <pwd.h> -#include <signal.h> #include <stdlib.h> #include <string.h> -#include <syslog.h> #include <unistd.h> #include "tmux.h" @@ -36,7 +33,6 @@ extern char *malloc_options; #endif -char *cfg_file; struct options global_options; /* server options */ struct options global_s_options; /* session options */ struct options global_w_options; /* window options */ @@ -44,28 +40,19 @@ struct environ global_environ; struct event_base *ev_base; +char *cfg_file; +char *shell_cmd; int debug_level; time_t start_time; -char *socket_path; +char socket_path[MAXPATHLEN]; int login_shell; - -struct env_data { - char *path; - pid_t pid; - u_int idx; -}; +char *environ_path; +pid_t environ_pid; +u_int environ_idx; __dead void usage(void); -void parse_env(struct env_data *); -char *makesockpath(const char *); -__dead void shell_exec(const char *, const char *); - -struct imsgbuf *main_ibuf; -struct event main_event; - -void main_signal(int, short, unused void *); -void main_callback(int, short, void *); -void main_dispatch(const char *); +void parseenvironment(void); +char *makesocketpath(const char *); #ifndef HAVE_PROGNAME char *__progname = (char *) "tmux"; @@ -139,14 +126,14 @@ areshell(const char *shell) } void -parse_env(struct env_data *data) +parseenvironment(void) { char *env, *path_pid, *pid_idx, buf[256]; size_t len; const char *errstr; long long ll; - data->pid = -1; + environ_pid = -1; if ((env = getenv("TMUX")) == NULL) return; @@ -159,9 +146,9 @@ parse_env(struct env_data *data) /* path */ len = path_pid - env; - data->path = xmalloc (len + 1); - memcpy(data->path, env, len); - data->path[len] = '\0'; + environ_path = xmalloc(len + 1); + memcpy(environ_path, env, len); + environ_path[len] = '\0'; /* pid */ len = pid_idx - path_pid - 1; @@ -173,17 +160,17 @@ parse_env(struct env_data *data) ll = strtonum(buf, 0, LONG_MAX, &errstr); if (errstr != NULL) return; - data->pid = ll; + environ_pid = ll; /* idx */ - ll = strtonum(pid_idx+1, 0, UINT_MAX, &errstr); + ll = strtonum(pid_idx + 1, 0, UINT_MAX, &errstr); if (errstr != NULL) return; - data->idx = ll; + environ_idx = ll; } char * -makesockpath(const char *label) +makesocketpath(const char *label) { char base[MAXPATHLEN], *path; struct stat sb; @@ -243,28 +230,18 @@ shell_exec(const char *shell, const char *shellcmd) int main(int argc, char **argv) { - struct cmd_list *cmdlist; - struct cmd *cmd; - enum msgtype msg; - struct passwd *pw; - struct options *oo, *so, *wo; - struct keylist *keylist; - struct env_data envdata; - struct msg_command_data cmddata; - char *s, *shellcmd, *path, *label, *home, *cause; - char **var; - void *buf; - size_t len; - int opt, flags, quiet = 0, cmdflags = 0; - short events; + struct passwd *pw; + struct options *oo, *so, *wo; + struct keylist *keylist; + char *s, *path, *label, *home, **var; + int opt, flags, quiet = 0; #if defined(DEBUG) && defined(__OpenBSD__) malloc_options = (char *) "AFGJPX"; #endif flags = 0; - shellcmd = label = path = NULL; - envdata.path = NULL; + label = path = NULL; login_shell = (**argv == '-'); while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) { switch (opt) { @@ -277,9 +254,9 @@ main(int argc, char **argv) flags &= ~IDENTIFY_256COLOURS; break; case 'c': - if (shellcmd != NULL) - xfree(shellcmd); - shellcmd = xstrdup(optarg); + if (shell_cmd != NULL) + xfree(shell_cmd); + shell_cmd = xstrdup(optarg); break; case 'f': if (cfg_file != NULL) @@ -315,7 +292,7 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (shellcmd != NULL && argc != 0) + if (shell_cmd != NULL && argc != 0) usage(); log_open_tty(debug_level); @@ -451,6 +428,7 @@ main(int argc, char **argv) options_set_number(wo, "utf8", 0); } + /* Locate the configuration file. */ if (cfg_file == NULL) { home = getenv("HOME"); if (home == NULL || *home == '\0') { @@ -466,21 +444,22 @@ main(int argc, char **argv) } /* - * Figure out the socket path. If specified on the command-line with - * -S or -L, use it, otherwise try $TMUX or assume -L default. + * Figure out the socket path. If specified on the command-line with -S + * or -L, use it, otherwise try $TMUX or assume -L default. */ - parse_env(&envdata); + parseenvironment(); if (path == NULL) { - /* No -L. Try $TMUX, or default. */ + /* If no -L, use the environment. */ if (label == NULL) { - path = envdata.path; - if (path == NULL) + if (environ_path != NULL) + path = xstrdup(environ_path); + else label = xstrdup("default"); } /* -L or default set. */ if (label != NULL) { - if ((path = makesockpath(label)) == NULL) { + if ((path = makesocketpath(label)) == NULL) { log_warn("can't create socket"); exit(1); } @@ -488,66 +467,14 @@ main(int argc, char **argv) } if (label != NULL) xfree(label); + if (realpath(path, socket_path) == NULL) + strlcpy(socket_path, path, sizeof socket_path); + xfree(path); - if (shellcmd != NULL) { - msg = MSG_SHELL; - buf = NULL; - len = 0; - } else { - cmddata.pid = envdata.pid; - cmddata.idx = envdata.idx; - - /* Prepare command for server. */ - cmddata.argc = argc; - if (cmd_pack_argv( - argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) { - log_warnx("command too long"); - exit(1); - } - - msg = MSG_COMMAND; - buf = &cmddata; - len = sizeof cmddata; - } - - if (shellcmd != NULL) - cmdflags |= CMD_STARTSERVER; - else if (argc == 0) /* new-session is the default */ - cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST; - else { - /* - * It sucks parsing the command string twice (in client and - * later in server) but it is necessary to get the start server - * flag. - */ - if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { - log_warnx("%s", cause); - exit(1); - } - cmdflags &= ~CMD_STARTSERVER; - TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { - if (cmd->entry->flags & CMD_STARTSERVER) - cmdflags |= CMD_STARTSERVER; - if (cmd->entry->flags & CMD_SENDENVIRON) - cmdflags |= CMD_SENDENVIRON; - if (cmd->entry->flags & CMD_CANTNEST) - cmdflags |= CMD_CANTNEST; - } - cmd_list_free(cmdlist); - } - - /* - * Check if this could be a nested session, if the command can't nest: - * if the socket path matches $TMUX, this is probably the same server. - */ - if (shellcmd == NULL && envdata.path != NULL && - cmdflags & CMD_CANTNEST && - (path == envdata.path || strcmp(path, envdata.path) == 0)) { - log_warnx("sessions should be nested with care. " - "unset $TMUX to force."); - exit(1); - } + /* Set process title. */ + setproctitle("%s (%s)", __progname, socket_path); + /* Pass control to the client. */ #ifdef HAVE_BROKEN_KQUEUE if (setenv("EVENT_NOKQUEUE", "1", 1) != 0) fatal("setenv failed"); @@ -563,120 +490,5 @@ main(int argc, char **argv) #ifdef HAVE_BROKEN_POLL unsetenv("EVENT_NOPOLL"); #endif - set_signals(main_signal); - - /* Initialise the client socket/start the server. */ - if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL) - exit(1); - xfree(path); - - imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len); - - events = EV_READ; - if (main_ibuf->w.queued > 0) - events |= EV_WRITE; - event_set(&main_event, main_ibuf->fd, events, main_callback, shellcmd); - event_add(&main_event, NULL); - - event_dispatch(); - - event_del(&main_event); - - clear_signals(0); - client_main(); /* doesn't return */ -} - -/* ARGSUSED */ -void -main_signal(int sig, unused short events, unused void *data) -{ - int status; - - switch (sig) { - case SIGTERM: - exit(1); - case SIGCHLD: - waitpid(WAIT_ANY, &status, WNOHANG); - break; - } -} - -/* ARGSUSED */ -void -main_callback(unused int fd, short events, void *data) -{ - char *shellcmd = data; - - if (events & EV_READ) - main_dispatch(shellcmd); - - if (events & EV_WRITE) { - if (msgbuf_write(&main_ibuf->w) < 0) - fatalx("msgbuf_write failed"); - } - - event_del(&main_event); - events = EV_READ; - if (main_ibuf->w.queued > 0) - events |= EV_WRITE; - event_set(&main_event, main_ibuf->fd, events, main_callback, shellcmd); - event_add(&main_event, NULL); -} - -void -main_dispatch(const char *shellcmd) -{ - struct imsg imsg; - ssize_t n, datalen; - struct msg_shell_data shelldata; - struct msg_exit_data exitdata; - - if ((n = imsg_read(main_ibuf)) == -1 || n == 0) - fatalx("imsg_read failed"); - - for (;;) { - if ((n = imsg_get(main_ibuf, &imsg)) == -1) - fatalx("imsg_get failed"); - if (n == 0) - return; - datalen = imsg.hdr.len - IMSG_HEADER_SIZE; - - switch (imsg.hdr.type) { - case MSG_EXIT: - case MSG_SHUTDOWN: - if (datalen != sizeof exitdata) { - if (datalen != 0) - fatalx("bad MSG_EXIT size"); - exit(0); - } - memcpy(&exitdata, imsg.data, sizeof exitdata); - exit(exitdata.retcode); - case MSG_READY: - if (datalen != 0) - fatalx("bad MSG_READY size"); - - event_loopexit(NULL); /* move to client_main() */ - break; - case MSG_VERSION: - if (datalen != 0) - fatalx("bad MSG_VERSION size"); - - log_warnx("protocol version mismatch (client %u, " - "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid); - exit(1); - case MSG_SHELL: - if (datalen != sizeof shelldata) - fatalx("bad MSG_SHELL size"); - memcpy(&shelldata, imsg.data, sizeof shelldata); - shelldata.shell[(sizeof shelldata.shell) - 1] = '\0'; - - clear_signals(0); - - shell_exec(shelldata.shell, shellcmd); - default: - fatalx("unexpected message"); - } - - imsg_free(&imsg); - } + exit(client_main(argc, argv, flags)); } @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.579 2010-10-09 14:30:26 tcunha Exp $ */ +/* $Id: tmux.h,v 1.580 2010-10-24 01:31:08 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1289,15 +1289,19 @@ extern struct options global_w_options; extern struct environ global_environ; extern struct event_base *ev_base; extern char *cfg_file; +extern char *shell_cmd; extern int debug_level; -extern int be_quiet; extern time_t start_time; -extern char *socket_path; +extern char socket_path[MAXPATHLEN]; extern int login_shell; +extern char *environ_path; +extern pid_t environ_pid; +extern u_int environ_idx; void logfile(const char *); const char *getshell(void); int checkshell(const char *); int areshell(const char *); +__dead void shell_exec(const char *, const char *); /* cfg.c */ extern int cfg_finished; @@ -1596,8 +1600,7 @@ void cmd_buffer_free(struct cmd *); size_t cmd_buffer_print(struct cmd *, char *, size_t); /* client.c */ -struct imsgbuf *client_init(char *, int, int); -__dead void client_main(void); +int client_main(int, char **, int); /* key-bindings.c */ extern struct key_bindings key_bindings; @@ -1620,7 +1623,7 @@ const char *key_string_lookup_key(int); /* server.c */ extern struct clients clients; extern struct clients dead_clients; -int server_start(char *); +int server_start(void); void server_update_socket(void); /* server-client.c */ |