summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2015-11-25 16:37:30 +0000
committerThomas Adam <thomas@xteddy.org>2015-11-25 16:37:30 +0000
commit890d8da2e3588d416ef178e2e74ed3df226a6040 (patch)
tree3d024b90830e8afe48f75f0cb741965a5bb76015
parent0a2ef2b932f37d54157d82e526a8097caf9143ba (diff)
parentac8678aefe157d7e40c5bcedd12333eaedf0df92 (diff)
Merge branch 'obsd-master'
Conflicts: log.c proc.c tmux.c
-rw-r--r--client.c94
-rw-r--r--cmd-detach-client.c2
-rw-r--r--cmd-kill-session.c13
-rw-r--r--cmd-set-environment.c4
-rw-r--r--cmd-show-messages.c25
-rw-r--r--environ.c46
-rw-r--r--format.c2
-rw-r--r--log.c35
-rw-r--r--proc.c8
-rw-r--r--server-fn.c11
-rw-r--r--server.c12
-rw-r--r--tmux.116
-rw-r--r--tmux.c116
-rw-r--r--tmux.h21
-rw-r--r--window.c7
15 files changed, 222 insertions, 190 deletions
diff --git a/client.c b/client.c
index cade3a63..e24d07e8 100644
--- a/client.c
+++ b/client.c
@@ -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;
diff --git a/environ.c b/environ.c
index 43a9ce01..de560896 100644
--- a/environ.c
+++ b/environ.c
@@ -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);
}
diff --git a/format.c b/format.c
index afa6af5d..b2426e9d 100644
--- a/format.c
+++ b/format.c
@@ -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);
}
diff --git a/log.c b/log.c
index a07000a7..d7f6fe4b 100644
--- a/log.c
+++ b/log.c
@@ -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;
diff --git a/proc.c b/proc.c
index 3e1e81dd..6a68d74b 100644
--- a/proc.c
+++ b/proc.c
@@ -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
diff --git a/server.c b/server.c
index ddc59c0d..c4a7789f 100644
--- a/server.c
+++ b/server.c
@@ -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();
diff --git a/tmux.1 b/tmux.1
index 118839e0..bee3ebdc 100644
--- a/tmux.1
+++ b/tmux.1
@@ -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"
diff --git a/tmux.c b/tmux.c
index cd0595dd..440bad59 100644
--- a/tmux.c
+++ b/tmux.c
@@ -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));
}
diff --git a/tmux.h b/tmux.h
index ed2893b6..6a9f0cb4 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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 *, ...);
diff --git a/window.c b/window.c
index d7eb22a2..90d78b90 100644
--- a/window.c
+++ b/window.c
@@ -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);