summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2015-09-06 20:47:50 +0100
committerThomas Adam <thomas@xteddy.org>2015-09-06 20:47:50 +0100
commit76688d204071b76fd3388e46e944e4b917c09625 (patch)
treeb6c7920003106991bbb8db46a432e47b16429c94
parent2ebef95994953e49ae84862a65f9ee649a72e200 (diff)
parentaceae73b9a401c0b124a3534079e9c0d998f0dbd (diff)
Merge branch 'obsd-master'
Conflicts: cfg.c tmux.c
-rw-r--r--alerts.c4
-rw-r--r--cfg.c60
-rw-r--r--client.c77
-rw-r--r--cmd-wait-for.c105
-rw-r--r--cmd.c87
-rw-r--r--format.c3
-rw-r--r--grid.c46
-rw-r--r--input.c8
-rw-r--r--log.c16
-rw-r--r--server-client.c2
-rw-r--r--server.c27
-rw-r--r--session.c2
-rw-r--r--tmux.c94
-rw-r--r--tmux.h106
-rw-r--r--tty-keys.c69
-rw-r--r--tty-term.c1
-rw-r--r--tty.c15
17 files changed, 347 insertions, 375 deletions
diff --git a/alerts.c b/alerts.c
index cfdd30e3..5d52f7ad 100644
--- a/alerts.c
+++ b/alerts.c
@@ -174,7 +174,7 @@ alerts_check_bell(struct session *s, struct winlink *wl)
(action == BELL_OTHER &&
c->session->curw->window != w) ||
action == BELL_ANY)
- tty_bell(&c->tty);
+ tty_putcode(&c->tty, TTYC_BEL);
continue;
}
if (action == BELL_CURRENT && c->session->curw->window == w)
@@ -258,6 +258,6 @@ alerts_ring_bell(struct session *s)
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == s && !(c->flags & CLIENT_CONTROL))
- tty_bell(&c->tty);
+ tty_putcode(&c->tty, TTYC_BEL);
}
}
diff --git a/cfg.c b/cfg.c
index 70c69027..ecb38fc0 100644
--- a/cfg.c
+++ b/cfg.c
@@ -23,15 +23,63 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <util.h>
#include "tmux.h"
-struct cmd_q *cfg_cmd_q;
-int cfg_finished;
-int cfg_references;
-char **cfg_causes;
-u_int cfg_ncauses;
-struct client *cfg_client;
+char *cfg_file;
+struct cmd_q *cfg_cmd_q;
+int cfg_finished;
+int cfg_references;
+char **cfg_causes;
+u_int cfg_ncauses;
+struct client *cfg_client;
+
+void cfg_default_done(struct cmd_q *);
+
+void
+set_cfg_file(const char *path)
+{
+ free(cfg_file);
+ cfg_file = xstrdup(path);
+}
+
+void
+start_cfg(void)
+{
+ char *cause = NULL;
+ const char *home;
+
+ cfg_cmd_q = cmdq_new(NULL);
+ cfg_cmd_q->emptyfn = cfg_default_done;
+
+ cfg_finished = 0;
+ cfg_references = 1;
+
+ cfg_client = TAILQ_FIRST(&clients);
+ if (cfg_client != NULL)
+ cfg_client->references++;
+
+ if (access(TMUX_CONF, R_OK) == 0) {
+ if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1)
+ cfg_add_cause("%s: %s", TMUX_CONF, cause);
+ } else if (errno != ENOENT)
+ cfg_add_cause("%s: %s", TMUX_CONF, strerror(errno));
+
+ if (cfg_file == NULL && (home = find_home()) != NULL) {
+ xasprintf(&cfg_file, "%s/.tmux.conf", home);
+ if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
+ free(cfg_file);
+ cfg_file = NULL;
+ }
+ }
+ if (cfg_file != NULL && load_cfg(cfg_file, cfg_cmd_q, &cause) == -1)
+ cfg_add_cause("%s: %s", cfg_file, cause);
+ free(cause);
+
+ cmdq_continue(cfg_cmd_q);
+}
int
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
diff --git a/client.c b/client.c
index 9a5ae455..ef560668 100644
--- a/client.c
+++ b/client.c
@@ -33,6 +33,7 @@
#include "tmux.h"
+int client_flags;
struct imsgbuf client_ibuf;
struct event client_event;
struct event client_stdin;
@@ -51,9 +52,10 @@ enum msgtype client_exittype;
const char *client_exitsession;
int client_attached;
+__dead void client_exec(const char *);
int client_get_lock(char *);
-int client_connect(char *, int);
-void client_send_identify(int);
+int client_connect(struct event_base *, char *, int);
+void client_send_identify(void);
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);
@@ -62,7 +64,7 @@ void client_stdin_callback(int, short, void *);
void client_write(int, const char *, size_t);
void client_callback(int, short, void *);
int client_dispatch_attached(void);
-int client_dispatch_wait(void *);
+int client_dispatch_wait(void);
const char *client_exit_message(void);
/*
@@ -96,7 +98,7 @@ client_get_lock(char *lockfile)
/* Connect client to server. */
int
-client_connect(char *path, int start_server)
+client_connect(struct event_base *base, char *path, int start_server)
{
struct sockaddr_un sa;
size_t size;
@@ -149,7 +151,7 @@ retry:
close(lockfd);
return (-1);
}
- fd = server_start(lockfd, lockfile);
+ fd = server_start(base, lockfd, lockfile);
}
if (locked) {
free(lockfile);
@@ -203,7 +205,7 @@ client_exit_message(void)
/* Client main loop. */
int
-client_main(int argc, char **argv, int flags)
+client_main(struct event_base *base, int argc, char **argv, int flags)
{
struct cmd *cmd;
struct cmd_list *cmdlist;
@@ -215,6 +217,9 @@ client_main(int argc, char **argv, int flags)
struct termios tio, saved_tio;
size_t size;
+ /* Save the flags. */
+ client_flags = flags;
+
/* Set up the initial command. */
cmdflags = 0;
if (shell_cmd != NULL) {
@@ -248,7 +253,7 @@ client_main(int argc, char **argv, int flags)
set_signals(client_signal);
/* Initialize the client socket and start the server. */
- fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
+ fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
if (fd == -1) {
if (errno == ECONNREFUSED) {
fprintf(stderr, "no server running on %s\n",
@@ -268,13 +273,13 @@ client_main(int argc, char **argv, int flags)
/* Create imsg. */
imsg_init(&client_ibuf, fd);
- event_set(&client_event, fd, EV_READ, client_callback, shell_cmd);
+ event_set(&client_event, fd, EV_READ, client_callback, NULL);
/* Create stdin handler. */
setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
client_stdin_callback, NULL);
- if (flags & CLIENT_CONTROLCONTROL) {
+ if (client_flags & CLIENT_CONTROLCONTROL) {
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
fprintf(stderr, "tcgetattr failed: %s\n",
strerror(errno));
@@ -295,7 +300,7 @@ client_main(int argc, char **argv, int flags)
}
/* Send identify messages. */
- client_send_identify(flags);
+ client_send_identify();
/* Send first command. */
if (msg == MSG_COMMAND) {
@@ -330,13 +335,13 @@ client_main(int argc, char **argv, int flags)
/* Print the exit message, if any, and exit. */
if (client_attached) {
- if (client_exitreason != CLIENT_EXIT_NONE && !login_shell)
+ if (client_exitreason != CLIENT_EXIT_NONE)
printf("[%s]\n", client_exit_message());
ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP);
- } else if (flags & CLIENT_CONTROLCONTROL) {
+ } else if (client_flags & CLIENT_CONTROLCONTROL) {
if (client_exitreason != CLIENT_EXIT_NONE)
printf("%%exit %s\n", client_exit_message());
else
@@ -350,12 +355,12 @@ client_main(int argc, char **argv, int flags)
/* Send identify messages to server. */
void
-client_send_identify(int flags)
+client_send_identify(void)
{
const char *s;
char **ss;
size_t sslen;
- int fd;
+ int fd, flags = client_flags;
pid_t pid;
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
@@ -425,14 +430,13 @@ client_update_event(void)
events = EV_READ;
if (client_ibuf.w.queued > 0)
events |= EV_WRITE;
- event_set(
- &client_event, client_ibuf.fd, events, client_callback, shell_cmd);
+ 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 *data)
+client_signal(int sig, unused short events, unused void *arg)
{
struct sigaction sigact;
int status;
@@ -474,7 +478,7 @@ client_signal(int sig, unused short events, unused void *data)
/* Callback for client imsg read events. */
void
-client_callback(unused int fd, short events, void *data)
+client_callback(unused int fd, short events, unused void *arg)
{
ssize_t n;
int retval;
@@ -485,7 +489,7 @@ client_callback(unused int fd, short events, void *data)
if (client_attached)
retval = client_dispatch_attached();
else
- retval = client_dispatch_wait(data);
+ retval = client_dispatch_wait();
if (retval != 0) {
event_loopexit(NULL);
return;
@@ -508,7 +512,7 @@ lost_server:
/* Callback for client stdin read events. */
void
-client_stdin_callback(unused int fd, unused short events, unused void *data1)
+client_stdin_callback(unused int fd, unused short events, unused void *arg)
{
struct msg_stdin_data data;
@@ -540,9 +544,38 @@ client_write(int fd, const char *data, size_t size)
}
}
+/* Run command in shell; used for -c. */
+__dead void
+client_exec(const char *shell)
+{
+ const char *name, *ptr;
+ char *argv0;
+
+ log_debug("shell %s, command %s", shell, shell_cmd);
+
+ ptr = strrchr(shell, '/');
+ if (ptr != NULL && *(ptr + 1) != '\0')
+ name = ptr + 1;
+ else
+ name = shell;
+ if (client_flags & CLIENT_LOGIN)
+ xasprintf(&argv0, "-%s", name);
+ else
+ xasprintf(&argv0, "%s", name);
+ setenv("SHELL", shell, 1);
+
+ setblocking(STDIN_FILENO, 1);
+ setblocking(STDOUT_FILENO, 1);
+ setblocking(STDERR_FILENO, 1);
+ closefrom(STDERR_FILENO + 1);
+
+ execl(shell, argv0, "-c", shell_cmd, (char *) NULL);
+ fatal("execl failed");
+}
+
/* Dispatch imsgs when in wait state (before MSG_READY). */
int
-client_dispatch_wait(void *data0)
+client_dispatch_wait(void)
{
struct imsg imsg;
char *data;
@@ -618,7 +651,7 @@ client_dispatch_wait(void *data0)
fatalx("bad MSG_SHELL string");
clear_signals(0);
- shell_exec(data, data0);
+ client_exec(data);
/* NOTREACHED */
case MSG_DETACH:
case MSG_DETACHKILL:
diff --git a/cmd-wait-for.c b/cmd-wait-for.c
index a3e85856..0dce438b 100644
--- a/cmd-wait-for.c
+++ b/cmd-wait-for.c
@@ -41,6 +41,7 @@ const struct cmd_entry cmd_wait_for_entry = {
struct wait_channel {
const char *name;
int locked;
+ int woken;
TAILQ_HEAD(, cmd_q) waiters;
TAILQ_HEAD(, cmd_q) lockers;
@@ -69,8 +70,49 @@ enum cmd_retval cmd_wait_for_lock(struct cmd_q *, const char *,
enum cmd_retval cmd_wait_for_unlock(struct cmd_q *, const char *,
struct wait_channel *);
+struct wait_channel *cmd_wait_for_add(const char *);
+void cmd_wait_for_remove(struct wait_channel *wc);
+
+struct wait_channel *
+cmd_wait_for_add(const char *name)
+{
+ struct wait_channel *wc;
+
+ wc = xmalloc(sizeof *wc);
+ wc->name = xstrdup(name);
+
+ wc->locked = 0;
+ wc->woken = 0;
+
+ TAILQ_INIT(&wc->waiters);
+ TAILQ_INIT(&wc->lockers);
+
+ RB_INSERT(wait_channels, &wait_channels, wc);
+
+ log_debug("add wait channel %s", wc->name);
+
+ return (wc);
+}
+
+void
+cmd_wait_for_remove(struct wait_channel *wc)
+{
+
+ if (wc->locked)
+ return;
+ if (!TAILQ_EMPTY(&wc->waiters) || !wc->woken)
+ return;
+
+ log_debug("remove wait channel %s", wc->name);
+
+ RB_REMOVE(wait_channels, &wait_channels, wc);
+
+ free((void *)wc->name);
+ free(wc);
+}
+
enum cmd_retval
-cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
+cmd_wait_for_exec(struct cmd *self, unused struct cmd_q *cmdq)
{
struct args *args = self->args;
const char *name = args->argv[0];
@@ -89,15 +131,20 @@ cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
-cmd_wait_for_signal(struct cmd_q *cmdq, const char *name,
+cmd_wait_for_signal(unused struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
struct cmd_q *wq, *wq1;
- if (wc == NULL || TAILQ_EMPTY(&wc->waiters)) {
- cmdq_error(cmdq, "no waiting clients on %s", name);
- return (CMD_RETURN_ERROR);
+ if (wc == NULL)
+ wc = cmd_wait_for_add(name);
+
+ if (TAILQ_EMPTY(&wc->waiters) && !wc->woken) {
+ log_debug("signal wait channel %s, no waiters", wc->name);
+ wc->woken = 1;
+ return (CMD_RETURN_NORMAL);
}
+ log_debug("signal wait channel %s, with waiters", wc->name);
TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
TAILQ_REMOVE(&wc->waiters, wq, waitentry);
@@ -105,12 +152,7 @@ cmd_wait_for_signal(struct cmd_q *cmdq, const char *name,
cmdq_continue(wq);
}
- if (!wc->locked) {
- RB_REMOVE(wait_channels, &wait_channels, wc);
- free((void *)wc->name);
- free(wc);
- }
-
+ cmd_wait_for_remove(wc);
return (CMD_RETURN_NORMAL);
}
@@ -118,19 +160,23 @@ enum cmd_retval
cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
- if (cmdq->client == NULL || cmdq->client->session != NULL) {
+ struct client *c = cmdq->client;
+
+ if (c == NULL || c->session != NULL) {
cmdq_error(cmdq, "not able to wait");
return (CMD_RETURN_ERROR);
}
- if (wc == NULL) {
- wc = xmalloc(sizeof *wc);
- wc->name = xstrdup(name);
- wc->locked = 0;
- TAILQ_INIT(&wc->waiters);
- TAILQ_INIT(&wc->lockers);
- RB_INSERT(wait_channels, &wait_channels, wc);
+ if (wc == NULL)
+ wc = cmd_wait_for_add(name);
+
+ if (wc->woken) {
+ log_debug("wait channel %s already woken (client %d)", wc->name,
+ c->tty.fd);
+ cmd_wait_for_remove(wc);
+ return (CMD_RETURN_NORMAL);
}
+ log_debug("wait channel %s not woken (client %d)", wc->name, c->tty.fd);
TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry);
cmdq->references++;
@@ -147,14 +193,8 @@ cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
return (CMD_RETURN_ERROR);
}
- if (wc == NULL) {
- wc = xmalloc(sizeof *wc);
- wc->name = xstrdup(name);
- wc->locked = 0;
- TAILQ_INIT(&wc->waiters);
- TAILQ_INIT(&wc->lockers);
- RB_INSERT(wait_channels, &wait_channels, wc);
- }
+ if (wc == NULL)
+ wc = cmd_wait_for_add(name);
if (wc->locked) {
TAILQ_INSERT_TAIL(&wc->lockers, cmdq, waitentry);
@@ -183,11 +223,7 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
cmdq_continue(wq);
} else {
wc->locked = 0;
- if (TAILQ_EMPTY(&wc->waiters)) {
- RB_REMOVE(wait_channels, &wait_channels, wc);
- free((void *)wc->name);
- free(wc);
- }
+ cmd_wait_for_remove(wc);
}
return (CMD_RETURN_NORMAL);
@@ -210,8 +246,7 @@ cmd_wait_for_flush(void)
if (!cmdq_free(wq))
cmdq_continue(wq);
}
- RB_REMOVE(wait_channels, &wait_channels, wc);
- free((void *)wc->name);
- free(wc);
+ wc->locked = 0;
+ cmd_wait_for_remove(wc);
}
}
diff --git a/cmd.c b/cmd.c
index 14d69a76..badfcb4a 100644
--- a/cmd.c
+++ b/cmd.c
@@ -27,6 +27,93 @@
#include "tmux.h"
+extern const struct cmd_entry cmd_attach_session_entry;
+extern const struct cmd_entry cmd_bind_key_entry;
+extern const struct cmd_entry cmd_break_pane_entry;
+extern const struct cmd_entry cmd_capture_pane_entry;
+extern const struct cmd_entry cmd_choose_buffer_entry;
+extern const struct cmd_entry cmd_choose_client_entry;
+extern const struct cmd_entry cmd_choose_session_entry;
+extern const struct cmd_entry cmd_choose_tree_entry;
+extern const struct cmd_entry cmd_choose_window_entry;
+extern const struct cmd_entry cmd_clear_history_entry;
+extern const struct cmd_entry cmd_clock_mode_entry;
+extern const struct cmd_entry cmd_command_prompt_entry;
+extern const struct cmd_entry cmd_confirm_before_entry;
+extern const struct cmd_entry cmd_copy_mode_entry;
+extern const struct cmd_entry cmd_delete_buffer_entry;
+extern const struct cmd_entry cmd_detach_client_entry;
+extern const struct cmd_entry cmd_display_message_entry;
+extern const struct cmd_entry cmd_display_panes_entry;
+extern const struct cmd_entry cmd_down_pane_entry;
+extern const struct cmd_entry cmd_find_window_entry;
+extern const struct cmd_entry cmd_has_session_entry;
+extern const struct cmd_entry cmd_if_shell_entry;
+extern const struct cmd_entry cmd_join_pane_entry;
+extern const struct cmd_entry cmd_kill_pane_entry;
+extern const struct cmd_entry cmd_kill_server_entry;
+extern const struct cmd_entry cmd_kill_session_entry;
+extern const struct cmd_entry cmd_kill_window_entry;
+extern const struct cmd_entry cmd_last_pane_entry;
+extern const struct cmd_entry cmd_last_window_entry;
+extern const struct cmd_entry cmd_link_window_entry;
+extern const struct cmd_entry cmd_list_buffers_entry;
+extern const struct cmd_entry cmd_list_clients_entry;
+extern const struct cmd_entry cmd_list_commands_entry;
+extern const struct cmd_entry cmd_list_keys_entry;
+extern const struct cmd_entry cmd_list_panes_entry;
+extern const struct cmd_entry cmd_list_sessions_entry;
+extern const struct cmd_entry cmd_list_windows_entry;
+extern const struct cmd_entry cmd_load_buffer_entry;
+extern const struct cmd_entry cmd_lock_client_entry;
+extern const struct cmd_entry cmd_lock_server_entry;
+extern const struct cmd_entry cmd_lock_session_entry;
+extern const struct cmd_entry cmd_move_pane_entry;
+extern const struct cmd_entry cmd_move_window_entry;
+extern const struct cmd_entry cmd_new_session_entry;
+extern const struct cmd_entry cmd_new_window_entry;
+extern const struct cmd_entry cmd_next_layout_entry;
+extern const struct cmd_entry cmd_next_window_entry;
+extern const struct cmd_entry cmd_paste_buffer_entry;
+extern const struct cmd_entry cmd_pipe_pane_entry;
+extern const struct cmd_entry cmd_previous_layout_entry;
+extern const struct cmd_entry cmd_previous_window_entry;
+extern const struct cmd_entry cmd_refresh_client_entry;
+extern const struct cmd_entry cmd_rename_session_entry;
+extern const struct cmd_entry cmd_rename_window_entry;
+extern const struct cmd_entry cmd_resize_pane_entry;
+extern const struct cmd_entry cmd_respawn_pane_entry;
+extern const struct cmd_entry cmd_respawn_window_entry;
+extern const struct cmd_entry cmd_rotate_window_entry;
+extern const struct cmd_entry cmd_run_shell_entry;
+extern const struct cmd_entry cmd_save_buffer_entry;
+extern const struct cmd_entry cmd_select_layout_entry;
+extern const struct cmd_entry cmd_select_pane_entry;
+extern const struct cmd_entry cmd_select_window_entry;
+extern const struct cmd_entry cmd_send_keys_entry;
+extern const struct cmd_entry cmd_send_prefix_entry;
+extern const struct cmd_entry cmd_server_info_entry;
+extern const struct cmd_entry cmd_set_buffer_entry;
+extern const struct cmd_entry cmd_set_environment_entry;
+extern const struct cmd_entry cmd_set_option_entry;
+extern const struct cmd_entry cmd_set_window_option_entry;
+extern const struct cmd_entry cmd_show_buffer_entry;
+extern const struct cmd_entry cmd_show_environment_entry;
+extern const struct cmd_entry cmd_show_messages_entry;
+extern const struct cmd_entry cmd_show_options_entry;
+extern const struct cmd_entry cmd_show_window_options_entry;
+extern const struct cmd_entry cmd_source_file_entry;
+extern const struct cmd_entry cmd_split_window_entry;
+extern const struct cmd_entry cmd_start_server_entry;
+extern const struct cmd_entry cmd_suspend_client_entry;
+extern const struct cmd_entry cmd_swap_pane_entry;
+extern const struct cmd_entry cmd_swap_window_entry;
+extern const struct cmd_entry cmd_switch_client_entry;
+extern const struct cmd_entry cmd_unbind_key_entry;
+extern const struct cmd_entry cmd_unlink_window_entry;
+extern const struct cmd_entry cmd_up_pane_entry;
+extern const struct cmd_entry cmd_wait_for_entry;
+
const struct cmd_entry *cmd_table[] = {
&cmd_attach_session_entry,
&cmd_bind_key_entry,
diff --git a/format.c b/format.c
index bbb172af..643b035f 100644
--- a/format.c
+++ b/format.c
@@ -220,8 +220,7 @@ format_job_get(struct format_tree *ft, const char *cmd)
struct format_job fj0, *fj;
fj0.cmd = cmd;
- if ((fj = RB_FIND(format_job_tree, &format_jobs, &fj0)) == NULL)
- {
+ if ((fj = RB_FIND(format_job_tree, &format_jobs, &fj0)) == NULL) {
fj = xcalloc(1, sizeof *fj);
fj->cmd = xstrdup(cmd);
fj->status = ft->status;
diff --git a/grid.c b/grid.c
index c339cdc5..93fed05e 100644
--- a/grid.c
+++ b/grid.c
@@ -395,29 +395,29 @@ grid_string_cells_fg(const struct grid_cell *gc, int *values)
values[n++] = gc->fg;
} else {
switch (gc->fg) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- values[n++] = gc->fg + 30;
- break;
- case 8:
- values[n++] = 39;
- break;
- case 90:
- case 91:
- case 92:
- case 93:
- case 94:
- case 95:
- case 96:
- case 97:
- values[n++] = gc->fg;
- break;
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ values[n++] = gc->fg + 30;
+ break;
+ case 8:
+ values[n++] = 39;
+ break;
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ values[n++] = gc->fg;
+ break;
}
}
return (n);
diff --git a/input.c b/input.c
index cfe6b4af..ab56fc38 100644
--- a/input.c
+++ b/input.c
@@ -862,10 +862,12 @@ input_parse(struct window_pane *wp)
notify_input(wp, evb);
off = 0;
+ log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
+ ictx->state->name, len, (int)len, buf);
+
/* Parse the input. */
while (off < len) {
ictx->ch = buf[off++];
- log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
/* Find the transition. */
itr = ictx->state->transitions;
@@ -876,7 +878,7 @@ input_parse(struct window_pane *wp)
}
if (itr->first == -1 || itr->last == -1) {
/* No transition? Eh? */
- fatalx("No transition from state!");
+ fatalx("no transition from state");
}
/*
@@ -1070,7 +1072,7 @@ input_c0_dispatch(struct input_ctx *ictx)
struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s;
- log_debug("%s: '%c", __func__, ictx->ch);
+ log_debug("%s: '%c'", __func__, ictx->ch);
switch (ictx->ch) {
case '\000': /* NUL */
diff --git a/log.c b/log.c
index 2fe12a17..2acc6f0e 100644
--- a/log.c
+++ b/log.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <vis.h>
#include "tmux.h"
@@ -67,19 +68,24 @@ log_close(void)
void
log_vwrite(const char *msg, va_list ap)
{
- char *fmt;
+ char *fmt, *out;
struct timeval tv;
if (log_file == NULL)
return;
- gettimeofday(&tv, NULL);
- if (asprintf(&fmt, "%lld.%06d %s\n", (long long)tv.tv_sec,
- (int)tv.tv_usec, msg) == -1)
+ if (vasprintf(&fmt, msg, ap) == -1)
exit(1);
- if (vfprintf(log_file, fmt, ap) == -1)
+ if (stravis(&out, fmt, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1)
+ exit(1);
+
+ gettimeofday(&tv, NULL);
+ if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec,
+ (int)tv.tv_usec, out) == -1)
exit(1);
fflush(log_file);
+
+ free(out);
free(fmt);
}
diff --git a/server-client.c b/server-client.c
index 632c5f99..c63c11d1 100644
--- a/server-client.c
+++ b/server-client.c
@@ -1069,7 +1069,7 @@ server_client_msg_dispatch(struct client *c)
s = c->session;
if (gettimeofday(&c->activity_time, NULL) != 0)
- fatal("gettimeofday");
+ fatal("gettimeofday failed");
if (s != NULL)
session_update_activity(s, &c->activity_time);
diff --git a/server.c b/server.c
index 2a888f22..ed7c83ec 100644
--- a/server.c
+++ b/server.c
@@ -157,10 +157,9 @@ server_create_socket(void)
/* Fork new server. */
int
-server_start(int lockfd, char *lockfile)
+server_start(struct event_base *base, int lockfd, char *lockfile)
{
- int pair[2];
- char *cause;
+ int pair[2];
/* The first client is special and gets a socketpair; create it. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
@@ -187,7 +186,7 @@ server_start(int lockfd, char *lockfile)
/* event_init() was called in our parent, need to reinit. */
clear_signals(0);
- if (event_reinit(ev_base) != 0)
+ if (event_reinit(base) != 0)
fatal("event_reinit failed");
logfile("server");
@@ -218,24 +217,8 @@ server_start(int lockfd, char *lockfile)
free(lockfile);
close(lockfd);
- cfg_cmd_q = cmdq_new(NULL);
- cfg_cmd_q->emptyfn = cfg_default_done;
- cfg_finished = 0;
- cfg_references = 1;
- cfg_client = TAILQ_FIRST(&clients);
- if (cfg_client != NULL)
- cfg_client->references++;
-
- if (access(TMUX_CONF, R_OK) == 0) {
- if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1)
- cfg_add_cause("%s: %s", TMUX_CONF, cause);
- } else if (errno != ENOENT)
- cfg_add_cause("%s: %s", TMUX_CONF, strerror(errno));
- if (cfg_file != NULL) {
- if (load_cfg(cfg_file, cfg_cmd_q, &cause) == -1)
- cfg_add_cause("%s: %s", cfg_file, cause);
- }
- cmdq_continue(cfg_cmd_q);
+ start_cfg();
+
status_prompt_load_history();
server_add_accept(0);
diff --git a/session.c b/session.c
index 604af6e6..80089e0d 100644
--- a/session.c
+++ b/session.c
@@ -186,7 +186,7 @@ session_free(unused int fd, unused short events, void *arg)
{
struct session *s = arg;
- log_debug("sesson %s freed (%d references)", s->name, s->references);
+ log_debug("session %s freed (%d references)", s->name, s->references);
if (s->references == 0) {
free(s->name);
diff --git a/tmux.c b/tmux.c
index 21dc15e1..86ed6f7e 100644
--- a/tmux.c
+++ b/tmux.c
@@ -39,15 +39,10 @@ struct options global_s_options; /* session options */
struct options global_w_options; /* window options */
struct environ global_environ;
-struct event_base *ev_base;
-
-char *cfg_file;
char *shell_cmd;
int debug_level;
time_t start_time;
char socket_path[PATH_MAX];
-int login_shell;
-char *environ_path;
__dead void usage(void);
char *makesocketpath(const char *);
@@ -174,37 +169,14 @@ setblocking(int fd, int state)
}
}
-__dead void
-shell_exec(const char *shell, const char *shellcmd)
-{
- const char *shellname, *ptr;
- char *argv0;
-
- ptr = strrchr(shell, '/');
- if (ptr != NULL && *(ptr + 1) != '\0')
- shellname = ptr + 1;
- else
- shellname = shell;
- if (login_shell)
- xasprintf(&argv0, "-%s", shellname);
- else
- xasprintf(&argv0, "%s", shellname);
- setenv("SHELL", shell, 1);
-
- setblocking(STDIN_FILENO, 1);
- setblocking(STDOUT_FILENO, 1);
- setblocking(STDERR_FILENO, 1);
- closefrom(STDERR_FILENO + 1);
-
- execl(shell, argv0, "-c", shellcmd, (char *) NULL);
- fatal("execl failed");
-}
-
const char *
find_home(void)
{
- struct passwd *pw;
- const char *home;
+ struct passwd *pw;
+ static const char *home;
+
+ if (home != NULL)
+ return (home);
home = getenv("HOME");
if (home == NULL || *home == '\0') {
@@ -221,11 +193,8 @@ find_home(void)
int
main(int argc, char **argv)
{
- char *s, *path, *label, **var, tmp[PATH_MAX];
- char in[256];
- const char *home;
- long long pid;
- int opt, flags, keys, session;
+ char *s, *path, *label, **var, tmp[PATH_MAX];
+ int opt, flags, keys;
#if defined(DEBUG) && defined(__OpenBSD__)
malloc_options = (char *) "AFGJPX";
@@ -233,9 +202,12 @@ main(int argc, char **argv)
setlocale(LC_TIME, "");
- flags = 0;
+ if (**argv == '-')
+ flags = CLIENT_LOGIN;
+ else
+ flags = 0;
+
label = path = NULL;
- login_shell = (**argv == '-');
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
switch (opt) {
case '2':
@@ -255,11 +227,10 @@ main(int argc, char **argv)
printf("%s %s\n", __progname, VERSION);
exit(0);
case 'f':
- free(cfg_file);
- cfg_file = xstrdup(optarg);
+ set_cfg_file(optarg);
break;
case 'l':
- login_shell = 1;
+ flags |= CLIENT_LOGIN;
break;
case 'L':
free(label);
@@ -340,23 +311,6 @@ main(int argc, char **argv)
options_set_number(&global_w_options, "mode-keys", keys);
}
- /* Locate the configuration file. */
- if (cfg_file == NULL) {
- home = find_home();
- if (home != NULL) {
- xasprintf(&cfg_file, "%s/.tmux.conf", home);
- if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
- free(cfg_file);
- cfg_file = NULL;
- }
- }
- }
-
- /* Get path from environment. */
- s = getenv("TMUX");
- if (s != NULL && sscanf(s, "%255[^,],%lld,%d", in, &pid, &session) == 3)
- environ_path = xstrdup(in);
-
/*
* Figure out the socket path. If specified on the command-line with -S
* or -L, use it, otherwise try $TMUX or assume -L default.
@@ -364,9 +318,15 @@ main(int argc, char **argv)
if (path == NULL) {
/* If no -L, use the environment. */
if (label == NULL) {
- if (environ_path != NULL)
- path = xstrdup(environ_path);
- else
+ s = getenv("TMUX");
+ if (s != NULL) {
+ path = xstrdup(s);
+ path[strcspn (path, ",")] = '\0';
+ if (*path == '\0') {
+ free(path);
+ label = xstrdup("default");
+ }
+ } else
label = xstrdup("default");
}
@@ -374,14 +334,15 @@ main(int argc, char **argv)
if (label != NULL) {
if ((path = makesocketpath(label)) == NULL) {
fprintf(stderr, "can't create socket: %s\n",
- strerror(errno));
+ strerror(errno));
exit(1);
}
}
}
free(label);
- if (strlcpy(socket_path, path, sizeof socket_path) >= sizeof socket_path) {
+ if (strlcpy(socket_path, path, sizeof socket_path) >=
+ sizeof socket_path) {
fprintf(stderr, "socket path too long: %s\n", path);
exit(1);
}
@@ -393,6 +354,5 @@ main(int argc, char **argv)
#endif
/* Pass control to the client. */
- ev_base = osdep_event_init();
- exit(client_main(argc, argv, flags));
+ exit(client_main(event_init(), argc, argv, flags));
}
diff --git a/tmux.h b/tmux.h
index 78d5eaa3..6a36c1aa 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1086,9 +1086,7 @@ LIST_HEAD(tty_terms, tty_term);
struct tty {
struct client *client;
-
char *path;
- u_int class;
u_int sx;
u_int sy;
@@ -1207,7 +1205,7 @@ struct client {
struct screen status;
#define CLIENT_TERMINAL 0x1
-/* 0x2 unused */
+#define CLIENT_LOGIN 0x2
#define CLIENT_EXIT 0x4
#define CLIENT_REDRAW 0x8
#define CLIENT_STATUS 0x10
@@ -1411,29 +1409,24 @@ extern struct options global_options;
extern str