aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2009-01-11 00:48:42 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2009-01-11 00:48:42 +0000
commite3feb067a503b53da253e4ed877d212d6d73842c (patch)
treef0ebedf15d81253ae1d0437b6dc9f47cbccdc291
parentee0a7cda880f01771470b2902839c5d6396057c3 (diff)
downloadrtmux-e3feb067a503b53da253e4ed877d212d6d73842c.tar.gz
rtmux-e3feb067a503b53da253e4ed877d212d6d73842c.tar.bz2
rtmux-e3feb067a503b53da253e4ed877d212d6d73842c.zip
Server locking. set-password and lock-server commands, plus automatic locking.
-rw-r--r--CHANGES9
-rw-r--r--GNUmakefile10
-rw-r--r--Makefile6
-rw-r--r--TODO7
-rw-r--r--client.c3
-rw-r--r--clock.c160
-rw-r--r--cmd-command-prompt.c22
-rw-r--r--cmd-lock-server.c55
-rw-r--r--cmd-new-session.c4
-rw-r--r--cmd-paste-buffer.c4
-rw-r--r--cmd-select-prompt.c18
-rw-r--r--cmd-set-option.c3
-rw-r--r--cmd-set-password.c169
-rw-r--r--cmd.c8
-rw-r--r--server-fn.c69
-rw-r--r--server-msg.c30
-rw-r--r--server.c154
-rw-r--r--status.c26
-rw-r--r--tmux.c111
-rw-r--r--tmux.h32
-rw-r--r--window-clock.c152
21 files changed, 776 insertions, 276 deletions
diff --git a/CHANGES b/CHANGES
index 9d9c8651..945e09c8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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))
diff --git a/Makefile b/Makefile
index a323334f..ac0ae27b 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/TODO b/TODO
index 2d825c0a..8e976fd5 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/client.c b/client.c
index 4e012a1b..3e985b35 100644
--- a/client.c
+++ b/client.c
@@ -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");
+}
diff --git a/cmd.c b/cmd.c
index f73ab7d3..7fc213f7 100644
--- a/cmd.c
+++ b/cmd.c
@@ -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);
+}
diff --git a/server.c b/server.c
index 078183b3..1c617092 100644
--- a/server.c
+++ b/server.c
@@ -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;