Sync OpenBSD patchset 347:

Remove the internal tmux locking and instead detach each client and run the
command specified by a new option "lock-command" (by default "lock -np") in
each client.

This means each terminal has to be unlocked individually but simplifies the
code and allows the system password to be used to unlock.

Note that the set-password command is gone, so it will need to be removed from
configuration files, and the -U command line flag has been removed.

This is the third protocol version change so again it is best to stop the tmux
server before upgrading.
This commit is contained in:
Tiago Cunha 2009-09-23 15:00:09 +00:00
parent 2acf349d4e
commit 1310ea2729
12 changed files with 66 additions and 466 deletions

View File

@ -1,4 +1,4 @@
/* $Id: client.c,v 1.73 2009-09-23 14:44:02 tcunha Exp $ */ /* $Id: client.c,v 1.74 2009-09-23 15:00:08 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -246,6 +246,7 @@ client_msg_dispatch(struct client_ctx *cctx)
{ {
struct imsg imsg; struct imsg imsg;
struct msg_print_data printdata; struct msg_print_data printdata;
struct msg_lock_data lockdata;
ssize_t n, datalen; ssize_t n, datalen;
for (;;) { for (;;) {
@ -299,6 +300,15 @@ client_msg_dispatch(struct client_ctx *cctx)
client_suspend(); client_suspend();
break; break;
case MSG_LOCK:
if (datalen != sizeof lockdata)
fatalx("bad MSG_LOCK size");
memcpy(&lockdata, imsg.data, sizeof lockdata);
lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
system(lockdata.cmd);
client_write_server(cctx, MSG_UNLOCK, NULL, 0);
break;
default: default:
fatalx("unexpected message"); fatalx("unexpected message");
} }

View File

@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.80 2009-09-22 14:22:20 tcunha Exp $ */ /* $Id: cmd-set-option.c,v 1.81 2009-09-23 15:00:08 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -62,6 +62,7 @@ const struct set_option_entry set_option_table[] = {
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-command", SET_OPTION_STRING, 0, 0, NULL },
{ "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "message-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "message-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },

View File

@ -1,145 +0,0 @@
/* $Id: cmd-set-password.c,v 1.9 2009-09-22 14:06:40 tcunha Exp $ */
/*
* Copyright (c) 2009 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 <pwd.h>
#include <unistd.h>
#include "tmux.h"
/*
* Set server password.
*/
int cmd_set_password_parse(struct cmd *, int, char **, char **);
int cmd_set_password_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_password_free(struct cmd *);
void cmd_set_password_init(struct cmd *, int);
size_t cmd_set_password_print(struct cmd *, char *, size_t);
struct cmd_set_password_data {
char *password;
int flag_encrypted;
};
const struct cmd_entry cmd_set_password_entry = {
"set-password", "pass",
"[-c] password",
0, 0,
cmd_set_password_init,
cmd_set_password_parse,
cmd_set_password_exec,
cmd_set_password_free,
cmd_set_password_print
};
void
cmd_set_password_init(struct cmd *self, unused int arg)
{
struct cmd_set_password_data *data;
self->data = data = xmalloc(sizeof *data);
data->password = NULL;
data->flag_encrypted = 0;
}
int
cmd_set_password_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_set_password_data *data;
int opt;
char *out;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "c")) != -1) {
switch (opt) {
case 'c':
data->flag_encrypted = 1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
goto usage;
if (!data->flag_encrypted) {
if ((out = crypt(argv[0], "$1")) != NULL)
data->password = xstrdup(out);
} else
data->password = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_set_password_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_set_password_data *data = self->data;
if (data->password == NULL) {
ctx->error(ctx, "failed to encrypt password");
return (-1);
}
if (server_password != NULL)
xfree(server_password);
if (*data->password == '\0')
server_password = NULL;
else
server_password = xstrdup(data->password);
return (0);
}
void
cmd_set_password_free(struct cmd *self)
{
struct cmd_set_password_data *data = self->data;
if (data->password != NULL)
xfree(data->password);
xfree(data);
}
size_t
cmd_set_password_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_set_password_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_encrypted)
off += xsnprintf(buf + off, len - off, " -c");
if (off < len && data->password != NULL)
off += xsnprintf(buf + off, len - off, " password");
return (off);
}

7
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.116 2009-09-20 22:20:10 tcunha Exp $ */ /* $Id: cmd.c,v 1.117 2009-09-23 15:00:08 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -88,7 +88,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_set_buffer_entry, &cmd_set_buffer_entry,
&cmd_set_environment_entry, &cmd_set_environment_entry,
&cmd_set_option_entry, &cmd_set_option_entry,
&cmd_set_password_entry,
&cmd_set_window_option_entry, &cmd_set_window_option_entry,
&cmd_show_buffer_entry, &cmd_show_buffer_entry,
&cmd_show_environment_entry, &cmd_show_environment_entry,
@ -259,10 +258,6 @@ usage:
int int
cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx) cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
{ {
if (server_locked) {
ctx->error(ctx, "server is locked");
return (-1);
}
return (cmd->entry->exec(cmd, ctx)); return (cmd->entry->exec(cmd, ctx));
} }

View File

@ -1,4 +1,4 @@
/* $Id: server-fn.c,v 1.89 2009-09-20 22:15:32 tcunha Exp $ */ /* $Id: server-fn.c,v 1.90 2009-09-23 15:00:08 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,15 +18,12 @@
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "tmux.h" #include "tmux.h"
int server_lock_callback(void *, const char *);
void void
server_fill_environ(struct session *s, struct environ *env) server_fill_environ(struct session *s, struct environ *env)
{ {
@ -160,117 +157,30 @@ server_status_window(struct window *w)
void void
server_lock(void) server_lock(void)
{ {
struct client *c; struct client *c;
static struct passwd *pw, pwstore; const char *cmd;
static char pwbuf[_PW_BUF_LEN]; struct msg_lock_data lockdata;
u_int i; u_int i;
if (server_locked)
return;
if (getpwuid_r(getuid(), &pwstore, pwbuf, sizeof pwbuf, &pw) != 0) {
server_locked_pw = NULL;
return;
}
server_locked_pw = pw;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; continue;
if (c->flags & CLIENT_SUSPENDED)
status_prompt_clear(c);
status_prompt_set(c,
"Password:", server_lock_callback, NULL, c, PROMPT_HIDDEN);
server_redraw_client(c);
}
server_locked = 1;
}
int
server_lock_callback(unused void *data, const char *s)
{
return (server_unlock(s));
}
int
server_unlock(const char *s)
{
struct client *c;
#ifdef HAVE_LOGIN_CAP
login_cap_t *lc;
#endif
u_int i;
char *out;
u_int failures, tries, backoff;
if (!server_locked || server_locked_pw == NULL)
return (0);
server_activity = time(NULL);
if (server_activity < password_backoff)
return (-2);
if (server_password != NULL) {
if (s == NULL)
return (-1);
out = crypt(s, server_password);
if (strcmp(out, server_password) != 0)
goto wrong;
}
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL)
continue; continue;
status_prompt_clear(c); cmd = options_get_string(&c->session->options, "lock-command");
server_redraw_client(c); if (strlcpy(lockdata.cmd,
} cmd, sizeof lockdata.cmd) >= sizeof lockdata.cmd)
server_locked = 0;
password_failures = 0;
password_backoff = 0;
return (0);
wrong:
password_failures++;
password_backoff = 0;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->prompt_buffer == NULL)
continue; continue;
*c->prompt_buffer = '\0'; tty_stop_tty(&c->tty);
c->prompt_index = 0; tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_SMCUP));
server_redraw_client(c); tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_CLEAR));
}
/* c->flags |= CLIENT_SUSPENDED;
* Start slowing down after "login-backoff" attempts and reset every server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
* "login-tries" attempts.
*/
#ifdef HAVE_LOGIN_CAP
lc = login_getclass(server_locked_pw->pw_class);
if (lc != NULL) {
tries = login_getcapnum(lc, (char *) "login-tries", 10, 10);
backoff = login_getcapnum(lc, (char *) "login-backoff", 3, 3);
} else {
tries = 10;
backoff = 3;
} }
#else
tries = 10;
backoff = 3;
#endif
failures = password_failures % tries;
if (failures > backoff) {
password_backoff =
server_activity + ((failures - backoff) * tries / 2);
return (-2);
}
return (-1);
} }
void void

View File

@ -1,4 +1,4 @@
/* $Id: server-msg.c,v 1.86 2009-09-23 14:44:02 tcunha Exp $ */ /* $Id: server-msg.c,v 1.87 2009-09-23 15:00:08 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -40,7 +40,6 @@ server_msg_dispatch(struct client *c)
struct imsg imsg; struct imsg imsg;
struct msg_command_data commanddata; struct msg_command_data commanddata;
struct msg_identify_data identifydata; struct msg_identify_data identifydata;
struct msg_unlock_data unlockdata;
struct msg_environ_data environdata; struct msg_environ_data environdata;
ssize_t n, datalen; ssize_t n, datalen;
@ -95,31 +94,15 @@ server_msg_dispatch(struct client *c)
tty_close(&c->tty); tty_close(&c->tty);
server_write_client(c, MSG_EXITED, NULL, 0); server_write_client(c, MSG_EXITED, NULL, 0);
break; break;
case MSG_UNLOCK:
if (datalen != sizeof unlockdata)
fatalx("bad MSG_UNLOCK size");
memcpy(&unlockdata, imsg.data, sizeof unlockdata);
unlockdata.pass[(sizeof unlockdata.pass) - 1] = '\0';
switch (server_unlock(unlockdata.pass)) {
case -1:
server_write_error(c, "bad password");
break;
case -2:
server_write_error(c,
"too many bad passwords, sleeping");
break;
}
memset(&unlockdata, 0, sizeof unlockdata);
server_write_client(c, MSG_EXIT, NULL, 0);
break;
case MSG_WAKEUP: case MSG_WAKEUP:
case MSG_UNLOCK:
if (datalen != 0) if (datalen != 0)
fatalx("bad MSG_WAKEUP size"); fatalx("bad MSG_WAKEUP size");
c->flags &= ~CLIENT_SUSPENDED; c->flags &= ~CLIENT_SUSPENDED;
tty_start_tty(&c->tty); tty_start_tty(&c->tty);
server_redraw_client(c); server_redraw_client(c);
server_activity = time(NULL);
break; break;
case MSG_ENVIRON: case MSG_ENVIRON:
if (datalen != sizeof environdata) if (datalen != sizeof environdata)

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.191 2009-09-22 14:22:20 tcunha Exp $ */ /* $Id: server.c,v 1.192 2009-09-23 15:00:08 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -66,7 +66,6 @@ void server_lost_client(struct client *);
void server_check_window(struct window *); void server_check_window(struct window *);
void server_check_redraw(struct client *); void server_check_redraw(struct client *);
void server_set_title(struct client *); void server_set_title(struct client *);
void server_redraw_locked(struct client *);
void server_check_timers(struct client *); void server_check_timers(struct client *);
void server_second_timers(void); void server_second_timers(void);
int server_update_socket(void); int server_update_socket(void);
@ -161,8 +160,6 @@ server_start(char *path)
key_bindings_init(); key_bindings_init();
utf8_build(); utf8_build();
server_locked = 0;
server_password = NULL;
server_activity = time(NULL); server_activity = time(NULL);
start_time = time(NULL); start_time = time(NULL);
@ -385,8 +382,6 @@ server_main(int srv_fd)
options_free(&global_s_options); options_free(&global_s_options);
options_free(&global_w_options); options_free(&global_w_options);
if (server_password != NULL)
xfree(server_password);
return (0); return (0);
} }
@ -544,10 +539,7 @@ server_check_redraw(struct client *c)
} }
if (c->flags & CLIENT_REDRAW) { if (c->flags & CLIENT_REDRAW) {
if (server_locked) screen_redraw_screen(c, 0);
server_redraw_locked(c);
else
screen_redraw_screen(c, 0);
c->flags &= ~CLIENT_STATUS; c->flags &= ~CLIENT_STATUS;
} else { } else {
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
@ -584,49 +576,6 @@ server_set_title(struct client *c)
xfree(title); xfree(title);
} }
/* Redraw client when locked. */
void
server_redraw_locked(struct client *c)
{
struct screen_write_ctx ctx;
struct screen screen;
struct grid_cell gc;
u_int colour, xx, yy, i;
int style;
xx = c->tty.sx;
yy = c->tty.sy - 1;
if (xx == 0 || yy == 0)
return;
colour = options_get_number(&global_w_options, "clock-mode-colour");
style = options_get_number(&global_w_options, "clock-mode-style");
memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_fg(&gc, colour);
gc.attr |= GRID_ATTR_BRIGHT;
screen_init(&screen, xx, yy, 0);
screen_write_start(&ctx, NULL, &screen);
clock_draw(&ctx, colour, style);
if (password_failures != 0) {
screen_write_cursormove(&ctx, 0, 0);
screen_write_puts(
&ctx, &gc, "%u failed attempts", password_failures);
if (time(NULL) < password_backoff)
screen_write_puts(&ctx, &gc, "; sleeping");
}
screen_write_stop(&ctx);
for (i = 0; i < screen_size_y(&screen); i++)
tty_draw_line(&c->tty, &screen, i, 0, 0);
screen_redraw_screen(c, 1);
screen_free(&screen);
}
/* Check for timers on client. */ /* Check for timers on client. */
void void
server_check_timers(struct client *c) server_check_timers(struct client *c)
@ -839,8 +788,6 @@ server_handle_client(struct client *c)
status_prompt_key(c, key); status_prompt_key(c, key);
continue; continue;
} }
if (server_locked)
continue;
/* Check for mouse keys. */ /* Check for mouse keys. */
if (key == KEYC_MOUSE) { if (key == KEYC_MOUSE) {
@ -932,8 +879,6 @@ server_handle_client(struct client *c)
tty_cursor(&c->tty, s->cx, s->cy, wp->xoff, wp->yoff); tty_cursor(&c->tty, s->cx, s->cy, wp->xoff, wp->yoff);
mode = s->mode; mode = s->mode;
if (server_locked)
mode &= ~TTY_NOCURSOR;
tty_update_mode(&c->tty, mode); tty_update_mode(&c->tty, mode);
tty_reset(&c->tty); tty_reset(&c->tty);
} }
@ -1238,12 +1183,9 @@ void
server_second_timers(void) server_second_timers(void)
{ {
struct window *w; struct window *w;
struct client *c;
struct window_pane *wp; struct window_pane *wp;
u_int i; u_int i;
int xtimeout; int xtimeout;
struct tm now, then;
static time_t last_t = 0;
time_t t; time_t t;
t = time(NULL); t = time(NULL);
@ -1262,29 +1204,6 @@ server_second_timers(void)
wp->mode->timer(wp); wp->mode->timer(wp);
} }
} }
if (password_backoff != 0 && t >= password_backoff) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
if ((c = ARRAY_ITEM(&clients, i)) != NULL)
server_redraw_client(c);
}
password_backoff = 0;
}
/* Check for a minute having passed. */
gmtime_r(&t, &now);
gmtime_r(&last_t, &then);
if (now.tm_min == then.tm_min)
return;
last_t = t;
/* If locked, redraw all clients. */
if (server_locked) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
if ((c = ARRAY_ITEM(&clients, i)) != NULL)
server_redraw_client(c);
}
}
} }
/* Update socket execute permissions based on whether sessions are attached. */ /* Update socket execute permissions based on whether sessions are attached. */

View File

@ -1,4 +1,4 @@
/* $Id: status.c,v 1.119 2009-09-20 22:11:27 tcunha Exp $ */ /* $Id: status.c,v 1.120 2009-09-23 15:00:09 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -890,9 +890,6 @@ status_prompt_key(struct client *c, int key)
} }
break; break;
case MODEKEYEDIT_HISTORYUP: case MODEKEYEDIT_HISTORYUP:
if (server_locked)
break;
if (ARRAY_LENGTH(&c->prompt_hdata) == 0) if (ARRAY_LENGTH(&c->prompt_hdata) == 0)
break; break;
if (c->prompt_flags & PROMPT_HIDDEN) if (c->prompt_flags & PROMPT_HIDDEN)
@ -908,9 +905,6 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
break; break;
case MODEKEYEDIT_HISTORYDOWN: case MODEKEYEDIT_HISTORYDOWN:
if (server_locked)
break;
if (c->prompt_flags & PROMPT_HIDDEN) if (c->prompt_flags & PROMPT_HIDDEN)
memset(c->prompt_buffer, 0, strlen(c->prompt_buffer)); memset(c->prompt_buffer, 0, strlen(c->prompt_buffer));
xfree(c->prompt_buffer); xfree(c->prompt_buffer);
@ -1003,9 +997,6 @@ status_prompt_key(struct client *c, int key)
void void
status_prompt_add_history(struct client *c) status_prompt_add_history(struct client *c)
{ {
if (server_locked)
return;
if (ARRAY_LENGTH(&c->prompt_hdata) > 0 && if (ARRAY_LENGTH(&c->prompt_hdata) > 0 &&
strcmp(ARRAY_LAST(&c->prompt_hdata), c->prompt_buffer) == 0) strcmp(ARRAY_LAST(&c->prompt_hdata), c->prompt_buffer) == 0)
return; return;

44
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.171 2009-09-22 14:22:20 tcunha Exp $ .\" $Id: tmux.1,v 1.172 2009-09-23 15:00:09 tcunha Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: September 22 2009 $ .Dd $Mdocdate: September 23 2009 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@ -23,7 +23,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm tmux .Nm tmux
.Bk -words .Bk -words
.Op Fl 28dlqUuv .Op Fl 28dlquv
.Op Fl f Ar file .Op Fl f Ar file
.Op Fl L Ar socket-name .Op Fl L Ar socket-name
.Op Fl S Ar socket-path .Op Fl S Ar socket-path
@ -154,8 +154,6 @@ If
is specified, the default socket directory is not used and any is specified, the default socket directory is not used and any
.Fl L .Fl L
flag is ignored. flag is ignored.
.It Fl U
Unlock the server.
.It Fl u .It Fl u
.Nm .Nm
attempts to guess if the terminal is likely to support UTF-8 by checking the attempts to guess if the terminal is likely to support UTF-8 by checking the
@ -337,8 +335,6 @@ rename-session -tfirst newname
set-window-option -t:0 monitor-activity on set-window-option -t:0 monitor-activity on
new-window ; split-window -d new-window ; split-window -d
bind-key D detach-client \e\; lock-server
.Ed .Ed
.Sh CLIENTS AND SESSIONS .Sh CLIENTS AND SESSIONS
The following commands are available: The following commands are available:
@ -1213,17 +1209,20 @@ Set the maximum number of lines held in window history.
This setting applies only to new windows - existing window histories are not This setting applies only to new windows - existing window histories are not
resized and retain the limit at the point they were created. resized and retain the limit at the point they were created.
.It Ic lock-after-time Ar number .It Ic lock-after-time Ar number
Lock the server after Lock the server (like the
.Ic lock-server
command) after
.Ar number .Ar number
seconds of inactivity. seconds of inactivity.
The default is off (set to 0). The default is off (set to 0).
This has no effect as a session option; it must be set as a global option using This has no effect as a session option; it must be set as a global option using
.Fl g . .Fl g .
When passwords are entered incorrectly, .It Ic lock-command Ar command
.Nm Command to run when locking each client.
follows the behaviour of The default is to run
.Xr login 1 .Xr lock 1
and ignores further password attempts for an increasing timeout. with
.Fl np .
.It Ic message-attr Ar attributes .It Ic message-attr Ar attributes
Set status line message attributes, where Set status line message attributes, where
.Ar attributes .Ar attributes
@ -1962,7 +1961,9 @@ if
returns success. returns success.
.It Ic lock-server .It Ic lock-server
.D1 (alias: Ic lock ) .D1 (alias: Ic lock )
Lock the server until a password is entered. Lock each client individually by running the command specified by the
.Ic lock-command
option.
.It Ic run-shell Ar command .It Ic run-shell Ar command
.D1 (alias: Ic run ) .D1 (alias: Ic run )
Execute Execute
@ -1975,21 +1976,6 @@ doesn't return success, the exit status is also displayed.
.It Ic server-info .It Ic server-info
.D1 (alias: Ic info ) .D1 (alias: Ic info )
Show server information and terminal details. Show server information and terminal details.
.It Xo Ic set-password
.Op Fl c
.Ar password
.Xc
.D1 (alias: Ic pass )
Set the server password.
If the
.Fl c
option is given, a pre-encrypted password may be specified.
By default, the password is blank, thus any entered password will be accepted
when unlocking the server (see the
.Ic lock-server
command).
To prevent variable expansion when an encrypted password is read from a
configuration file, enclose it in single quotes (').
.El .El
.Sh FILES .Sh FILES
.Bl -tag -width "/etc/tmux.confXXX" -compact .Bl -tag -width "/etc/tmux.confXXX" -compact

60
tmux.c
View File

@ -1,4 +1,4 @@
/* $Id: tmux.c,v 1.173 2009-09-22 14:22:21 tcunha Exp $ */ /* $Id: tmux.c,v 1.174 2009-09-23 15:00:09 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -51,11 +51,6 @@ 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;
int server_locked;
struct passwd *server_locked_pw;
u_int password_failures;
time_t password_backoff;
char *server_password;
time_t server_activity; time_t server_activity;
int debug_level; int debug_level;
@ -66,7 +61,6 @@ int login_shell;
__dead void usage(void); __dead void usage(void);
char *makesockpath(const char *); char *makesockpath(const char *);
int prepare_unlock(enum msgtype *, void **, size_t *, int);
int prepare_cmd(enum msgtype *, void **, size_t *, int, char **); int prepare_cmd(enum msgtype *, void **, size_t *, int, char **);
int dispatch_imsg(struct client_ctx *, int *); int dispatch_imsg(struct client_ctx *, int *);
@ -78,7 +72,7 @@ __dead void
usage(void) usage(void)
{ {
fprintf(stderr, fprintf(stderr,
"usage: %s [-28dlqUuv] [-f file] [-L socket-name]\n" "usage: %s [-28dlquv] [-f file] [-L socket-name]\n"
" [-S socket-path] [command [flags]]\n", " [-S socket-path] [command [flags]]\n",
__progname); __progname);
exit(1); exit(1);
@ -259,35 +253,6 @@ makesockpath(const char *label)
return (path); return (path);
} }
int
prepare_unlock(enum msgtype *msg, void **buf, size_t *len, int argc)
{
static struct msg_unlock_data unlockdata;
char *pass;
if (argc != 0) {
log_warnx("can't specify a command when unlocking");
return (-1);
}
if ((pass = getpass("Password:")) == NULL)
return (-1);
if (strlen(pass) >= sizeof unlockdata.pass) {
log_warnx("password too long");
return (-1);
}
strlcpy(unlockdata.pass, pass, sizeof unlockdata.pass);
memset(pass, 0, strlen(pass));
*buf = &unlockdata;
*len = sizeof unlockdata;
*msg = MSG_UNLOCK;
return (0);
}
int int
prepare_cmd(enum msgtype *msg, void **buf, size_t *len, int argc, char **argv) prepare_cmd(enum msgtype *msg, void **buf, size_t *len, int argc, char **argv)
{ {
@ -323,10 +288,10 @@ main(int argc, char **argv)
char cwd[MAXPATHLEN]; char cwd[MAXPATHLEN];
void *buf; void *buf;
size_t len; size_t len;
int retcode, opt, flags, unlock, cmdflags = 0; int retcode, opt, flags, cmdflags = 0;
int nfds; int nfds;
unlock = flags = 0; flags = 0;
label = path = NULL; label = path = NULL;
login_shell = (**argv == '-'); login_shell = (**argv == '-');
while ((opt = getopt(argc, argv, "28df:lL:qS:uUv")) != -1) { while ((opt = getopt(argc, argv, "28df:lL:qS:uUv")) != -1) {
@ -366,9 +331,6 @@ main(int argc, char **argv)
case 'u': case 'u':
flags |= IDENTIFY_UTF8; flags |= IDENTIFY_UTF8;
break; break;
case 'U':
unlock = 1;
break;
case 'v': case 'v':
debug_level++; debug_level++;
break; break;
@ -416,6 +378,7 @@ main(int argc, char **argv)
options_set_number(so, "display-time", 750); options_set_number(so, "display-time", 750);
options_set_number(so, "history-limit", 2000); options_set_number(so, "history-limit", 2000);
options_set_number(so, "lock-after-time", 0); options_set_number(so, "lock-after-time", 0);
options_set_string(so, "lock-command", "lock -np");
options_set_number(so, "message-attr", 0); options_set_number(so, "message-attr", 0);
options_set_number(so, "message-bg", 3); options_set_number(so, "message-bg", 3);
options_set_number(so, "message-fg", 0); options_set_number(so, "message-fg", 0);
@ -523,17 +486,10 @@ main(int argc, char **argv)
} }
xfree(label); xfree(label);
if (unlock) { if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0)
if (prepare_unlock(&msg, &buf, &len, argc) != 0) exit(1);
exit(1);
} else {
if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0)
exit(1);
}
if (unlock) if (argc == 0) /* new-session is the default */
cmdflags &= ~CMD_STARTSERVER;
else if (argc == 0) /* new-session is the default */
cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON; cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON;
else { else {
/* /*

20
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.452 2009-09-23 14:44:02 tcunha Exp $ */ /* $Id: tmux.h,v 1.453 2009-09-23 15:00:09 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -21,7 +21,7 @@
#include "config.h" #include "config.h"
#define PROTOCOL_VERSION 3 #define PROTOCOL_VERSION 4
#include <sys/param.h> #include <sys/param.h>
#include <sys/time.h> #include <sys/time.h>
@ -302,10 +302,11 @@ enum msgtype {
MSG_RESIZE, MSG_RESIZE,
MSG_SHUTDOWN, MSG_SHUTDOWN,
MSG_SUSPEND, MSG_SUSPEND,
MSG_UNLOCK,
MSG_VERSION, MSG_VERSION,
MSG_WAKEUP, MSG_WAKEUP,
MSG_ENVIRON MSG_ENVIRON,
MSG_UNLOCK,
MSG_LOCK
}; };
/* /*
@ -337,8 +338,8 @@ struct msg_identify_data {
int flags; int flags;
}; };
struct msg_unlock_data { struct msg_lock_data {
char pass[PASS_MAX]; char cmd[COMMAND_LENGTH];
}; };
struct msg_environ_data { struct msg_environ_data {
@ -1106,11 +1107,6 @@ 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 *cfg_file; extern char *cfg_file;
extern int server_locked;
extern struct passwd *server_locked_pw;
extern u_int password_failures;
extern time_t password_backoff;
extern char *server_password;
extern time_t server_activity; extern time_t server_activity;
extern int debug_level; extern int debug_level;
extern int be_quiet; extern int be_quiet;
@ -1177,6 +1173,7 @@ void environ_unset(struct environ *, const char *);
void environ_update(const char *, struct environ *, struct environ *); void environ_update(const char *, struct environ *, struct environ *);
/* tty.c */ /* tty.c */
void tty_raw(struct tty *, const char *);
u_char tty_get_acs(struct tty *, u_char); u_char tty_get_acs(struct tty *, u_char);
void tty_attributes(struct tty *, const struct grid_cell *); void tty_attributes(struct tty *, const struct grid_cell *);
void tty_reset(struct tty *); void tty_reset(struct tty *);
@ -1350,7 +1347,6 @@ 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_buffer_entry;
extern const struct cmd_entry cmd_set_environment_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_option_entry;
extern const struct cmd_entry cmd_set_password_entry;
extern const struct cmd_entry cmd_set_window_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_buffer_entry;
extern const struct cmd_entry cmd_show_environment_entry; extern const struct cmd_entry cmd_show_environment_entry;

4
tty.c
View File

@ -1,4 +1,4 @@
/* $Id: tty.c,v 1.135 2009-09-23 14:44:02 tcunha Exp $ */ /* $Id: tty.c,v 1.136 2009-09-23 15:00:09 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,8 +29,6 @@
void tty_fill_acs(struct tty *); void tty_fill_acs(struct tty *);
void tty_raw(struct tty *, const char *);
int tty_try_256(struct tty *, u_char, const char *); int tty_try_256(struct tty *, u_char, const char *);
int tty_try_88(struct tty *, u_char, const char *); int tty_try_88(struct tty *, u_char, const char *);