1
0
mirror of https://github.com/tmux/tmux.git synced 2025-04-24 22:01:01 +00:00

Login shell can be a client flag, and move the exec code into client.c.

This commit is contained in:
nicm 2015-08-30 22:40:25 +00:00
parent dd92b6e83d
commit c6e9160c67
3 changed files with 57 additions and 50 deletions

View File

@ -33,6 +33,7 @@
#include "tmux.h" #include "tmux.h"
int client_flags;
struct imsgbuf client_ibuf; struct imsgbuf client_ibuf;
struct event client_event; struct event client_event;
struct event client_stdin; struct event client_stdin;
@ -51,9 +52,10 @@ enum msgtype client_exittype;
const char *client_exitsession; const char *client_exitsession;
int client_attached; int client_attached;
__dead void client_exec(const char *);
int client_get_lock(char *); int client_get_lock(char *);
int client_connect(struct event_base *, char *, int); 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_one(enum msgtype, int, const void *, size_t);
int client_write_server(enum msgtype, const void *, size_t); int client_write_server(enum msgtype, const void *, size_t);
void client_update_event(void); 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_write(int, const char *, size_t);
void client_callback(int, short, void *); void client_callback(int, short, void *);
int client_dispatch_attached(void); int client_dispatch_attached(void);
int client_dispatch_wait(void *); int client_dispatch_wait(void);
const char *client_exit_message(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; struct termios tio, saved_tio;
size_t size; size_t size;
/* Save the flags. */
client_flags = flags;
/* Set up the initial command. */ /* Set up the initial command. */
cmdflags = 0; cmdflags = 0;
if (shell_cmd != NULL) { if (shell_cmd != NULL) {
@ -266,13 +271,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
/* Create imsg. */ /* Create imsg. */
imsg_init(&client_ibuf, fd); 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. */ /* Create stdin handler. */
setblocking(STDIN_FILENO, 0); setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST, event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
client_stdin_callback, NULL); client_stdin_callback, NULL);
if (flags & CLIENT_CONTROLCONTROL) { if (client_flags & CLIENT_CONTROLCONTROL) {
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
fprintf(stderr, "tcgetattr failed: %s\n", fprintf(stderr, "tcgetattr failed: %s\n",
strerror(errno)); strerror(errno));
@ -291,7 +296,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
} }
/* Send identify messages. */ /* Send identify messages. */
client_send_identify(flags); client_send_identify();
/* Send first command. */ /* Send first command. */
if (msg == MSG_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. */ /* Print the exit message, if any, and exit. */
if (client_attached) { if (client_attached) {
if (client_exitreason != CLIENT_EXIT_NONE && !login_shell) if (client_exitreason != CLIENT_EXIT_NONE)
printf("[%s]\n", client_exit_message()); printf("[%s]\n", client_exit_message());
ppid = getppid(); ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1) if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP); kill(ppid, SIGHUP);
} else if (flags & CLIENT_CONTROLCONTROL) { } else if (client_flags & CLIENT_CONTROLCONTROL) {
if (client_exitreason != CLIENT_EXIT_NONE) if (client_exitreason != CLIENT_EXIT_NONE)
printf("%%exit %s\n", client_exit_message()); printf("%%exit %s\n", client_exit_message());
else else
@ -346,12 +351,12 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
/* Send identify messages to server. */ /* Send identify messages to server. */
void void
client_send_identify(int flags) client_send_identify(void)
{ {
const char *s; const char *s;
char **ss; char **ss;
size_t sslen; size_t sslen;
int fd; int fd, flags = client_flags;
pid_t pid; pid_t pid;
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
@ -421,14 +426,13 @@ client_update_event(void)
events = EV_READ; events = EV_READ;
if (client_ibuf.w.queued > 0) if (client_ibuf.w.queued > 0)
events |= EV_WRITE; events |= EV_WRITE;
event_set( event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
&client_event, client_ibuf.fd, events, client_callback, shell_cmd);
event_add(&client_event, NULL); event_add(&client_event, NULL);
} }
/* Callback to handle signals in the client. */ /* Callback to handle signals in the client. */
void void
client_signal(int sig, unused short events, unused void *data) client_signal(int sig, unused short events, unused void *arg)
{ {
struct sigaction sigact; struct sigaction sigact;
int status; int status;
@ -470,7 +474,7 @@ client_signal(int sig, unused short events, unused void *data)
/* Callback for client imsg read events. */ /* Callback for client imsg read events. */
void void
client_callback(unused int fd, short events, void *data) client_callback(unused int fd, short events, unused void *arg)
{ {
ssize_t n; ssize_t n;
int retval; int retval;
@ -481,7 +485,7 @@ client_callback(unused int fd, short events, void *data)
if (client_attached) if (client_attached)
retval = client_dispatch_attached(); retval = client_dispatch_attached();
else else
retval = client_dispatch_wait(data); retval = client_dispatch_wait();
if (retval != 0) { if (retval != 0) {
event_loopexit(NULL); event_loopexit(NULL);
return; return;
@ -504,7 +508,7 @@ lost_server:
/* Callback for client stdin read events. */ /* Callback for client stdin read events. */
void 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; 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). */ /* Dispatch imsgs when in wait state (before MSG_READY). */
int int
client_dispatch_wait(void *data0) client_dispatch_wait(void)
{ {
struct imsg imsg; struct imsg imsg;
char *data; char *data;
@ -614,7 +647,7 @@ client_dispatch_wait(void *data0)
fatalx("bad MSG_SHELL string"); fatalx("bad MSG_SHELL string");
clear_signals(0); clear_signals(0);
shell_exec(data, data0); client_exec(data);
/* NOTREACHED */ /* NOTREACHED */
case MSG_DETACH: case MSG_DETACH:
case MSG_DETACHKILL: case MSG_DETACHKILL:

36
tmux.c
View File

@ -46,7 +46,6 @@ char *shell_cmd;
int debug_level; int debug_level;
time_t start_time; time_t start_time;
char socket_path[PATH_MAX]; char socket_path[PATH_MAX];
int login_shell;
char *environ_path; char *environ_path;
__dead void usage(void); __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 * const char *
find_home(void) find_home(void)
{ {
@ -229,9 +202,12 @@ main(int argc, char **argv)
setlocale(LC_TIME, ""); setlocale(LC_TIME, "");
flags = 0; if (**argv == '-')
flags = CLIENT_LOGIN;
else
flags = 0;
label = path = NULL; label = path = NULL;
login_shell = (**argv == '-');
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUv")) != -1) { while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUv")) != -1) {
switch (opt) { switch (opt) {
case '2': case '2':
@ -252,7 +228,7 @@ main(int argc, char **argv)
cfg_file = xstrdup(optarg); cfg_file = xstrdup(optarg);
break; break;
case 'l': case 'l':
login_shell = 1; flags |= CLIENT_LOGIN;
break; break;
case 'L': case 'L':
free(label); free(label);

4
tmux.h
View File

@ -1203,7 +1203,7 @@ struct client {
struct screen status; struct screen status;
#define CLIENT_TERMINAL 0x1 #define CLIENT_TERMINAL 0x1
/* 0x2 unused */ #define CLIENT_LOGIN 0x2
#define CLIENT_EXIT 0x4 #define CLIENT_EXIT 0x4
#define CLIENT_REDRAW 0x8 #define CLIENT_REDRAW 0x8
#define CLIENT_STATUS 0x10 #define CLIENT_STATUS 0x10
@ -1412,14 +1412,12 @@ extern char *shell_cmd;
extern int debug_level; extern int debug_level;
extern time_t start_time; extern time_t start_time;
extern char socket_path[PATH_MAX]; extern char socket_path[PATH_MAX];
extern int login_shell;
extern char *environ_path; extern char *environ_path;
void logfile(const char *); void logfile(const char *);
const char *getshell(void); const char *getshell(void);
int checkshell(const char *); int checkshell(const char *);
int areshell(const char *); int areshell(const char *);
void setblocking(int, int); void setblocking(int, int);
__dead void shell_exec(const char *, const char *);
const char *find_home(void); const char *find_home(void);
/* cfg.c */ /* cfg.c */