Merge branch 'obsd-master'

Conflicts:
	tmux.1
	window.c
This commit is contained in:
Thomas Adam 2017-06-05 11:59:38 +01:00
commit e62e17d046
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;
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);
}

21
log.c
View File

@ -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)

View File

@ -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) {

6
proc.c
View File

@ -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);
}

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);
if (selected && (~gc->flags & GRID_FLAG_SELECTED)) {
memcpy(&tmp_gc, gc, sizeof tmp_gc);

View File

@ -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. */

View File

@ -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;
}
}

View File

@ -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);
}
}

21
tmux.1
View File

@ -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."

3
tmux.h
View File

@ -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 *, ...);

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) {
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;

24
utf8.c
View File

@ -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

View File

@ -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);
}