diff --git a/client.c b/client.c index 271568da..55c5aa56 100644 --- a/client.c +++ b/client.c @@ -33,6 +33,7 @@ #include "tmux.h" +int client_flags; struct imsgbuf client_ibuf; struct event client_event; struct event client_stdin; @@ -51,9 +52,10 @@ enum msgtype client_exittype; 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(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,7 +64,7 @@ void client_stdin_callback(int, short, void *); void client_write(int, const char *, size_t); void client_callback(int, short, void *); int client_dispatch_attached(void); -int client_dispatch_wait(void *); +int client_dispatch_wait(void); const char *client_exit_message(void); /* @@ -215,6 +217,9 @@ client_main(struct event_base *base, int argc, char **argv, int flags) 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,13 +271,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags) /* Create imsg. */ imsg_init(&client_ibuf, fd); - event_set(&client_event, fd, EV_READ, client_callback, shell_cmd); + 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 (flags & CLIENT_CONTROLCONTROL) { + if (client_flags & CLIENT_CONTROLCONTROL) { if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { fprintf(stderr, "tcgetattr failed: %s\n", strerror(errno)); @@ -291,7 +296,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags) } /* Send identify messages. */ - client_send_identify(flags); + client_send_identify(); /* Send first command. */ if (msg == MSG_COMMAND) { @@ -326,13 +331,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags) /* Print the exit message, if any, and exit. */ if (client_attached) { - if (client_exitreason != CLIENT_EXIT_NONE && !login_shell) + 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 (flags & CLIENT_CONTROLCONTROL) { + } else if (client_flags & CLIENT_CONTROLCONTROL) { if (client_exitreason != CLIENT_EXIT_NONE) printf("%%exit %s\n", client_exit_message()); else @@ -346,12 +351,12 @@ client_main(struct event_base *base, int argc, char **argv, int flags) /* Send identify messages to server. */ void -client_send_identify(int flags) +client_send_identify(void) { const char *s; char **ss; size_t sslen; - int fd; + int fd, flags = client_flags; pid_t pid; client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); @@ -421,14 +426,13 @@ 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, shell_cmd); + 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 *data) +client_signal(int sig, unused short events, unused void *arg) { struct sigaction sigact; int status; @@ -470,7 +474,7 @@ client_signal(int sig, unused short events, unused void *data) /* Callback for client imsg read events. */ void -client_callback(unused int fd, short events, void *data) +client_callback(unused int fd, short events, unused void *arg) { ssize_t n; int retval; @@ -481,7 +485,7 @@ client_callback(unused int fd, short events, void *data) if (client_attached) retval = client_dispatch_attached(); else - retval = client_dispatch_wait(data); + retval = client_dispatch_wait(); if (retval != 0) { event_loopexit(NULL); return; @@ -504,7 +508,7 @@ lost_server: /* Callback for client stdin read events. */ void -client_stdin_callback(unused int fd, unused short events, unused void *data1) +client_stdin_callback(unused int fd, unused short events, unused void *arg) { struct msg_stdin_data data; @@ -536,9 +540,38 @@ client_write(int fd, const char *data, size_t size) } } +/* 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 *data0) +client_dispatch_wait(void) { struct imsg imsg; char *data; @@ -614,7 +647,7 @@ client_dispatch_wait(void *data0) fatalx("bad MSG_SHELL string"); clear_signals(0); - shell_exec(data, data0); + client_exec(data); /* NOTREACHED */ case MSG_DETACH: case MSG_DETACHKILL: diff --git a/tmux.c b/tmux.c index b984b903..1ef23915 100644 --- a/tmux.c +++ b/tmux.c @@ -46,7 +46,6 @@ char *shell_cmd; int debug_level; time_t start_time; char socket_path[PATH_MAX]; -int login_shell; char *environ_path; __dead void usage(void); @@ -170,32 +169,6 @@ setblocking(int fd, int state) } } -__dead void -shell_exec(const char *shell, const char *shellcmd) -{ - const char *shellname, *ptr; - char *argv0; - - ptr = strrchr(shell, '/'); - if (ptr != NULL && *(ptr + 1) != '\0') - shellname = ptr + 1; - else - shellname = shell; - if (login_shell) - xasprintf(&argv0, "-%s", shellname); - else - xasprintf(&argv0, "%s", shellname); - setenv("SHELL", shell, 1); - - setblocking(STDIN_FILENO, 1); - setblocking(STDOUT_FILENO, 1); - setblocking(STDERR_FILENO, 1); - closefrom(STDERR_FILENO + 1); - - execl(shell, argv0, "-c", shellcmd, (char *) NULL); - fatal("execl failed"); -} - const char * find_home(void) { @@ -229,9 +202,12 @@ main(int argc, char **argv) setlocale(LC_TIME, ""); - flags = 0; + if (**argv == '-') + flags = CLIENT_LOGIN; + else + flags = 0; + label = path = NULL; - login_shell = (**argv == '-'); while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUv")) != -1) { switch (opt) { case '2': @@ -252,7 +228,7 @@ main(int argc, char **argv) cfg_file = xstrdup(optarg); break; case 'l': - login_shell = 1; + flags |= CLIENT_LOGIN; break; case 'L': free(label); diff --git a/tmux.h b/tmux.h index 3b67470f..528c3e71 100644 --- a/tmux.h +++ b/tmux.h @@ -1203,7 +1203,7 @@ struct client { struct screen status; #define CLIENT_TERMINAL 0x1 -/* 0x2 unused */ +#define CLIENT_LOGIN 0x2 #define CLIENT_EXIT 0x4 #define CLIENT_REDRAW 0x8 #define CLIENT_STATUS 0x10 @@ -1412,14 +1412,12 @@ extern char *shell_cmd; extern int debug_level; extern time_t start_time; extern char socket_path[PATH_MAX]; -extern int login_shell; extern char *environ_path; void logfile(const char *); const char *getshell(void); int checkshell(const char *); int areshell(const char *); void setblocking(int, int); -__dead void shell_exec(const char *, const char *); const char *find_home(void); /* cfg.c */