diff options
| author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2009-01-11 00:48:42 +0000 |
|---|---|---|
| committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2009-01-11 00:48:42 +0000 |
| commit | e3feb067a503b53da253e4ed877d212d6d73842c (patch) | |
| tree | f0ebedf15d81253ae1d0437b6dc9f47cbccdc291 | |
| parent | ee0a7cda880f01771470b2902839c5d6396057c3 (diff) | |
| download | rtmux-e3feb067a503b53da253e4ed877d212d6d73842c.tar.gz rtmux-e3feb067a503b53da253e4ed877d212d6d73842c.tar.bz2 rtmux-e3feb067a503b53da253e4ed877d212d6d73842c.zip | |
Server locking. set-password and lock-server commands, plus automatic locking.
| -rw-r--r-- | CHANGES | 9 | ||||
| -rw-r--r-- | GNUmakefile | 10 | ||||
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | TODO | 7 | ||||
| -rw-r--r-- | client.c | 3 | ||||
| -rw-r--r-- | clock.c | 160 | ||||
| -rw-r--r-- | cmd-command-prompt.c | 22 | ||||
| -rw-r--r-- | cmd-lock-server.c | 55 | ||||
| -rw-r--r-- | cmd-new-session.c | 4 | ||||
| -rw-r--r-- | cmd-paste-buffer.c | 4 | ||||
| -rw-r--r-- | cmd-select-prompt.c | 18 | ||||
| -rw-r--r-- | cmd-set-option.c | 3 | ||||
| -rw-r--r-- | cmd-set-password.c | 169 | ||||
| -rw-r--r-- | cmd.c | 8 | ||||
| -rw-r--r-- | server-fn.c | 69 | ||||
| -rw-r--r-- | server-msg.c | 30 | ||||
| -rw-r--r-- | server.c | 154 | ||||
| -rw-r--r-- | status.c | 26 | ||||
| -rw-r--r-- | tmux.c | 111 | ||||
| -rw-r--r-- | tmux.h | 32 | ||||
| -rw-r--r-- | window-clock.c | 152 |
21 files changed, 776 insertions, 276 deletions
@@ -1,5 +1,12 @@ 10 January 2009 +* New option, lock-after-time. If there is no activity in the period specified + by this option (in seconds), tmux will lock the server. Default is 1800 (30 + minutes), set to 0 to disable. +* Server locking. Two new commands: set-password to set a password (a + preencrypted password may be specified with -c); and lock-server to lock the + server until the password is entered. Also an additional command line flag, + -U, to unlock from the shell. * If a window is created from the command line, tmux will now use the same current working directory for the new process. A new default-path option to sets the working directory for processes created from keys or interactively @@ -845,7 +852,7 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.189 2009-01-10 19:37:35 nicm Exp $ +$Id: CHANGES,v 1.190 2009-01-11 00:48:41 nicm Exp $ LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB diff --git a/GNUmakefile b/GNUmakefile index ecb1eb0e..bb8144c8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -# $Id: GNUmakefile,v 1.48 2009-01-10 19:40:01 nicm Exp $ +# $Id: GNUmakefile,v 1.49 2009-01-11 00:48:42 nicm Exp $ .PHONY: clean @@ -32,9 +32,9 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \ - cmd-clock-mode.c \ + cmd-clock-mode.c cmd-lock-server.c cmd-set-password.c \ window-clock.c window-scroll.c window-more.c window-copy.c \ - options.c options-cmd.c paste.c colour.c utf8.c \ + options.c options-cmd.c paste.c colour.c utf8.c clock.c \ tty.c tty-term.c tty-keys.c tty-write.c CC?= gcc @@ -73,7 +73,7 @@ endif ifeq ($(shell uname),SunOS) INCDIRS+= -Icompat -I/usr/local/include/ncurses SRCS+= compat/strtonum.c compat/daemon.c compat/forkpty-sunos.c \ - compat/asprintf.c compat/fgetln.c + compat/asprintf.c compat/fgetln.c compat/vis.c CFLAGS+= -DNO_STRTONUM -DNO_TREE_H -DNO_PATHS_H -DNO_SETPROCTITLE \ -DNO_DAEMON -DNO_FORKPTY -DNO_PROGNAME -DNO_ASPRINTF -DNO_FGETLN LDFLAGS+= -L/usr/local/lib @@ -95,7 +95,7 @@ CFLAGS+= $(shell getconf LFS_CFLAGS) -D_GNU_SOURCE \ -DNO_STRLCPY -DNO_STRLCAT -DNO_STRTONUM -DNO_SETPROCTITLE \ -DNO_QUEUE_H -DNO_TREE_H -DUSE_PTY_H -DNO_FGETLN \ -DBROKEN_GETOPT -std=c99 -LIBS+= -lrt -lutil +LIBS+= -lcrypt -lutil endif OBJS= $(patsubst %.c,%.o,$(SRCS)) @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.85 2009-01-10 19:35:39 nicm Exp $ +# $Id: Makefile,v 1.86 2009-01-11 00:48:42 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -36,9 +36,9 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \ - cmd-clock-mode.c \ + cmd-clock-mode.c cmd-lock-server.c cmd-set-password.c \ window-clock.c window-scroll.c window-more.c window-copy.c \ - options.c options-cmd.c paste.c colour.c utf8.c \ + options.c options-cmd.c paste.c colour.c utf8.c clock.c \ tty.c tty-term.c tty-keys.c tty-write.c CC?= cc @@ -64,8 +64,9 @@ - document server-info - document window options changes - document clock-mode -- automatic lock/screensaver after $time inactivity (switch all windows into - clock mode/blank) -- a key binding to display the status line when it is turned off +- document password/locking commands +- document lock-after-time +- automatic lock/screensaver after $time inactivity +- a key binding to display the status line briefly when it is turned off - FAQ "Can I have some examples of cool things I can do with tmux?" -- linkw - clone session command @@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.36 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: client.c,v 1.37 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -24,6 +24,7 @@ #include <errno.h> #include <fcntl.h> +#include <pwd.h> #include <stdlib.h> #include <string.h> #include <syslog.h> diff --git a/clock.c b/clock.c new file mode 100644 index 00000000..f79546d0 --- /dev/null +++ b/clock.c @@ -0,0 +1,160 @@ +/* $Id: clock.c,v 1.1 2009-01-11 00:48:42 nicm 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 <string.h> +#include <time.h> + +#include "tmux.h" + +char clock_table[14][5][5] = { + { { 1,1,1,1,1 }, /* 0 */ + { 1,0,0,0,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 0,0,0,0,1 }, /* 1 */ + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 2 */ + { 0,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,0 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 3 */ + { 0,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,0,0,0,1 }, /* 4 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 5 */ + { 1,0,0,0,0 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 6 */ + { 1,0,0,0,0 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 7 */ + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 8 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 9 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 0,0,0,0,0 }, /* : */ + { 0,0,1,0,0 }, + { 0,0,0,0,0 }, + { 0,0,1,0,0 }, + { 0,0,0,0,0 } }, + { { 1,1,1,1,1 }, /* A */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* P */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,0 }, + { 1,0,0,0,0 } }, + { { 1,0,0,0,1 }, /* M */ + { 1,1,0,1,1 }, + { 1,0,1,0,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 } }, +}; + +void +clock_draw(struct screen_write_ctx *ctx, u_int colour, int style) +{ + struct screen *s = ctx->s; + struct grid_cell gc; + char tim[64], *ptr; + time_t t; + u_int i, j, x, y, idx; + + t = time(NULL); + if (style == 0) + strftime(tim, sizeof tim, "%l:%M %p", localtime(&t)); + else + strftime(tim, sizeof tim, "%H:%M", localtime(&t)); + + screen_write_clearscreen(ctx); + memcpy(&gc, &grid_default_cell, sizeof gc); + + if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { + if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { + x = (screen_size_x(s) / 2) - (strlen(tim) / 2); + y = screen_size_y(s) / 2; + screen_write_cursormove(ctx, x, y); + + gc.fg = colour; + screen_write_puts(ctx, &gc, "%s", tim); + } + return; + } + + x = (screen_size_x(s) / 2) - 3 * strlen(tim); + y = (screen_size_y(s) / 2) - 3; + + for (ptr = tim; *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr <= '9') + idx = *ptr - '0'; + else if (*ptr == ':') + idx = 10; + else if (*ptr == 'A') + idx = 11; + else if (*ptr == 'P') + idx = 12; + else if (*ptr == 'M') + idx = 13; + else { + x += 6; + continue; + } + + for (j = 0; j < 5; j++) { + screen_write_cursormove(ctx, x, y + j); + for (i = 0; i < 5; i++) { + if (clock_table[idx][j][i]) + gc.bg = colour; + else + gc.bg = 0; + screen_write_putc(ctx, &gc, ' '); + } + } + x += 6; + } +} diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 752ec7e8..0bf3c084 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -1,4 +1,4 @@ -/* $Id: cmd-command-prompt.c,v 1.6 2008-09-26 06:45:25 nicm Exp $ */ +/* $Id: cmd-command-prompt.c,v 1.7 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -28,7 +28,7 @@ void cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); -void cmd_command_prompt_callback(void *, char *); +int cmd_command_prompt_callback(void *, const char *); const struct cmd_entry cmd_command_prompt_entry = { "command-prompt", NULL, @@ -55,14 +55,14 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) if (c->prompt_string != NULL) return; - server_set_client_prompt(c, ":", cmd_command_prompt_callback, c); + server_set_client_prompt(c, ":", cmd_command_prompt_callback, c, 0); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } -void -cmd_command_prompt_callback(void *data, char *s) +int +cmd_command_prompt_callback(void *data, const char *s) { struct client *c = data; struct cmd *cmd; @@ -70,18 +70,18 @@ cmd_command_prompt_callback(void *data, char *s) char *cause; if (s == NULL) - return; + return (0); if (cmd_string_parse(s, &cmd, &cause) != 0) { if (cause == NULL) - return; + return (0); *cause = toupper((u_char) *cause); server_set_client_message(c, cause); xfree(cause); - return; + return (0); } if (cmd == NULL) - return; + return (0); ctx.msgdata = NULL; ctx.cursession = c->session; @@ -94,4 +94,8 @@ cmd_command_prompt_callback(void *data, char *s) ctx.cmdclient = NULL; cmd_exec(cmd, &ctx); + + if (c->prompt_callback != (void *) &cmd_command_prompt_callback) + return (1); + return (0); } diff --git a/cmd-lock-server.c b/cmd-lock-server.c new file mode 100644 index 00000000..f1cf4d48 --- /dev/null +++ b/cmd-lock-server.c @@ -0,0 +1,55 @@ +/* $Id: cmd-lock-server.c,v 1.1 2009-01-11 00:48:42 nicm Exp $ */ + +/* + * Copyright (c) 2008 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 <string.h> +#include <unistd.h> + +#include "tmux.h" + +/* + * Lock server. + */ + +void cmd_lock_server_exec(struct cmd *, struct cmd_ctx *); + +int cmd_lock_server_callback(void *, const char *); + +const struct cmd_entry cmd_lock_server_entry = { + "lock-server", "lock", + "", + 0, + NULL, + NULL, + cmd_lock_server_exec, + NULL, + NULL, + NULL, + NULL, +}; + +void +cmd_lock_server_exec(unused struct cmd *self, struct cmd_ctx *ctx) +{ + server_lock(); + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} diff --git a/cmd-new-session.c b/cmd-new-session.c index 711e0776..fbb92894 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-session.c,v 1.33 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: cmd-new-session.c,v 1.34 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -118,7 +118,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) if (ctx->curclient != NULL) return; - + if (!data->flag_detached) { if (c == NULL) { ctx->error(ctx, "no client to attach to"); diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index 7f69a155..93ad57b5 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -1,4 +1,4 @@ -/* $Id: cmd-paste-buffer.c,v 1.12 2009-01-07 19:52:36 nicm Exp $ */ +/* $Id: cmd-paste-buffer.c,v 1.13 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -70,6 +70,6 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) paste_free_index(&s->buffers, data->buffer); } - if (ctx->cmdclient != NULL) + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-select-prompt.c b/cmd-select-prompt.c index 8b1fb76b..16c6fe53 100644 --- a/cmd-select-prompt.c +++ b/cmd-select-prompt.c @@ -1,4 +1,4 @@ -/* $Id: cmd-select-prompt.c,v 1.4 2009-01-05 11:04:06 nicm Exp $ */ +/* $Id: cmd-select-prompt.c,v 1.5 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -28,7 +28,7 @@ void cmd_select_prompt_exec(struct cmd *, struct cmd_ctx *); -void cmd_select_prompt_callback(void *, char *); +int cmd_select_prompt_callback(void *, const char *); const struct cmd_entry cmd_select_prompt_entry = { "select-prompt", NULL, @@ -55,14 +55,14 @@ cmd_select_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) if (c->prompt_string != NULL) return; - server_set_client_prompt(c, "index ", cmd_select_prompt_callback, c); + server_set_client_prompt(c, "index ", cmd_select_prompt_callback, c, 0); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } -void -cmd_select_prompt_callback(void *data, char *s) +int +cmd_select_prompt_callback(void *data, const char *s) { struct client *c = data; const char *errstr; @@ -70,23 +70,25 @@ cmd_select_prompt_callback(void *data, char *s) u_int idx; if (s == NULL) - return; + return (0); idx = strtonum(s, 0, UINT_MAX, &errstr); if (errstr != NULL) { xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s); server_set_client_message(c, msg); - return; + return (0); } if (winlink_find_by_index(&c->session->windows, idx) == NULL) { xsnprintf(msg, sizeof msg, "Window not found: %s:%d", c->session->name, idx); server_set_client_message(c, msg); - return; + return (0); } if (session_select(c->session, idx) == 0) server_redraw_session(c->session); recalculate_sizes(); + + return (0); } diff --git a/cmd-set-option.c b/cmd-set-option.c index 55d1a7cf..4af2e06c 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-option.c,v 1.50 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: cmd-set-option.c,v 1.51 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -52,6 +52,7 @@ const struct set_option_entry set_option_table[NSETOPTION] = { { "default-path", SET_OPTION_STRING, 0, 0, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, + { "lock-after", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "message-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "message-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "prefix", SET_OPTION_KEY, 0, 0, NULL }, diff --git a/cmd-set-password.c b/cmd-set-password.c new file mode 100644 index 00000000..583914c9 --- /dev/null +++ b/cmd-set-password.c @@ -0,0 +1,169 @@ +/* $Id: cmd-set-password.c,v 1.1 2009-01-11 00:48:42 nicm 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 **); +void cmd_set_password_exec(struct cmd *, struct cmd_ctx *); +void cmd_set_password_send(struct cmd *, struct buffer *); +void cmd_set_password_recv(struct cmd *, struct buffer *); +void cmd_set_password_free(struct cmd *); +void cmd_set_password_init(struct cmd *, int); +void 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, + cmd_set_password_init, + cmd_set_password_parse, + cmd_set_password_exec, + cmd_set_password_send, + cmd_set_password_recv, + 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, 0); + 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); +} + +void +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; + } + + if (server_password != NULL) + xfree(server_password); + if (*data->password == '\0') + server_password = NULL; + else + server_password = xstrdup(data->password); + log_debug("pw now %s", server_password); + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} + +void +cmd_set_password_send(struct cmd *self, struct buffer *b) +{ + struct cmd_set_password_data *data = self->data; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->password); +} + +void +cmd_set_password_recv(struct cmd *self, struct buffer *b) +{ + struct cmd_set_password_data *data; + + self->data = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->password = cmd_recv_string(b); +} + +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); +} + +void +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; + 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"); +} @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.71 2009-01-10 19:35:39 nicm Exp $ */ +/* $Id: cmd.c,v 1.72 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -45,6 +45,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_list_keys_entry, &cmd_list_sessions_entry, &cmd_list_windows_entry, + &cmd_lock_server_entry, &cmd_move_window_entry, &cmd_new_session_entry, &cmd_new_window_entry, @@ -63,6 +64,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_server_info_entry, &cmd_set_buffer_entry, &cmd_set_option_entry, + &cmd_set_password_entry, &cmd_set_window_option_entry, &cmd_show_buffer_entry, &cmd_show_options_entry, @@ -159,6 +161,10 @@ usage: void cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx) { + if (server_locked) { + ctx->error(ctx, "server is locked"); + return; + } cmd->entry->exec(cmd, ctx); } diff --git a/server-fn.c b/server-fn.c index fd158b9f..c24fc49a 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.52 2009-01-10 14:43:43 nicm Exp $ */ +/* $Id: server-fn.c,v 1.53 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -24,6 +24,8 @@ #include "tmux.h" +int server_lock_callback(void *, const char *); + void server_set_client_message(struct client *c, const char *msg) { @@ -57,8 +59,8 @@ server_clear_client_message(struct client *c) } void -server_set_client_prompt( - struct client *c, const char *msg, void (*fn)(void *, char *), void *data) +server_set_client_prompt(struct client *c, + const char *msg, int (*fn)(void *, const char *), void *data, int hide) { c->prompt_string = xstrdup(msg); @@ -70,6 +72,8 @@ server_set_client_prompt( c->prompt_hindex = 0; + c->prompt_hidden = hide; + c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE); c->flags |= CLIENT_STATUS; } @@ -213,3 +217,62 @@ server_status_window(struct window *w) server_status_session(s); } } + +void +server_lock(void) +{ + struct client *c; + u_int i; + + if (server_locked) + return; + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL) + continue; + + server_clear_client_prompt(c); + server_set_client_prompt( + c, "Password: ", server_lock_callback, c, 1); + 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; + u_int i; + char *out; + + if (!server_locked) + return (0); + + if (server_password != NULL) { + if (s == NULL) + return (-1); + out = crypt(s, server_password); + if (strcmp(out, server_password) != 0) + return (-1); + } + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL) + continue; + + server_clear_client_prompt(c); + server_redraw_client(c); + } + server_locked = 0; + + return (0); +} diff --git a/server-msg.c b/server-msg.c index 2f1fc681..1912a829 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.55 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: server-msg.c,v 1.56 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -29,6 +29,7 @@ int server_msg_fn_command(struct hdr *, struct client *); int server_msg_fn_identify(struct hdr *, struct client *); int server_msg_fn_resize(struct hdr *, struct client *); int server_msg_fn_exiting(struct hdr *, struct client *); +int server_msg_fn_unlock(struct hdr *, struct client *); void printflike2 server_msg_fn_command_error( struct cmd_ctx *, const char *, ...); @@ -45,7 +46,8 @@ const struct server_msg server_msg_table[] = { { MSG_IDENTIFY, server_msg_fn_identify }, { MSG_COMMAND, server_msg_fn_command }, { MSG_RESIZE, server_msg_fn_resize }, - { MSG_EXITING, server_msg_fn_exiting } + { MSG_EXITING, server_msg_fn_exiting }, + { MSG_UNLOCK, server_msg_fn_unlock } }; int @@ -135,6 +137,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) cmd = cmd_recv(c->in); log_debug("got command %s from client %d", cmd->entry->name, c->fd); + server_activity = time(NULL); ctx.error = server_msg_fn_command_error; ctx.print = server_msg_fn_command_print; @@ -244,3 +247,26 @@ server_msg_fn_exiting(struct hdr *hdr, struct client *c) return (0); } + +int +server_msg_fn_unlock(struct hdr *hdr, struct client *c) +{ + char *pass; + + if (hdr->size == 0) + fatalx("bad MSG_UNLOCK size"); + pass = cmd_recv_string(c->in); + + log_debug("unlock msg from client"); + + if (server_unlock(pass) != 0) { +#define MSG "bad password" + server_write_client(c, MSG_ERROR, MSG, (sizeof MSG) - 1); + return (0); +#undef MSG + } + + server_write_client(c, MSG_EXIT, NULL, 0); + + return (0); +} @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.93 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: server.c,v 1.94 2009-01-11 00:48:42 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -53,6 +53,8 @@ void server_handle_window(struct window *); void server_lost_client(struct client *); void server_lost_window(struct window *); void server_check_redraw(struct client *); +void server_do_redraw_client(struct client *); +void server_do_redraw_locked(struct client *); void server_check_timers(struct client *); void server_second_timers(void); int server_update_socket(const char *); @@ -101,7 +103,7 @@ server_start(const char *path) * Must daemonise before loading configuration as the PID changes so * $TMUX would be wrong for sessions created in the config file. */ - if (daemon(0, 1) != 0) + if (daemon(1, 1) != 0) fatal("daemon failed"); ARRAY_INIT(&windows); @@ -109,6 +111,10 @@ server_start(const char *path) ARRAY_INIT(&sessions); key_bindings_init(); + server_locked = 0; + server_password = NULL; + server_activity = time(NULL); + if (cfg_file != NULL && load_cfg(cfg_file, &cause) != 0) { log_warnx("%s", cause); exit(1); @@ -121,7 +127,7 @@ server_start(const char *path) log_debug("server started, pid %ld", (long) getpid()); start_time = time(NULL); socket_path = path; - + memset(&sa, 0, sizeof sa); sa.sun_family = AF_UNIX; size = strlcpy(sa.sun_path, path, sizeof sa.sun_path); @@ -215,7 +221,7 @@ server_main(const char *srv_path, int srv_fd) } pfd++; - /* Call seconds-based timers. */ + /* Call second-based timers. */ now = time(NULL); if (now != last) { last = now; @@ -311,13 +317,9 @@ server_handle_windows(struct pollfd **pfd) void server_check_redraw(struct client *c) { - struct session *s; - struct screen_redraw_ctx ctx; |