Merge branch 'obsd-master'

Conflicts:
	tmux.1
	window.c
This commit is contained in:
Thomas Adam
2017-06-05 11:59:38 +01:00
13 changed files with 144 additions and 26 deletions

71
input.c
View File

@@ -93,6 +93,8 @@ struct input_ctx {
const struct input_state *state; const struct input_state *state;
struct event timer;
/* /*
* All input received since we were last in the ground state. Sent to * All input received since we were last in the ground state. Sent to
* control clients on connection. * control clients on connection.
@@ -118,6 +120,7 @@ static void input_osc_104(struct window_pane *, const char *);
/* Transition entry/exit handlers. */ /* Transition entry/exit handlers. */
static void input_clear(struct input_ctx *); static void input_clear(struct input_ctx *);
static void input_ground(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_enter_osc(struct input_ctx *);
static void input_exit_osc(struct input_ctx *); static void input_exit_osc(struct input_ctx *);
static void input_enter_apc(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. */ /* dcs_enter state definition. */
static const struct input_state input_state_dcs_enter = { static const struct input_state input_state_dcs_enter = {
"dcs_enter", "dcs_enter",
input_clear, NULL, input_enter_dcs, NULL,
input_state_dcs_enter_table 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)); 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. */ /* Reset cell state to default. */
static void static void
input_reset_cell(struct input_ctx *ictx) input_reset_cell(struct input_ctx *ictx)
@@ -782,6 +809,8 @@ input_init(struct window_pane *wp)
ictx->since_ground = evbuffer_new(); ictx->since_ground = evbuffer_new();
evtimer_set(&ictx->timer, input_timer_callback, ictx);
input_reset(wp, 0); input_reset(wp, 0);
} }
@@ -791,6 +820,8 @@ input_free(struct window_pane *wp)
{ {
struct input_ctx *ictx = wp->ictx; struct input_ctx *ictx = wp->ictx;
event_del(&ictx->timer);
free(ictx->input_buf); free(ictx->input_buf);
evbuffer_free(ictx->since_ground); evbuffer_free(ictx->since_ground);
@@ -815,14 +846,7 @@ input_reset(struct window_pane *wp, int clear)
screen_write_stop(&ictx->ctx); screen_write_stop(&ictx->ctx);
} }
*ictx->interm_buf = '\0'; input_clear(ictx);
ictx->interm_len = 0;
*ictx->param_buf = '\0';
ictx->param_len = 0;
*ictx->input_buf = '\0';
ictx->input_len = 0;
ictx->state = &input_state_ground; ictx->state = &input_state_ground;
ictx->flags = 0; ictx->flags = 0;
@@ -997,6 +1021,8 @@ input_reply(struct input_ctx *ictx, const char *fmt, ...)
static void static void
input_clear(struct input_ctx *ictx) input_clear(struct input_ctx *ictx)
{ {
event_del(&ictx->timer);
*ictx->interm_buf = '\0'; *ictx->interm_buf = '\0';
ictx->interm_len = 0; ictx->interm_len = 0;
@@ -1013,6 +1039,7 @@ input_clear(struct input_ctx *ictx)
static void static void
input_ground(struct input_ctx *ictx) input_ground(struct input_ctx *ictx)
{ {
event_del(&ictx->timer);
evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground)); evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
if (ictx->input_space > INPUT_BUF_START) { 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. */ /* DCS terminator (ST) received. */
static int static int
input_dcs_dispatch(struct input_ctx *ictx) input_dcs_dispatch(struct input_ctx *ictx)
@@ -1871,6 +1908,7 @@ input_enter_osc(struct input_ctx *ictx)
log_debug("%s", __func__); log_debug("%s", __func__);
input_clear(ictx); input_clear(ictx);
input_start_timer(ictx);
} }
/* OSC terminator (ST) received. */ /* OSC terminator (ST) received. */
@@ -1896,8 +1934,10 @@ input_exit_osc(struct input_ctx *ictx)
switch (option) { switch (option) {
case 0: case 0:
case 2: case 2:
screen_set_title(ictx->ctx.s, p); if (utf8_isvalid(p)) {
server_status_window(ictx->wp->window); screen_set_title(ictx->ctx.s, p);
server_status_window(ictx->wp->window);
}
break; break;
case 4: case 4:
input_osc_4(ictx->wp, p); input_osc_4(ictx->wp, p);
@@ -1909,7 +1949,7 @@ input_exit_osc(struct input_ctx *ictx)
input_osc_11(ictx->wp, p); input_osc_11(ictx->wp, p);
break; break;
case 12: case 12:
if (*p != '?') /* ? is colour request */ if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
screen_set_cursor_colour(ictx->ctx.s, p); screen_set_cursor_colour(ictx->ctx.s, p);
break; break;
case 52: case 52:
@@ -1935,6 +1975,7 @@ input_enter_apc(struct input_ctx *ictx)
log_debug("%s", __func__); log_debug("%s", __func__);
input_clear(ictx); input_clear(ictx);
input_start_timer(ictx);
} }
/* APC terminator (ST) received. */ /* APC terminator (ST) received. */
@@ -1945,6 +1986,8 @@ input_exit_apc(struct input_ctx *ictx)
return; return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf); log_debug("%s: \"%s\"", __func__, ictx->input_buf);
if (!utf8_isvalid(ictx->input_buf))
return;
screen_set_title(ictx->ctx.s, ictx->input_buf); screen_set_title(ictx->ctx.s, ictx->input_buf);
server_status_window(ictx->wp->window); server_status_window(ictx->wp->window);
} }
@@ -1956,6 +1999,7 @@ input_enter_rename(struct input_ctx *ictx)
log_debug("%s", __func__); log_debug("%s", __func__);
input_clear(ictx); input_clear(ictx);
input_start_timer(ictx);
} }
/* Rename terminator (ST) received. */ /* Rename terminator (ST) received. */
@@ -1968,9 +2012,10 @@ input_exit_rename(struct input_ctx *ictx)
return; return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf); log_debug("%s: \"%s\"", __func__, ictx->input_buf);
if (!utf8_isvalid(ictx->input_buf))
return;
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);
} }

21
log.c
View File

@@ -61,12 +61,10 @@ log_open(const char *name)
if (log_level == 0) if (log_level == 0)
return; return;
log_close();
if (log_file != NULL)
fclose(log_file);
xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid()); xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
log_file = fopen(path, "w"); log_file = fopen(path, "a");
free(path); free(path);
if (log_file == NULL) if (log_file == NULL)
return; return;
@@ -75,6 +73,21 @@ log_open(const char *name)
event_set_log_callback(log_event_cb); 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. */ /* Close logging. */
void void
log_close(void) log_close(void)

View File

@@ -685,8 +685,10 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs,
char *command, *cause; char *command, *cause;
command = cmd_template_replace(template, name, 1); command = cmd_template_replace(template, name, 1);
if (command == NULL || *command == '\0') if (command == NULL || *command == '\0') {
free(command);
return; return;
}
cmdlist = cmd_string_parse(command, NULL, 0, &cause); cmdlist = cmd_string_parse(command, NULL, 0, &cause);
if (cmdlist == NULL) { if (cmdlist == NULL) {

6
proc.c
View File

@@ -263,3 +263,9 @@ proc_kill_peer(struct tmuxpeer *peer)
{ {
peer->flags |= PEER_BAD; peer->flags |= PEER_BAD;
} }
void
proc_toggle_log(struct tmuxproc *tp)
{
log_toggle(tp->name);
}

View File

@@ -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); selected = screen_check_selection(s, s->cx, s->cy);
if (selected && (~gc->flags & GRID_FLAG_SELECTED)) { if (selected && (~gc->flags & GRID_FLAG_SELECTED)) {
memcpy(&tmp_gc, gc, sizeof tmp_gc); memcpy(&tmp_gc, gc, sizeof tmp_gc);

View File

@@ -21,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <vis.h>
#include "tmux.h" #include "tmux.h"
@@ -107,7 +108,7 @@ void
screen_set_title(struct screen *s, const char *title) screen_set_title(struct screen *s, const char *title)
{ {
free(s->title); free(s->title);
s->title = xstrdup(title); utf8_stravis(&s->title, title, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
} }
/* Resize screen. */ /* Resize screen. */

View File

@@ -150,7 +150,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
} }
close(pair[0]); close(pair[0]);
if (log_get_level() > 3) if (log_get_level() > 1)
tty_create_log(); tty_create_log();
if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec " if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec "
"tty ps", NULL) != 0) "tty ps", NULL) != 0)
@@ -364,6 +364,9 @@ server_signal(int sig)
} }
server_add_accept(0); server_add_accept(0);
break; break;
case SIGUSR2:
proc_toggle_log(server_proc);
break;
} }
} }

View File

@@ -29,6 +29,7 @@ static struct event ev_sigchld;
static struct event ev_sigcont; static struct event ev_sigcont;
static struct event ev_sigterm; static struct event ev_sigterm;
static struct event ev_sigusr1; static struct event ev_sigusr1;
static struct event ev_sigusr2;
static struct event ev_sigwinch; static struct event ev_sigwinch;
void void
@@ -59,6 +60,8 @@ set_signals(void (*handler)(int, short, void *), void *arg)
signal_add(&ev_sigterm, NULL); signal_add(&ev_sigterm, NULL);
signal_set(&ev_sigusr1, SIGUSR1, handler, arg); signal_set(&ev_sigusr1, SIGUSR1, handler, arg);
signal_add(&ev_sigusr1, NULL); 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_set(&ev_sigwinch, SIGWINCH, handler, arg);
signal_add(&ev_sigwinch, NULL); signal_add(&ev_sigwinch, NULL);
} }
@@ -92,6 +95,8 @@ clear_signals(int after_fork)
fatal("sigaction failed"); fatal("sigaction failed");
if (sigaction(SIGUSR1, &sigact, NULL) != 0) if (sigaction(SIGUSR1, &sigact, NULL) != 0)
fatal("sigaction failed"); fatal("sigaction failed");
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGWINCH, &sigact, NULL) != 0) if (sigaction(SIGWINCH, &sigact, NULL) != 0)
fatal("sigaction failed"); fatal("sigaction failed");
} else { } else {
@@ -100,6 +105,7 @@ clear_signals(int after_fork)
event_del(&ev_sigcont); event_del(&ev_sigcont);
event_del(&ev_sigterm); event_del(&ev_sigterm);
event_del(&ev_sigusr1); event_del(&ev_sigusr1);
event_del(&ev_sigusr2);
event_del(&ev_sigwinch); event_del(&ev_sigwinch);
} }
} }

21
tmux.1
View File

@@ -199,7 +199,6 @@ characters to the terminal it is running (if not, they are replaced by
.Ql _ ) . .Ql _ ) .
.It Fl v .It Fl v
Request verbose logging. Request verbose logging.
This option may be specified multiple times for increasing verbosity.
Log messages will be saved into Log messages will be saved into
.Pa tmux-client-PID.log .Pa tmux-client-PID.log
and and
@@ -211,6 +210,22 @@ is the PID of the server or client process.
Report the Report the
.Nm .Nm
version. 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 .It Ar command Op Ar flags
This specifies one of a set of commands used to control This specifies one of a set of commands used to control
.Nm , .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 "Toggle if item is tagged"
.It Li "T" Ta "Tag no items" .It Li "T" Ta "Tag no items"
.It Li "C-t" Ta "Tag all 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 "f" Ta "Enter a format to filter items"
.It Li "O" Ta "Change sort order" .It Li "O" Ta "Change sort order"
.It Li "q" Ta "Exit mode" .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 "Denotes the current window."
.It Li "-" Ta "Marks the last window (previously selected)." .It Li "-" Ta "Marks the last window (previously selected)."
.It Li "#" Ta "Window is monitored and activity has been detected." .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 "~" Ta "The window has been silent for the monitor-silence interval."
.It Li "M" Ta "The window contains the marked pane." .It Li "M" Ta "The window contains the marked pane."
.It Li "Z" Ta "The window's active pane is zoomed." .It Li "Z" Ta "The window's active pane is zoomed."

3
tmux.h
View File

@@ -1497,6 +1497,7 @@ struct tmuxpeer *proc_add_peer(struct tmuxproc *, int,
void (*)(struct imsg *, void *), void *); void (*)(struct imsg *, void *), void *);
void proc_remove_peer(struct tmuxpeer *); void proc_remove_peer(struct tmuxpeer *);
void proc_kill_peer(struct tmuxpeer *); void proc_kill_peer(struct tmuxpeer *);
void proc_toggle_log(struct tmuxproc *);
/* cfg.c */ /* cfg.c */
extern int cfg_finished; 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_append(struct utf8_data *, u_char);
enum utf8_state utf8_combine(const struct utf8_data *, wchar_t *); enum utf8_state utf8_combine(const struct utf8_data *, wchar_t *);
enum utf8_state utf8_split(wchar_t, struct utf8_data *); 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_strvis(char *, const char *, size_t, int);
int utf8_stravis(char **, const char *, int); int utf8_stravis(char **, const char *, int);
char *utf8_sanitize(const char *); char *utf8_sanitize(const char *);
@@ -2342,6 +2344,7 @@ struct event_base *osdep_event_init(void);
void log_add_level(void); void log_add_level(void);
int log_get_level(void); int log_get_level(void);
void log_open(const char *); void log_open(const char *);
void log_toggle(const char *);
void log_close(void); void log_close(void);
void printflike(1, 2) log_debug(const char *, ...); void printflike(1, 2) log_debug(const char *, ...);
__dead void printflike(1, 2) fatal(const char *, ...); __dead void printflike(1, 2) fatal(const char *, ...);

2
tty.c
View File

@@ -1848,7 +1848,7 @@ tty_check_fg(struct tty *tty, const struct window_pane *wp,
*/ */
if (~gc->flags & GRID_FLAG_NOPALETTE) { if (~gc->flags & GRID_FLAG_NOPALETTE) {
c = gc->fg; c = gc->fg;
if (gc->fg < 8 && gc->attr & GRID_ATTR_BRIGHT) if (c < 8 && gc->attr & GRID_ATTR_BRIGHT)
c += 90; c += 90;
if ((c = window_pane_get_palette(wp, c)) != -1) if ((c = window_pane_get_palette(wp, c)) != -1)
gc->fg = c; gc->fg = c;

24
utf8.c
View File

@@ -232,6 +232,30 @@ utf8_stravis(char **dst, const char *src, int flag)
return (len); 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 * Sanitize a string, changing any UTF-8 characters to '_'. Caller should free
* the returned string. Anything not valid printable ASCII or UTF-8 is * the returned string. Anything not valid printable ASCII or UTF-8 is

View File

@@ -408,7 +408,7 @@ void
window_set_name(struct window *w, const char *new_name) window_set_name(struct window *w, const char *new_name)
{ {
free(w->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); notify_window("window-renamed", w);
} }