Merge branch 'obsd-master'

Conflicts:
	Makefile
	client.c
	server-client.c
	server.c
	tmux.c
	tmux.h
This commit is contained in:
Thomas Adam 2015-10-27 23:27:26 +00:00
commit da1f6fc2c8
43 changed files with 872 additions and 824 deletions

View File

@ -154,6 +154,7 @@ dist_tmux_SOURCES = \
options-table.c \ options-table.c \
options.c \ options.c \
paste.c \ paste.c \
proc.c \
resize.c \ resize.c \
screen-redraw.c \ screen-redraw.c \
screen-write.c \ screen-write.c \

View File

@ -80,11 +80,11 @@ alerts_enabled(struct window *w, int flags)
struct session *s; struct session *s;
if (flags & WINDOW_ACTIVITY) { if (flags & WINDOW_ACTIVITY) {
if (options_get_number(&w->options, "monitor-activity")) if (options_get_number(w->options, "monitor-activity"))
return (1); return (1);
} }
if (flags & WINDOW_SILENCE) { if (flags & WINDOW_SILENCE) {
if (options_get_number(&w->options, "monitor-silence") != 0) if (options_get_number(w->options, "monitor-silence") != 0)
return (1); return (1);
} }
if (~flags & WINDOW_BELL) if (~flags & WINDOW_BELL)
@ -92,7 +92,7 @@ alerts_enabled(struct window *w, int flags)
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
if (!session_has(s, w)) if (!session_has(s, w))
continue; continue;
if (options_get_number(&s->options, "bell-action") != BELL_NONE) if (options_get_number(s->options, "bell-action") != BELL_NONE)
return (1); return (1);
} }
return (0); return (0);
@ -116,7 +116,7 @@ alerts_reset(struct window *w)
event_del(&w->alerts_timer); event_del(&w->alerts_timer);
timerclear(&tv); timerclear(&tv);
tv.tv_sec = options_get_number(&w->options, "monitor-silence"); tv.tv_sec = options_get_number(w->options, "monitor-silence");
log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec); log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
if (tv.tv_sec != 0) if (tv.tv_sec != 0)
@ -160,11 +160,11 @@ alerts_check_bell(struct session *s, struct winlink *wl)
if (s->curw->window == w) if (s->curw->window == w)
w->flags &= ~WINDOW_BELL; w->flags &= ~WINDOW_BELL;
action = options_get_number(&s->options, "bell-action"); action = options_get_number(s->options, "bell-action");
if (action == BELL_NONE) if (action == BELL_NONE)
return (0); return (0);
visual = options_get_number(&s->options, "visual-bell"); visual = options_get_number(s->options, "visual-bell");
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s || c->flags & CLIENT_CONTROL) if (c->session != s || c->flags & CLIENT_CONTROL)
continue; continue;
@ -201,14 +201,14 @@ alerts_check_activity(struct session *s, struct winlink *wl)
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED)) if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
return (0); return (0);
if (!options_get_number(&w->options, "monitor-activity")) if (!options_get_number(w->options, "monitor-activity"))
return (0); return (0);
if (options_get_number(&s->options, "bell-on-alert")) if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s); alerts_ring_bell(s);
wl->flags |= WINLINK_ACTIVITY; wl->flags |= WINLINK_ACTIVITY;
if (options_get_number(&s->options, "visual-activity")) { if (options_get_number(s->options, "visual-activity")) {
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s) if (c->session != s)
continue; continue;
@ -233,14 +233,14 @@ alerts_check_silence(struct session *s, struct winlink *wl)
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED)) if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
return (0); return (0);
if (options_get_number(&w->options, "monitor-silence") == 0) if (options_get_number(w->options, "monitor-silence") == 0)
return (0); return (0);
if (options_get_number(&s->options, "bell-on-alert")) if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s); alerts_ring_bell(s);
wl->flags |= WINLINK_SILENCE; wl->flags |= WINLINK_SILENCE;
if (options_get_number(&s->options, "visual-silence")) { if (options_get_number(s->options, "visual-silence")) {
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s) if (c->session != s)
continue; continue;

516
client.c
View File

@ -33,10 +33,10 @@
#include "tmux.h" #include "tmux.h"
int client_flags; struct tmuxproc *client_proc;
struct imsgbuf client_ibuf; struct tmuxpeer *client_peer;
struct event client_event; int client_flags;
struct event client_stdin; struct event client_stdin;
enum { enum {
CLIENT_EXIT_NONE, CLIENT_EXIT_NONE,
CLIENT_EXIT_DETACHED, CLIENT_EXIT_DETACHED,
@ -47,24 +47,21 @@ enum {
CLIENT_EXIT_EXITED, CLIENT_EXIT_EXITED,
CLIENT_EXIT_SERVER_EXITED, CLIENT_EXIT_SERVER_EXITED,
} client_exitreason = CLIENT_EXIT_NONE; } client_exitreason = CLIENT_EXIT_NONE;
int client_exitval; int client_exitval;
enum msgtype client_exittype; 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 *);
int client_get_lock(char *); int client_get_lock(char *);
int client_connect(struct event_base *, char *, int); int client_connect(struct event_base *, char *, int);
void client_send_identify(const char *, const char *); void client_send_identify(const char *, const char *);
int client_write_one(enum msgtype, int, const void *, size_t);
int client_write_server(enum msgtype, const void *, size_t);
void client_update_event(void);
void client_signal(int, short, void *);
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_callback(int, short, void *); void client_signal(int);
int client_dispatch_attached(void); void client_dispatch(struct imsg *, void *);
int client_dispatch_wait(void); void client_dispatch_attached(struct imsg *);
void client_dispatch_wait(struct imsg *);
const char *client_exit_message(void); const char *client_exit_message(void);
/* /*
@ -222,6 +219,9 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
struct termios tio, saved_tio; struct termios tio, saved_tio;
size_t size; size_t size;
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
signal(SIGCHLD, SIG_IGN);
/* Save the flags. */ /* Save the flags. */
client_flags = flags; client_flags = flags;
@ -254,9 +254,6 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
} }
/* Establish signal handlers. */
set_signals(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) {
@ -270,6 +267,10 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
return (1); 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);
/* Save these before pledge(). */ /* Save these before pledge(). */
if ((cwd = getcwd(path, sizeof path)) == NULL) if ((cwd = getcwd(path, sizeof path)) == NULL)
cwd = "/"; cwd = "/";
@ -291,21 +292,11 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
#endif #endif
/* Free stuff that is not used in the client. */ /* Free stuff that is not used in the client. */
options_free(&global_options); options_free(global_options);
options_free(&global_s_options); options_free(global_s_options);
options_free(&global_w_options); options_free(global_w_options);
environ_free(&global_environ); environ_free(&global_environ);
/* Set process title, log and signals now this is the client. */
#ifdef HAVE_SETPROCTITLE
setproctitle("client (%s)", socket_path);
#endif
logfile("client");
/* Create imsg. */
imsg_init(&client_ibuf, fd);
event_set(&client_event, fd, EV_READ, client_callback, NULL);
/* Create stdin handler. */ /* Create stdin handler. */
setblocking(STDIN_FILENO, 0); setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST, event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
@ -351,18 +342,17 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
size += sizeof *data; size += sizeof *data;
/* Send the command. */ /* Send the command. */
if (client_write_server(msg, data, size) != 0) { if (proc_send(client_peer, msg, -1, data, size) != 0) {
fprintf(stderr, "failed to send command\n"); fprintf(stderr, "failed to send command\n");
free(data); free(data);
return (1); return (1);
} }
free(data); free(data);
} else if (msg == MSG_SHELL) } else if (msg == MSG_SHELL)
client_write_server(msg, NULL, 0); proc_send(client_peer, msg, -1, NULL, 0);
/* Set the event and dispatch. */ /* Start main loop. */
client_update_event(); proc_loop(client_proc, NULL);
event_dispatch();
/* Print the exit message, if any, and exit. */ /* Print the exit message, if any, and exit. */
if (client_attached) { if (client_attached) {
@ -394,144 +384,29 @@ client_send_identify(const char *ttynam, const char *cwd)
int fd, flags = client_flags; int fd, flags = client_flags;
pid_t pid; pid_t pid;
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
if ((s = getenv("TERM")) == NULL) if ((s = getenv("TERM")) == NULL)
s = ""; s = "";
client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1); proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
client_write_one(MSG_IDENTIFY_TTYNAME, -1, ttynam, strlen(ttynam) + 1); proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam, strlen(ttynam) + 1);
client_write_one(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)
fatal("dup failed"); fatal("dup failed");
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0); proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0);
pid = getpid(); pid = getpid();
client_write_one(MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid); proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
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)
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, sslen); proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
} }
client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0); proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0);
}
/* Helper to send one message. */
int
client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
{
int retval;
retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd,
(void *)buf, len);
if (retval != 1)
return (-1);
return (0);
}
/* Write a message to the server without a file descriptor. */
int
client_write_server(enum msgtype type, const void *buf, size_t len)
{
int retval;
retval = client_write_one(type, -1, buf, len);
if (retval == 0)
client_update_event();
return (retval);
}
/* Update client event based on whether it needs to read or read and write. */
void
client_update_event(void)
{
short events;
event_del(&client_event);
events = EV_READ;
if (client_ibuf.w.queued > 0)
events |= EV_WRITE;
event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
event_add(&client_event, NULL);
}
/* Callback to handle signals in the client. */
void
client_signal(int sig, unused short events, unused void *arg)
{
struct sigaction sigact;
int status;
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGTERM)
event_loopexit(NULL);
} else {
switch (sig) {
case SIGHUP:
client_exitreason = CLIENT_EXIT_LOST_TTY;
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
case SIGTERM:
client_exitreason = CLIENT_EXIT_TERMINATED;
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
case SIGWINCH:
client_write_server(MSG_RESIZE, NULL, 0);
break;
case SIGCONT:
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
client_write_server(MSG_WAKEUP, NULL, 0);
break;
}
}
client_update_event();
}
/* Callback for client imsg read events. */
void
client_callback(unused int fd, short events, unused void *arg)
{
ssize_t n;
int retval;
if (events & EV_READ) {
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
goto lost_server;
if (client_attached)
retval = client_dispatch_attached();
else
retval = client_dispatch_wait();
if (retval != 0) {
event_loopexit(NULL);
return;
}
}
if (events & EV_WRITE) {
if (msgbuf_write(&client_ibuf.w) <= 0 && errno != EAGAIN)
goto lost_server;
}
client_update_event();
return;
lost_server:
client_exitreason = CLIENT_EXIT_LOST_SERVER;
client_exitval = 1;
event_loopexit(NULL);
} }
/* Callback for client stdin read events. */ /* Callback for client stdin read events. */
@ -544,10 +419,9 @@ client_stdin_callback(unused int fd, unused short events, unused void *arg)
if (data.size < 0 && (errno == EINTR || errno == EAGAIN)) if (data.size < 0 && (errno == EINTR || errno == EAGAIN))
return; return;
client_write_server(MSG_STDIN, &data, sizeof data); proc_send(client_peer, MSG_STDIN, -1, &data, sizeof data);
if (data.size <= 0) if (data.size <= 0)
event_del(&client_stdin); event_del(&client_stdin);
client_update_event();
} }
/* Force write to file descriptor. */ /* Force write to file descriptor. */
@ -597,13 +471,65 @@ client_exec(const char *shell)
fatal("execl failed"); fatal("execl failed");
} }
/* Dispatch imsgs when in wait state (before MSG_READY). */ /* Callback to handle signals in the client. */
int void
client_dispatch_wait(void) client_signal(int sig)
{
struct sigaction sigact;
int status;
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGTERM)
proc_exit(client_proc);
} else {
switch (sig) {
case SIGHUP:
client_exitreason = CLIENT_EXIT_LOST_TTY;
client_exitval = 1;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case SIGTERM:
client_exitreason = CLIENT_EXIT_TERMINATED;
client_exitval = 1;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case SIGWINCH:
proc_send(client_peer, MSG_RESIZE, -1, NULL, 0);
break;
case SIGCONT:
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
proc_send(client_peer, MSG_WAKEUP, -1, NULL, 0);
break;
}
}
}
/* Callback for client read events. */
void
client_dispatch(struct imsg *imsg, unused void *arg)
{
if (imsg == NULL) {
client_exitreason = CLIENT_EXIT_LOST_SERVER;
client_exitval = 1;
} else if (client_attached)
client_dispatch_attached(imsg);
else
client_dispatch_wait(imsg);
}
/* Dispatch imsgs when in wait state (before MSG_READY). */
void
client_dispatch_wait(struct imsg *imsg)
{ {
struct imsg imsg;
char *data; char *data;
ssize_t n, datalen; ssize_t datalen;
struct msg_stdout_data stdoutdata; struct msg_stdout_data stdoutdata;
struct msg_stderr_data stderrdata; struct msg_stderr_data stderrdata;
int retval; int retval;
@ -623,163 +549,141 @@ client_dispatch_wait(void)
}; };
#endif #endif
for (;;) { data = imsg->data;
if ((n = imsg_get(&client_ibuf, &imsg)) == -1) datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
fatalx("imsg_get failed");
if (n == 0)
return (0);
data = imsg.data; switch (imsg->hdr.type) {
datalen = imsg.hdr.len - IMSG_HEADER_SIZE; case MSG_EXIT:
case MSG_SHUTDOWN:
log_debug("got %u from server", imsg.hdr.type); if (datalen != sizeof retval && datalen != 0)
switch (imsg.hdr.type) { fatalx("bad MSG_EXIT size");
case MSG_EXIT: if (datalen == sizeof retval) {
case MSG_SHUTDOWN: memcpy(&retval, data, sizeof retval);
if (datalen != sizeof retval && datalen != 0) client_exitval = retval;
fatalx("bad MSG_EXIT size");
if (datalen == sizeof retval) {
memcpy(&retval, data, sizeof retval);
client_exitval = retval;
}
imsg_free(&imsg);
return (-1);
case MSG_READY:
if (datalen != 0)
fatalx("bad MSG_READY size");
event_del(&client_stdin);
client_attached = 1;
client_write_server(MSG_RESIZE, NULL, 0);
break;
case MSG_STDIN:
if (datalen != 0)
fatalx("bad MSG_STDIN size");
event_add(&client_stdin, NULL);
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
fatalx("bad MSG_STDOUT size");
memcpy(&stdoutdata, data, sizeof stdoutdata);
client_write(STDOUT_FILENO, stdoutdata.data,
stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
fatalx("bad MSG_STDERR size");
memcpy(&stderrdata, data, sizeof stderrdata);
client_write(STDERR_FILENO, stderrdata.data,
stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
fatalx("bad MSG_VERSION size");
fprintf(stderr, "protocol version mismatch "
"(client %d, server %u)\n", PROTOCOL_VERSION,
imsg.hdr.peerid);
client_exitval = 1;
imsg_free(&imsg);
return (-1);
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_SHELL string");
clear_signals(0);
client_exec(data);
/* NOTREACHED */
case MSG_DETACH:
case MSG_DETACHKILL:
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
} }
proc_exit(client_proc);
break;
case MSG_READY:
if (datalen != 0)
fatalx("bad MSG_READY size");
imsg_free(&imsg); event_del(&client_stdin);
client_attached = 1;
proc_send(client_peer, MSG_RESIZE, -1, NULL, 0);
break;
case MSG_STDIN:
if (datalen != 0)
fatalx("bad MSG_STDIN size");
event_add(&client_stdin, NULL);
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
fatalx("bad MSG_STDOUT size");
memcpy(&stdoutdata, data, sizeof stdoutdata);
client_write(STDOUT_FILENO, stdoutdata.data,
stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
fatalx("bad MSG_STDERR size");
memcpy(&stderrdata, data, sizeof stderrdata);
client_write(STDERR_FILENO, stderrdata.data,
stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
fatalx("bad MSG_VERSION size");
fprintf(stderr, "protocol version mismatch "
"(client %d, server %u)\n", PROTOCOL_VERSION,
imsg->hdr.peerid);
client_exitval = 1;
proc_exit(client_proc);
break;
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_SHELL string");
clear_signals(0);
client_exec(data);
/* NOTREACHED */
case MSG_DETACH:
case MSG_DETACHKILL:
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXITED:
proc_exit(client_proc);
break;
} }
} }
/* Dispatch imsgs in attached state (after MSG_READY). */ /* Dispatch imsgs in attached state (after MSG_READY). */
int void
client_dispatch_attached(void) client_dispatch_attached(struct imsg *imsg)
{ {
struct imsg imsg;
struct sigaction sigact; struct sigaction sigact;
char *data; char *data;
ssize_t n, datalen; ssize_t datalen;
for (;;) { data = imsg->data;
if ((n = imsg_get(&client_ibuf, &imsg)) == -1) datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
fatalx("imsg_get failed");
if (n == 0)
return (0);
data = imsg.data; switch (imsg->hdr.type) {
datalen = imsg.hdr.len - IMSG_HEADER_SIZE; case MSG_DETACH:
case MSG_DETACHKILL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_DETACH string");
log_debug("got %u from server", imsg.hdr.type); client_exitsession = xstrdup(data);
switch (imsg.hdr.type) { client_exittype = imsg->hdr.type;
case MSG_DETACH: if (imsg->hdr.type == MSG_DETACHKILL)
case MSG_DETACHKILL: client_exitreason = CLIENT_EXIT_DETACHED_HUP;
if (datalen == 0 || data[datalen - 1] != '\0') else
fatalx("bad MSG_DETACH string"); client_exitreason = CLIENT_EXIT_DETACHED;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size");
client_exitsession = xstrdup(data); proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
client_exittype = imsg.hdr.type; client_exitreason = CLIENT_EXIT_EXITED;
if (imsg.hdr.type == MSG_DETACHKILL) break;
client_exitreason = CLIENT_EXIT_DETACHED_HUP; case MSG_EXITED:
else if (datalen != 0)
client_exitreason = CLIENT_EXIT_DETACHED; fatalx("bad MSG_EXITED size");
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size");
client_write_server(MSG_EXITING, NULL, 0); proc_exit(client_proc);
client_exitreason = CLIENT_EXIT_EXITED; break;
break; case MSG_SHUTDOWN:
case MSG_EXITED: if (datalen != 0)
if (datalen != 0) fatalx("bad MSG_SHUTDOWN size");
fatalx("bad MSG_EXITED size");
imsg_free(&imsg); proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
return (-1); client_exitreason = CLIENT_EXIT_SERVER_EXITED;
case MSG_SHUTDOWN: client_exitval = 1;
if (datalen != 0) break;
fatalx("bad MSG_SHUTDOWN size"); case MSG_SUSPEND:
if (datalen != 0)
fatalx("bad MSG_SUSPEND size");
client_write_server(MSG_EXITING, NULL, 0); memset(&sigact, 0, sizeof sigact);
client_exitreason = CLIENT_EXIT_SERVER_EXITED; sigemptyset(&sigact.sa_mask);
client_exitval = 1; sigact.sa_flags = SA_RESTART;
break; sigact.sa_handler = SIG_DFL;
case MSG_SUSPEND: if (sigaction(SIGTSTP, &sigact, NULL) != 0)
if (datalen != 0) fatal("sigaction failed");
fatalx("bad MSG_SUSPEND size"); kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_LOCK string");
memset(&sigact, 0, sizeof sigact); system(data);
sigemptyset(&sigact.sa_mask); proc_send(client_peer, MSG_UNLOCK, -1, NULL, 0);
sigact.sa_flags = SA_RESTART; break;
sigact.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_LOCK string");
system(data);
client_write_server(MSG_UNLOCK, NULL, 0);
break;
}
imsg_free(&imsg);
} }
} }

View File

@ -113,21 +113,15 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
if (c->session != NULL) { if (c->session != NULL) {
if (dflag) { if (dflag) {
/*
* Can't use server_write_session in case attaching to
* the same session as currently attached to.
*/
TAILQ_FOREACH(c_loop, &clients, entry) { TAILQ_FOREACH(c_loop, &clients, entry) {
if (c_loop->session != s || c == c_loop) if (c_loop->session != s || c == c_loop)
continue; continue;
server_write_client(c, MSG_DETACH, proc_send_s(c->peer, MSG_DETACH, s->name);
c_loop->session->name,
strlen(c_loop->session->name) + 1);
} }
} }
if (!Eflag) { if (!Eflag) {
update = options_get_string(&s->options, update = options_get_string(s->options,
"update-environment"); "update-environment");
environ_update(update, &c->environ, &s->environ); environ_update(update, &c->environ, &s->environ);
} }
@ -150,12 +144,15 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
c->flags |= CLIENT_READONLY; c->flags |= CLIENT_READONLY;
if (dflag) { if (dflag) {
server_write_session(s, MSG_DETACH, s->name, TAILQ_FOREACH(c_loop, &clients, entry) {
strlen(s->name) + 1); if (c_loop->session != s || c == c_loop)
continue;
proc_send_s(c->peer, MSG_DETACH, s->name);
}
} }
if (!Eflag) { if (!Eflag) {
update = options_get_string(&s->options, update = options_get_string(s->options,
"update-environment"); "update-environment");
environ_update(update, &c->environ, &s->environ); environ_update(update, &c->environ, &s->environ);
} }
@ -168,7 +165,8 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
server_redraw_client(c); server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS; s->curw->flags &= ~WINLINK_ALERTFLAGS;
server_write_ready(c); if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
cmdq->client_exit = 0; cmdq->client_exit = 0;
} }
recalculate_sizes(); recalculate_sizes();

View File

@ -84,7 +84,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
layout_init(w, wp); layout_init(w, wp);
if (idx == -1) if (idx == -1)
idx = -1 - options_get_number(&dst_s->options, "base-index"); idx = -1 - options_get_number(dst_s->options, "base-index");
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */ wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
if (!args_has(self->args, 'd')) if (!args_has(self->args, 'd'))
session_select(dst_s, wl->idx); session_select(dst_s, wl->idx);

View File

@ -63,7 +63,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
utf8flag = options_get_number(&wl->window->options, "utf8"); utf8flag = options_get_number(wl->window->options, "utf8");
if (paste_get_top(NULL) == NULL) if (paste_get_top(NULL) == NULL)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@ -57,7 +57,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
tty_stop_tty(&c->tty); tty_stop_tty(&c->tty);
c->flags |= CLIENT_SUSPENDED; c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_SUSPEND, NULL, 0); proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
@ -74,9 +74,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
TAILQ_FOREACH(cloop, &clients, entry) { TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session != s) if (cloop->session != s)
continue; continue;
server_write_client(cloop, msgtype, proc_send_s(cloop->peer, msgtype, cloop->session->name);
cloop->session->name,
strlen(cloop->session->name) + 1);
} }
return (CMD_RETURN_STOP); return (CMD_RETURN_STOP);
} }
@ -89,14 +87,11 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
TAILQ_FOREACH(cloop, &clients, entry) { TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session == NULL || cloop == c) if (cloop->session == NULL || cloop == c)
continue; continue;
server_write_client(cloop, msgtype, proc_send_s(cloop->peer, msgtype, cloop->session->name);
cloop->session->name,
strlen(cloop->session->name) + 1);
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
server_write_client(c, msgtype, c->session->name, proc_send_s(c->peer, msgtype, c->session->name);
strlen(c->session->name) + 1);
return (CMD_RETURN_STOP); return (CMD_RETURN_STOP);
} }

View File

@ -128,8 +128,8 @@ cmd_find_try_TMUX(struct client *c, struct window *w)
return (NULL); return (NULL);
if (pid != getpid()) if (pid != getpid())
return (NULL); return (NULL);
log_debug("client %d TMUX is %s (session @%u)", c->ibuf.fd, log_debug("client %p TMUX is %s (session @%u)", c, envent->value,
envent->value, session); session);
s = session_find_by_id(session); s = session_find_by_id(session);
if (s == NULL || (w != NULL && !session_has(s, w))) if (s == NULL || (w != NULL && !session_has(s, w)))
@ -332,6 +332,8 @@ cmd_find_current_session(struct cmd_find_state *fs)
{ {
/* If we know the current client, use it. */ /* If we know the current client, use it. */
if (fs->cmdq->client != NULL) { if (fs->cmdq->client != NULL) {
log_debug("%s: have client %p%s", __func__, fs->cmdq->client,
fs->cmdq->client->session == NULL ? "" : " (with session)");
if (fs->cmdq->client->session == NULL) if (fs->cmdq->client->session == NULL)
return (cmd_find_current_session_with_client(fs)); return (cmd_find_current_session_with_client(fs));
fs->s = fs->cmdq->client->session; fs->s = fs->cmdq->client->session;
@ -364,8 +366,11 @@ cmd_find_current_client(struct cmd_q *cmdq)
u_int csize; u_int csize;
/* If the queue client has a session, use it. */ /* If the queue client has a session, use it. */
if (cmdq->client != NULL && cmdq->client->session != NULL) if (cmdq->client != NULL && cmdq->client->session != NULL) {
log_debug("%s: using cmdq %p client %p", __func__, cmdq,
cmdq->client);
return (cmdq->client); return (cmdq->client);
}
/* Otherwise find the current session. */ /* Otherwise find the current session. */
cmd_find_clear_state(&current, cmdq, 0); cmd_find_clear_state(&current, cmdq, 0);
@ -374,6 +379,7 @@ cmd_find_current_client(struct cmd_q *cmdq)
/* If it is attached, find the best of it's clients. */ /* If it is attached, find the best of it's clients. */
s = current.s; s = current.s;
log_debug("%s: current session $%u %s", __func__, s->id, s->name);
if (~s->flags & SESSION_UNATTACHED) { if (~s->flags & SESSION_UNATTACHED) {
csize = 0; csize = 0;
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
@ -1219,6 +1225,7 @@ cmd_find_client(struct cmd_q *cmdq, const char *target, int quiet)
c = cmd_find_current_client(cmdq); c = cmd_find_current_client(cmdq);
if (c == NULL && !quiet) if (c == NULL && !quiet)
cmdq_error(cmdq, "no current client"); cmdq_error(cmdq, "no current client");
log_debug("%s: no target, return %p", __func__, c);
return (c); return (c);
} }
copy = xstrdup(target); copy = xstrdup(target);
@ -1250,6 +1257,7 @@ cmd_find_client(struct cmd_q *cmdq, const char *target, int quiet)
cmdq_error(cmdq, "can't find client %s", copy); cmdq_error(cmdq, "can't find client %s", copy);
free(copy); free(copy);
log_debug("%s: target %s, return %p", __func__, target, c);
return (c); return (c);
} }

View File

@ -95,7 +95,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
* session already has the correct winlink id to us, either * session already has the correct winlink id to us, either
* automatically or specified by -s. * automatically or specified by -s.
*/ */
if (!sflag && options_get_number(&src->options, "renumber-windows")) if (!sflag && options_get_number(src->options, "renumber-windows"))
session_renumber_windows(src); session_renumber_windows(src);
recalculate_sizes(); recalculate_sizes();

View File

@ -197,7 +197,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
goto error; goto error;
} }
} }
if (sy > 0 && options_get_number(&global_s_options, "status")) if (sy > 0 && options_get_number(global_s_options, "status"))
sy--; sy--;
if (sx == 0) if (sx == 0)
sx = 1; sx = 1;
@ -211,7 +211,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
argc = args->argc; argc = args->argc;
argv = args->argv; argv = args->argv;
} else if (target == NULL) { } else if (target == NULL) {
cmd = options_get_string(&global_s_options, "default-command"); cmd = options_get_string(global_s_options, "default-command");
if (cmd != NULL && *cmd != '\0') { if (cmd != NULL && *cmd != '\0') {
argc = 1; argc = 1;
argv = &cmd; argv = &cmd;
@ -232,13 +232,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Construct the environment. */ /* Construct the environment. */
environ_init(&env); environ_init(&env);
if (c != NULL && !args_has(args, 'E')) { if (c != NULL && !args_has(args, 'E')) {
update = options_get_string(&global_s_options, update = options_get_string(global_s_options,
"update-environment"); "update-environment");
environ_update(update, &c->environ, &env); environ_update(update, &c->environ, &env);
} }
/* Create the new session. */ /* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index"); idx = -1 - options_get_number(global_s_options, "base-index");
s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx, s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
sy, &cause); sy, &cause);
if (s == NULL) { if (s == NULL) {
@ -252,7 +252,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (argc >= 0 && args_has(args, 'n')) { if (argc >= 0 && args_has(args, 'n')) {
w = s->curw->window; w = s->curw->window;
window_set_name(w, args_get(args, 'n')); window_set_name(w, args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0); options_set_number(w->options, "automatic-rename", 0);
} }
/* /*
@ -270,9 +270,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
* taking this session and needs to get MSG_READY and stay around. * taking this session and needs to get MSG_READY and stay around.
*/ */
if (!detached) { if (!detached) {
if (!already_attached) if (!already_attached) {
server_write_ready(c); if (~c->flags & CLIENT_CONTROL)
else if (c->session != NULL) proc_send(c->peer, MSG_READY, -1, NULL, 0);
} else if (c->session != NULL)
c->last_session = c->session; c->last_session = c->session;
c->session = s; c->session = s;
status_timer_start(c); status_timer_start(c);

View File

@ -71,7 +71,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
detached = args_has(args, 'd'); detached = args_has(args, 'd');
if (args->argc == 0) { if (args->argc == 0) {
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(s->options, "default-command");
if (cmd != NULL && *cmd != '\0') { if (cmd != NULL && *cmd != '\0') {
argc = 1; argc = 1;
argv = (char **)&cmd; argv = (char **)&cmd;
@ -136,7 +136,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
} }
if (idx == -1) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); idx = -1 - options_get_number(s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx, wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
&cause); &cause);
if (wl == NULL) { if (wl == NULL) {

View File

@ -47,7 +47,7 @@ cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
window_set_name(wl->window, args->argv[0]); window_set_name(wl->window, args->argv[0]);
options_set_number(&wl->window->options, "automatic-rename", 0); options_set_number(wl->window->options, "automatic-rename", 0);
server_status_window(wl->window); server_status_window(wl->window);

View File

@ -70,9 +70,9 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
if (self->entry == &cmd_send_prefix_entry) { if (self->entry == &cmd_send_prefix_entry) {
if (args_has(args, '2')) if (args_has(args, '2'))
key = options_get_number(&s->options, "prefix2"); key = options_get_number(s->options, "prefix2");
else else
key = options_get_number(&s->options, "prefix"); key = options_get_number(s->options, "prefix");
window_pane_key(wp, NULL, s, key, NULL); window_pane_key(wp, NULL, s, key, NULL);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

View File

@ -126,10 +126,10 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
/* Work out the tree from the table. */ /* Work out the tree from the table. */
if (table == server_options_table) if (table == server_options_table)
oo = &global_options; oo = global_options;
else if (table == window_options_table) { else if (table == window_options_table) {
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_w_options; oo = global_w_options;
else { else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL); wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) { if (wl == NULL) {
@ -139,11 +139,11 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
'g')) ? " need target window or -g" : ""); 'g')) ? " need target window or -g" : "");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
oo = &wl->window->options; oo = wl->window->options;
} }
} else if (table == session_options_table) { } else if (table == session_options_table) {
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = global_s_options;
else { else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) { if (s == NULL) {
@ -153,7 +153,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
'g')) ? " need target session or -g" : ""); 'g')) ? " need target session or -g" : "");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
oo = &s->options; oo = s->options;
} }
} else { } else {
cmdq_error(cmdq, "unknown table"); cmdq_error(cmdq, "unknown table");
@ -179,7 +179,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
/* Start or stop timers if necessary. */ /* Start or stop timers if necessary. */
if (strcmp(oe->name, "automatic-rename") == 0) { if (strcmp(oe->name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) { RB_FOREACH(w, windows, &windows) {
if (options_get_number(&w->options, "automatic-rename")) if (options_get_number(w->options, "automatic-rename"))
w->active->flags |= PANE_CHANGED; w->active->flags |= PANE_CHANGED;
} }
} }
@ -210,25 +210,25 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr,
struct options *oo; struct options *oo;
if (args_has(args, 's')) if (args_has(args, 's'))
oo = &global_options; oo = global_options;
else if (args_has(self->args, 'w') || else if (args_has(self->args, 'w') ||
self->entry == &cmd_set_window_option_entry) { self->entry == &cmd_set_window_option_entry) {
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_w_options; oo = global_w_options;
else { else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL); wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &wl->window->options; oo = wl->window->options;
} }
} else { } else {
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = global_s_options;
else { else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &s->options; oo = s->options;
} }
} }
@ -276,7 +276,7 @@ cmd_set_option_unset(struct cmd *self, struct cmd_q *cmdq,
return (-1); return (-1);
} }
if (args_has(args, 'g') || oo == &global_options) { if (args_has(args, 'g') || oo == global_options) {
switch (oe->type) { switch (oe->type) {
case OPTIONS_TABLE_STRING: case OPTIONS_TABLE_STRING:
options_set_string(oo, oe->name, "%s", oe->default_str); options_set_string(oo, oe->name, "%s", oe->default_str);

View File

@ -61,28 +61,28 @@ cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
int quiet; int quiet;
if (args_has(self->args, 's')) { if (args_has(self->args, 's')) {
oo = &global_options; oo = global_options;
table = server_options_table; table = server_options_table;
} else if (args_has(self->args, 'w') || } else if (args_has(self->args, 'w') ||
self->entry == &cmd_show_window_options_entry) { self->entry == &cmd_show_window_options_entry) {
table = window_options_table; table = window_options_table;
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_w_options; oo = global_w_options;
else { else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL); wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &wl->window->options; oo = wl->window->options;
} }
} else { } else {
table = session_options_table; table = session_options_table;
if (args_has(self->args, 'g')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = global_s_options;
else { else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0); s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
oo = &s->options; oo = s->options;
} }
} }
@ -151,13 +151,15 @@ cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq,
struct options_entry *o; struct options_entry *o;
const char *optval; const char *optval;
RB_FOREACH(o, options_tree, &oo->tree) { o = options_first(oo);
while (o != NULL) {
if (*o->name == '@') { if (*o->name == '@') {
if (args_has(self->args, 'v')) if (args_has(self->args, 'v'))
cmdq_print(cmdq, "%s", o->str); cmdq_print(cmdq, "%s", o->str);
else else
cmdq_print(cmdq, "%s \"%s\"", o->name, o->str); cmdq_print(cmdq, "%s \"%s\"", o->name, o->str);
} }
o = options_next(o);
} }
for (oe = table; oe->name != NULL; oe++) { for (oe = table; oe->name != NULL; oe++) {

View File

@ -72,7 +72,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
server_fill_environ(s, &env); server_fill_environ(s, &env);
if (args->argc == 0) { if (args->argc == 0) {
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(s->options, "default-command");
if (cmd != NULL && *cmd != '\0') { if (cmd != NULL && *cmd != '\0') {
argc = 1; argc = 1;
argv = (char **)&cmd; argv = (char **)&cmd;
@ -134,9 +134,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
else else
size = (wp->sx * percentage) / 100; size = (wp->sx * percentage) / 100;
} }
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(s->options, "history-limit");
shell = options_get_string(&s->options, "default-shell"); shell = options_get_string(s->options, "default-shell");
if (*shell == '\0' || areshell(shell)) if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL; shell = _PATH_BSHELL;

View File

@ -120,7 +120,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
} }
if (c != NULL && !args_has(args, 'E')) { if (c != NULL && !args_has(args, 'E')) {
update = options_get_string(&s->options, "update-environment"); update = options_get_string(s->options, "update-environment");
environ_update(update, &c->environ, &s->environ); environ_update(update, &c->environ, &s->environ);
} }

View File

@ -598,15 +598,15 @@ format_find(struct format_tree *ft, const char *key, int modifiers)
found = NULL; found = NULL;
if (~modifiers & FORMAT_TIMESTRING) { if (~modifiers & FORMAT_TIMESTRING) {
o = options_find(&global_options, key); o = options_find(global_options, key);
if (o == NULL && ft->w != NULL) if (o == NULL && ft->w != NULL)
o = options_find(&ft->w->options, key); o = options_find(ft->w->options, key);
if (o == NULL) if (o == NULL)
o = options_find(&global_w_options, key); o = options_find(global_w_options, key);
if (o == NULL && ft->s != NULL) if (o == NULL && ft->s != NULL)
o = options_find(&ft->s->options, key); o = options_find(ft->s->options, key);
if (o == NULL) if (o == NULL)
o = options_find(&global_s_options, key); o = options_find(global_s_options, key);
if (o != NULL) { if (o != NULL) {
switch (o->type) { switch (o->type) {
case OPTIONS_STRING: case OPTIONS_STRING:
@ -1118,7 +1118,7 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base); format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
format_add(ft, "pane_synchronized", "%d", format_add(ft, "pane_synchronized", "%d",
!!options_get_number(&wp->window->options, "synchronize-panes")); !!options_get_number(wp->window->options, "synchronize-panes"));
format_add(ft, "pane_tty", "%s", wp->tty); format_add(ft, "pane_tty", "%s", wp->tty);
format_add(ft, "pane_pid", "%ld", (long) wp->pid); format_add(ft, "pane_pid", "%ld", (long) wp->pid);

View File

@ -170,7 +170,7 @@ input_key(struct window_pane *wp, int key, struct mouse_event *m)
* Then try to look this up as an xterm key, if the flag to output them * Then try to look this up as an xterm key, if the flag to output them
* is set. * is set.
*/ */
if (options_get_number(&wp->window->options, "xterm-keys")) { if (options_get_number(wp->window->options, "xterm-keys")) {
if ((out = xterm_keys_lookup(key)) != NULL) { if ((out = xterm_keys_lookup(key)) != NULL) {
bufferevent_write(wp->event, out, strlen(out)); bufferevent_write(wp->event, out, strlen(out));
free(out); free(out);

View File

@ -1907,12 +1907,12 @@ input_exit_rename(struct input_ctx *ictx)
{ {
if (ictx->flags & INPUT_DISCARD) if (ictx->flags & INPUT_DISCARD)
return; return;
if (!options_get_number(&ictx->wp->window->options, "allow-rename")) if (!options_get_number(ictx->wp->window->options, "allow-rename"))
return; return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf); log_debug("%s: \"%s\"", __func__, ictx->input_buf);
window_set_name(ictx->wp->window, ictx->input_buf); window_set_name(ictx->wp->window, ictx->input_buf);
options_set_number(&ictx->wp->window->options, "automatic-rename", 0); options_set_number(ictx->wp->window->options, "automatic-rename", 0);
server_status_window(ictx->wp->window); server_status_window(ictx->wp->window);
} }
@ -1921,7 +1921,7 @@ input_exit_rename(struct input_ctx *ictx)
int int
input_utf8_open(struct input_ctx *ictx) input_utf8_open(struct input_ctx *ictx)
{ {
if (!options_get_number(&ictx->wp->window->options, "utf8")) { if (!options_get_number(ictx->wp->window->options, "utf8")) {
/* Print, and do not switch state. */ /* Print, and do not switch state. */
input_print(ictx); input_print(ictx);
return (-1); return (-1);

View File

@ -245,10 +245,10 @@ layout_set_main_h(struct window *w)
width = (w->sx - (n - 1)) / columns; width = (w->sx - (n - 1)) / columns;
/* Get the main pane height and add one for separator line. */ /* Get the main pane height and add one for separator line. */
mainheight = options_get_number(&w->options, "main-pane-height") + 1; mainheight = options_get_number(w->options, "main-pane-height") + 1;
/* Get the optional other pane height and add one for separator line. */ /* Get the optional other pane height and add one for separator line. */
otherheight = options_get_number(&w->options, "other-pane-height") + 1; otherheight = options_get_number(w->options, "other-pane-height") + 1;
/* /*
* If an other pane height was specified, honour it so long as it * If an other pane height was specified, honour it so long as it
@ -366,10 +366,10 @@ layout_set_main_v(struct window *w)
height = (w->sy - (n - 1)) / rows; height = (w->sy - (n - 1)) / rows;
/* Get the main pane width and add one for separator line. */ /* Get the main pane width and add one for separator line. */
mainwidth = options_get_number(&w->options, "main-pane-width") + 1; mainwidth = options_get_number(w->options, "main-pane-width") + 1;
/* Get the optional other pane width and add one for separator line. */ /* Get the optional other pane width and add one for separator line. */
otherwidth = options_get_number(&w->options, "other-pane-width") + 1; otherwidth = options_get_number(w->options, "other-pane-width") + 1;
/* /*
* If an other pane width was specified, honour it so long as it * If an other pane width was specified, honour it so long as it

View File

@ -58,7 +58,7 @@ check_window_name(struct window *w)
if (w->active == NULL) if (w->active == NULL)
return; return;
if (!options_get_number(&w->options, "automatic-rename")) if (!options_get_number(w->options, "automatic-rename"))
return; return;
if (~w->active->flags & PANE_CHANGED) { if (~w->active->flags & PANE_CHANGED) {
@ -122,7 +122,7 @@ format_window_name(struct window *w)
format_defaults_window(ft, w); format_defaults_window(ft, w);
format_defaults_pane(ft, w->active); format_defaults_pane(ft, w->active);
fmt = options_get_string(&w->options, "automatic-rename-format"); fmt = options_get_string(w->options, "automatic-rename-format");
name = format_expand(ft, fmt); name = format_expand(ft, fmt);
format_free(ft); format_free(ft);

View File

@ -29,6 +29,13 @@
* a red-black tree. * a red-black tree.
*/ */
struct options {
RB_HEAD(options_tree, options_entry) tree;
struct options *parent;
};
int options_cmp(struct options_entry *, struct options_entry *);
RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
RB_GENERATE(options_tree, options_entry, entry, options_cmp); RB_GENERATE(options_tree, options_entry, entry, options_cmp);
int int
@ -37,11 +44,15 @@ options_cmp(struct options_entry *o1, struct options_entry *o2)
return (strcmp(o1->name, o2->name)); return (strcmp(o1->name, o2->name));
} }
void struct options *
options_init(struct options *oo, struct options *parent) options_create(struct options *parent)
{ {
struct options *oo;
oo = xcalloc(1, sizeof *oo);
RB_INIT(&oo->tree); RB_INIT(&oo->tree);
oo->parent = parent; oo->parent = parent;
return (oo);
} }
void void
@ -57,6 +68,19 @@ options_free(struct options *oo)
free(o->str); free(o->str);
free(o); free(o);
} }
free(oo);
}
struct options_entry *
options_first(struct options *oo)
{
return (RB_MIN(options_tree, &oo->tree));
}
struct options_entry *
options_next(struct options_entry *o)
{
return (RB_NEXT(options_tree, &oo->tree, o));
} }
struct options_entry * struct options_entry *

View File

@ -150,7 +150,7 @@ paste_add(char *data, size_t size)
if (size == 0) if (size == 0)
return; return;
limit = options_get_number(&global_options, "buffer-limit"); limit = options_get_number(global_options, "buffer-limit");
RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) { RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) {
if (paste_num_automatic < limit) if (paste_num_automatic < limit)
break; break;

251
proc.c Normal file
View File

@ -0,0 +1,251 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/uio.h>
#include <errno.h>
#include <event.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
struct tmuxproc {
const char *name;
int exit;
void (*signalcb)(int);
};
struct tmuxpeer {
struct tmuxproc *parent;
struct imsgbuf ibuf;
struct event event;
int flags;
#define PEER_BAD 0x1
void (*dispatchcb)(struct imsg *, void *);
void *arg;
};
static void proc_update_event(struct tmuxpeer *);
static void
proc_event_cb(unused int fd, short events, void *arg)
{
struct tmuxpeer *peer = arg;
ssize_t n;
struct imsg imsg;
int v;
if (!(peer->flags & PEER_BAD) && (events & EV_READ)) {
if ((n = imsg_read(&peer->ibuf)) == -1 || n == 0) {
peer->dispatchcb(NULL, peer->arg);
return;
}
for (;;) {
if ((n = imsg_get(&peer->ibuf, &imsg)) == -1) {
peer->dispatchcb(NULL, peer->arg);
return;
}
if (n == 0)
break;
log_debug("peer %p message %d", peer, imsg.hdr.type);
v = imsg.hdr.peerid;
if (imsg.hdr.type != MSG_VERSION &&
v != PROTOCOL_VERSION) {
log_debug("peer %p bad version %d", peer, v);
proc_send(peer, MSG_VERSION, -1, NULL, 0);
peer->flags |= PEER_BAD;
if (imsg.fd != -1)
close(imsg.fd);
imsg_free(&imsg);
break;
}
peer->dispatchcb(&imsg, peer->arg);
imsg_free(&imsg);
}
}
if (events & EV_WRITE) {
if (msgbuf_write(&peer->ibuf.w) <= 0 && errno != EAGAIN) {
peer->dispatchcb(NULL, peer->arg);
return;
}
}
if ((peer->flags & PEER_BAD) && peer->ibuf.w.queued == 0) {
peer->dispatchcb(NULL, peer->arg);
return;
}
proc_update_event(peer);
}
static void
proc_signal_cb(int signo, unused short events, void *arg)
{
struct tmuxproc *tp = arg;
tp->signalcb(signo);
}
static void
proc_update_event(struct tmuxpeer *peer)
{
short events;
event_del(&peer->event);
events = EV_READ;
if (peer->ibuf.w.queued > 0)
events |= EV_WRITE;
event_set(&peer->event, peer->ibuf.fd, events, proc_event_cb, peer);
event_add(&peer->event, NULL);
}
int
proc_send(struct tmuxpeer *peer, enum msgtype type, int fd, const void *buf,
size_t len)
{
struct imsgbuf *ibuf = &peer->ibuf;
void *vp = (void *)buf;
int retval;
if (peer->flags & PEER_BAD)
return (-1);
log_debug("sending message %d to peer %p (%zu bytes)", type, peer, len);
retval = imsg_compose(ibuf, type, PROTOCOL_VERSION, -1, fd, vp, len);
if (retval != 1)
return (-1);
proc_update_event(peer);
return (0);
}
int
proc_send_s(struct tmuxpeer *peer, enum msgtype type, const char *s)
{
return (proc_send(peer, type, -1, s, strlen(s) + 1));
}
struct tmuxproc *
proc_start(const char *name, struct event_base *base, int forkflag,
void (*signalcb)(int))
{
struct tmuxproc *tp;
if (forkflag) {
switch (fork()) {
case -1:
fatal("fork failed");
case 0:
break;
default:
return (NULL);
}
if (daemon(1, 0) != 0)
fatal("daemon failed");
clear_signals(0);
if (event_reinit(base) != 0)
fatalx("event_reinit failed");
}
logfile(name);
#ifdef HAVE_SETPROCTITLE
setproctitle("%s (%s)", name, socket_path);
#endif
log_debug("%s started (%ld): socket %s, protocol %d", name,
(long)getpid(), socket_path, PROTOCOL_VERSION);
tp = xcalloc(1, sizeof *tp);
tp->name = xstrdup(name);
tp->signalcb = signalcb;
set_signals(proc_signal_cb, tp);
return (tp);
}
void
proc_loop(struct tmuxproc *tp, int (*loopcb)(void))
{
log_debug("%s loop enter", tp->name);
do
event_loop(EVLOOP_ONCE);
while (!tp->exit && (loopcb == NULL || !loopcb ()));
log_debug("%s loop exit", tp->name);
}
void
proc_exit(struct tmuxproc *tp)
{
tp->exit = 1;
}
struct tmuxpeer *
proc_add_peer(struct tmuxproc *tp, int fd,
void (*dispatchcb)(struct imsg *, void *), void *arg)
{
struct tmuxpeer *peer;
peer = xcalloc(1, sizeof *peer);
peer->parent = tp;
peer->dispatchcb = dispatchcb;
peer->arg = arg;
imsg_init(&peer->ibuf, fd);
event_set(&peer->event, fd, EV_READ, proc_event_cb, peer);
log_debug("add peer %p: %d (%p)", peer, fd, arg);
proc_update_event(peer);
return (peer);
}
void
proc_remove_peer(struct tmuxpeer *peer)
{
log_debug("remove peer %p", peer);
event_del(&peer->event);
imsg_clear(&peer->ibuf);
close(peer->ibuf.fd);
free(peer);
}
void
proc_kill_peer(struct tmuxpeer *peer)
{
peer->flags |= PEER_BAD;
}

View File

@ -53,7 +53,7 @@ recalculate_sizes(void)
int flag, has_status, is_zoomed, forced; int flag, has_status, is_zoomed, forced;
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
has_status = options_get_number(&s->options, "status"); has_status = options_get_number(s->options, "status");
s->attached = 0; s->attached = 0;
ssx = ssy = UINT_MAX; ssx = ssy = UINT_MAX;
@ -94,7 +94,7 @@ recalculate_sizes(void)
RB_FOREACH(w, windows, &windows) { RB_FOREACH(w, windows, &windows) {
if (w->active == NULL) if (w->active == NULL)
continue; continue;
flag = options_get_number(&w->options, "aggressive-resize"); flag = options_get_number(w->options, "aggressive-resize");
ssx = ssy = UINT_MAX; ssx = ssy = UINT_MAX;
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
@ -115,12 +115,12 @@ recalculate_sizes(void)
continue; continue;
forced = 0; forced = 0;
limit = options_get_number(&w->options, "force-width"); limit = options_get_number(w->options, "force-width");
if (limit >= PANE_MINIMUM && ssx > limit) { if (limit >= PANE_MINIMUM && ssx > limit) {
ssx = limit; ssx = limit;
forced |= WINDOW_FORCEWIDTH; forced |= WINDOW_FORCEWIDTH;
} }
limit = options_get_number(&w->options, "force-height"); limit = options_get_number(w->options, "force-height");
if (limit >= PANE_MINIMUM && ssy > limit) { if (limit >= PANE_MINIMUM && ssy > limit) {
ssy = limit; ssy = limit;
forced |= WINDOW_FORCEHEIGHT; forced |= WINDOW_FORCEHEIGHT;

View File

@ -222,7 +222,7 @@ void
screen_redraw_screen(struct client *c, int draw_panes, int draw_status, screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
int draw_borders) int draw_borders)
{ {
struct options *oo = &c->session->options; struct options *oo = c->session->options;
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
u_int top; u_int top;
int status, spos; int status, spos;
@ -276,7 +276,7 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
{ {
struct session *s = c->session; struct session *s = c->session;
struct window *w = s->curw->window; struct window *w = s->curw->window;
struct options *oo = &w->options; struct options *oo = w->options;
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct window_pane *wp; struct window_pane *wp;
struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc; struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc;
@ -392,7 +392,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
{ {
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct session *s = c->session; struct session *s = c->session;
struct options *oo = &s->options; struct options *oo = s->options;
struct window *w = wp->window; struct window *w = wp->window;
struct grid_cell gc; struct grid_cell gc;
u_int idx, px, py, i, j, xoff, yoff; u_int idx, px, py, i, j, xoff, yoff;

View File

@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <event.h> #include <event.h>
@ -41,10 +42,10 @@ void server_client_set_title(struct client *);
void server_client_reset_state(struct client *); void server_client_reset_state(struct client *);
int server_client_assume_paste(struct session *); int server_client_assume_paste(struct session *);
int server_client_msg_dispatch(struct client *); void server_client_dispatch(struct imsg *, void *);
void server_client_msg_command(struct client *, struct imsg *); void server_client_dispatch_command(struct client *, struct imsg *);
void server_client_msg_identify(struct client *, struct imsg *); void server_client_dispatch_identify(struct client *, struct imsg *);
void server_client_msg_shell(struct client *); void server_client_dispatch_shell(struct client *);
/* Check if this client is inside this server. */ /* Check if this client is inside this server. */
int int
@ -86,8 +87,7 @@ server_client_create(int fd)
c = xcalloc(1, sizeof *c); c = xcalloc(1, sizeof *c);
c->references = 1; c->references = 1;
imsg_init(&c->ibuf, fd); c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c);
server_update_event(c);
if (gettimeofday(&c->creation_time, NULL) != 0) if (gettimeofday(&c->creation_time, NULL) != 0)
fatal("gettimeofday failed"); fatal("gettimeofday failed");
@ -219,10 +219,8 @@ server_client_lost(struct client *c)
environ_free(&c->environ); environ_free(&c->environ);
close(c->ibuf.fd); proc_remove_peer(c->peer);
imsg_clear(&c->ibuf); c->peer = NULL;
if (event_initialized(&c->event))
event_del(&c->event);
server_client_unref(c); server_client_unref(c);
@ -256,40 +254,6 @@ server_client_free(unused int fd, unused short events, void *arg)
free(c); free(c);
} }
/* Process a single client event. */
void
server_client_callback(int fd, short events, void *data)
{
struct client *c = data;
if (c->flags & CLIENT_DEAD)
return;
if (fd == c->ibuf.fd) {
if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) <= 0 &&
errno != EAGAIN)
goto client_lost;
if (c->flags & CLIENT_BAD) {
if (c->ibuf.w.queued == 0)
goto client_lost;
return;
}
if (events & EV_READ && server_client_msg_dispatch(c) != 0)
goto client_lost;
}
server_push_stdout(c);
server_push_stderr(c);
server_update_event(c);
return;
client_lost:
server_client_lost(c);
}
/* Check for mouse keys. */ /* Check for mouse keys. */
int int
server_client_check_mouse(struct client *c) server_client_check_mouse(struct client *c)
@ -524,7 +488,7 @@ server_client_assume_paste(struct session *s)
struct timeval tv; struct timeval tv;
int t; int t;
if ((t = options_get_number(&s->options, "assume-paste-time")) == 0) if ((t = options_get_number(s->options, "assume-paste-time")) == 0)
return (0); return (0);
timersub(&s->activity_time, &s->last_activity_time, &tv); timersub(&s->activity_time, &s->last_activity_time, &tv);
@ -590,7 +554,7 @@ server_client_handle_key(struct client *c, int key)
m->valid = 1; m->valid = 1;
m->key = key; m->key = key;
if (!options_get_number(&s->options, "mouse")) if (!options_get_number(s->options, "mouse"))
goto forward; goto forward;
} else } else
m->valid = 0; m->valid = 0;
@ -627,7 +591,7 @@ retry:
* If this is a repeating key, start the timer. Otherwise reset * If this is a repeating key, start the timer. Otherwise reset
* the client back to the root table. * the client back to the root table.
*/ */
xtimeout = options_get_number(&s->options, "repeat-time"); xtimeout = options_get_number(s->options, "repeat-time");
if (xtimeout != 0 && bd->can_repeat) { if (xtimeout != 0 && bd->can_repeat) {
c->flags |= CLIENT_REPEAT; c->flags |= CLIENT_REPEAT;
@ -669,8 +633,8 @@ retry:
* No match, but in the root table. Prefix switches to the prefix table * No match, but in the root table. Prefix switches to the prefix table
* and everything else is passed through. * and everything else is passed through.
*/ */
if (key == options_get_number(&s->options, "prefix") || if (key == options_get_number(s->options, "prefix") ||
key == options_get_number(&s->options, "prefix2")) { key == options_get_number(s->options, "prefix2")) {
server_client_key_table(c, "prefix"); server_client_key_table(c, "prefix");
server_status_client(c); server_status_client(c);
return; return;
@ -757,7 +721,7 @@ server_client_check_focus(struct window_pane *wp)
int push; int push;
/* Are focus events off? */ /* Are focus events off? */
if (!options_get_number(&global_options, "focus-events")) if (!options_get_number(global_options, "focus-events"))
return; return;
/* Do we need to push the focus state? */ /* Do we need to push the focus state? */
@ -817,7 +781,7 @@ server_client_reset_state(struct client *c)
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
struct window_pane *wp = w->active; struct window_pane *wp = w->active;
struct screen *s = wp->screen; struct screen *s = wp->screen;
struct options *oo = &c->session->options; struct options *oo = c->session->options;
int status, mode, o; int status, mode, o;
if (c->flags & CLIENT_SUSPENDED) if (c->flags & CLIENT_SUSPENDED)
@ -889,7 +853,7 @@ server_client_check_exit(struct client *c)
if (EVBUFFER_LENGTH(c->stderr_data) != 0) if (EVBUFFER_LENGTH(c->stderr_data) != 0)
return; return;
server_write_client(c, MSG_EXIT, &c->retval, sizeof c->retval); proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval);
c->flags &= ~CLIENT_EXIT; c->flags &= ~CLIENT_EXIT;
} }
@ -906,7 +870,7 @@ server_client_check_redraw(struct client *c)
return; return;
if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
if (options_get_number(&s->options, "set-titles")) if (options_get_number(s->options, "set-titles"))
server_client_set_title(c); server_client_set_title(c);
if (c->message_string != NULL) if (c->message_string != NULL)
@ -966,7 +930,7 @@ server_client_set_title(struct client *c)
char *title; char *title;
struct format_tree *ft; struct format_tree *ft;
template = options_get_string(&s->options, "set-titles-string"); template = options_get_string(s->options, "set-titles-string");
ft = format_create(); ft = format_create();
format_defaults(ft, c, NULL, NULL, NULL); format_defaults(ft, c, NULL, NULL, NULL);
@ -983,123 +947,112 @@ server_client_set_title(struct client *c)
} }
/* Dispatch message from client. */ /* Dispatch message from client. */
int void
server_client_msg_dispatch(struct client *c) server_client_dispatch(struct imsg *imsg, void *arg)
{ {
struct imsg imsg; struct client *c = arg;
struct msg_stdin_data stdindata; struct msg_stdin_data stdindata;
const char *data; const char *data;
ssize_t n, datalen; ssize_t datalen;
struct session *s; struct session *s;
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) if (c->flags & CLIENT_DEAD)
return (-1); return;
for (;;) { if (imsg == NULL) {
if ((n = imsg_get(&c->ibuf, &imsg)) == -1) server_client_lost(c);
return (-1); return;
if (n == 0)
return (0);
data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
if (imsg.hdr.peerid != PROTOCOL_VERSION) {
server_write_client(c, MSG_VERSION, NULL, 0);
c->flags |= CLIENT_BAD;
if (imsg.fd != -1)
close(imsg.fd);
imsg_free(&imsg);
continue;
}
log_debug("got %u from client %p", imsg.hdr.type, c);
switch (imsg.hdr.type) {
case MSG_IDENTIFY_FLAGS:
case MSG_IDENTIFY_TERM:
case MSG_IDENTIFY_TTYNAME:
case MSG_IDENTIFY_CWD:
case MSG_IDENTIFY_STDIN:
case MSG_IDENTIFY_ENVIRON:
case MSG_IDENTIFY_CLIENTPID:
case MSG_IDENTIFY_DONE:
server_client_msg_identify(c, &imsg);
break;
case MSG_COMMAND:
server_client_msg_command(c, &imsg);
break;
case MSG_STDIN:
if (datalen != sizeof stdindata)
fatalx("bad MSG_STDIN size");
memcpy(&stdindata, data, sizeof stdindata);
if (c->stdin_callback == NULL)
break;
if (stdindata.size <= 0)
c->stdin_closed = 1;
else {
evbuffer_add(c->stdin_data, stdindata.data,
stdindata.size);
}
c->stdin_callback(c, c->stdin_closed,
c->stdin_callback_data);
break;
case MSG_RESIZE:
if (datalen != 0)
fatalx("bad MSG_RESIZE size");
if (c->flags & CLIENT_CONTROL)
break;
if (tty_resize(&c->tty)) {
recalculate_sizes();
server_redraw_client(c);
}
break;
case MSG_EXITING:
if (datalen != 0)
fatalx("bad MSG_EXITING size");
c->session = NULL;
tty_close(&c->tty);
server_write_client(c, MSG_EXITED, NULL, 0);
break;
case MSG_WAKEUP:
case MSG_UNLOCK:
if (datalen != 0)
fatalx("bad MSG_WAKEUP size");
if (!(c->flags & CLIENT_SUSPENDED))
break;
c->flags &= ~CLIENT_SUSPENDED;
if (c->tty.fd == -1) /* exited in the meantime */
break;
s = c->session;
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday failed");
if (s != NULL)
session_update_activity(s, &c->activity_time);
tty_start_tty(&c->tty);
server_redraw_client(c);
recalculate_sizes();
break;
case MSG_SHELL:
if (datalen != 0)
fatalx("bad MSG_SHELL size");
server_client_msg_shell(c);
break;
}
imsg_free(&imsg);
} }
data = imsg->data;
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
switch (imsg->hdr.type) {
case MSG_IDENTIFY_FLAGS:
case MSG_IDENTIFY_TERM:
case MSG_IDENTIFY_TTYNAME:
case MSG_IDENTIFY_CWD:
case MSG_IDENTIFY_STDIN:
case MSG_IDENTIFY_ENVIRON:
case MSG_IDENTIFY_CLIENTPID:
case MSG_IDENTIFY_DONE:
server_client_dispatch_identify(c, imsg);
break;
case MSG_COMMAND:
server_client_dispatch_command(c, imsg);
break;
case MSG_STDIN:
if (datalen != sizeof stdindata)
fatalx("bad MSG_STDIN size");
memcpy(&stdindata, data, sizeof stdindata);
if (c->stdin_callback == NULL)
break;
if (stdindata.size <= 0)
c->stdin_closed = 1;
else {
evbuffer_add(c->stdin_data, stdindata.data,
stdindata.size);
}
c->stdin_callback(c, c->stdin_closed,
c->stdin_callback_data);
break;
case MSG_RESIZE:
if (datalen != 0)
fatalx("bad MSG_RESIZE size");
if (c->flags & CLIENT_CONTROL)
break;
if (tty_resize(&c->tty)) {
recalculate_sizes();
server_redraw_client(c);
}
break;
case MSG_EXITING:
if (datalen != 0)
fatalx("bad MSG_EXITING size");
c->session = NULL;
tty_close(&c->tty);
proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
break;
case MSG_WAKEUP:
case MSG_UNLOCK:
if (datalen != 0)
fatalx("bad MSG_WAKEUP size");
if (!(c->flags & CLIENT_SUSPENDED))
break;
c->flags &= ~CLIENT_SUSPENDED;
if (c->tty.fd == -1) /* exited in the meantime */
break;
s = c->session;
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday failed");
if (s != NULL)
session_update_activity(s, &c->activity_time);
tty_start_tty(&c->tty);
server_redraw_client(c);
recalculate_sizes();
break;
case MSG_SHELL:
if (datalen != 0)
fatalx("bad MSG_SHELL size");
server_client_dispatch_shell(c);
break;
}
server_push_stdout(c);
server_push_stderr(c);
} }
/* Handle command message. */ /* Handle command message. */
void void
server_client_msg_command(struct client *c, struct imsg *imsg) server_client_dispatch_command(struct client *c, struct imsg *imsg)
{ {
struct msg_command_data data; struct msg_command_data data;
char *buf; char *buf;
@ -1152,7 +1105,7 @@ error:
/* Handle identify message. */ /* Handle identify message. */
void void
server_client_msg_identify(struct client *c, struct imsg *imsg) server_client_dispatch_identify(struct client *c, struct imsg *imsg)
{ {
const char *data; const char *data;
size_t datalen; size_t datalen;
@ -1231,7 +1184,7 @@ server_client_msg_identify(struct client *c, struct imsg *imsg)
if (c->flags & CLIENT_CONTROLCONTROL) if (c->flags & CLIENT_CONTROLCONTROL)
evbuffer_add_printf(c->stdout_data, "\033P1000p"); evbuffer_add_printf(c->stdout_data, "\033P1000p");
server_write_client(c, MSG_STDIN, NULL, 0); proc_send(c->peer, MSG_STDIN, -1, NULL, 0);
c->tty.fd = -1; c->tty.fd = -1;
c->tty.log_fd = -1; c->tty.log_fd = -1;
@ -1262,14 +1215,14 @@ server_client_msg_identify(struct client *c, struct imsg *imsg)
/* Handle shell message. */ /* Handle shell message. */
void void
server_client_msg_shell(struct client *c) server_client_dispatch_shell(struct client *c)
{ {
const char *shell; const char *shell;
shell = options_get_string(&global_s_options, "default-shell"); shell = options_get_string(global_s_options, "default-shell");
if (*shell == '\0' || areshell(shell)) if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
server_write_client(c, MSG_SHELL, shell, strlen(shell) + 1); proc_send_s(c->peer, MSG_SHELL, shell);
c->flags |= CLIENT_BAD; /* it will die after exec */ proc_kill_peer(c->peer);
} }

View File

@ -17,6 +17,7 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -36,7 +37,7 @@ server_fill_environ(struct session *s, struct environ *env)
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", term);
idx = s->id; idx = s->id;
@ -47,43 +48,6 @@ server_fill_environ(struct session *s, struct environ *env)
environ_set(env, "TMUX", var); environ_set(env, "TMUX", var);
} }
void
server_write_ready(struct client *c)
{
if (c->flags & CLIENT_CONTROL)
return;
server_write_client(c, MSG_READY, NULL, 0);
}
int
server_write_client(struct client *c, enum msgtype type, const void *buf,
size_t len)
{
struct imsgbuf *ibuf = &c->ibuf;
int error;
if (c->flags & CLIENT_BAD)
return (-1);
log_debug("writing %d to client %p", type, c);
error = imsg_compose(ibuf, type, PROTOCOL_VERSION, -1, -1,
(void *) buf, len);
if (error == 1)
server_update_event(c);
return (error == 1 ? 0 : -1);
}
void
server_write_session(struct session *s, enum msgtype type, const void *buf,
size_t len)
{
struct client *c;
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == s)
server_write_client(c, type, buf, len);
}
}
void void
server_redraw_client(struct client *c) server_redraw_client(struct client *c)
{ {
@ -217,7 +181,7 @@ server_lock_client(struct client *c)
if (c->flags & CLIENT_SUSPENDED) if (c->flags & CLIENT_SUSPENDED)
return; return;
cmd = options_get_string(&c->session->options, "lock-command"); cmd = options_get_string(c->session->options, "lock-command");
if (strlen(cmd) + 1 > MAX_IMSGSIZE - IMSG_HEADER_SIZE) if (strlen(cmd) + 1 > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
return; return;
@ -227,7 +191,7 @@ server_lock_client(struct client *c)
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3)); tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3));
c->flags |= CLIENT_SUSPENDED; c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_LOCK, cmd, strlen(cmd) + 1); proc_send_s(c->peer, MSG_LOCK, cmd);
} }
void void
@ -253,7 +217,7 @@ server_kill_window(struct window *w)
server_redraw_session_group(s); server_redraw_session_group(s);
} }
if (options_get_number(&s->options, "renumber-windows")) { if (options_get_number(s->options, "renumber-windows")) {
if ((sg = session_group_find(s)) != NULL) { if ((sg = session_group_find(s)) != NULL) {
TAILQ_FOREACH(target_s, &sg->sessions, gentry) TAILQ_FOREACH(target_s, &sg->sessions, gentry)
session_renumber_windows(target_s); session_renumber_windows(target_s);
@ -306,7 +270,7 @@ server_link_window(struct session *src, struct winlink *srcwl,
} }
if (dstidx == -1) if (dstidx == -1)
dstidx = -1 - options_get_number(&dst->options, "base-index"); dstidx = -1 - options_get_number(dst->options, "base-index");
dstwl = session_attach(dst, srcwl->window, dstidx, cause); dstwl = session_attach(dst, srcwl->window, dstidx, cause);
if (dstwl == NULL) if (dstwl == NULL)
return (-1); return (-1);
@ -345,7 +309,7 @@ server_destroy_pane(struct window_pane *wp)
wp->fd = -1; wp->fd = -1;
} }
if (options_get_number(&w->options, "remain-on-exit")) { if (options_get_number(w->options, "remain-on-exit")) {
if (old_fd == -1) if (old_fd == -1)
return; return;
screen_write_start(&ctx, wp, &wp->base); screen_write_start(&ctx, wp, &wp->base);
@ -408,7 +372,7 @@ server_destroy_session(struct session *s)
struct client *c; struct client *c;
struct session *s_new; struct session *s_new;
if (!options_get_number(&s->options, "detach-on-destroy")) if (!options_get_number(s->options, "detach-on-destroy"))
s_new = server_next_session(s); s_new = server_next_session(s);
else else
s_new = NULL; s_new = NULL;
@ -444,7 +408,7 @@ server_check_unattached(void)
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
if (!(s->flags & SESSION_UNATTACHED)) if (!(s->flags & SESSION_UNATTACHED))
continue; continue;
if (options_get_number (&s->options, "destroy-unattached")) if (options_get_number (s->options, "destroy-unattached"))
session_destroy(s); session_destroy(s);
} }
} }
@ -455,7 +419,7 @@ server_set_identify(struct client *c)
struct timeval tv; struct timeval tv;
int delay; int delay;
delay = options_get_number(&c->session->options, "display-panes-time"); delay = options_get_number(c->session->options, "display-panes-time");
tv.tv_sec = delay / 1000; tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L; tv.tv_usec = (delay % 1000) * 1000L;
@ -487,22 +451,6 @@ server_callback_identify(unused int fd, unused short events, void *data)
server_clear_identify(c); server_clear_identify(c);
} }
void
server_update_event(struct client *c)
{
short events;
events = 0;
if (!(c->flags & CLIENT_BAD))
events |= EV_READ;
if (c->ibuf.w.queued > 0)
events |= EV_WRITE;
if (event_initialized(&c->event))
event_del(&c->event);
event_set(&c->event, c->ibuf.fd, events, server_client_callback, c);
event_add(&c->event, NULL);
}
/* Push stdout to client if possible. */ /* Push stdout to client if possible. */
void void
server_push_stdout(struct client *c) server_push_stdout(struct client *c)
@ -519,7 +467,7 @@ server_push_stdout(struct client *c)
memcpy(data.data, EVBUFFER_DATA(c->stdout_data), size); memcpy(data.data, EVBUFFER_DATA(c->stdout_data), size);
data.size = size; data.size = size;
if (server_write_client(c, MSG_STDOUT, &data, sizeof data) == 0) if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) == 0)
evbuffer_drain(c->stdout_data, size); evbuffer_drain(c->stdout_data, size);
} }
@ -543,7 +491,7 @@ server_push_stderr(struct client *c)
memcpy(data.data, EVBUFFER_DATA(c->stderr_data), size); memcpy(data.data, EVBUFFER_DATA(c->stderr_data), size);
data.size = size; data.size = size;
if (server_write_client(c, MSG_STDERR, &data, sizeof data) == 0) if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) == 0)
evbuffer_drain(c->stderr_data, size); evbuffer_drain(c->stderr_data, size);
} }
@ -573,7 +521,7 @@ server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
if (c->stdin_closed) if (c->stdin_closed)
c->stdin_callback(c, 1, c->stdin_callback_data); c->stdin_callback(c, 1, c->stdin_callback_data);
server_write_client(c, MSG_STDIN, NULL, 0); proc_send(c->peer, MSG_STDIN, -1, NULL, 0);
return (0); return (0);
} }

View File

@ -42,6 +42,7 @@
struct clients clients; struct clients clients;
struct tmuxproc *server_proc;
int server_fd; int server_fd;
int server_exit; int server_exit;
struct event server_ev_accept; struct event server_ev_accept;
@ -53,11 +54,11 @@ struct window_pane *marked_window_pane;
struct layout_cell *marked_layout_cell; struct layout_cell *marked_layout_cell;
int server_create_socket(void); int server_create_socket(void);
void server_loop(void); int server_loop(void);
int server_should_exit(void); int server_should_exit(void);
void server_send_exit(void); void server_send_exit(void);
void server_accept_callback(int, short, void *); void server_accept(int, short, void *);
void server_signal_callback(int, short, void *); void server_signal(int);
void server_child_signal(void); void server_child_signal(void);
void server_child_exited(pid_t, int); void server_child_exited(pid_t, int);
void server_child_stopped(pid_t, int); void server_child_stopped(pid_t, int);
@ -161,17 +162,11 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
{ {
int pair[2]; int pair[2];
/* The first client is special and gets a socketpair; create it. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
fatal("socketpair failed"); fatal("socketpair failed");
log_debug("starting server");
switch (fork()) { server_proc = proc_start("server", base, 1, server_signal);
case -1: if (server_proc == NULL) {
fatal("fork failed");
case 0:
break;
default:
close(pair[1]); close(pair[1]);
return (pair[0]); return (pair[0]);
} }
@ -183,21 +178,6 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
fatal("pledge failed"); fatal("pledge failed");
#endif #endif
/*
* Must daemonise before loading configuration as the PID changes so
* $TMUX would be wrong for sessions created in the config file.
*/
if (daemon(1, 0) != 0)
fatal("daemon failed");
/* event_init() was called in our parent, need to reinit. */
clear_signals(0);
if (event_reinit(base) != 0)
fatal("event_reinit failed");
logfile("server");
log_debug("server started, pid %ld", (long) getpid());
RB_INIT(&windows); RB_INIT(&windows);
RB_INIT(&all_window_panes); RB_INIT(&all_window_panes);
TAILQ_INIT(&clients); TAILQ_INIT(&clients);
@ -208,10 +188,6 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
utf8_build(); utf8_build();
start_time = time(NULL); start_time = time(NULL);
log_debug("socket path %s", socket_path);
#ifdef HAVE_SETPROCTITLE
setproctitle("server (%s)", socket_path);
#endif
server_fd = server_create_socket(); server_fd = server_create_socket();
if (server_fd == -1) if (server_fd == -1)
@ -229,32 +205,20 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
server_add_accept(0); server_add_accept(0);
set_signals(server_signal_callback); proc_loop(server_proc, server_loop);
server_loop();
status_prompt_save_history(); status_prompt_save_history();
exit(0); exit(0);
} }
/* Main server loop. */ /* Server loop callback. */
void
server_loop(void)
{
while (!server_should_exit()) {
log_debug("event dispatch enter");
event_loop(EVLOOP_ONCE);
log_debug("event dispatch exit");
server_client_loop();
}
}
/* Check if the server should exit (no more clients or sessions). */
int int
server_should_exit(void) server_loop(void)
{ {
struct client *c; struct client *c;
if (!options_get_number(&global_options, "exit-unattached")) { server_client_loop();
if (!options_get_number(global_options, "exit-unattached")) {
if (!RB_EMPTY(&sessions)) if (!RB_EMPTY(&sessions))
return (0); return (0);
} }
@ -285,10 +249,10 @@ server_send_exit(void)
cmd_wait_for_flush(); cmd_wait_for_flush();
TAILQ_FOREACH_SAFE(c, &clients, entry, c1) { TAILQ_FOREACH_SAFE(c, &clients, entry, c1) {
if (c->flags & (CLIENT_BAD|CLIENT_SUSPENDED)) if (c->flags & CLIENT_SUSPENDED)
server_client_lost(c); server_client_lost(c);
else else
server_write_client(c, MSG_SHUTDOWN, NULL, 0); proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0);
c->session = NULL; c->session = NULL;
} }
@ -334,7 +298,7 @@ server_update_socket(void)
/* Callback for server socket. */ /* Callback for server socket. */
void void
server_accept_callback(int fd, short events, unused void *data) server_accept(int fd, short events, unused void *data)
{ {
struct sockaddr_storage sa; struct sockaddr_storage sa;
socklen_t slen = sizeof sa; socklen_t slen = sizeof sa;
@ -375,19 +339,19 @@ server_add_accept(int timeout)
event_del(&server_ev_accept); event_del(&server_ev_accept);
if (timeout == 0) { if (timeout == 0) {
event_set(&server_ev_accept, event_set(&server_ev_accept, server_fd, EV_READ, server_accept,
server_fd, EV_READ, server_accept_callback, NULL); NULL);
event_add(&server_ev_accept, NULL); event_add(&server_ev_accept, NULL);
} else { } else {
event_set(&server_ev_accept, event_set(&server_ev_accept, server_fd, EV_TIMEOUT,
server_fd, EV_TIMEOUT, server_accept_callback, NULL); server_accept, NULL);
event_add(&server_ev_accept, &tv); event_add(&server_ev_accept, &tv);
} }
} }
/* Signal handler. */ /* Signal handler. */
void void
server_signal_callback(int sig, unused short events, unused void *data) server_signal(int sig)
{ {
int fd; int fd;

View File

@ -119,10 +119,10 @@ session_create(const char *name, int argc, char **argv, const char *path,
TAILQ_INIT(&s->lastw); TAILQ_INIT(&s->lastw);
RB_INIT(&s->windows); RB_INIT(&s->windows);
options_init(&s->options, &global_s_options);
environ_init(&s->environ); environ_init(&s->environ);
if (env != NULL) if (env != NULL)
environ_copy(env, &s->environ); environ_copy(env, &s->environ);
s->options = options_create(global_s_options);
s->tio = NULL; s->tio = NULL;
if (tio != NULL) { if (tio != NULL) {
@ -189,6 +189,9 @@ session_free(unused int fd, unused short events, void *arg)
log_debug("session %s freed (%d references)", s->name, s->references); log_debug("session %s freed (%d references)", s->name, s->references);
if (s->references == 0) { if (s->references == 0) {
environ_free(&s->environ);
options_free(s->options);
free(s->name); free(s->name);
free(s); free(s);
} }
@ -211,8 +214,6 @@ session_destroy(struct session *s)
event_del(&s->lock_timer); event_del(&s->lock_timer);
session_group_remove(s); session_group_remove(s);
environ_free(&s->environ);
options_free(&s->options);
while (!TAILQ_EMPTY(&s->lastw)) while (!TAILQ_EMPTY(&s->lastw))
winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw)); winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));
@ -270,7 +271,7 @@ session_update_activity(struct session *s, struct timeval *from)
if (~s->flags & SESSION_UNATTACHED) { if (~s->flags & SESSION_UNATTACHED) {
timerclear(&tv); timerclear(&tv);
tv.tv_sec = options_get_number(&s->options, "lock-after-time"); tv.tv_sec = options_get_number(s->options, "lock-after-time");
if (tv.tv_sec != 0) if (tv.tv_sec != 0)
evtimer_add(&s->lock_timer, &tv); evtimer_add(&s->lock_timer, &tv);
} }
@ -331,11 +332,11 @@ session_new(struct session *s, const char *name, int argc, char **argv,
environ_copy(&s->environ, &env); environ_copy(&s->environ, &env);
server_fill_environ(s, &env); server_fill_environ(s, &env);
shell = options_get_string(&s->options, "default-shell"); shell = options_get_string(s->options, "default-shell");
if (*shell == '\0' || areshell(shell)) if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(s->options, "history-limit");
w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio, w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
s->sx, s->sy, hlimit, cause); s->sx, s->sy, hlimit, cause);
if (w == NULL) { if (w == NULL) {
@ -347,8 +348,8 @@ session_new(struct session *s, const char *name, int argc, char **argv,
notify_window_linked(s, w); notify_window_linked(s, w);
environ_free(&env); environ_free(&env);
if (options_get_number(&s->options, "set-remain-on-exit")) if (options_get_number(s->options, "set-remain-on-exit"))
options_set_number(&w->options, "remain-on-exit", 1); options_set_number(w->options, "remain-on-exit", 1);
session_group_synchronize_from(s); session_group_synchronize_from(s);
return (wl); return (wl);
@ -711,7 +712,7 @@ session_renumber_windows(struct session *s)
RB_INIT(&s->windows); RB_INIT(&s->windows);
/* Start renumbering from the base-index if it's set. */ /* Start renumbering from the base-index if it's set. */
new_idx = options_get_number(&s->options, "base-index"); new_idx = options_get_number(s->options, "base-index");
new_curw_idx = 0; new_curw_idx = 0;
/* Go through the winlinks and assign new indexes. */ /* Go through the winlinks and assign new indexes. */

View File

@ -32,7 +32,7 @@ struct event ev_sigusr1;
struct event ev_sigwinch; struct event ev_sigwinch;
void void
set_signals(void(*handler)(int, short, unused void *)) set_signals(void (*handler)(int, short, void *), void *arg)
{ {
struct sigaction sigact; struct sigaction sigact;
@ -49,17 +49,17 @@ set_signals(void(*handler)(int, short, unused void *))
if (sigaction(SIGTSTP, &sigact, NULL) != 0) if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed"); fatal("sigaction failed");
signal_set(&ev_sighup, SIGHUP, handler, NULL); signal_set(&ev_sighup, SIGHUP, handler, arg);
signal_add(&ev_sighup, NULL); signal_add(&ev_sighup, NULL);
signal_set(&ev_sigchld, SIGCHLD, handler, NULL); signal_set(&ev_sigchld, SIGCHLD, handler, arg);
signal_add(&ev_sigchld, NULL); signal_add(&ev_sigchld, NULL);
signal_set(&ev_sigcont, SIGCONT, handler, NULL); signal_set(&ev_sigcont, SIGCONT, handler, arg);
signal_add(&ev_sigcont, NULL); signal_add(&ev_sigcont, NULL);
signal_set(&ev_sigterm, SIGTERM, handler, NULL); signal_set(&ev_sigterm, SIGTERM, handler, arg);
signal_add(&ev_sigterm, NULL); signal_add(&ev_sigterm, NULL);
signal_set(&ev_sigusr1, SIGUSR1, handler, NULL); signal_set(&ev_sigusr1, SIGUSR1, handler, arg);
signal_add(&ev_sigusr1, NULL); signal_add(&ev_sigusr1, NULL);
signal_set(&ev_sigwinch, SIGWINCH, handler, NULL); signal_set(&ev_sigwinch, SIGWINCH, handler, arg);
signal_add(&ev_sigwinch, NULL); signal_add(&ev_sigwinch, NULL);
} }

View File

@ -61,7 +61,7 @@ status_prompt_find_history_file(void)
const char *home, *history_file; const char *home, *history_file;
char *path; char *path;
history_file = options_get_string(&global_options, "history-file"); history_file = options_get_string(global_options, "history-file");
if (*history_file == '\0') if (*history_file == '\0')
return (NULL); return (NULL);
if (*history_file == '/') if (*history_file == '/')
@ -160,7 +160,7 @@ status_timer_callback(unused int fd, unused short events, void *arg)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
timerclear(&tv); timerclear(&tv);
tv.tv_sec = options_get_number(&s->options, "status-interval"); tv.tv_sec = options_get_number(s->options, "status-interval");
if (tv.tv_sec != 0) if (tv.tv_sec != 0)
evtimer_add(&c->status_timer, &tv); evtimer_add(&c->status_timer, &tv);
@ -178,7 +178,7 @@ status_timer_start(struct client *c)
else else
evtimer_set(&c->status_timer, status_timer_callback, c); evtimer_set(&c->status_timer, status_timer_callback, c);
if (s != NULL && options_get_number(&s->options, "status")) if (s != NULL && options_get_number(s->options, "status"))
status_timer_callback(-1, 0, c); status_timer_callback(-1, 0, c);
} }
@ -198,10 +198,10 @@ status_at_line(struct client *c)
{ {
struct session *s = c->session; struct session *s = c->session;
if (!options_get_number(&s->options, "status")) if (!options_get_number(s->options, "status"))
return (-1); return (-1);
if (options_get_number(&s->options, "status-position") == 0) if (options_get_number(s->options, "status-position") == 0)
return (0); return (0);
return (c->tty.sy - 1); return (c->tty.sy - 1);
} }
@ -216,12 +216,12 @@ status_redraw_get_left(struct client *c, time_t t, int utf8flag,
char *left; char *left;
size_t leftlen; size_t leftlen;
style_apply_update(gc, &s->options, "status-left-style"); style_apply_update(gc, s->options, "status-left-style");
template = options_get_string(&s->options, "status-left"); template = options_get_string(s->options, "status-left");
left = status_replace(c, NULL, template, t); left = status_replace(c, NULL, template, t);
*size = options_get_number(&s->options, "status-left-length"); *size = options_get_number(s->options, "status-left-length");
leftlen = screen_write_cstrlen(utf8flag, "%s", left); leftlen = screen_write_cstrlen(utf8flag, "%s", left);
if (leftlen < *size) if (leftlen < *size)
*size = leftlen; *size = leftlen;
@ -238,12 +238,12 @@ status_redraw_get_right(struct client *c, time_t t, int utf8flag,
char *right; char *right;
size_t rightlen; size_t rightlen;
style_apply_update(gc, &s->options, "status-right-style"); style_apply_update(gc, s->options, "status-right-style");
template = options_get_string(&s->options, "status-right"); template = options_get_string(s->options, "status-right");
right = status_replace(c, NULL, template, t); right = status_replace(c, NULL, template, t);
*size = options_get_number(&s->options, "status-right-length"); *size = options_get_number(s->options, "status-right-length");
rightlen = screen_write_cstrlen(utf8flag, "%s", right); rightlen = screen_write_cstrlen(utf8flag, "%s", right);
if (rightlen < *size) if (rightlen < *size)
*size = rightlen; *size = rightlen;
@ -261,7 +261,7 @@ status_get_window_at(struct client *c, u_int x)
x += c->wlmouse; x += c->wlmouse;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
oo = &wl->window->options; oo = wl->window->options;
len = strlen(options_get_string(oo, "window-status-separator")); len = strlen(options_get_string(oo, "window-status-separator"));
if (x < wl->status_width) if (x < wl->status_width)
@ -289,7 +289,7 @@ status_redraw(struct client *c)
int larrow, rarrow, utf8flag; int larrow, rarrow, utf8flag;
/* No status line? */ /* No status line? */
if (c->tty.sy == 0 || !options_get_number(&s->options, "status")) if (c->tty.sy == 0 || !options_get_number(s->options, "status"))
return (1); return (1);
left = right = NULL; left = right = NULL;
larrow = rarrow = 0; larrow = rarrow = 0;
@ -298,7 +298,7 @@ status_redraw(struct client *c)
t = time(NULL); t = time(NULL);
/* Set up default colour. */ /* Set up default colour. */
style_apply(&stdgc, &s->options, "status-style"); style_apply(&stdgc, s->options, "status-style");
/* Create the target screen. */ /* Create the target screen. */
memcpy(&old_status, &c->status, sizeof old_status); memcpy(&old_status, &c->status, sizeof old_status);
@ -313,7 +313,7 @@ status_redraw(struct client *c)
goto out; goto out;
/* Get UTF-8 flag. */ /* Get UTF-8 flag. */
utf8flag = options_get_number(&s->options, "status-utf8"); utf8flag = options_get_number(s->options, "status-utf8");
/* Work out left and right strings. */ /* Work out left and right strings. */
memcpy(&lgc, &stdgc, sizeof lgc); memcpy(&lgc, &stdgc, sizeof lgc);
@ -346,7 +346,7 @@ status_redraw(struct client *c)
if (wl == s->curw) if (wl == s->curw)
wloffset = wlwidth; wloffset = wlwidth;
oo = &wl->window->options; oo = wl->window->options;
sep = options_get_string(oo, "window-status-separator"); sep = options_get_string(oo, "window-status-separator");
seplen = screen_write_strlen(utf8flag, "%s", sep); seplen = screen_write_strlen(utf8flag, "%s", sep);
wlwidth += wl->status_width + seplen; wlwidth += wl->status_width + seplen;
@ -361,7 +361,7 @@ status_redraw(struct client *c)
screen_write_cnputs(&ctx, screen_write_cnputs(&ctx,
-1, &wl->status_cell, utf8flag, "%s", wl->status_text); -1, &wl->status_cell, utf8flag, "%s", wl->status_text);
oo = &wl->window->options; oo = wl->window->options;
sep = options_get_string(oo, "window-status-separator"); sep = options_get_string(oo, "window-status-separator");
screen_write_nputs(&ctx, -1, &stdgc, utf8flag, "%s", sep); screen_write_nputs(&ctx, -1, &stdgc, utf8flag, "%s", sep);
} }
@ -461,7 +461,7 @@ draw:
else else
wloffset = 0; wloffset = 0;
if (wlwidth < wlavailable) { if (wlwidth < wlavailable) {
switch (options_get_number(&s->options, "status-justify")) { switch (options_get_number(s->options, "status-justify")) {
case 1: /* centred */ case 1: /* centred */
wloffset += (wlavailable - wlwidth) / 2; wloffset += (wlavailable - wlwidth) / 2;
break; break;
@ -520,7 +520,7 @@ char *
status_print(struct client *c, struct winlink *wl, time_t t, status_print(struct client *c, struct winlink *wl, time_t t,
struct grid_cell *gc) struct grid_cell *gc)
{ {
struct options *oo = &wl->window->options; struct options *oo = wl->window->options;
struct session *s = c->session; struct session *s = c->session;
const char *fmt; const char *fmt;
char *text; char *text;
@ -553,7 +553,7 @@ status_message_set(struct client *c, const char *fmt, ...)
int delay; int delay;
u_int first, limit; u_int first, limit;
limit = options_get_number(&global_options, "message-limit"); limit = options_get_number(global_options, "message-limit");
status_prompt_clear(c); status_prompt_clear(c);
status_message_clear(c); status_message_clear(c);
@ -577,7 +577,7 @@ status_message_set(struct client *c, const char *fmt, ...)
free(msg); free(msg);
} }
delay = options_get_number(&c->session->options, "display-time"); delay = options_get_number(c->session->options, "display-time");
tv.tv_sec = delay / 1000; tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L; tv.tv_usec = (delay % 1000) * 1000L;
@ -631,13 +631,13 @@ status_message_redraw(struct client *c)
memcpy(&old_status, &c->status, sizeof old_status); memcpy(&old_status, &c->status, sizeof old_status);
screen_init(&c->status, c->tty.sx, 1, 0); screen_init(&c->status, c->tty.sx, 1, 0);
utf8flag = options_get_number(&s->options, "status-utf8"); utf8flag = options_get_number(s->options, "status-utf8");
len = screen_write_strlen(utf8flag, "%s", c->message_string); len = screen_write_strlen(utf8flag, "%s", c->message_string);
if (len > c->tty.sx) if (len > c->tty.sx)
len = c->tty.sx; len = c->tty.sx;
style_apply(&gc, &s->options, "message-style"); style_apply(&gc, s->options, "message-style");
screen_write_start(&ctx, NULL, &c->status); screen_write_start(&ctx, NULL, &c->status);
@ -686,7 +686,7 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
c->prompt_flags = flags; c->prompt_flags = flags;
keys = options_get_number(&c->session->options, "status-keys"); keys = options_get_number(c->session->options, "status-keys");
if (keys == MODEKEY_EMACS) if (keys == MODEKEY_EMACS)
mode_key_init(&c->prompt_mdata, &mode_key_tree_emacs_edit); mode_key_init(&c->prompt_mdata, &mode_key_tree_emacs_edit);
else else
@ -761,7 +761,7 @@ status_prompt_redraw(struct client *c)
memcpy(&old_status, &c->status, sizeof old_status); memcpy(&old_status, &c->status, sizeof old_status);
screen_init(&c->status, c->tty.sx, 1, 0); screen_init(&c->status, c->tty.sx, 1, 0);
utf8flag = options_get_number(&s->options, "status-utf8"); utf8flag = options_get_number(s->options, "status-utf8");
len = screen_write_strlen(utf8flag, "%s", c->prompt_string); len = screen_write_strlen(utf8flag, "%s", c->prompt_string);
if (len > c->tty.sx) if (len > c->tty.sx)
@ -770,9 +770,9 @@ status_prompt_redraw(struct client *c)
/* Change colours for command mode. */ /* Change colours for command mode. */
if (c->prompt_mdata.mode == 1) if (c->prompt_mdata.mode == 1)
style_apply(&gc, &s->options, "message-command-style"); style_apply(&gc, s->options, "message-command-style");
else else
style_apply(&gc, &s->options, "message-style"); style_apply(&gc, s->options, "message-style");
screen_write_start(&ctx, NULL, &c->status); screen_write_start(&ctx, NULL, &c->status);
@ -815,7 +815,7 @@ void
status_prompt_key(struct client *c, int key) status_prompt_key(struct client *c, int key)
{ {
struct session *sess = c->session; struct session *sess = c->session;
struct options *oo = &sess->options; struct options *oo = sess->options;
struct paste_buffer *pb; struct paste_buffer *pb;
char *s, *first, *last, word[64], swapc; char *s, *first, *last, word[64], swapc;
const char *histstr, *bufdata, *wsep = NULL; const char *histstr, *bufdata, *wsep = NULL;

7
tmux.1
View File

@ -143,11 +143,10 @@ session created, and continues to process the rest of the configuration file.
.It Fl L Ar socket-name .It Fl L Ar socket-name
.Nm .Nm
stores the server socket in a directory under stores the server socket in a directory under
.Ev TMUX_TMPDIR , .Ev TMUX_TMPDIR
.Ev TMPDIR or
if it is unset, or
.Pa /tmp .Pa /tmp
if both are unset. if it is unset.
The default socket is named The default socket is named
.Em default . .Em default .
This option allows a different socket name to be specified, allowing several This option allows a different socket name to be specified, allowing several

36
tmux.c
View File

@ -36,9 +36,9 @@
extern char *malloc_options; extern char *malloc_options;
#endif #endif
struct options global_options; /* server options */ struct options *global_options; /* server options */
struct options global_s_options; /* session options */ 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; char *shell_cmd;
@ -288,22 +288,21 @@ main(int argc, char **argv)
if (getcwd(tmp, sizeof tmp) != NULL) if (getcwd(tmp, sizeof tmp) != NULL)
environ_set(&global_environ, "PWD", tmp); environ_set(&global_environ, "PWD", tmp);
options_init(&global_options, NULL); global_options = options_create(NULL);
options_table_populate_tree(server_options_table, &global_options); options_table_populate_tree(server_options_table, global_options);
options_init(&global_s_options, NULL); global_s_options = options_create(NULL);
options_table_populate_tree(session_options_table, &global_s_options); options_table_populate_tree(session_options_table, global_s_options);
options_set_string(&global_s_options, "default-shell", "%s", options_set_string(global_s_options, "default-shell", "%s", getshell());
getshell());
options_init(&global_w_options, NULL); global_w_options = options_create(NULL);
options_table_populate_tree(window_options_table, &global_w_options); options_table_populate_tree(window_options_table, global_w_options);
/* Enable UTF-8 if the first client is on UTF-8 terminal. */ /* Enable UTF-8 if the first client is on UTF-8 terminal. */
if (flags & CLIENT_UTF8) { if (flags & CLIENT_UTF8) {
options_set_number(&global_s_options, "status-utf8", 1); options_set_number(global_s_options, "status-utf8", 1);
options_set_number(&global_s_options, "mouse-utf8", 1); options_set_number(global_s_options, "mouse-utf8", 1);
options_set_number(&global_w_options, "utf8", 1); options_set_number(global_w_options, "utf8", 1);
} }
/* Override keys to vi if VISUAL or EDITOR are set. */ /* Override keys to vi if VISUAL or EDITOR are set. */
@ -314,8 +313,8 @@ main(int argc, char **argv)
keys = MODEKEY_VI; keys = MODEKEY_VI;
else else
keys = MODEKEY_EMACS; keys = MODEKEY_EMACS;
options_set_number(&global_s_options, "status-keys", keys); options_set_number(global_s_options, "status-keys", keys);
options_set_number(&global_w_options, "mode-keys", keys); options_set_number(global_w_options, "mode-keys", keys);
} }
/* /*
@ -355,11 +354,6 @@ main(int argc, char **argv)
} }
free(path); free(path);
#ifdef HAVE_SETPROCTITLE
/* Set process title. */
setproctitle("%s (%s)", __progname, socket_path);
#endif
/* Pass control to the client. */ /* Pass control to the client. */
exit(client_main(osdep_event_init(), argc, argv, flags)); exit(client_main(osdep_event_init(), argc, argv, flags));
} }

51
tmux.h
View File

@ -683,11 +683,6 @@ struct options_entry {
RB_ENTRY(options_entry) entry; RB_ENTRY(options_entry) entry;
}; };
struct options {
RB_HEAD(options_tree, options_entry) tree;
struct options *parent;
};
/* Scheduled job. */ /* Scheduled job. */
struct job { struct job {
enum { enum {
@ -869,6 +864,7 @@ TAILQ_HEAD(window_panes, window_pane);
RB_HEAD(window_pane_tree, window_pane); RB_HEAD(window_pane_tree, window_pane);
/* Window structure. */ /* Window structure. */
struct options;
struct window { struct window {
u_int id; u_int id;
@ -902,7 +898,7 @@ struct window {
#define WINDOW_FORCEHEIGHT 0x4000 #define WINDOW_FORCEHEIGHT 0x4000
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE) #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
struct options options; struct options *options;
u_int references; u_int references;
@ -996,7 +992,7 @@ struct session {
struct winlink_stack lastw; struct winlink_stack lastw;
struct winlinks windows; struct winlinks windows;
struct options options; struct options *options;
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */ #define SESSION_UNATTACHED 0x1 /* not attached to any clients */
int flags; int flags;
@ -1171,8 +1167,10 @@ struct message_entry {
}; };
/* Client connection. */ /* Client connection. */
struct tmuxproc;
struct tmuxpeer;
struct client { struct client {
struct imsgbuf ibuf; struct tmuxpeer *peer;
pid_t pid; pid_t pid;
int fd; int fd;
@ -1210,7 +1208,7 @@ struct client {
#define CLIENT_STATUS 0x10 #define CLIENT_STATUS 0x10
#define CLIENT_REPEAT 0x20 #define CLIENT_REPEAT 0x20
#define CLIENT_SUSPENDED 0x40 #define CLIENT_SUSPENDED 0x40
#define CLIENT_BAD 0x80 /* 0x80 unused */
#define CLIENT_IDENTIFY 0x100 #define CLIENT_IDENTIFY 0x100
#define CLIENT_DEAD 0x200 #define CLIENT_DEAD 0x200
#define CLIENT_BORDERS 0x400 #define CLIENT_BORDERS 0x400
@ -1406,9 +1404,9 @@ struct options_table_entry {
#define CMD_BUFFER_USAGE "[-b buffer-name]" #define CMD_BUFFER_USAGE "[-b buffer-name]"
/* tmux.c */ /* tmux.c */
extern struct options global_options; 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 char *shell_cmd;
extern int debug_level; extern int debug_level;
@ -1421,6 +1419,19 @@ int areshell(const char *);
void setblocking(int, int); void setblocking(int, int);
const char *find_home(void); const char *find_home(void);
/* proc.c */
struct imsg;
int proc_send(struct tmuxpeer *, enum msgtype, int, const void *, size_t);
int proc_send_s(struct tmuxpeer *, enum msgtype, const char *);
struct tmuxproc *proc_start(const char *, struct event_base *, int,
void (*)(int));
void proc_loop(struct tmuxproc *, int (*)(void));
void proc_exit(struct tmuxproc *);
struct tmuxpeer *proc_add_peer(struct tmuxproc *, int,
void (*)(struct imsg *, void *), void *);
void proc_remove_peer(struct tmuxpeer *);
void proc_kill_peer(struct tmuxpeer *);
/* cfg.c */ /* cfg.c */
extern int cfg_finished; extern int cfg_finished;
extern int cfg_references; extern int cfg_references;
@ -1497,10 +1508,10 @@ void notify_session_created(struct session *);
void notify_session_closed(struct session *); void notify_session_closed(struct session *);
/* options.c */ /* options.c */
int options_cmp(struct options_entry *, struct options_entry *); struct options *options_create(struct options *);
RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
void options_init(struct options *, struct options *);
void options_free(struct options *); void options_free(struct options *);
struct options_entry *options_first(struct options *);
struct options_entry *options_next(struct options_entry *);
struct options_entry *options_find1(struct options *, const char *); struct options_entry *options_find1(struct options *, const char *);
struct options_entry *options_find(struct options *, const char *); struct options_entry *options_find(struct options *, const char *);
void options_remove(struct options *, const char *); void options_remove(struct options *, const char *);
@ -1728,6 +1739,7 @@ void alerts_reset_all(void);
void alerts_queue(struct window *, int); void alerts_queue(struct window *, int);
/* server.c */ /* server.c */
extern struct tmuxproc *server_proc;
extern struct clients clients; extern struct clients clients;
extern struct session *marked_session; extern struct session *marked_session;
extern struct winlink *marked_winlink; extern struct winlink *marked_winlink;
@ -1749,16 +1761,10 @@ void server_client_create(int);
int server_client_open(struct client *, char **); int server_client_open(struct client *, char **);
void server_client_unref(struct client *); void server_client_unref(struct client *);
void server_client_lost(struct client *); void server_client_lost(struct client *);
void server_client_callback(int, short, void *);
void server_client_loop(void); void server_client_loop(void);
/* server-fn.c */ /* server-fn.c */
void server_fill_environ(struct session *, struct environ *); void server_fill_environ(struct session *, struct environ *);
void server_write_ready(struct client *);
int server_write_client(struct client *, enum msgtype, const void *,
size_t);
void server_write_session(struct session *, enum msgtype, const void *,
size_t);
void server_redraw_client(struct client *); void server_redraw_client(struct client *);
void server_status_client(struct client *); void server_status_client(struct client *);
void server_redraw_session(struct session *); void server_redraw_session(struct session *);
@ -1781,7 +1787,6 @@ void server_destroy_session(struct session *);
void server_check_unattached(void); void server_check_unattached(void);
void server_set_identify(struct client *); void server_set_identify(struct client *);
void server_clear_identify(struct client *); void server_clear_identify(struct client *);
void server_update_event(struct client *);
void server_push_stdout(struct client *); void server_push_stdout(struct client *);
void server_push_stderr(struct client *); void server_push_stderr(struct client *);
int server_set_stdin_callback(struct client *, void (*)(struct client *, int server_set_stdin_callback(struct client *, void (*)(struct client *,
@ -2111,7 +2116,7 @@ char *format_window_name(struct window *);
char *parse_window_name(const char *); char *parse_window_name(const char *);
/* signal.c */ /* signal.c */
void set_signals(void(*)(int, short, void *)); void set_signals(void(*)(int, short, void *), void *);
void clear_signals(int); void clear_signals(int);
/* control.c */ /* control.c */

View File

@ -564,7 +564,7 @@ partial_key:
} }
/* Get the time period. */ /* Get the time period. */
delay = options_get_number(&global_options, "escape-time"); delay = options_get_number(global_options, "escape-time");
tv.tv_sec = delay / 1000; tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L; tv.tv_usec = (delay % 1000) * 1000L;

View File

@ -460,7 +460,7 @@ tty_term_find(char *name, int fd, char **cause)
} }
/* Apply terminal overrides. */ /* Apply terminal overrides. */
s = options_get_string(&global_options, "terminal-overrides"); s = options_get_string(global_options, "terminal-overrides");
tty_term_override(term, s); tty_term_override(term, s);
/* Delete curses data. */ /* Delete curses data. */

8
tty.c
View File

@ -229,7 +229,7 @@ tty_start_tty(struct tty *tty)
tty_puts(tty, "\033[?1000l\033[?1002l\033[?1006l\033[?1005l"); tty_puts(tty, "\033[?1000l\033[?1002l\033[?1006l\033[?1005l");
if (tty_term_flag(tty->term, TTYC_XT)) { if (tty_term_flag(tty->term, TTYC_XT)) {
if (options_get_number(&global_options, "focus-events")) { if (options_get_number(global_options, "focus-events")) {
tty->flags |= TTY_FOCUS; tty->flags |= TTY_FOCUS;
tty_puts(tty, "\033[?1004h"); tty_puts(tty, "\033[?1004h");
} }
@ -457,7 +457,7 @@ tty_set_italics(struct tty *tty)
const char *s; const char *s;
if (tty_term_has(tty->term, TTYC_SITM)) { if (tty_term_has(tty->term, TTYC_SITM)) {
s = options_get_string(&global_options, "default-terminal"); s = options_get_string(global_options, "default-terminal");
if (strcmp(s, "screen") != 0 && strncmp(s, "screen-", 7) != 0) { if (strcmp(s, "screen") != 0 && strncmp(s, "screen-", 7) != 0) {
tty_putcode(tty, TTYC_SITM); tty_putcode(tty, TTYC_SITM);
return; return;
@ -1686,8 +1686,8 @@ tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
return; return;
pgc = &wp->colgc; pgc = &wp->colgc;
agc = options_get_style(&wp->window->options, "window-active-style"); agc = options_get_style(wp->window->options, "window-active-style");
wgc = options_get_style(&wp->window->options, "window-style"); wgc = options_get_style(wp->window->options, "window-style");
if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) { if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) {
if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) { if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) {

View File

@ -169,7 +169,7 @@ window_choose_init(struct window_pane *wp)
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
keys = options_get_number(&wp->window->options, "mode-keys"); keys = options_get_number(wp->window->options, "mode-keys");
if (keys == MODEKEY_EMACS) if (keys == MODEKEY_EMACS)
mode_key_init(&data->mdata, &mode_key_tree_emacs_choice); mode_key_init(&data->mdata, &mode_key_tree_emacs_choice);
else else
@ -748,7 +748,7 @@ window_choose_write_line(
{ {
struct window_choose_mode_data *data = wp->modedata; struct window_choose_mode_data *data = wp->modedata;
struct window_choose_mode_item *item; struct window_choose_mode_item *item;
struct options *oo = &wp->window->options; struct options *oo = wp->window->options;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct grid_cell gc; struct grid_cell gc;
size_t last, xoff = 0; size_t last, xoff = 0;
@ -759,7 +759,7 @@ window_choose_write_line(
fatalx("called before callback assigned"); fatalx("called before callback assigned");
last = screen_size_y(s) - 1; last = screen_size_y(s) - 1;
utf8flag = options_get_number(&wp->window->options, "utf8"); utf8flag = options_get_number(wp->window->options, "utf8");
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
if (data->selected == data->top + py) if (data->selected == data->top + py)
style_apply(&gc, oo, "mode-style"); style_apply(&gc, oo, "mode-style");

View File

@ -204,8 +204,8 @@ window_clock_draw_screen(struct window_pane *wp)
struct tm *tm; struct tm *tm;
u_int i, j, x, y, idx; u_int i, j, x, y, idx;
colour = options_get_number(&wp->window->options, "clock-mode-colour"); colour = options_get_number(wp->window->options, "clock-mode-colour");
style = options_get_number(&wp->window->options, "clock-mode-style"); style = options_get_number(wp->window->options, "clock-mode-style");
screen_write_start(&ctx, NULL, s); screen_write_start(&ctx, NULL, s);

View File

@ -195,7 +195,7 @@ window_copy_init(struct window_pane *wp)
s = &data->screen; s = &data->screen;
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
keys = options_get_number(&wp->window->options, "mode-keys"); keys = options_get_number(wp->window->options, "mode-keys");
if (keys == MODEKEY_EMACS) if (keys == MODEKEY_EMACS)
mode_key_init(&data->mdata, &mode_key_tree_emacs_copy); mode_key_init(&data->mdata, &mode_key_tree_emacs_copy);
else else
@ -286,7 +286,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
if (backing == &wp->base) if (backing == &wp->base)
return; return;
utf8flag = options_get_number(&wp->window->options, "utf8"); utf8flag = options_get_number(wp->window->options, "utf8");
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
old_hsize = screen_hsize(data->backing); old_hsize = screen_hsize(data->backing);
@ -629,13 +629,13 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
break; break;
case MODEKEYCOPY_NEXTWORD: case MODEKEYCOPY_NEXTWORD:
word_separators = word_separators =
options_get_string(&sess->options, "word-separators"); options_get_string(sess->options, "word-separators");
for (; np != 0; np--) for (; np != 0; np--)
window_copy_cursor_next_word(wp, word_separators); window_copy_cursor_next_word(wp, word_separators);
break; break;
case MODEKEYCOPY_NEXTWORDEND: case MODEKEYCOPY_NEXTWORDEND:
word_separators = word_separators =
options_get_string(&sess->options, "word-separators"); options_get_string(sess->options, "word-separators");
for (; np != 0; np--) for (; np != 0; np--)
window_copy_cursor_next_word_end(wp, word_separators); window_copy_cursor_next_word_end(wp, word_separators);
break; break;
@ -645,7 +645,7 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
break; break;
case MODEKEYCOPY_PREVIOUSWORD: case MODEKEYCOPY_PREVIOUSWORD:
word_separators = word_separators =
options_get_string(&sess->options, "word-separators"); options_get_string(sess->options, "word-separators");
for (; np != 0; np--) for (; np != 0; np--)
window_copy_cursor_previous_word(wp, word_separators); window_copy_cursor_previous_word(wp, word_separators);
break; break;
@ -777,7 +777,7 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
return; return;
input_on: input_on:
keys = options_get_number(&wp->window->options, "mode-keys"); keys = options_get_number(wp->window->options, "mode-keys");
if (keys == MODEKEY_EMACS) if (keys == MODEKEY_EMACS)
mode_key_init(&data->mdata, &mode_key_tree_emacs_edit); mode_key_init(&data->mdata, &mode_key_tree_emacs_edit);
else else
@ -787,7 +787,7 @@ input_on:
return; return;
input_off: input_off:
keys = options_get_number(&wp->window->options, "mode-keys"); keys = options_get_number(wp->window->options, "mode-keys");
if (keys == MODEKEY_EMACS) if (keys == MODEKEY_EMACS)
mode_key_init(&data->mdata, &mode_key_tree_emacs_copy); mode_key_init(&data->mdata, &mode_key_tree_emacs_copy);
else else
@ -1026,8 +1026,8 @@ window_copy_search_up(struct window_pane *wp, const char *searchstr)
if (*searchstr == '\0') if (*searchstr == '\0')
return; return;
utf8flag = options_get_number(&wp->window->options, "utf8"); utf8flag = options_get_number(wp->window->options, "utf8");
wrapflag = options_get_number(&wp->window->options, "wrap-search"); wrapflag = options_get_number(wp->window->options, "wrap-search");
searchlen = screen_write_strlen(utf8flag, "%s", searchstr); searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
screen_init(&ss, searchlen, 1, 0); screen_init(&ss, searchlen, 1, 0);
@ -1093,8 +1093,8 @@ window_copy_search_down(struct window_pane *wp, const char *searchstr)
if (*searchstr == '\0') if (*searchstr == '\0')
return; return;
utf8flag = options_get_number(&wp->window->options, "utf8"); utf8flag = options_get_number(wp->window->options, "utf8");
wrapflag = options_get_number(&wp->window->options, "wrap-search"); wrapflag = options_get_number(wp->window->options, "wrap-search");
searchlen = screen_write_strlen(utf8flag, "%s", searchstr); searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
screen_init(&ss, searchlen, 1, 0); screen_init(&ss, searchlen, 1, 0);
@ -1168,7 +1168,7 @@ window_copy_write_line(struct window_pane *wp, struct screen_write_ctx *ctx,
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct options *oo = &wp->window->options; struct options *oo = wp->window->options;
struct grid_cell gc; struct grid_cell gc;
char hdr[512]; char hdr[512];
size_t last, xoff = 0, size = 0, limit; size_t last, xoff = 0, size = 0, limit;
@ -1301,7 +1301,7 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct options *oo = &wp->window->options; struct options *oo = wp->window->options;
struct grid_cell gc; struct grid_cell gc;
u_int sx, sy, ty, cy; u_int sx, sy, ty, cy;
@ -1401,7 +1401,7 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
* bottom-right-most, regardless of copy direction. If it is vi, also * bottom-right-most, regardless of copy direction. If it is vi, also
* keep bottom-right-most character. * keep bottom-right-most character.
*/ */
keys = options_get_number(&wp->window->options, "mode-keys"); keys = options_get_number(wp->window->options, "mode-keys");
if (data->rectflag) { if (data->rectflag) {
/* /*
* Need to ignore the column with the cursor in it, which for * Need to ignore the column with the cursor in it, which for
@ -1460,7 +1460,7 @@ window_copy_copy_buffer(struct window_pane *wp, const char *bufname, void *buf,
{ {
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
if (options_get_number(&global_options, "set-clipboard")) { if (options_get_number(global_options, "set-clipboard")) {
screen_write_start(&ctx, wp, NULL); screen_write_start(&ctx, wp, NULL);
screen_write_setselection(&ctx, buf, len); screen_write_setselection(&ctx, buf, len);
screen_write_stop(&ctx); screen_write_stop(&ctx);
@ -1523,7 +1523,7 @@ window_copy_append_selection(struct window_pane *wp, const char *bufname)
if (buf == NULL) if (buf == NULL)
return; return;
if (options_get_number(&global_options, "set-clipboard")) { if (options_get_number(global_options, "set-clipboard")) {
screen_write_start(&ctx, wp, NULL); screen_write_start(&ctx, wp, NULL);
screen_write_setselection(&ctx, buf, len); screen_write_setselection(&ctx, buf, len);
screen_write_stop(&ctx); screen_write_stop(&ctx);
@ -2074,7 +2074,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp,
const char *separators) const char *separators)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct options *oo = &wp->window->options; struct options *oo = wp->window->options;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
u_int px, py, xx, yy; u_int px, py, xx, yy;
int keys, expected = 1; int keys, expected = 1;

View File

@ -301,7 +301,7 @@ window_create1(u_int sx, u_int sy)
w->sx = sx; w->sx = sx;
w->sy = sy; w->sy = sy;
options_init(&w->options, &global_w_options); w->options = options_create(global_w_options);
w->references = 0; w->references = 0;
@ -334,7 +334,7 @@ window_create(const char *name, int argc, char **argv, const char *path,
w->active = TAILQ_FIRST(&w->panes); w->active = TAILQ_FIRST(&w->panes);
if (name != NULL) { if (name != NULL) {
w->name = xstrdup(name); w->name = xstrdup(name);
options_set_number(&w->options, "automatic-rename", 0); options_set_number(w->options, "automatic-rename", 0);
} else } else
w->name = default_window_name(w); w->name = default_window_name(w);
@ -358,7 +358,7 @@ window_destroy(struct window *w)
if (event_initialized(&w->alerts_timer)) if (event_initialized(&w->alerts_timer))
evtimer_del(&w->alerts_timer); evtimer_del(&w->alerts_timer);
options_free(&w->options); options_free(w->options);
window_destroy_panes(w); window_destroy_panes(w);
@ -436,8 +436,8 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
* active or inactive pane do not have a custom style, they will need * active or inactive pane do not have a custom style, they will need
* to be redrawn. * to be redrawn.
*/ */
agc = options_get_style(&w->options, "window-active-style"); agc = options_get_style(w->options, "window-active-style");
wgc = options_get_style(&w->options, "window-style"); wgc = options_get_style(w->options, "window-style");
if (style_equal(agc, wgc)) if (style_equal(agc, wgc))
return; return;
if (style_equal(&grid_default_cell, &w->active->colgc)) if (style_equal(&grid_default_cell, &w->active->colgc))
@ -597,7 +597,7 @@ window_pane_at_index(struct window *w, u_int idx)
struct window_pane *wp; struct window_pane *wp;
u_int n; u_int n;
n = options_get_number(&w->options, "pane-base-index"); n = options_get_number(w->options, "pane-base-index");
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (n == idx) if (n == idx)
return (wp); return (wp);
@ -635,7 +635,7 @@ window_pane_index(struct window_pane *wp, u_int *i)
struct window_pane *wq; struct window_pane *wq;
struct window *w = wp->window; struct window *w = wp->window;
*i = options_get_number(&w->options, "pane-base-index"); *i = options_get_number(w->options, "pane-base-index");
TAILQ_FOREACH(wq, &w->panes, entry) { TAILQ_FOREACH(wq, &w->panes, entry) {
if (wp == wq) { if (wp == wq) {
return (0); return (0);
@ -861,7 +861,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
memcpy(tio2.c_cc, tio->c_cc, sizeof tio2.c_cc); memcpy(tio2.c_cc, tio->c_cc, sizeof tio2.c_cc);
tio2.c_cc[VERASE] = '\177'; tio2.c_cc[VERASE] = '\177';
#ifdef IUTF8 #ifdef IUTF8
if (options_get_number(&wp->window->options, "utf8")) if (options_get_number(wp->window->options, "utf8"))
tio2.c_iflag |= IUTF8; tio2.c_iflag |= IUTF8;
#endif #endif
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0) if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
@ -1016,7 +1016,7 @@ window_pane_alternate_on(struct window_pane *wp, struct grid_cell *gc,
if (wp->saved_grid != NULL) if (wp->saved_grid != NULL)
return; return;
if (!options_get_number(&wp->window->options, "alternate-screen")) if (!options_get_number(wp->window->options, "alternate-screen"))
return; return;
sx = screen_size_x(s); sx = screen_size_x(s);
sy = screen_size_y(s); sy = screen_size_y(s);
@ -1046,7 +1046,7 @@ window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc,
if (wp->saved_grid == NULL) if (wp->saved_grid == NULL)
return; return;
if (!options_get_number(&wp->window->options, "alternate-screen")) if (!options_get_number(wp->window->options, "alternate-screen"))
return; return;
sx = screen_size_x(s); sx = screen_size_x(s);
sy = screen_size_y(s); sy = screen_size_y(s);
@ -1134,7 +1134,7 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
if (KEYC_IS_MOUSE(key)) if (KEYC_IS_MOUSE(key))
return; return;
if (options_get_number(&wp->window->options, "synchronize-panes")) { if (options_get_number(wp->window->options, "synchronize-panes")) {
TAILQ_FOREACH(wp2, &wp->window->panes, entry) { TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (wp2 == wp || wp2->mode != NULL) if (wp2 == wp || wp2->mode != NULL)
continue; continue;