diff options
author | Thomas Adam <thomas@xteddy.org> | 2015-11-25 16:37:30 +0000 |
---|---|---|
committer | Thomas Adam <thomas@xteddy.org> | 2015-11-25 16:37:30 +0000 |
commit | 890d8da2e3588d416ef178e2e74ed3df226a6040 (patch) | |
tree | 3d024b90830e8afe48f75f0cb741965a5bb76015 | |
parent | 0a2ef2b932f37d54157d82e526a8097caf9143ba (diff) | |
parent | ac8678aefe157d7e40c5bcedd12333eaedf0df92 (diff) | |
download | rtmux-890d8da2e3588d416ef178e2e74ed3df226a6040.tar.gz rtmux-890d8da2e3588d416ef178e2e74ed3df226a6040.tar.bz2 rtmux-890d8da2e3588d416ef178e2e74ed3df226a6040.zip |
Merge branch 'obsd-master'
Conflicts:
log.c
proc.c
tmux.c
-rw-r--r-- | client.c | 94 | ||||
-rw-r--r-- | cmd-detach-client.c | 2 | ||||
-rw-r--r-- | cmd-kill-session.c | 13 | ||||
-rw-r--r-- | cmd-set-environment.c | 4 | ||||
-rw-r--r-- | cmd-show-messages.c | 25 | ||||
-rw-r--r-- | environ.c | 46 | ||||
-rw-r--r-- | format.c | 2 | ||||
-rw-r--r-- | log.c | 35 | ||||
-rw-r--r-- | proc.c | 8 | ||||
-rw-r--r-- | server-fn.c | 11 | ||||
-rw-r--r-- | server.c | 12 | ||||
-rw-r--r-- | tmux.1 | 16 | ||||
-rw-r--r-- | tmux.c | 116 | ||||
-rw-r--r-- | tmux.h | 21 | ||||
-rw-r--r-- | window.c | 7 |
15 files changed, 222 insertions, 190 deletions
@@ -52,33 +52,35 @@ enum msgtype client_exittype; const char *client_exitsession; int client_attached; -__dead void client_exec(const char *); +__dead void client_exec(const char *,const 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_stdin_callback(int, short, void *); void client_write(int, const char *, size_t); void client_signal(int); void client_dispatch(struct imsg *, void *); 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); /* * 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 - * retry. Ignore other errors - just continue and start the server without the - * lock. + * another client, so block until the lock is released and return -2 to + * retry. Return -1 on failure to continue and start the server anyway. */ int client_get_lock(char *lockfile) { int lockfd; - if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) - fatal("open failed"); 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) { log_debug("flock failed: %s", strerror(errno)); if (errno != EAGAIN) @@ -86,7 +88,7 @@ client_get_lock(char *lockfile) while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR) /* nothing */; close(lockfd); - return (-1); + return (-2); } log_debug("flock succeeded"); @@ -95,7 +97,7 @@ client_get_lock(char *lockfile) /* Connect client to server. */ 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; size_t size; @@ -113,10 +115,10 @@ client_connect(struct event_base *base, char *path, int start_server) retry: if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - fatal("socket failed"); + return (-1); 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)); if (errno != ECONNREFUSED && errno != ENOENT) goto failed; @@ -126,12 +128,16 @@ retry: if (!locked) { xasprintf(&lockfile, "%s.lock", path); - if ((lockfd = client_get_lock(lockfile)) == -1) { - log_debug("didn't get lock"); + if ((lockfd = client_get_lock(lockfile)) < 0) { + log_debug("didn't get lock (%d)", lockfd); + 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, @@ -143,7 +149,7 @@ retry: goto retry; } - if (unlink(path) != 0 && errno != ENOENT) { + if (lockfd >= 0 && unlink(path) != 0 && errno != ENOENT) { free(lockfile); close(lockfd); return (-1); @@ -151,7 +157,7 @@ retry: fd = server_start(base, lockfd, lockfile); } - if (locked) { + if (locked && lockfd >= 0) { free(lockfile); close(lockfd); } @@ -206,7 +212,8 @@ client_exit_message(void) /* Client main loop. */ 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_list *cmdlist; @@ -227,7 +234,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags) /* Set up the initial command. */ cmdflags = 0; - if (shell_cmd != NULL) { + if (shellcmd != NULL) { msg = MSG_SHELL; cmdflags = CMD_STARTSERVER; } else if (argc == 0) { @@ -254,6 +261,9 @@ client_main(struct event_base *base, int argc, char **argv, int flags) 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. */ fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER); if (fd == -1) { @@ -266,10 +276,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags) } return (1); } - - /* Build process state. */ - client_proc = proc_start("client", base, 0, client_signal); - client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL); + client_peer = proc_add_peer(client_proc, fd, client_dispatch, + (void *)shellcmd); /* Save these before pledge(). */ 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, client_stdin_callback, NULL); if (client_flags & CLIENT_CONTROLCONTROL) { - if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) { - fprintf(stderr, "tcgetattr failed: %s\n", - strerror(errno)); - return (1); - } + if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) + fatal("tcgetattr failed"); cfmakeraw(&tio); tio.c_iflag = ICRNL|IXANY; 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("\033\\"); tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio); - } + } else if (client_exitreason != CLIENT_EXIT_NONE) + fprintf(stderr, "%s\n", client_exit_message()); setblocking(STDIN_FILENO, 1); return (client_exitval); } @@ -392,7 +398,8 @@ client_send_identify(const char *ttynam, const char *cwd) s = ""; 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); 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++) { sslen = strlen(*ss) + 1; - if (sslen <= MAX_IMSGSIZE - IMSG_HEADER_SIZE) - proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen); + if (sslen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) + continue; + proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen); } 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. */ __dead void -client_exec(const char *shell) +client_exec(const char *shell, const char *shellcmd) { const char *name, *ptr; char *argv0; - log_debug("shell %s, command %s", shell, shell_cmd); + log_debug("shell %s, command %s", shell, shellcmd); ptr = strrchr(shell, '/'); if (ptr != NULL && *(ptr + 1) != '\0') @@ -470,7 +478,7 @@ client_exec(const char *shell) setblocking(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"); } @@ -516,20 +524,24 @@ client_signal(int sig) /* Callback for client read events. */ void -client_dispatch(struct imsg *imsg, __unused void *arg) +client_dispatch(struct imsg *imsg, void *arg) { if (imsg == NULL) { client_exitreason = CLIENT_EXIT_LOST_SERVER; client_exitval = 1; - } else if (client_attached) + proc_exit(client_proc); + return; + } + + if (client_attached) client_dispatch_attached(imsg); else - client_dispatch_wait(imsg); + client_dispatch_wait(imsg, arg); } /* Dispatch imsgs when in wait state (before MSG_READY). */ void -client_dispatch_wait(struct imsg *imsg) +client_dispatch_wait(struct imsg *imsg, const char *shellcmd) { char *data; ssize_t datalen; @@ -611,7 +623,7 @@ client_dispatch_wait(struct imsg *imsg) fatalx("bad MSG_SHELL string"); clear_signals(0); - client_exec(data); + client_exec(data, shellcmd); /* NOTREACHED */ case MSG_DETACH: case MSG_DETACHKILL: diff --git a/cmd-detach-client.c b/cmd-detach-client.c index 813ac032..f7369df0 100644 --- a/cmd-detach-client.c +++ b/cmd-detach-client.c @@ -31,7 +31,7 @@ enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_detach_client_entry = { "detach-client", "detach", "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_detach_client_exec }; diff --git a/cmd-kill-session.c b/cmd-kill-session.c index 74843eb6..3f39c241 100644 --- a/cmd-kill-session.c +++ b/cmd-kill-session.c @@ -31,8 +31,8 @@ enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_kill_session_entry = { "kill-session", NULL, - "at:", 0, 0, - "[-a] " CMD_TARGET_SESSION_USAGE, + "aCt:", 0, 0, + "[-aC] " CMD_TARGET_SESSION_USAGE, 0, 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 session *s, *sloop, *stmp; + struct winlink *wl; if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL) 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) { if (sloop != s) { server_destroy_session(sloop); diff --git a/cmd-set-environment.c b/cmd-set-environment.c index 864e1d9b..2c0010af 100644 --- a/cmd-set-environment.c +++ b/cmd-set-environment.c @@ -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"); return (CMD_RETURN_ERROR); } - environ_set(env, name, NULL); + environ_clear(env, name); } else { if (value == NULL) { cmdq_error(cmdq, "no value specified"); return (CMD_RETURN_ERROR); } - environ_set(env, name, value); + environ_set(env, name, "%s", value); } return (CMD_RETURN_NORMAL); diff --git a/cmd-show-messages.c b/cmd-show-messages.c index d85baba9..d1a8ce88 100644 --- a/cmd-show-messages.c +++ b/cmd-show-messages.c @@ -32,8 +32,8 @@ enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_show_messages_entry = { "show-messages", "showmsgs", - "IJTt:", 0, 0, - "[-IJT] " CMD_TARGET_CLIENT_USAGE, + "JTt:", 0, 0, + "[-JT] " CMD_TARGET_CLIENT_USAGE, 0, cmd_show_messages_exec }; @@ -46,27 +46,10 @@ const struct cmd_entry cmd_server_info_entry = { 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_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 cmd_show_messages_terminals(struct cmd_q *cmdq, int blank) { struct tty_term *term; @@ -116,10 +99,6 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq) int done, blank; 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) { blank = cmd_show_messages_terminals(cmdq, blank); done = 1; @@ -83,8 +83,12 @@ environ_copy(struct environ *srcenv, struct environ *dstenv) { struct environ_entry *envent; - RB_FOREACH(envent, environ, srcenv) - environ_set(dstenv, envent->name, envent->value); + RB_FOREACH(envent, environ, srcenv) { + if (envent->value == NULL) + environ_clear(dstenv, envent->name); + else + environ_set(dstenv, envent->name, "%s", envent->value); + } } /* Find an environment variable. */ @@ -99,23 +103,37 @@ environ_find(struct environ *env, const char *name) /* Set an environment variable. */ 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); - if (value != NULL) - envent->value = xstrdup(value); - else - envent->value = NULL; + xvasprintf(&envent->value, fmt, ap); } else { envent = xmalloc(sizeof *envent); envent->name = xstrdup(name); - if (value != NULL) - envent->value = xstrdup(value); - else - envent->value = NULL; + 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; + + if ((envent = environ_find(env, name)) != NULL) { + free(envent->value); + envent->value = NULL; + } else { + envent = xmalloc(sizeof *envent); + envent->name = xstrdup(name); + envent->value = NULL; RB_INSERT(environ, env, envent); } } @@ -134,7 +152,7 @@ environ_put(struct environ *env, const char *var) name = xstrdup(var); name[strcspn(name, "=")] = '\0'; - environ_set(env, name, value); + environ_set(env, name, "%s", value); free(name); } @@ -166,9 +184,9 @@ environ_update(const char *vars, struct environ *srcenv, copyvars = next = xstrdup(vars); while ((var = strsep(&next, " ")) != NULL) { if ((envent = environ_find(srcenv, var)) == NULL) - environ_set(dstenv, var, NULL); + environ_clear(dstenv, var); else - environ_set(dstenv, envent->name, envent->value); + environ_set(dstenv, envent->name, "%s", envent->value); } free(copyvars); } @@ -505,6 +505,8 @@ format_create_flags(int flags) format_add_cb(ft, "host", format_cb_host); format_add_cb(ft, "host_short", format_cb_host_short); 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); } @@ -22,29 +22,52 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "tmux.h" -FILE *log_file; +static FILE *log_file; +static int log_level; -void log_event_cb(int, const char *); -void log_vwrite(const char *, va_list); +static void log_event_cb(int, const char *); +static void log_vwrite(const char *, va_list); /* Log callback for libevent. */ -void +static void log_event_cb(__unused int severity, const char *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. */ void -log_open(const char *path) +log_open(const char *name) { + char *path; + + if (log_level == 0) + return; + if (log_file != NULL) fclose(log_file); + xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid()); log_file = fopen(path, "w"); + free(path); if (log_file == NULL) return; @@ -64,7 +87,7 @@ log_close(void) } /* Write a log message. */ -void +static void log_vwrite(const char *msg, va_list ap) { char *fmt, *out; @@ -18,6 +18,7 @@ #include <sys/types.h> #include <sys/uio.h> +#include <sys/utsname.h> #include <errno.h> #include <event.h> @@ -168,6 +169,7 @@ proc_start(const char *name, struct event_base *base, int forkflag, void (*signalcb)(int)) { struct tmuxproc *tp; + struct utsname u; if (forkflag) { switch (fork()) { @@ -189,11 +191,17 @@ proc_start(const char *name, struct event_base *base, int forkflag, logfile(name); #ifdef HAVE_SETPROCTITLE + log_open(name); setproctitle("%s (%s)", name, socket_path); #endif + if (uname(&u) < 0) + memset(&u, 0, sizeof u); + log_debug("%s started (%ld): socket %s, protocol %d", name, (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->name = xstrdup(name); diff --git a/server-fn.c b/server-fn.c index 56c98462..1e1198dd 100644 --- a/server-fn.c +++ b/server-fn.c @@ -32,20 +32,19 @@ void server_callback_identify(int, short, void *); void server_fill_environ(struct session *s, struct environ *env) { - char var[PATH_MAX], *term; - u_int idx; - long pid; + char *term; + u_int idx; + long pid; if (s != NULL) { term = options_get_string(global_options, "default-terminal"); - environ_set(env, "TERM", term); + environ_set(env, "TERM", "%s", term); idx = s->id; } else idx = (u_int)-1; pid = getpid(); - xsnprintf(var, sizeof var, "%s,%ld,%u", socket_path, pid, idx); - environ_set(env, "TMUX", var); + environ_set(env, "TMUX", "%s,%ld,%u", socket_path, pid, idx); } void @@ -172,7 +172,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile) } close(pair[0]); - if (debug_level > 3) + if (log_get_level() > 3) tty_create_log(); #ifdef __OpenBSD__ @@ -189,7 +189,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile) mode_key_init_trees(); key_bindings_init(); - start_time = time(NULL); + gettimeofday(&start_time, NULL); server_fd = server_create_socket(); if (server_fd == -1) @@ -197,9 +197,11 @@ server_start(struct event_base *base, int lockfd, char *lockfile) server_update_socket(); server_client_create(pair[1]); - unlink(lockfile); - free(lockfile); - close(lockfd); + if (lockfd >= 0) { + unlink(lockfile); + free(lockfile); + close(lockfd); + } start_cfg(); @@ -718,8 +718,7 @@ is used, .Ic update-environment option will not be applied. .It Xo Ic detach-client -.Op Fl P -.Op Fl a +.Op Fl aP .Op Fl s Ar target-session .Op Fl t Ar target-client .Xc @@ -745,7 +744,7 @@ Kill the .Nm server and clients and destroy all sessions. .It Xo Ic kill-session -.Op Fl a +.Op Fl aC .Op Fl t Ar target-session .Xc 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 .Fl a 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 .Op Fl F Ar format .Op Fl t Ar target-session @@ -892,7 +895,7 @@ is specified, only update the client's status bar. Rename the session to .Ar new-name . .It Xo Ic show-messages -.Op Fl IJT +.Op Fl JT .Op Fl t Ar target-client .Xc .D1 (alias: Ic showmsgs ) @@ -905,11 +908,10 @@ With .Fl t , display the log for .Ar target-client . -.Fl I , .Fl J and .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 .D1 (alias: Ic source ) 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_width" Ta "" Ta "Width of 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_active" Ta "" Ta "1 if window active" .It Li "window_bell_flag" Ta "" Ta "1 if window has bell" @@ -41,13 +41,11 @@ struct options *global_s_options; /* session options */ struct options *global_w_options; /* window options */ struct environ *global_environ; -char *shell_cmd; -int debug_level; -time_t start_time; -char socket_path[PATH_MAX]; +struct timeval start_time; +const char *socket_path; __dead void usage(void); -char *makesocketpath(const char *); +static char *make_label(const char *); #ifndef HAVE___PROGNAME char *__progname = (char *) "tmux"; @@ -63,18 +61,6 @@ usage(void) 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 * getshell(void) { @@ -121,38 +107,48 @@ areshell(const char *shell) return (0); } -char * -makesocketpath(const char *label) +static char * +make_label(const char *label) { - char base[PATH_MAX], realbase[PATH_MAX], *path, *s; - struct stat sb; - u_int uid; + char *base, resolved[PATH_MAX], *path, *s; + struct stat sb; + u_int uid; + int saved_errno; + + if (label == NULL) + label = "default"; uid = getuid(); + 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 - 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) - return (NULL); + goto fail; if (lstat(base, &sb) != 0) - return (NULL); + goto fail; if (!S_ISDIR(sb.st_mode)) { errno = ENOTDIR; - return (NULL); + goto fail; } if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) { errno = EACCES; - return (NULL); + goto fail; } - if (realpath(base, realbase) == NULL) - strlcpy(realbase, base, sizeof realbase); - - xasprintf(&path, "%s/%s", realbase, label); + if (realpath(base, resolved) == NULL) + strlcpy(resolved, base, sizeof resolved); + xasprintf(&path, "%s/%s", resolved, label); return (path); + +fail: + saved_errno = errno; + free(base); + errno = saved_errno; + return (NULL); } void @@ -193,7 +189,7 @@ find_home(void) int main(int argc, char **argv) { - char *path, *label, **var, tmp[PATH_MAX]; + char *path, *label, **var, tmp[PATH_MAX], *shellcmd = NULL; const char *s; int opt, flags, keys; @@ -216,8 +212,8 @@ main(int argc, char **argv) flags |= CLIENT_256COLOURS; break; case 'c': - free(shell_cmd); - shell_cmd = xstrdup(optarg); + free(shellcmd); + shellcmd = xstrdup(optarg); break; case 'C': if (flags & CLIENT_CONTROL) @@ -248,7 +244,7 @@ main(int argc, char **argv) flags |= CLIENT_UTF8; break; case 'v': - debug_level++; + log_add_level(); break; default: usage(); @@ -257,7 +253,7 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (shell_cmd != NULL && argc != 0) + if (shellcmd != NULL && argc != 0) usage(); #ifdef __OpenBSD__ @@ -292,7 +288,7 @@ main(int argc, char **argv) for (var = environ; *var != NULL; var++) environ_put(global_environ, *var); if (getcwd(tmp, sizeof tmp) != NULL) - environ_set(global_environ, "PWD", tmp); + environ_set(global_environ, "PWD", "%s", tmp); global_options = options_create(NULL); 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 - * or -L, use it, otherwise try $TMUX or assume -L default. + * If socket is specified on the command-line with -S or -L, it is + * used. Otherwise, $TMUX is checked and if that fails "default" is + * used. */ - if (path == NULL) { - /* If no -L, use the environment. */ - if (label == NULL) { - s = getenv("TMUX"); - if (s != NULL) { - 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); - } + if (path == NULL && label == NULL) { + s = getenv("TMUX"); + if (s != NULL && *s != '\0' && *s != ',') { + path = xstrdup(s); + path[strcspn (path, ",")] = '\0'; } } - free(label); - - if (strlcpy(socket_path, path, sizeof socket_path) >= - sizeof socket_path) { - fprintf(stderr, "socket path too long: %s\n", path); + if (path == NULL && (path = make_label(label)) == NULL) { + fprintf(stderr, "can't create socket: %s\n", strerror(errno)); exit(1); } - free(path); + socket_path = path; + free(label); /* Pass control to the client. */ - exit(client_main(osdep_event_init(), argc, argv, flags)); + exit(client_main(event_init(), argc, argv, flags, shellcmd)); } @@ -1433,11 +1433,8 @@ extern struct options *global_options; extern struct options *global_s_options; extern struct options *global_w_options; extern struct environ *global_environ; -extern char *shell_cmd; -extern int debug_level; -extern time_t start_time; -extern char socket_path[PATH_MAX]; -void logfile(const char *); +extern struct timeval start_time; +extern const char *socket_path; const char *getshell(void); int checkshell(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 *); void environ_copy(struct environ *, struct environ *); 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_unset(struct environ *, const char *); 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); /* 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 */ 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; int key_table_cmp(struct key_table *, struct key_table *); 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_add(const char *, key_code, int, struct cmd_list *); void key_bindings_remove(const char *, key_code); @@ -2214,8 +2213,10 @@ char *osdep_get_cwd(int); struct event_base *osdep_event_init(void); /* log.c */ -void log_open(const char *); -void log_close(void); +void log_add_level(void); +int log_get_level(void); +void log_open(const char *); +void log_close(void); void printflike(1, 2) log_debug(const char *, ...); __dead void printflike(1, 2) fatal(const char *, ...); __dead void printflike(1, 2) fatalx(const char *, ...); @@ -810,7 +810,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv, struct termios *tio, char **cause) { struct winsize ws; - char *argv0, *cmd, **argvp, paneid[16]; + char *argv0, *cmd, **argvp; const char *ptr, *first, *home; struct termios tio2; #ifdef HAVE_UTEMPTER @@ -871,9 +871,8 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv, closefrom(STDERR_FILENO + 1); if (path != NULL) - environ_set(env, "PATH", path); - xsnprintf(paneid, sizeof paneid, "%%%u", wp->id); - environ_set(env, "TMUX_PANE", paneid); + environ_set(env, "PATH", "%s", path); + environ_set(env, "TMUX_PANE", "%%%u", wp->id); environ_push(env); clear_signals(1); |