aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2017-06-05 11:59:38 +0100
committerThomas Adam <thomas@xteddy.org>2017-06-05 11:59:38 +0100
commite62e17d0461cfb0bfb55ae3c9c7a3815235298fb (patch)
tree258f2a1e09eb8553842383636a9f6f8a3f75074a
parent1c83c0ebcd483c668f02f5f7a8cb80f8a0dc162c (diff)
parent2f04108f3a35271ef60b3028699b6363e1714140 (diff)
downloadrtmux-e62e17d0461cfb0bfb55ae3c9c7a3815235298fb.tar.gz
rtmux-e62e17d0461cfb0bfb55ae3c9c7a3815235298fb.tar.bz2
rtmux-e62e17d0461cfb0bfb55ae3c9c7a3815235298fb.zip
Merge branch 'obsd-master'
Conflicts: tmux.1 window.c
-rw-r--r--input.c71
-rw-r--r--log.c21
-rw-r--r--mode-tree.c4
-rw-r--r--proc.c6
-rw-r--r--screen-write.c2
-rw-r--r--screen.c3
-rw-r--r--server.c5
-rw-r--r--signal.c6
-rw-r--r--tmux.121
-rw-r--r--tmux.h3
-rw-r--r--tty.c2
-rw-r--r--utf8.c24
-rw-r--r--window.c2
13 files changed, 144 insertions, 26 deletions
diff --git a/input.c b/input.c
index 5ba2ec5f..8131c164 100644
--- a/input.c
+++ b/input.c
@@ -93,6 +93,8 @@ struct input_ctx {
const struct input_state *state;
+ struct event timer;
+
/*
* All input received since we were last in the ground state. Sent to
* control clients on connection.
@@ -118,6 +120,7 @@ static void input_osc_104(struct window_pane *, const char *);
/* Transition entry/exit handlers. */
static void input_clear(struct input_ctx *);
static void input_ground(struct input_ctx *);
+static void input_enter_dcs(struct input_ctx *);
static void input_enter_osc(struct input_ctx *);
static void input_exit_osc(struct input_ctx *);
static void input_enter_apc(struct input_ctx *);
@@ -364,7 +367,7 @@ static const struct input_state input_state_csi_ignore = {
/* dcs_enter state definition. */
static const struct input_state input_state_dcs_enter = {
"dcs_enter",
- input_clear, NULL,
+ input_enter_dcs, NULL,
input_state_dcs_enter_table
};
@@ -756,6 +759,30 @@ input_table_compare(const void *key, const void *value)
return (strcmp(ictx->interm_buf, entry->interm));
}
+/*
+ * Timer - if this expires then have been waiting for a terminator for too
+ * long, so reset to ground.
+ */
+static void
+input_timer_callback(__unused int fd, __unused short events, void *arg)
+{
+ struct input_ctx *ictx = arg;
+ struct window_pane *wp = ictx->wp;
+
+ log_debug("%s: %%%u %s expired" , __func__, wp->id, ictx->state->name);
+ input_reset(wp, 0);
+}
+
+/* Start the timer. */
+static void
+input_start_timer(struct input_ctx *ictx)
+{
+ struct timeval tv = { .tv_usec = 100000 };
+
+ event_del(&ictx->timer);
+ event_add(&ictx->timer, &tv);
+}
+
/* Reset cell state to default. */
static void
input_reset_cell(struct input_ctx *ictx)
@@ -782,6 +809,8 @@ input_init(struct window_pane *wp)
ictx->since_ground = evbuffer_new();
+ evtimer_set(&ictx->timer, input_timer_callback, ictx);
+
input_reset(wp, 0);
}
@@ -791,6 +820,8 @@ input_free(struct window_pane *wp)
{
struct input_ctx *ictx = wp->ictx;
+ event_del(&ictx->timer);
+
free(ictx->input_buf);
evbuffer_free(ictx->since_ground);
@@ -815,14 +846,7 @@ input_reset(struct window_pane *wp, int clear)
screen_write_stop(&ictx->ctx);
}
- *ictx->interm_buf = '\0';
- ictx->interm_len = 0;
-
- *ictx->param_buf = '\0';
- ictx->param_len = 0;
-
- *ictx->input_buf = '\0';
- ictx->input_len = 0;
+ input_clear(ictx);
ictx->state = &input_state_ground;
ictx->flags = 0;
@@ -997,6 +1021,8 @@ input_reply(struct input_ctx *ictx, const char *fmt, ...)
static void
input_clear(struct input_ctx *ictx)
{
+ event_del(&ictx->timer);
+
*ictx->interm_buf = '\0';
ictx->interm_len = 0;
@@ -1013,6 +1039,7 @@ input_clear(struct input_ctx *ictx)
static void
input_ground(struct input_ctx *ictx)
{
+ event_del(&ictx->timer);
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
if (ictx->input_space > INPUT_BUF_START) {
@@ -1842,6 +1869,16 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
}
}
+/* DCS string started. */
+static void
+input_enter_dcs(struct input_ctx *ictx)
+{
+ log_debug("%s", __func__);
+
+ input_clear(ictx);
+ input_start_timer(ictx);
+}
+
/* DCS terminator (ST) received. */
static int
input_dcs_dispatch(struct input_ctx *ictx)
@@ -1871,6 +1908,7 @@ input_enter_osc(struct input_ctx *ictx)
log_debug("%s", __func__);
input_clear(ictx);
+ input_start_timer(ictx);
}
/* OSC terminator (ST) received. */
@@ -1896,8 +1934,10 @@ input_exit_osc(struct input_ctx *ictx)
switch (option) {
case 0:
case 2:
- screen_set_title(ictx->ctx.s, p);
- server_status_window(ictx->wp->window);
+ if (utf8_isvalid(p)) {
+ screen_set_title(ictx->ctx.s, p);
+ server_status_window(ictx->wp->window);
+ }
break;
case 4:
input_osc_4(ictx->wp, p);
@@ -1909,7 +1949,7 @@ input_exit_osc(struct input_ctx *ictx)
input_osc_11(ictx->wp, p);
break;
case 12:
- if (*p != '?') /* ? is colour request */
+ if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
screen_set_cursor_colour(ictx->ctx.s, p);
break;
case 52:
@@ -1935,6 +1975,7 @@ input_enter_apc(struct input_ctx *ictx)
log_debug("%s", __func__);
input_clear(ictx);
+ input_start_timer(ictx);
}
/* APC terminator (ST) received. */
@@ -1945,6 +1986,8 @@ input_exit_apc(struct input_ctx *ictx)
return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+ if (!utf8_isvalid(ictx->input_buf))
+ return;
screen_set_title(ictx->ctx.s, ictx->input_buf);
server_status_window(ictx->wp->window);
}
@@ -1956,6 +1999,7 @@ input_enter_rename(struct input_ctx *ictx)
log_debug("%s", __func__);
input_clear(ictx);
+ input_start_timer(ictx);
}
/* Rename terminator (ST) received. */
@@ -1968,9 +2012,10 @@ input_exit_rename(struct input_ctx *ictx)
return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
+ if (!utf8_isvalid(ictx->input_buf))
+ return;
window_set_name(ictx->wp->window, ictx->input_buf);
options_set_number(ictx->wp->window->options, "automatic-rename", 0);
-
server_status_window(ictx->wp->window);
}
diff --git a/log.c b/log.c
index caf3996a..8998cf2a 100644
--- a/log.c
+++ b/log.c
@@ -61,12 +61,10 @@ log_open(const char *name)
if (log_level == 0)
return;
-
- if (log_file != NULL)
- fclose(log_file);
+ log_close();
xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
- log_file = fopen(path, "w");
+ log_file = fopen(path, "a");
free(path);
if (log_file == NULL)
return;
@@ -75,6 +73,21 @@ log_open(const char *name)
event_set_log_callback(log_event_cb);
}
+/* Toggle logging. */
+void
+log_toggle(const char *name)
+{
+ if (log_level == 0) {
+ log_level = 1;
+ log_open(name);
+ log_debug("log opened");
+ } else {
+ log_debug("log closed");
+ log_level = 0;
+ log_close();
+ }
+}
+
/* Close logging. */
void
log_close(void)
diff --git a/mode-tree.c b/mode-tree.c
index f3155fbf..437f0008 100644
--- a/mode-tree.c
+++ b/mode-tree.c
@@ -685,8 +685,10 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs,
char *command, *cause;
command = cmd_template_replace(template, name, 1);
- if (command == NULL || *command == '\0')
+ if (command == NULL || *command == '\0') {
+ free(command);
return;
+ }
cmdlist = cmd_string_parse(command, NULL, 0, &cause);
if (cmdlist == NULL) {
diff --git a/proc.c b/proc.c
index 48890809..dabf462f 100644
--- a/proc.c
+++ b/proc.c
@@ -263,3 +263,9 @@ proc_kill_peer(struct tmuxpeer *peer)
{
peer->flags |= PEER_BAD;
}
+
+void
+proc_toggle_log(struct tmuxproc *tp)
+{
+ log_toggle(tp->name);
+}
diff --git a/screen-write.c b/screen-write.c
index c5af7c07..1f122482 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1390,7 +1390,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
}
}
- /* Update the selection the flag and set the cell. */
+ /* Update the selected flag and set the cell. */
selected = screen_check_selection(s, s->cx, s->cy);
if (selected && (~gc->flags & GRID_FLAG_SELECTED)) {
memcpy(&tmp_gc, gc, sizeof tmp_gc);
diff --git a/screen.c b/screen.c
index 087611ae..ebd117a0 100644
--- a/screen.c
+++ b/screen.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <vis.h>
#include "tmux.h"
@@ -107,7 +108,7 @@ void
screen_set_title(struct screen *s, const char *title)
{
free(s->title);
- s->title = xstrdup(title);
+ utf8_stravis(&s->title, title, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
}
/* Resize screen. */
diff --git a/server.c b/server.c
index bdbe9223..72395119 100644
--- a/server.c
+++ b/server.c
@@ -150,7 +150,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
}
close(pair[0]);
- if (log_get_level() > 3)
+ if (log_get_level() > 1)
tty_create_log();
if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec "
"tty ps", NULL) != 0)
@@ -364,6 +364,9 @@ server_signal(int sig)
}
server_add_accept(0);
break;
+ case SIGUSR2:
+ proc_toggle_log(server_proc);
+ break;
}
}
diff --git a/signal.c b/signal.c
index 79d23af0..49360514 100644
--- a/signal.c
+++ b/signal.c
@@ -29,6 +29,7 @@ static struct event ev_sigchld;
static struct event ev_sigcont;
static struct event ev_sigterm;
static struct event ev_sigusr1;
+static struct event ev_sigusr2;
static struct event ev_sigwinch;
void
@@ -59,6 +60,8 @@ set_signals(void (*handler)(int, short, void *), void *arg)
signal_add(&ev_sigterm, NULL);
signal_set(&ev_sigusr1, SIGUSR1, handler, arg);
signal_add(&ev_sigusr1, NULL);
+ signal_set(&ev_sigusr2, SIGUSR2, handler, arg);
+ signal_add(&ev_sigusr2, NULL);
signal_set(&ev_sigwinch, SIGWINCH, handler, arg);
signal_add(&ev_sigwinch, NULL);
}
@@ -92,6 +95,8 @@ clear_signals(int after_fork)
fatal("sigaction failed");
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
fatal("sigaction failed");
+ if (sigaction(SIGUSR2, &sigact, NULL) != 0)
+ fatal("sigaction failed");
if (sigaction(SIGWINCH, &sigact, NULL) != 0)
fatal("sigaction failed");
} else {
@@ -100,6 +105,7 @@ clear_signals(int after_fork)
event_del(&ev_sigcont);
event_del(&ev_sigterm);
event_del(&ev_sigusr1);
+ event_del(&ev_sigusr2);
event_del(&ev_sigwinch);
}
}
diff --git a/tmux.1 b/tmux.1
index ec3d9e7b..d0c3fe10 100644
--- a/tmux.1
+++ b/tmux.1
@@ -199,7 +199,6 @@ characters to the terminal it is running (if not, they are replaced by
.Ql _ ) .
.It Fl v
Request verbose logging.
-This option may be specified multiple times for increasing verbosity.
Log messages will be saved into
.Pa tmux-client-PID.log
and
@@ -211,6 +210,22 @@ is the PID of the server or client process.
Report the
.Nm
version.
+.Pp
+If
+.Fl v
+is specified twice, an additional
+.Pa tmux-out-PID.log
+file is generated with a copy of everything
+.Nm
+writes to the terminal.
+.Pp
+The
+.Dv SIGUSR2
+signal may be sent to the
+.Nm
+server process to toggle logging between on (as if
+.Fl v
+was given) and off.
.It Ar command Op Ar flags
This specifies one of a set of commands used to control
.Nm ,
@@ -1398,7 +1413,7 @@ The following keys may be used in tree mode:
.It Li "t" Ta "Toggle if item is tagged"
.It Li "T" Ta "Tag no items"
.It Li "C-t" Ta "Tag all items"
-.It Li ":" Ta "Run a command for each tagged item"
+.It Li "\&:" Ta "Run a command for each tagged item"
.It Li "f" Ta "Enter a format to filter items"
.It Li "O" Ta "Change sort order"
.It Li "q" Ta "Exit mode"
@@ -3742,7 +3757,7 @@ The flag is one of the following symbols appended to the window name:
.It Li "*" Ta "Denotes the current window."
.It Li "-" Ta "Marks the last window (previously selected)."
.It Li "#" Ta "Window is monitored and activity has been detected."
-.It Li "!" Ta "A bell has occurred in the window."
+.It Li "\&!" Ta "A bell has occurred in the window."
.It Li "~" Ta "The window has been silent for the monitor-silence interval."
.It Li "M" Ta "The window contains the marked pane."
.It Li "Z" Ta "The window's active pane is zoomed."
diff --git a/tmux.h b/tmux.h
index 66e4a044..8684c6db 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1497,6 +1497,7 @@ 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 *);
+void proc_toggle_log(struct tmuxproc *);
/* cfg.c */
extern int cfg_finished;
@@ -2321,6 +2322,7 @@ enum utf8_state utf8_open(struct utf8_data *, u_char);
enum utf8_state utf8_append(struct utf8_data *, u_char);
enum utf8_state utf8_combine(const struct utf8_data *, wchar_t *);
enum utf8_state utf8_split(wchar_t, struct utf8_data *);
+int utf8_isvalid(const char *);
int utf8_strvis(char *, const char *, size_t, int);
int utf8_stravis(char **, const char *, int);
char *utf8_sanitize(const char *);
@@ -2342,6 +2344,7 @@ struct event_base *osdep_event_init(void);
void log_add_level(void);
int log_get_level(void);
void log_open(const char *);
+void log_toggle(const char *);
void log_close(void);
void printflike(1, 2) log_debug(const char *, ...);
__dead void printflike(1, 2) fatal(const char *, ...);
diff --git a/tty.c b/tty.c
index 7759e0ea..3d0e210b 100644
--- a/tty.c
+++ b/tty.c
@@ -1848,7 +1848,7 @@ tty_check_fg(struct tty *tty, const struct window_pane *wp,
*/
if (~gc->flags & GRID_FLAG_NOPALETTE) {
c = gc->fg;
- if (gc->fg < 8 && gc->attr & GRID_ATTR_BRIGHT)
+ if (c < 8 && gc->attr & GRID_ATTR_BRIGHT)
c += 90;
if ((c = window_pane_get_palette(wp, c)) != -1)
gc->fg = c;
diff --git a/utf8.c b/utf8.c
index 8afdac97..a91da360 100644
--- a/utf8.c
+++ b/utf8.c
@@ -232,6 +232,30 @@ utf8_stravis(char **dst, const char *src, int flag)
return (len);
}
+/* Does this string contain anything that isn't valid UTF-8? */
+int
+utf8_isvalid(const char *s)
+{
+ struct utf8_data ud;
+ const char *end;
+ enum utf8_state more;
+
+ end = s + strlen(s);
+ while (s < end) {
+ if ((more = utf8_open(&ud, *s)) == UTF8_MORE) {
+ while (++s < end && more == UTF8_MORE)
+ more = utf8_append(&ud, *s);
+ if (more == UTF8_DONE)
+ continue;
+ return (0);
+ }
+ if (*s < 0x20 || *s > 0x7e)
+ return (0);
+ s++;
+ }
+ return (1);
+}
+
/*
* Sanitize a string, changing any UTF-8 characters to '_'. Caller should free
* the returned string. Anything not valid printable ASCII or UTF-8 is
diff --git a/window.c b/window.c
index c949565b..bbcc109c 100644
--- a/window.c
+++ b/window.c
@@ -408,7 +408,7 @@ void
window_set_name(struct window *w, const char *new_name)
{
free(w->name);
- w->name = xstrdup(new_name);
+ utf8_stravis(&w->name, new_name, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
notify_window("window-renamed", w);
}