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:
parent
dd92b6e83d
commit
c6e9160c67
67
client.c
67
client.c
@ -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
36
tmux.c
@ -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
4
tmux.h
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user