mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Merge branch 'obsd-master'
Conflicts: log.c proc.c tmux.c
This commit is contained in:
commit
890d8da2e3
94
client.c
94
client.c
@ -52,33 +52,35 @@ enum msgtype client_exittype;
|
|||||||
const char *client_exitsession;
|
const char *client_exitsession;
|
||||||
int client_attached;
|
int client_attached;
|
||||||
|
|
||||||
__dead void client_exec(const char *);
|
__dead void client_exec(const char *,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 *, const char *, int);
|
||||||
void client_send_identify(const char *, const char *);
|
void client_send_identify(const char *, const char *);
|
||||||
void client_stdin_callback(int, short, void *);
|
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_signal(int);
|
void client_signal(int);
|
||||||
void client_dispatch(struct imsg *, void *);
|
void client_dispatch(struct imsg *, void *);
|
||||||
void client_dispatch_attached(struct imsg *);
|
void client_dispatch_attached(struct imsg *);
|
||||||
void client_dispatch_wait(struct imsg *);
|
void client_dispatch_wait(struct imsg *, const char *);
|
||||||
const char *client_exit_message(void);
|
const char *client_exit_message(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get server create lock. If already held then server start is happening in
|
* Get server create lock. If already held then server start is happening in
|
||||||
* another client, so block until the lock is released and return -1 to
|
* another client, so block until the lock is released and return -2 to
|
||||||
* retry. Ignore other errors - just continue and start the server without the
|
* retry. Return -1 on failure to continue and start the server anyway.
|
||||||
* lock.
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
client_get_lock(char *lockfile)
|
client_get_lock(char *lockfile)
|
||||||
{
|
{
|
||||||
int lockfd;
|
int lockfd;
|
||||||
|
|
||||||
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1)
|
|
||||||
fatal("open failed");
|
|
||||||
log_debug("lock file is %s", lockfile);
|
log_debug("lock file is %s", lockfile);
|
||||||
|
|
||||||
|
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) {
|
||||||
|
log_debug("open failed: %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
|
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
|
||||||
log_debug("flock failed: %s", strerror(errno));
|
log_debug("flock failed: %s", strerror(errno));
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
@ -86,7 +88,7 @@ client_get_lock(char *lockfile)
|
|||||||
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
|
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
|
||||||
/* nothing */;
|
/* nothing */;
|
||||||
close(lockfd);
|
close(lockfd);
|
||||||
return (-1);
|
return (-2);
|
||||||
}
|
}
|
||||||
log_debug("flock succeeded");
|
log_debug("flock succeeded");
|
||||||
|
|
||||||
@ -95,7 +97,7 @@ client_get_lock(char *lockfile)
|
|||||||
|
|
||||||
/* Connect client to server. */
|
/* Connect client to server. */
|
||||||
int
|
int
|
||||||
client_connect(struct event_base *base, char *path, int start_server)
|
client_connect(struct event_base *base, const char *path, int start_server)
|
||||||
{
|
{
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -113,10 +115,10 @@ client_connect(struct event_base *base, char *path, int start_server)
|
|||||||
|
|
||||||
retry:
|
retry:
|
||||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||||
fatal("socket failed");
|
return (-1);
|
||||||
|
|
||||||
log_debug("trying connect");
|
log_debug("trying connect");
|
||||||
if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
|
if (connect(fd, (struct sockaddr *)&sa, sizeof sa) == -1) {
|
||||||
log_debug("connect failed: %s", strerror(errno));
|
log_debug("connect failed: %s", strerror(errno));
|
||||||
if (errno != ECONNREFUSED && errno != ENOENT)
|
if (errno != ECONNREFUSED && errno != ENOENT)
|
||||||
goto failed;
|
goto failed;
|
||||||
@ -126,12 +128,16 @@ retry:
|
|||||||
|
|
||||||
if (!locked) {
|
if (!locked) {
|
||||||
xasprintf(&lockfile, "%s.lock", path);
|
xasprintf(&lockfile, "%s.lock", path);
|
||||||
if ((lockfd = client_get_lock(lockfile)) == -1) {
|
if ((lockfd = client_get_lock(lockfile)) < 0) {
|
||||||
log_debug("didn't get lock");
|
log_debug("didn't get lock (%d)", lockfd);
|
||||||
|
|
||||||
free(lockfile);
|
free(lockfile);
|
||||||
goto retry;
|
lockfile = NULL;
|
||||||
|
|
||||||
|
if (lockfd == -2)
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
log_debug("got lock");
|
log_debug("got lock (%d)", lockfd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always retry at least once, even if we got the lock,
|
* Always retry at least once, even if we got the lock,
|
||||||
@ -143,7 +149,7 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlink(path) != 0 && errno != ENOENT) {
|
if (lockfd >= 0 && unlink(path) != 0 && errno != ENOENT) {
|
||||||
free(lockfile);
|
free(lockfile);
|
||||||
close(lockfd);
|
close(lockfd);
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -151,7 +157,7 @@ retry:
|
|||||||
fd = server_start(base, lockfd, lockfile);
|
fd = server_start(base, lockfd, lockfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locked) {
|
if (locked && lockfd >= 0) {
|
||||||
free(lockfile);
|
free(lockfile);
|
||||||
close(lockfd);
|
close(lockfd);
|
||||||
}
|
}
|
||||||
@ -206,7 +212,8 @@ client_exit_message(void)
|
|||||||
|
|
||||||
/* Client main loop. */
|
/* Client main loop. */
|
||||||
int
|
int
|
||||||
client_main(struct event_base *base, int argc, char **argv, int flags)
|
client_main(struct event_base *base, int argc, char **argv, int flags,
|
||||||
|
const char *shellcmd)
|
||||||
{
|
{
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
@ -227,7 +234,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
|||||||
|
|
||||||
/* Set up the initial command. */
|
/* Set up the initial command. */
|
||||||
cmdflags = 0;
|
cmdflags = 0;
|
||||||
if (shell_cmd != NULL) {
|
if (shellcmd != NULL) {
|
||||||
msg = MSG_SHELL;
|
msg = MSG_SHELL;
|
||||||
cmdflags = CMD_STARTSERVER;
|
cmdflags = CMD_STARTSERVER;
|
||||||
} else if (argc == 0) {
|
} else if (argc == 0) {
|
||||||
@ -254,6 +261,9 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
|||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create client process structure (starts logging). */
|
||||||
|
client_proc = proc_start("client", base, 0, client_signal);
|
||||||
|
|
||||||
/* Initialize the client socket and start the server. */
|
/* Initialize the client socket and start the server. */
|
||||||
fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
|
fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@ -266,10 +276,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
|||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
client_peer = proc_add_peer(client_proc, fd, client_dispatch,
|
||||||
/* Build process state. */
|
(void *)shellcmd);
|
||||||
client_proc = proc_start("client", base, 0, client_signal);
|
|
||||||
client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL);
|
|
||||||
|
|
||||||
/* Save these before pledge(). */
|
/* Save these before pledge(). */
|
||||||
if ((cwd = getcwd(path, sizeof path)) == NULL) {
|
if ((cwd = getcwd(path, sizeof path)) == NULL) {
|
||||||
@ -304,11 +312,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
|||||||
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 (client_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",
|
fatal("tcgetattr failed");
|
||||||
strerror(errno));
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
cfmakeraw(&tio);
|
cfmakeraw(&tio);
|
||||||
tio.c_iflag = ICRNL|IXANY;
|
tio.c_iflag = ICRNL|IXANY;
|
||||||
tio.c_oflag = OPOST|ONLCR;
|
tio.c_oflag = OPOST|ONLCR;
|
||||||
@ -371,7 +376,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
|
|||||||
printf("%%exit\n");
|
printf("%%exit\n");
|
||||||
printf("\033\\");
|
printf("\033\\");
|
||||||
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
|
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
|
||||||
}
|
} else if (client_exitreason != CLIENT_EXIT_NONE)
|
||||||
|
fprintf(stderr, "%s\n", client_exit_message());
|
||||||
setblocking(STDIN_FILENO, 1);
|
setblocking(STDIN_FILENO, 1);
|
||||||
return (client_exitval);
|
return (client_exitval);
|
||||||
}
|
}
|
||||||
@ -392,7 +398,8 @@ client_send_identify(const char *ttynam, const char *cwd)
|
|||||||
s = "";
|
s = "";
|
||||||
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
|
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
|
||||||
|
|
||||||
proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam, strlen(ttynam) + 1);
|
proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam,
|
||||||
|
strlen(ttynam) + 1);
|
||||||
proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1);
|
proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1);
|
||||||
|
|
||||||
if ((fd = dup(STDIN_FILENO)) == -1)
|
if ((fd = dup(STDIN_FILENO)) == -1)
|
||||||
@ -404,8 +411,9 @@ client_send_identify(const char *ttynam, const char *cwd)
|
|||||||
|
|
||||||
for (ss = environ; *ss != NULL; ss++) {
|
for (ss = environ; *ss != NULL; ss++) {
|
||||||
sslen = strlen(*ss) + 1;
|
sslen = strlen(*ss) + 1;
|
||||||
if (sslen <= MAX_IMSGSIZE - IMSG_HEADER_SIZE)
|
if (sslen > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
|
||||||
proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
|
continue;
|
||||||
|
proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
|
||||||
}
|
}
|
||||||
|
|
||||||
proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0);
|
proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0);
|
||||||
@ -447,12 +455,12 @@ client_write(int fd, const char *data, size_t size)
|
|||||||
|
|
||||||
/* Run command in shell; used for -c. */
|
/* Run command in shell; used for -c. */
|
||||||
__dead void
|
__dead void
|
||||||
client_exec(const char *shell)
|
client_exec(const char *shell, const char *shellcmd)
|
||||||
{
|
{
|
||||||
const char *name, *ptr;
|
const char *name, *ptr;
|
||||||
char *argv0;
|
char *argv0;
|
||||||
|
|
||||||
log_debug("shell %s, command %s", shell, shell_cmd);
|
log_debug("shell %s, command %s", shell, shellcmd);
|
||||||
|
|
||||||
ptr = strrchr(shell, '/');
|
ptr = strrchr(shell, '/');
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||||
@ -470,7 +478,7 @@ client_exec(const char *shell)
|
|||||||
setblocking(STDERR_FILENO, 1);
|
setblocking(STDERR_FILENO, 1);
|
||||||
closefrom(STDERR_FILENO + 1);
|
closefrom(STDERR_FILENO + 1);
|
||||||
|
|
||||||
execl(shell, argv0, "-c", shell_cmd, (char *) NULL);
|
execl(shell, argv0, "-c", shellcmd, (char *) NULL);
|
||||||
fatal("execl failed");
|
fatal("execl failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,20 +524,24 @@ client_signal(int sig)
|
|||||||
|
|
||||||
/* Callback for client read events. */
|
/* Callback for client read events. */
|
||||||
void
|
void
|
||||||
client_dispatch(struct imsg *imsg, __unused void *arg)
|
client_dispatch(struct imsg *imsg, void *arg)
|
||||||
{
|
{
|
||||||
if (imsg == NULL) {
|
if (imsg == NULL) {
|
||||||
client_exitreason = CLIENT_EXIT_LOST_SERVER;
|
client_exitreason = CLIENT_EXIT_LOST_SERVER;
|
||||||
client_exitval = 1;
|
client_exitval = 1;
|
||||||
} else if (client_attached)
|
proc_exit(client_proc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_attached)
|
||||||
client_dispatch_attached(imsg);
|
client_dispatch_attached(imsg);
|
||||||
else
|
else
|
||||||
client_dispatch_wait(imsg);
|
client_dispatch_wait(imsg, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dispatch imsgs when in wait state (before MSG_READY). */
|
/* Dispatch imsgs when in wait state (before MSG_READY). */
|
||||||
void
|
void
|
||||||
client_dispatch_wait(struct imsg *imsg)
|
client_dispatch_wait(struct imsg *imsg, const char *shellcmd)
|
||||||
{
|
{
|
||||||
char *data;
|
char *data;
|
||||||
ssize_t datalen;
|
ssize_t datalen;
|
||||||
@ -611,7 +623,7 @@ client_dispatch_wait(struct imsg *imsg)
|
|||||||
fatalx("bad MSG_SHELL string");
|
fatalx("bad MSG_SHELL string");
|
||||||
|
|
||||||
clear_signals(0);
|
clear_signals(0);
|
||||||
client_exec(data);
|
client_exec(data, shellcmd);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case MSG_DETACH:
|
case MSG_DETACH:
|
||||||
case MSG_DETACHKILL:
|
case MSG_DETACHKILL:
|
||||||
|
@ -31,7 +31,7 @@ enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_q *);
|
|||||||
const struct cmd_entry cmd_detach_client_entry = {
|
const struct cmd_entry cmd_detach_client_entry = {
|
||||||
"detach-client", "detach",
|
"detach-client", "detach",
|
||||||
"as:t:P", 0, 0,
|
"as:t:P", 0, 0,
|
||||||
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
|
"[-aP] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
|
||||||
CMD_READONLY,
|
CMD_READONLY,
|
||||||
cmd_detach_client_exec
|
cmd_detach_client_exec
|
||||||
};
|
};
|
||||||
|
@ -31,8 +31,8 @@ enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_kill_session_entry = {
|
const struct cmd_entry cmd_kill_session_entry = {
|
||||||
"kill-session", NULL,
|
"kill-session", NULL,
|
||||||
"at:", 0, 0,
|
"aCt:", 0, 0,
|
||||||
"[-a] " CMD_TARGET_SESSION_USAGE,
|
"[-aC] " CMD_TARGET_SESSION_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_kill_session_exec
|
cmd_kill_session_exec
|
||||||
};
|
};
|
||||||
@ -42,11 +42,18 @@ cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct session *s, *sloop, *stmp;
|
struct session *s, *sloop, *stmp;
|
||||||
|
struct winlink *wl;
|
||||||
|
|
||||||
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
|
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
if (args_has(args, 'a')) {
|
if (args_has(args, 'C')) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
wl->window->flags &= ~WINDOW_ALERTFLAGS;
|
||||||
|
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||||
|
}
|
||||||
|
server_redraw_session(s);
|
||||||
|
} else if (args_has(args, 'a')) {
|
||||||
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
|
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
|
||||||
if (sloop != s) {
|
if (sloop != s) {
|
||||||
server_destroy_session(sloop);
|
server_destroy_session(sloop);
|
||||||
|
@ -79,13 +79,13 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
cmdq_error(cmdq, "can't specify a value with -r");
|
cmdq_error(cmdq, "can't specify a value with -r");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
environ_set(env, name, NULL);
|
environ_clear(env, name);
|
||||||
} else {
|
} else {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
cmdq_error(cmdq, "no value specified");
|
cmdq_error(cmdq, "no value specified");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
environ_set(env, name, value);
|
environ_set(env, name, "%s", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
@ -32,8 +32,8 @@ enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_show_messages_entry = {
|
const struct cmd_entry cmd_show_messages_entry = {
|
||||||
"show-messages", "showmsgs",
|
"show-messages", "showmsgs",
|
||||||
"IJTt:", 0, 0,
|
"JTt:", 0, 0,
|
||||||
"[-IJT] " CMD_TARGET_CLIENT_USAGE,
|
"[-JT] " CMD_TARGET_CLIENT_USAGE,
|
||||||
0,
|
0,
|
||||||
cmd_show_messages_exec
|
cmd_show_messages_exec
|
||||||
};
|
};
|
||||||
@ -46,26 +46,9 @@ const struct cmd_entry cmd_server_info_entry = {
|
|||||||
cmd_show_messages_exec
|
cmd_show_messages_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
int cmd_show_messages_server(struct cmd_q *);
|
|
||||||
int cmd_show_messages_terminals(struct cmd_q *, int);
|
int cmd_show_messages_terminals(struct cmd_q *, int);
|
||||||
int cmd_show_messages_jobs(struct cmd_q *, int);
|
int cmd_show_messages_jobs(struct cmd_q *, int);
|
||||||
|
|
||||||
int
|
|
||||||
cmd_show_messages_server(struct cmd_q *cmdq)
|
|
||||||
{
|
|
||||||
char *tim;
|
|
||||||
|
|
||||||
tim = ctime(&start_time);
|
|
||||||
*strchr(tim, '\n') = '\0';
|
|
||||||
|
|
||||||
cmdq_print(cmdq, "started %s", tim);
|
|
||||||
cmdq_print(cmdq, "socket path %s", socket_path);
|
|
||||||
cmdq_print(cmdq, "debug level %d", debug_level);
|
|
||||||
cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION);
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_show_messages_terminals(struct cmd_q *cmdq, int blank)
|
cmd_show_messages_terminals(struct cmd_q *cmdq, int blank)
|
||||||
{
|
{
|
||||||
@ -116,10 +99,6 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
int done, blank;
|
int done, blank;
|
||||||
|
|
||||||
done = blank = 0;
|
done = blank = 0;
|
||||||
if (args_has(args, 'I') || self->entry == &cmd_server_info_entry) {
|
|
||||||
blank = cmd_show_messages_server(cmdq);
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
|
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
|
||||||
blank = cmd_show_messages_terminals(cmdq, blank);
|
blank = cmd_show_messages_terminals(cmdq, blank);
|
||||||
done = 1;
|
done = 1;
|
||||||
|
46
environ.c
46
environ.c
@ -83,8 +83,12 @@ environ_copy(struct environ *srcenv, struct environ *dstenv)
|
|||||||
{
|
{
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
|
|
||||||
RB_FOREACH(envent, environ, srcenv)
|
RB_FOREACH(envent, environ, srcenv) {
|
||||||
environ_set(dstenv, envent->name, envent->value);
|
if (envent->value == NULL)
|
||||||
|
environ_clear(dstenv, envent->name);
|
||||||
|
else
|
||||||
|
environ_set(dstenv, envent->name, "%s", envent->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find an environment variable. */
|
/* Find an environment variable. */
|
||||||
@ -99,23 +103,37 @@ environ_find(struct environ *env, const char *name)
|
|||||||
|
|
||||||
/* Set an environment variable. */
|
/* Set an environment variable. */
|
||||||
void
|
void
|
||||||
environ_set(struct environ *env, const char *name, const char *value)
|
environ_set(struct environ *env, const char *name, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct environ_entry *envent;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if ((envent = environ_find(env, name)) != NULL) {
|
||||||
|
free(envent->value);
|
||||||
|
xvasprintf(&envent->value, fmt, ap);
|
||||||
|
} else {
|
||||||
|
envent = xmalloc(sizeof *envent);
|
||||||
|
envent->name = xstrdup(name);
|
||||||
|
xvasprintf(&envent->value, fmt, ap);
|
||||||
|
RB_INSERT(environ, env, envent);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear an environment variable. */
|
||||||
|
void
|
||||||
|
environ_clear(struct environ *env, const char *name)
|
||||||
{
|
{
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
|
|
||||||
if ((envent = environ_find(env, name)) != NULL) {
|
if ((envent = environ_find(env, name)) != NULL) {
|
||||||
free(envent->value);
|
free(envent->value);
|
||||||
if (value != NULL)
|
envent->value = NULL;
|
||||||
envent->value = xstrdup(value);
|
|
||||||
else
|
|
||||||
envent->value = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
envent = xmalloc(sizeof *envent);
|
envent = xmalloc(sizeof *envent);
|
||||||
envent->name = xstrdup(name);
|
envent->name = xstrdup(name);
|
||||||
if (value != NULL)
|
envent->value = NULL;
|
||||||
envent->value = xstrdup(value);
|
|
||||||
else
|
|
||||||
envent->value = NULL;
|
|
||||||
RB_INSERT(environ, env, envent);
|
RB_INSERT(environ, env, envent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +152,7 @@ environ_put(struct environ *env, const char *var)
|
|||||||
name = xstrdup(var);
|
name = xstrdup(var);
|
||||||
name[strcspn(name, "=")] = '\0';
|
name[strcspn(name, "=")] = '\0';
|
||||||
|
|
||||||
environ_set(env, name, value);
|
environ_set(env, name, "%s", value);
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,9 +184,9 @@ environ_update(const char *vars, struct environ *srcenv,
|
|||||||
copyvars = next = xstrdup(vars);
|
copyvars = next = xstrdup(vars);
|
||||||
while ((var = strsep(&next, " ")) != NULL) {
|
while ((var = strsep(&next, " ")) != NULL) {
|
||||||
if ((envent = environ_find(srcenv, var)) == NULL)
|
if ((envent = environ_find(srcenv, var)) == NULL)
|
||||||
environ_set(dstenv, var, NULL);
|
environ_clear(dstenv, var);
|
||||||
else
|
else
|
||||||
environ_set(dstenv, envent->name, envent->value);
|
environ_set(dstenv, envent->name, "%s", envent->value);
|
||||||
}
|
}
|
||||||
free(copyvars);
|
free(copyvars);
|
||||||
}
|
}
|
||||||
|
2
format.c
2
format.c
@ -505,6 +505,8 @@ format_create_flags(int flags)
|
|||||||
format_add_cb(ft, "host", format_cb_host);
|
format_add_cb(ft, "host", format_cb_host);
|
||||||
format_add_cb(ft, "host_short", format_cb_host_short);
|
format_add_cb(ft, "host_short", format_cb_host_short);
|
||||||
format_add_cb(ft, "pid", format_cb_pid);
|
format_add_cb(ft, "pid", format_cb_pid);
|
||||||
|
format_add(ft, "socket_path", "%s", socket_path);
|
||||||
|
format_add_tv(ft, "start_time", &start_time);
|
||||||
|
|
||||||
return (ft);
|
return (ft);
|
||||||
}
|
}
|
||||||
|
35
log.c
35
log.c
@ -22,29 +22,52 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
FILE *log_file;
|
static FILE *log_file;
|
||||||
|
static int log_level;
|
||||||
|
|
||||||
void log_event_cb(int, const char *);
|
static void log_event_cb(int, const char *);
|
||||||
void log_vwrite(const char *, va_list);
|
static void log_vwrite(const char *, va_list);
|
||||||
|
|
||||||
/* Log callback for libevent. */
|
/* Log callback for libevent. */
|
||||||
void
|
static void
|
||||||
log_event_cb(__unused int severity, const char *msg)
|
log_event_cb(__unused int severity, const char *msg)
|
||||||
{
|
{
|
||||||
log_debug("%s", msg);
|
log_debug("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Increment log level. */
|
||||||
|
void
|
||||||
|
log_add_level(void)
|
||||||
|
{
|
||||||
|
log_level++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get log level. */
|
||||||
|
int
|
||||||
|
log_get_level(void)
|
||||||
|
{
|
||||||
|
return (log_level);
|
||||||
|
}
|
||||||
|
|
||||||
/* Open logging to file. */
|
/* Open logging to file. */
|
||||||
void
|
void
|
||||||
log_open(const char *path)
|
log_open(const char *name)
|
||||||
{
|
{
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
if (log_level == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (log_file != NULL)
|
if (log_file != NULL)
|
||||||
fclose(log_file);
|
fclose(log_file);
|
||||||
|
|
||||||
|
xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
|
||||||
log_file = fopen(path, "w");
|
log_file = fopen(path, "w");
|
||||||
|
free(path);
|
||||||
if (log_file == NULL)
|
if (log_file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -64,7 +87,7 @@ log_close(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write a log message. */
|
/* Write a log message. */
|
||||||
void
|
static void
|
||||||
log_vwrite(const char *msg, va_list ap)
|
log_vwrite(const char *msg, va_list ap)
|
||||||
{
|
{
|
||||||
char *fmt, *out;
|
char *fmt, *out;
|
||||||
|
8
proc.c
8
proc.c
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
@ -168,6 +169,7 @@ proc_start(const char *name, struct event_base *base, int forkflag,
|
|||||||
void (*signalcb)(int))
|
void (*signalcb)(int))
|
||||||
{
|
{
|
||||||
struct tmuxproc *tp;
|
struct tmuxproc *tp;
|
||||||
|
struct utsname u;
|
||||||
|
|
||||||
if (forkflag) {
|
if (forkflag) {
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
@ -189,11 +191,17 @@ proc_start(const char *name, struct event_base *base, int forkflag,
|
|||||||
logfile(name);
|
logfile(name);
|
||||||
|
|
||||||
#ifdef HAVE_SETPROCTITLE
|
#ifdef HAVE_SETPROCTITLE
|
||||||
|
log_open(name);
|
||||||
setproctitle("%s (%s)", name, socket_path);
|
setproctitle("%s (%s)", name, socket_path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (uname(&u) < 0)
|
||||||
|
memset(&u, 0, sizeof u);
|
||||||
|
|
||||||
log_debug("%s started (%ld): socket %s, protocol %d", name,
|
log_debug("%s started (%ld): socket %s, protocol %d", name,
|
||||||
(long)getpid(), socket_path, PROTOCOL_VERSION);
|
(long)getpid(), socket_path, PROTOCOL_VERSION);
|
||||||
|
log_debug("on %s %s %s; libevent %s (%s)", u.sysname, u.release,
|
||||||
|
u.version, event_get_version(), event_get_method());
|
||||||
|
|
||||||
tp = xcalloc(1, sizeof *tp);
|
tp = xcalloc(1, sizeof *tp);
|
||||||
tp->name = xstrdup(name);
|
tp->name = xstrdup(name);
|
||||||
|
11
server-fn.c
11
server-fn.c
@ -32,20 +32,19 @@ void server_callback_identify(int, short, void *);
|
|||||||
void
|
void
|
||||||
server_fill_environ(struct session *s, struct environ *env)
|
server_fill_environ(struct session *s, struct environ *env)
|
||||||
{
|
{
|
||||||
char var[PATH_MAX], *term;
|
char *term;
|
||||||
u_int idx;
|
u_int idx;
|
||||||
long pid;
|
long pid;
|
||||||
|
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
term = options_get_string(global_options, "default-terminal");
|
term = options_get_string(global_options, "default-terminal");
|
||||||
environ_set(env, "TERM", term);
|
environ_set(env, "TERM", "%s", term);
|
||||||
|
|
||||||
idx = s->id;
|
idx = s->id;
|
||||||
} else
|
} else
|
||||||
idx = (u_int)-1;
|
idx = (u_int)-1;
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
xsnprintf(var, sizeof var, "%s,%ld,%u", socket_path, pid, idx);
|
environ_set(env, "TMUX", "%s,%ld,%u", socket_path, pid, idx);
|
||||||
environ_set(env, "TMUX", var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
12
server.c
12
server.c
@ -172,7 +172,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
|
|||||||
}
|
}
|
||||||
close(pair[0]);
|
close(pair[0]);
|
||||||
|
|
||||||
if (debug_level > 3)
|
if (log_get_level() > 3)
|
||||||
tty_create_log();
|
tty_create_log();
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
@ -189,7 +189,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
|
|||||||
mode_key_init_trees();
|
mode_key_init_trees();
|
||||||
key_bindings_init();
|
key_bindings_init();
|
||||||
|
|
||||||
start_time = time(NULL);
|
gettimeofday(&start_time, NULL);
|
||||||
|
|
||||||
server_fd = server_create_socket();
|
server_fd = server_create_socket();
|
||||||
if (server_fd == -1)
|
if (server_fd == -1)
|
||||||
@ -197,9 +197,11 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
|
|||||||
server_update_socket();
|
server_update_socket();
|
||||||
server_client_create(pair[1]);
|
server_client_create(pair[1]);
|
||||||
|
|
||||||
unlink(lockfile);
|
if (lockfd >= 0) {
|
||||||
free(lockfile);
|
unlink(lockfile);
|
||||||
close(lockfd);
|
free(lockfile);
|
||||||
|
close(lockfd);
|
||||||
|
}
|
||||||
|
|
||||||
start_cfg();
|
start_cfg();
|
||||||
|
|
||||||
|
16
tmux.1
16
tmux.1
@ -718,8 +718,7 @@ is used,
|
|||||||
.Ic update-environment
|
.Ic update-environment
|
||||||
option will not be applied.
|
option will not be applied.
|
||||||
.It Xo Ic detach-client
|
.It Xo Ic detach-client
|
||||||
.Op Fl P
|
.Op Fl aP
|
||||||
.Op Fl a
|
|
||||||
.Op Fl s Ar target-session
|
.Op Fl s Ar target-session
|
||||||
.Op Fl t Ar target-client
|
.Op Fl t Ar target-client
|
||||||
.Xc
|
.Xc
|
||||||
@ -745,7 +744,7 @@ Kill the
|
|||||||
.Nm
|
.Nm
|
||||||
server and clients and destroy all sessions.
|
server and clients and destroy all sessions.
|
||||||
.It Xo Ic kill-session
|
.It Xo Ic kill-session
|
||||||
.Op Fl a
|
.Op Fl aC
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
Destroy the given session, closing any windows linked to it and no other
|
Destroy the given session, closing any windows linked to it and no other
|
||||||
@ -753,6 +752,10 @@ sessions, and detaching all clients attached to it.
|
|||||||
If
|
If
|
||||||
.Fl a
|
.Fl a
|
||||||
is given, all sessions but the specified one is killed.
|
is given, all sessions but the specified one is killed.
|
||||||
|
The
|
||||||
|
.Fl C
|
||||||
|
flag clears alerts (bell, activity, or silence) in all windows linked to the
|
||||||
|
session.
|
||||||
.It Xo Ic list-clients
|
.It Xo Ic list-clients
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
@ -892,7 +895,7 @@ is specified, only update the client's status bar.
|
|||||||
Rename the session to
|
Rename the session to
|
||||||
.Ar new-name .
|
.Ar new-name .
|
||||||
.It Xo Ic show-messages
|
.It Xo Ic show-messages
|
||||||
.Op Fl IJT
|
.Op Fl JT
|
||||||
.Op Fl t Ar target-client
|
.Op Fl t Ar target-client
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic showmsgs )
|
.D1 (alias: Ic showmsgs )
|
||||||
@ -905,11 +908,10 @@ With
|
|||||||
.Fl t ,
|
.Fl t ,
|
||||||
display the log for
|
display the log for
|
||||||
.Ar target-client .
|
.Ar target-client .
|
||||||
.Fl I ,
|
|
||||||
.Fl J
|
.Fl J
|
||||||
and
|
and
|
||||||
.Fl T
|
.Fl T
|
||||||
show debugging information about the running server, jobs and terminals.
|
show debugging information about jobs and terminals.
|
||||||
.It Ic source-file Ar path
|
.It Ic source-file Ar path
|
||||||
.D1 (alias: Ic source )
|
.D1 (alias: Ic source )
|
||||||
Execute commands from
|
Execute commands from
|
||||||
@ -3416,6 +3418,8 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "session_name" Ta "#S" Ta "Name of session"
|
.It Li "session_name" Ta "#S" Ta "Name of session"
|
||||||
.It Li "session_width" Ta "" Ta "Width of session"
|
.It Li "session_width" Ta "" Ta "Width of session"
|
||||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
||||||
|
.It Li "socket_path" Ta "" "Server socket path"
|
||||||
|
.It Li "start_time" Ta "" Ta "Server start time"
|
||||||
.It Li "window_activity" Ta "" Ta "Integer time of window last activity"
|
.It Li "window_activity" Ta "" Ta "Integer time of window last activity"
|
||||||
.It Li "window_active" Ta "" Ta "1 if window active"
|
.It Li "window_active" Ta "" Ta "1 if window active"
|
||||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
||||||
|
116
tmux.c
116
tmux.c
@ -41,13 +41,11 @@ struct options *global_s_options; /* session options */
|
|||||||
struct options *global_w_options; /* window options */
|
struct options *global_w_options; /* window options */
|
||||||
struct environ *global_environ;
|
struct environ *global_environ;
|
||||||
|
|
||||||
char *shell_cmd;
|
struct timeval start_time;
|
||||||
int debug_level;
|
const char *socket_path;
|
||||||
time_t start_time;
|
|
||||||
char socket_path[PATH_MAX];
|
|
||||||
|
|
||||||
__dead void usage(void);
|
__dead void usage(void);
|
||||||
char *makesocketpath(const char *);
|
static char *make_label(const char *);
|
||||||
|
|
||||||
#ifndef HAVE___PROGNAME
|
#ifndef HAVE___PROGNAME
|
||||||
char *__progname = (char *) "tmux";
|
char *__progname = (char *) "tmux";
|
||||||
@ -63,18 +61,6 @@ usage(void)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
logfile(const char *name)
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
if (debug_level > 0) {
|
|
||||||
xasprintf(&path, "tmux-%s-%ld.log", name, (long) getpid());
|
|
||||||
log_open(path);
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
getshell(void)
|
getshell(void)
|
||||||
{
|
{
|
||||||
@ -121,38 +107,48 @@ areshell(const char *shell)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
static char *
|
||||||
makesocketpath(const char *label)
|
make_label(const char *label)
|
||||||
{
|
{
|
||||||
char base[PATH_MAX], realbase[PATH_MAX], *path, *s;
|
char *base, resolved[PATH_MAX], *path, *s;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
u_int uid;
|
u_int uid;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
if (label == NULL)
|
||||||
|
label = "default";
|
||||||
|
|
||||||
uid = getuid();
|
uid = getuid();
|
||||||
|
|
||||||
if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
|
if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
|
||||||
xsnprintf(base, sizeof base, "%s/tmux-%u", s, uid);
|
xasprintf(&base, "%s/tmux-%u", s, uid);
|
||||||
else
|
else
|
||||||
xsnprintf(base, sizeof base, "%s/tmux-%u", _PATH_TMP, uid);
|
xasprintf(&base, "%s/tmux-%u", _PATH_TMP, uid);
|
||||||
|
|
||||||
if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
|
if (mkdir(base, S_IRWXU) != 0 && errno != EEXIST)
|
||||||
return (NULL);
|
goto fail;
|
||||||
|
|
||||||
if (lstat(base, &sb) != 0)
|
if (lstat(base, &sb) != 0)
|
||||||
return (NULL);
|
goto fail;
|
||||||
if (!S_ISDIR(sb.st_mode)) {
|
if (!S_ISDIR(sb.st_mode)) {
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
return (NULL);
|
goto fail;
|
||||||
}
|
}
|
||||||
if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) {
|
if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) {
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return (NULL);
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realpath(base, realbase) == NULL)
|
if (realpath(base, resolved) == NULL)
|
||||||
strlcpy(realbase, base, sizeof realbase);
|
strlcpy(resolved, base, sizeof resolved);
|
||||||
|
xasprintf(&path, "%s/%s", resolved, label);
|
||||||
xasprintf(&path, "%s/%s", realbase, label);
|
|
||||||
return (path);
|
return (path);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
saved_errno = errno;
|
||||||
|
free(base);
|
||||||
|
errno = saved_errno;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -193,7 +189,7 @@ find_home(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *path, *label, **var, tmp[PATH_MAX];
|
char *path, *label, **var, tmp[PATH_MAX], *shellcmd = NULL;
|
||||||
const char *s;
|
const char *s;
|
||||||
int opt, flags, keys;
|
int opt, flags, keys;
|
||||||
|
|
||||||
@ -216,8 +212,8 @@ main(int argc, char **argv)
|
|||||||
flags |= CLIENT_256COLOURS;
|
flags |= CLIENT_256COLOURS;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
free(shell_cmd);
|
free(shellcmd);
|
||||||
shell_cmd = xstrdup(optarg);
|
shellcmd = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
if (flags & CLIENT_CONTROL)
|
if (flags & CLIENT_CONTROL)
|
||||||
@ -248,7 +244,7 @@ main(int argc, char **argv)
|
|||||||
flags |= CLIENT_UTF8;
|
flags |= CLIENT_UTF8;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
debug_level++;
|
log_add_level();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
@ -257,7 +253,7 @@ main(int argc, char **argv)
|
|||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (shell_cmd != NULL && argc != 0)
|
if (shellcmd != NULL && argc != 0)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
@ -292,7 +288,7 @@ main(int argc, char **argv)
|
|||||||
for (var = environ; *var != NULL; var++)
|
for (var = environ; *var != NULL; var++)
|
||||||
environ_put(global_environ, *var);
|
environ_put(global_environ, *var);
|
||||||
if (getcwd(tmp, sizeof tmp) != NULL)
|
if (getcwd(tmp, sizeof tmp) != NULL)
|
||||||
environ_set(global_environ, "PWD", tmp);
|
environ_set(global_environ, "PWD", "%s", tmp);
|
||||||
|
|
||||||
global_options = options_create(NULL);
|
global_options = options_create(NULL);
|
||||||
options_table_populate_tree(OPTIONS_TABLE_SERVER, global_options);
|
options_table_populate_tree(OPTIONS_TABLE_SERVER, global_options);
|
||||||
@ -317,42 +313,24 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out the socket path. If specified on the command-line with -S
|
* If socket is specified on the command-line with -S or -L, it is
|
||||||
* or -L, use it, otherwise try $TMUX or assume -L default.
|
* used. Otherwise, $TMUX is checked and if that fails "default" is
|
||||||
|
* used.
|
||||||
*/
|
*/
|
||||||
if (path == NULL) {
|
if (path == NULL && label == NULL) {
|
||||||
/* If no -L, use the environment. */
|
s = getenv("TMUX");
|
||||||
if (label == NULL) {
|
if (s != NULL && *s != '\0' && *s != ',') {
|
||||||
s = getenv("TMUX");
|
path = xstrdup(s);
|
||||||
if (s != NULL) {
|
path[strcspn (path, ",")] = '\0';
|
||||||
path = xstrdup(s);
|
|
||||||
path[strcspn (path, ",")] = '\0';
|
|
||||||
if (*path == '\0') {
|
|
||||||
free(path);
|
|
||||||
label = xstrdup("default");
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
label = xstrdup("default");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -L or default set. */
|
|
||||||
if (label != NULL) {
|
|
||||||
if ((path = makesocketpath(label)) == NULL) {
|
|
||||||
fprintf(stderr, "can't create socket: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(label);
|
if (path == NULL && (path = make_label(label)) == NULL) {
|
||||||
|
fprintf(stderr, "can't create socket: %s\n", strerror(errno));
|
||||||
if (strlcpy(socket_path, path, sizeof socket_path) >=
|
|
||||||
sizeof socket_path) {
|
|
||||||
fprintf(stderr, "socket path too long: %s\n", path);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
free(path);
|
socket_path = path;
|
||||||
|
free(label);
|
||||||
|
|
||||||
/* Pass control to the client. */
|
/* Pass control to the client. */
|
||||||
exit(client_main(osdep_event_init(), argc, argv, flags));
|
exit(client_main(event_init(), argc, argv, flags, shellcmd));
|
||||||
}
|
}
|
||||||
|
21
tmux.h
21
tmux.h
@ -1433,11 +1433,8 @@ extern struct options *global_options;
|
|||||||
extern struct options *global_s_options;
|
extern struct options *global_s_options;
|
||||||
extern struct options *global_w_options;
|
extern struct options *global_w_options;
|
||||||
extern struct environ *global_environ;
|
extern struct environ *global_environ;
|
||||||
extern char *shell_cmd;
|
extern struct timeval start_time;
|
||||||
extern int debug_level;
|
extern const char *socket_path;
|
||||||
extern time_t start_time;
|
|
||||||
extern char socket_path[PATH_MAX];
|
|
||||||
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 *);
|
||||||
@ -1572,7 +1569,9 @@ struct environ_entry *environ_first(struct environ *);
|
|||||||
struct environ_entry *environ_next(struct environ_entry *);
|
struct environ_entry *environ_next(struct environ_entry *);
|
||||||
void environ_copy(struct environ *, struct environ *);
|
void environ_copy(struct environ *, struct environ *);
|
||||||
struct environ_entry *environ_find(struct environ *, const char *);
|
struct environ_entry *environ_find(struct environ *, const char *);
|
||||||
void environ_set(struct environ *, const char *, const char *);
|
void printflike(3, 4) environ_set(struct environ *, const char *, const char *,
|
||||||
|
...);
|
||||||
|
void environ_clear(struct environ *, const char *);
|
||||||
void environ_put(struct environ *, const char *);
|
void environ_put(struct environ *, const char *);
|
||||||
void environ_unset(struct environ *, const char *);
|
void environ_unset(struct environ *, const char *);
|
||||||
void environ_update(const char *, struct environ *, struct environ *);
|
void environ_update(const char *, struct environ *, struct environ *);
|
||||||
@ -1736,7 +1735,7 @@ int cmd_string_parse(const char *, struct cmd_list **, const char *,
|
|||||||
void cmd_wait_for_flush(void);
|
void cmd_wait_for_flush(void);
|
||||||
|
|
||||||
/* client.c */
|
/* client.c */
|
||||||
int client_main(struct event_base *, int, char **, int);
|
int client_main(struct event_base *, int, char **, int, const char *);
|
||||||
|
|
||||||
/* key-bindings.c */
|
/* key-bindings.c */
|
||||||
RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
|
RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
|
||||||
@ -1744,7 +1743,7 @@ RB_PROTOTYPE(key_tables, key_table, entry, key_table_cmp);
|
|||||||
extern struct key_tables key_tables;
|
extern struct key_tables key_tables;
|
||||||
int key_table_cmp(struct key_table *, struct key_table *);
|
int key_table_cmp(struct key_table *, struct key_table *);
|
||||||
int key_bindings_cmp(struct key_binding *, struct key_binding *);
|
int key_bindings_cmp(struct key_binding *, struct key_binding *);
|
||||||
struct key_table *key_bindings_get_table(const char *, int);
|
struct key_table *key_bindings_get_table(const char *, int);
|
||||||
void key_bindings_unref_table(struct key_table *);
|
void key_bindings_unref_table(struct key_table *);
|
||||||
void key_bindings_add(const char *, key_code, int, struct cmd_list *);
|
void key_bindings_add(const char *, key_code, int, struct cmd_list *);
|
||||||
void key_bindings_remove(const char *, key_code);
|
void key_bindings_remove(const char *, key_code);
|
||||||
@ -2214,8 +2213,10 @@ char *osdep_get_cwd(int);
|
|||||||
struct event_base *osdep_event_init(void);
|
struct event_base *osdep_event_init(void);
|
||||||
|
|
||||||
/* log.c */
|
/* log.c */
|
||||||
void log_open(const char *);
|
void log_add_level(void);
|
||||||
void log_close(void);
|
int log_get_level(void);
|
||||||
|
void log_open(const char *);
|
||||||
|
void log_close(void);
|
||||||
void printflike(1, 2) log_debug(const char *, ...);
|
void printflike(1, 2) log_debug(const char *, ...);
|
||||||
__dead void printflike(1, 2) fatal(const char *, ...);
|
__dead void printflike(1, 2) fatal(const char *, ...);
|
||||||
__dead void printflike(1, 2) fatalx(const char *, ...);
|
__dead void printflike(1, 2) fatalx(const char *, ...);
|
||||||
|
7
window.c
7
window.c
@ -810,7 +810,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
|||||||
struct termios *tio, char **cause)
|
struct termios *tio, char **cause)
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
char *argv0, *cmd, **argvp, paneid[16];
|
char *argv0, *cmd, **argvp;
|
||||||
const char *ptr, *first, *home;
|
const char *ptr, *first, *home;
|
||||||
struct termios tio2;
|
struct termios tio2;
|
||||||
#ifdef HAVE_UTEMPTER
|
#ifdef HAVE_UTEMPTER
|
||||||
@ -871,9 +871,8 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
|||||||
closefrom(STDERR_FILENO + 1);
|
closefrom(STDERR_FILENO + 1);
|
||||||
|
|
||||||
if (path != NULL)
|
if (path != NULL)
|
||||||
environ_set(env, "PATH", path);
|
environ_set(env, "PATH", "%s", path);
|
||||||
xsnprintf(paneid, sizeof paneid, "%%%u", wp->id);
|
environ_set(env, "TMUX_PANE", "%%%u", wp->id);
|
||||||
environ_set(env, "TMUX_PANE", paneid);
|
|
||||||
environ_push(env);
|
environ_push(env);
|
||||||
|
|
||||||
clear_signals(1);
|
clear_signals(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user