=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/client.c,v retrieving revision 1.92 retrieving revision 1.93 diff -c -r1.92 -r1.93 *** src/usr.bin/tmux/client.c 2015/08/30 22:19:07 1.92 --- src/usr.bin/tmux/client.c 2015/08/30 22:40:25 1.93 *************** *** 1,4 **** ! /* $OpenBSD: client.c,v 1.92 2015/08/30 22:19:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: client.c,v 1.93 2015/08/30 22:40:25 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 33,38 **** --- 33,39 ---- #include "tmux.h" + int client_flags; struct imsgbuf client_ibuf; struct event client_event; struct event client_stdin; *************** *** 51,59 **** const char *client_exitsession; int client_attached; int client_get_lock(char *); int client_connect(struct event_base *, char *, int); ! void client_send_identify(int); int client_write_one(enum msgtype, int, const void *, size_t); int client_write_server(enum msgtype, const void *, size_t); void client_update_event(void); --- 52,61 ---- const char *client_exitsession; int client_attached; + __dead void client_exec(const char *); int client_get_lock(char *); int client_connect(struct event_base *, char *, int); ! void client_send_identify(void); int client_write_one(enum msgtype, int, const void *, size_t); int client_write_server(enum msgtype, const void *, size_t); void client_update_event(void); *************** *** 62,68 **** void client_write(int, const char *, size_t); void client_callback(int, short, void *); int client_dispatch_attached(void); ! int client_dispatch_wait(void *); const char *client_exit_message(void); /* --- 64,70 ---- void client_write(int, const char *, size_t); void client_callback(int, short, void *); int client_dispatch_attached(void); ! int client_dispatch_wait(void); const char *client_exit_message(void); /* *************** *** 215,220 **** --- 217,225 ---- struct termios tio, saved_tio; size_t size; + /* Save the flags. */ + client_flags = flags; + /* Set up the initial command. */ cmdflags = 0; if (shell_cmd != NULL) { *************** *** 266,278 **** /* Create imsg. */ imsg_init(&client_ibuf, fd); ! event_set(&client_event, fd, EV_READ, client_callback, shell_cmd); /* Create stdin handler. */ setblocking(STDIN_FILENO, 0); event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST, client_stdin_callback, NULL); ! if (flags & CLIENT_CONTROLCONTROL) { if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { fprintf(stderr, "tcgetattr failed: %s\n", strerror(errno)); --- 271,283 ---- /* Create imsg. */ imsg_init(&client_ibuf, fd); ! event_set(&client_event, fd, EV_READ, client_callback, NULL); /* Create stdin handler. */ setblocking(STDIN_FILENO, 0); event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST, client_stdin_callback, NULL); ! if (client_flags & CLIENT_CONTROLCONTROL) { if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { fprintf(stderr, "tcgetattr failed: %s\n", strerror(errno)); *************** *** 291,297 **** } /* Send identify messages. */ ! client_send_identify(flags); /* Send first command. */ if (msg == MSG_COMMAND) { --- 296,302 ---- } /* Send identify messages. */ ! client_send_identify(); /* Send first command. */ if (msg == MSG_COMMAND) { *************** *** 326,338 **** /* Print the exit message, if any, and exit. */ if (client_attached) { ! if (client_exitreason != CLIENT_EXIT_NONE && !login_shell) printf("[%s]\n", client_exit_message()); ppid = getppid(); if (client_exittype == MSG_DETACHKILL && ppid > 1) kill(ppid, SIGHUP); ! } else if (flags & CLIENT_CONTROLCONTROL) { if (client_exitreason != CLIENT_EXIT_NONE) printf("%%exit %s\n", client_exit_message()); else --- 331,343 ---- /* Print the exit message, if any, and exit. */ if (client_attached) { ! if (client_exitreason != CLIENT_EXIT_NONE) printf("[%s]\n", client_exit_message()); ppid = getppid(); if (client_exittype == MSG_DETACHKILL && ppid > 1) kill(ppid, SIGHUP); ! } else if (client_flags & CLIENT_CONTROLCONTROL) { if (client_exitreason != CLIENT_EXIT_NONE) printf("%%exit %s\n", client_exit_message()); else *************** *** 346,357 **** /* Send identify messages to server. */ void ! client_send_identify(int flags) { const char *s; char **ss; size_t sslen; ! int fd; pid_t pid; client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); --- 351,362 ---- /* Send identify messages to server. */ void ! client_send_identify(void) { const char *s; char **ss; size_t sslen; ! int fd, flags = client_flags; pid_t pid; client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); *************** *** 421,434 **** events = EV_READ; if (client_ibuf.w.queued > 0) events |= EV_WRITE; ! event_set( ! &client_event, client_ibuf.fd, events, client_callback, shell_cmd); event_add(&client_event, NULL); } /* Callback to handle signals in the client. */ void ! client_signal(int sig, unused short events, unused void *data) { struct sigaction sigact; int status; --- 426,438 ---- events = EV_READ; if (client_ibuf.w.queued > 0) events |= EV_WRITE; ! event_set(&client_event, client_ibuf.fd, events, client_callback, NULL); event_add(&client_event, NULL); } /* Callback to handle signals in the client. */ void ! client_signal(int sig, unused short events, unused void *arg) { struct sigaction sigact; int status; *************** *** 470,476 **** /* Callback for client imsg read events. */ void ! client_callback(unused int fd, short events, void *data) { ssize_t n; int retval; --- 474,480 ---- /* Callback for client imsg read events. */ void ! client_callback(unused int fd, short events, unused void *arg) { ssize_t n; int retval; *************** *** 481,487 **** if (client_attached) retval = client_dispatch_attached(); else ! retval = client_dispatch_wait(data); if (retval != 0) { event_loopexit(NULL); return; --- 485,491 ---- if (client_attached) retval = client_dispatch_attached(); else ! retval = client_dispatch_wait(); if (retval != 0) { event_loopexit(NULL); return; *************** *** 504,510 **** /* Callback for client stdin read events. */ void ! client_stdin_callback(unused int fd, unused short events, unused void *data1) { struct msg_stdin_data data; --- 508,514 ---- /* Callback for client stdin read events. */ void ! client_stdin_callback(unused int fd, unused short events, unused void *arg) { struct msg_stdin_data data; *************** *** 536,544 **** } } /* Dispatch imsgs when in wait state (before MSG_READY). */ int ! client_dispatch_wait(void *data0) { struct imsg imsg; char *data; --- 540,577 ---- } } + /* Run command in shell; used for -c. */ + __dead void + client_exec(const char *shell) + { + const char *name, *ptr; + char *argv0; + + log_debug("shell %s, command %s", shell, shell_cmd); + + ptr = strrchr(shell, '/'); + if (ptr != NULL && *(ptr + 1) != '\0') + name = ptr + 1; + else + name = shell; + if (client_flags & CLIENT_LOGIN) + xasprintf(&argv0, "-%s", name); + else + xasprintf(&argv0, "%s", name); + setenv("SHELL", shell, 1); + + setblocking(STDIN_FILENO, 1); + setblocking(STDOUT_FILENO, 1); + setblocking(STDERR_FILENO, 1); + closefrom(STDERR_FILENO + 1); + + execl(shell, argv0, "-c", shell_cmd, (char *) NULL); + fatal("execl failed"); + } + /* Dispatch imsgs when in wait state (before MSG_READY). */ int ! client_dispatch_wait(void) { struct imsg imsg; char *data; *************** *** 614,620 **** fatalx("bad MSG_SHELL string"); clear_signals(0); ! shell_exec(data, data0); /* NOTREACHED */ case MSG_DETACH: case MSG_DETACHKILL: --- 647,653 ---- fatalx("bad MSG_SHELL string"); clear_signals(0); ! client_exec(data); /* NOTREACHED */ case MSG_DETACH: case MSG_DETACHKILL: