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;
- struct screen screen;
- struct grid_cell gc;
- u_int xx, yy, sx, sy;
- char *title;
- int flags;
+ struct session *s;
+ char *title;
+ int flags;
if (c == NULL || c->session == NULL)
return;
@@ -336,36 +338,11 @@ server_check_redraw(struct client *c)
}
}
- xx = c->sx;
- yy = c->sy - 1;
if (c->flags & CLIENT_REDRAW) {
- sx = screen_size_x(s->curw->window->screen);
- sy = screen_size_y(s->curw->window->screen);
- if (sx < xx || sy < yy) {
- /*
- * Fake up a blank(ish) screen and use it to draw the
- * empty regions. NOTE: because this uses
- * tty_write_client but doesn't write the client's
- * screen, this can't use anything which relies on
- * cursor position.
- */
- screen_init(&screen, xx, yy, 0);
- screen_redraw_start(&ctx, &screen, tty_write_client, c);
- if (sx < xx)
- screen_redraw_columns(&ctx, sx, xx - sx);
- if (sy < yy) {
- memcpy(&gc, &grid_default_cell, sizeof gc);
- gc.data = '-';
- grid_view_fill(screen.grid, &gc, 0, sy, xx, 1);
- screen_redraw_lines(&ctx, sy, yy - sy);
- }
- screen_redraw_stop(&ctx);
- screen_free(&screen);
- }
-
- screen_redraw_start_client(&ctx, c);
- screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
- screen_redraw_stop(&ctx);
+ if (server_locked)
+ server_do_redraw_locked(c);
+ else
+ server_do_redraw_client(c);
c->flags |= CLIENT_STATUS;
}
@@ -384,6 +361,76 @@ server_check_redraw(struct client *c)
c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS);
}
+/* Redraw client normally. */
+void
+server_do_redraw_client(struct client *c)
+{
+ struct session *s = c->session;
+ struct screen_redraw_ctx ctx;
+ struct screen screen;
+ struct grid_cell gc;
+ u_int xx, yy, sx, sy;
+
+ xx = c->sx;
+ yy = c->sy - 1;
+
+ sx = screen_size_x(s->curw->window->screen);
+ sy = screen_size_y(s->curw->window->screen);
+
+ if (sx < xx || sy < yy) {
+ /*
+ * Fake up a blank(ish) screen and use it to draw the empty
+ * regions. NOTE: because this uses tty_write_client but
+ * doesn't write the client's screen, this can't use anything
+ * which relies on cursor position.
+ */
+
+ screen_init(&screen, xx, yy, 0);
+ screen_redraw_start(&ctx, &screen, tty_write_client, c);
+ if (sx < xx)
+ screen_redraw_columns(&ctx, sx, xx - sx);
+ if (sy < yy) {
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ gc.data = '-';
+ grid_view_fill(screen.grid, &gc, 0, sy, xx, 1);
+ screen_redraw_lines(&ctx, sy, yy - sy);
+ }
+ screen_redraw_stop(&ctx);
+ screen_free(&screen);
+ }
+
+ screen_redraw_start_client(&ctx, c);
+ screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
+ screen_redraw_stop(&ctx);
+}
+
+/* Redraw client when locked. */
+void
+server_do_redraw_locked(struct client *c)
+{
+ struct session *s = c->session;
+ struct window *w = s->curw->window;
+ struct screen_write_ctx ctx;
+ struct screen screen;
+ u_int colour, xx, yy;
+ int style;
+
+ xx = c->sx;
+ yy = c->sy - 1;
+ if (xx == 0 || yy == 0)
+ return;
+ colour = options_get_number(&w->options, "clock-mode-colour");
+ style = options_get_number(&w->options, "clock-mode-style");
+
+ screen_init(&screen, xx, yy, 0);
+
+ screen_write_start(&ctx, &screen, tty_write_client, c);
+ clock_draw(&ctx, colour, style);
+ screen_write_stop(&ctx);
+
+ screen_free(&screen);
+}
+
/* Check for timers on client. */
void
server_check_timers(struct client *c)
@@ -546,11 +593,15 @@ server_handle_client(struct client *c)
prefix = options_get_number(&c->session->options, "prefix");
while (tty_keys_next(&c->tty, &key) == 0) {
+ server_activity = time(NULL);
+
server_clear_client_message(c);
if (c->prompt_string != NULL) {
status_prompt_key(c, key);
continue;
}
+ if (server_locked)
+ continue;
if (c->flags & CLIENT_PREFIX) {
key_bindings_dispatch(key, c);
@@ -708,12 +759,35 @@ server_second_timers(void)
{
struct window *w;
u_int i;
+ int xtimeout;
+ struct tm now, then;
+ static time_t last_t = 0;
+ time_t t;
+
+ t = time(NULL);
+ xtimeout = options_get_number(&global_options, "lock-after-time");
+ if (xtimeout > 0 && t > server_activity + xtimeout)
+ server_lock();
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
w = ARRAY_ITEM(&windows, i);
if (w->mode != NULL && w->mode->timer != NULL)
w->mode->timer(w);
}
+
+ 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 (ARRAY_ITEM(&clients, i) != NULL)
+ server_redraw_client(ARRAY_ITEM(&clients, i));
+ }
+ }
}
/* Update socket execute permissions based on whether sessions are attached. */
diff --git a/status.c b/status.c
index ab094cce..2a8a7efa 100644
--- a/status.c
+++ b/status.c
@@ -1,4 +1,4 @@
-/* $Id: status.c,v 1.58 2009-01-10 01:51:22 nicm Exp $ */
+/* $Id: status.c,v 1.59 2009-01-11 00:48:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -407,7 +407,7 @@ status_prompt_redraw(struct client *c)
{
struct screen_redraw_ctx ctx;
struct session *s = c->session;
- size_t i, xx, yy, left, size, offset;
+ size_t i, xx, yy, left, size, offset, n;
char ch;
struct grid_cell gc;
@@ -439,8 +439,16 @@ status_prompt_redraw(struct client *c)
left--;
size = left;
}
- screen_redraw_puts(
- &ctx, &gc, "%.*s", (int) left, c->prompt_buffer + offset);
+ if (c->prompt_hidden) {
+ n = strlen(c->prompt_buffer);
+ if (n > left)
+ n = left;
+ for (i = 0; i < n; i++)
+ screen_redraw_putc(&ctx, &gc, '*');
+ } else {
+ screen_redraw_puts(&ctx, &gc,
+ "%.*s", (int) left, c->prompt_buffer + offset);
+ }
for (i = xx + size; i < c->sx; i++) {
screen_redraw_putc(&ctx, &gc, ' ');
@@ -601,15 +609,15 @@ status_prompt_key(struct client *c, int key)
case '\r': /* enter */
if (*c->prompt_buffer != '\0') {
status_prompt_add_history(c);
-
- c->prompt_callback(c->prompt_data, c->prompt_buffer);
- server_clear_client_prompt(c);
+ if (c->prompt_callback(
+ c->prompt_data, c->prompt_buffer) == 0)
+ server_clear_client_prompt(c);
break;
}
/* FALLTHROUGH */
case '\033': /* escape */
- c->prompt_callback(c->prompt_data, NULL);
- server_clear_client_prompt(c);
+ if (c->prompt_callback(c->prompt_data, NULL) == 0)
+ server_clear_client_prompt(c);
break;
default:
if (key < 32)
diff --git a/tmux.c b/tmux.c
index 64d50743..580c59e4 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id: tmux.c,v 1.91 2009-01-10 19:37:35 nicm Exp $ */
+/* $Id: tmux.c,v 1.92 2009-01-11 00:48:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -50,6 +50,10 @@ char *cfg_file;
struct options global_options;
struct options global_window_options;
+int server_locked;
+char *server_password;
+time_t server_activity;
+
int debug_level;
int be_quiet;
time_t start_time;
@@ -170,20 +174,20 @@ int
main(int argc, char **argv)
{
struct client_ctx cctx;
- struct msg_command_data data;
+ struct msg_command_data cmddata;
struct buffer *b;
struct cmd *cmd;
struct pollfd pfd;
struct hdr hdr;
const char *shell;
struct passwd *pw;
- char *path, *cause, *home;
+ char *path, *cause, *home, *pass = NULL;
char rpath[MAXPATHLEN], cwd[MAXPATHLEN];
- int n, opt, flags;
+ int n, opt, flags, unlock, start_server;
- flags = 0;
+ unlock = flags = 0;
path = NULL;
- while ((opt = getopt(argc, argv, "2df:qS:uVv")) != -1) {
+ while ((opt = getopt(argc, argv, "2df:qS:uUVv")) != -1) {
switch (opt) {
case '2':
flags |= IDENTIFY_256COLOURS;
@@ -200,6 +204,9 @@ main(int argc, char **argv)
case 'u':
flags |= IDENTIFY_UTF8;
break;
+ case 'U':
+ unlock = 1;
+ break;
case 'd':
flags |= IDENTIFY_HASDEFAULTS;
break;
@@ -220,36 +227,37 @@ main(int argc, char **argv)
siginit();
options_init(&global_options, NULL);
- options_set_number(&global_options, "status", 1);
- options_set_number(&global_options, "status-fg", 0);
- options_set_number(&global_options, "status-bg", 2);
options_set_number(&global_options, "bell-action", BELL_ANY);
- options_set_number(&global_options, "history-limit", 2000);
+ options_set_number(&global_options, "buffer-limit", 9);
options_set_number(&global_options, "display-time", 750);
+ options_set_number(&global_options, "history-limit", 2000);
+ options_set_number(&global_options, "message-bg", 3);
+ options_set_number(&global_options, "message-fg", 0);
options_set_number(&global_options, "prefix", META);
+ options_set_number(&global_options, "set-titles", 1);
+ options_set_number(&global_options, "lock-after-time", 1800);
+ options_set_number(&global_options, "status", 1);
+ options_set_number(&global_options, "status-bg", 2);
+ options_set_number(&global_options, "status-fg", 0);
+ options_set_number(&global_options, "status-interval", 15);
+ options_set_number(&global_options, "status-left-length", 10);
+ options_set_number(&global_options, "status-right-length", 40);
options_set_string(&global_options, "status-left", "%s", ""); /* ugh */
options_set_string(
&global_options, "status-right", "\"#24T\" %%H:%%M %%d-%%b-%%y");
- options_set_number(&global_options, "status-left-length", 10);
- options_set_number(&global_options, "status-right-length", 40);
- options_set_number(&global_options, "status-interval", 15);
- options_set_number(&global_options, "set-titles", 1);
- options_set_number(&global_options, "buffer-limit", 9);
- options_set_number(&global_options, "message-fg", 0);
- options_set_number(&global_options, "message-bg", 3);
options_init(&global_window_options, NULL);
- options_set_number(&global_window_options, "xterm-keys", 0);
- options_set_number(&global_window_options, "monitor-activity", 0);
options_set_number(&global_window_options, "aggressive-resize", 0);
- options_set_number(&global_window_options, "remain-on-exit", 0);
- options_set_number(&global_window_options, "utf8", 0);
- options_set_number(&global_window_options, "mode-fg", 0);
- options_set_number(&global_window_options, "mode-bg", 3);
- options_set_number(&global_window_options, "mode-keys", MODEKEY_EMACS);
- options_set_number(&global_window_options, "force-width", 0);
- options_set_number(&global_window_options, "force-height", 0);
options_set_number(&global_window_options, "clock-mode-colour", 4);
options_set_number(&global_window_options, "clock-mode-style", 1);
+ options_set_number(&global_window_options, "force-height", 0);
+ options_set_number(&global_window_options, "force-width", 0);
+ options_set_number(&global_window_options, "mode-bg", 3);
+ options_set_number(&global_window_options, "mode-fg", 0);
+ options_set_number(&global_window_options, "mode-keys", MODEKEY_EMACS);
+ options_set_number(&global_window_options, "monitor-activity", 0);
+ options_set_number(&global_window_options, "utf8", 0);
+ options_set_number(&global_window_options, "xterm-keys", 0);
+ options_set_number(&global_window_options, "remain-on-exit", 0);
if (cfg_file == NULL) {
home = getenv("HOME");
@@ -311,26 +319,43 @@ main(int argc, char **argv)
}
options_set_string(&global_options, "default-path", "%s", cwd);
- if (argc == 0) {
- cmd = xmalloc(sizeof *cmd);
- cmd->entry = &cmd_new_session_entry;
- cmd->entry->init(cmd, 0);
- } else if ((cmd = cmd_parse(argc, argv, &cause)) == NULL) {
- log_warnx("%s", cause);
- exit(1);
+ if (unlock) {
+ if (argc != 0) {
+ log_warnx("can't specify a command when unlocking");
+ exit(1);
+ }
+ cmd = NULL;
+ if ((pass = getpass("Password: ")) == NULL)
+ exit(1);
+ start_server = 0;
+ } else {
+ if (argc == 0) {
+ cmd = xmalloc(sizeof *cmd);
+ cmd->entry = &cmd_new_session_entry;
+ cmd->entry->init(cmd, 0);
+ } else if ((cmd = cmd_parse(argc, argv, &cause)) == NULL) {
+ log_warnx("%s", cause);
+ exit(1);
+ }
+ start_server = cmd->entry->flags & CMD_STARTSERVER;
}
-
- memset(&cctx, 0, sizeof cctx);
- client_fill_session(&data);
- if (client_init(
- rpath, &cctx, cmd->entry->flags & CMD_STARTSERVER, flags) != 0)
+
+ memset(&cctx, 0, sizeof cctx);
+ if (client_init(rpath, &cctx, start_server, flags) != 0)
exit(1);
- b = buffer_create(BUFSIZ);
- cmd_send(cmd, b);
- cmd_free(cmd);
- client_write_server2(&cctx,
- MSG_COMMAND, &data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
+ b = buffer_create(BUFSIZ);
+ if (unlock) {
+ cmd_send_string(b, pass);
+ client_write_server(
+ &cctx, MSG_UNLOCK, BUFFER_OUT(b), BUFFER_USED(b));
+ } else {
+ cmd_send(cmd, b);
+ cmd_free(cmd);
+ client_fill_session(&cmddata);
+ client_write_server2(&cctx, MSG_COMMAND,
+ &cmddata, sizeof cmddata, BUFFER_OUT(b), BUFFER_USED(b));
+ }
buffer_destroy(b);
for (;;) {
diff --git a/tmux.h b/tmux.h
index 96e387e6..c280845b 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.220 2009-01-10 22:28:40 nicm Exp $ */
+/* $Id: tmux.h,v 1.221 2009-01-11 00:48:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,7 +19,7 @@
#ifndef TMUX_H
#define TMUX_H
-#define PROTOCOL_VERSION -4
+#define PROTOCOL_VERSION -6
/* Shut up gcc warnings about empty if bodies. */
#define RB_AUGMENT(x) do {} while (0)
@@ -361,15 +361,16 @@ enum tty_cmd {
/* Message codes. */
enum hdrtype {
MSG_COMMAND,
+ MSG_DETACH,
MSG_ERROR,
- MSG_PRINT,
MSG_EXIT,
- MSG_EXITING,
MSG_EXITED,
- MSG_DETACH,
+ MSG_EXITING,
MSG_IDENTIFY,
+ MSG_PRINT,
MSG_READY,
MSG_RESIZE,
+ MSG_UNLOCK,
};
/* Message header structure. */
@@ -754,8 +755,9 @@ struct client {
char *prompt_string;
char *prompt_buffer;
size_t prompt_index;
- void (*prompt_callback)(void *, char *);
+ int (*prompt_callback)(void *, const char *);
void *prompt_data;
+ int prompt_hidden;
u_int prompt_hindex;
ARRAY_DECL(, char *) prompt_hdata;
@@ -872,7 +874,7 @@ struct set_option_entry {
};
extern const struct set_option_entry set_option_table[];
extern const struct set_option_entry set_window_option_table[];
-#define NSETOPTION 18
+#define NSETOPTION 19
#define NSETWINDOWOPTION 12
/* Edit keys. */
@@ -938,6 +940,9 @@ extern volatile sig_atomic_t sigterm;
extern struct options global_options;
extern struct options global_window_options;
extern char *cfg_file;
+extern int server_locked;
+extern char *server_password;
+extern time_t server_activity;
extern int debug_level;
extern int be_quiet;
extern time_t start_time;
@@ -1029,6 +1034,9 @@ int paste_free_index(struct paste_stack *, u_int);
void paste_add(struct paste_stack *, const char *, u_int);
int paste_replace(struct paste_stack *, u_int, const char *);
+/* clock.c */
+void clock_draw(struct screen_write_ctx *, u_int, int);
+
/* arg.c */
struct client *arg_parse_client(const char *);
struct session *arg_parse_session(const char *);
@@ -1067,6 +1075,7 @@ extern const struct cmd_entry cmd_list_commands_entry;
extern const struct cmd_entry cmd_list_keys_entry;
extern const struct cmd_entry cmd_list_sessions_entry;
extern const struct cmd_entry cmd_list_windows_entry;
+extern const struct cmd_entry cmd_lock_server_entry;
extern const struct cmd_entry cmd_move_window_entry;
extern const struct cmd_entry cmd_new_session_entry;
extern const struct cmd_entry cmd_new_window_entry;
@@ -1078,13 +1087,14 @@ extern const struct cmd_entry cmd_rename_session_entry;
extern const struct cmd_entry cmd_rename_window_entry;
extern const struct cmd_entry cmd_respawn_window_entry;
extern const struct cmd_entry cmd_scroll_mode_entry;
+extern const struct cmd_entry cmd_select_prompt_entry;
extern const struct cmd_entry cmd_select_window_entry;
extern const struct cmd_entry cmd_send_keys_entry;
extern const struct cmd_entry cmd_send_prefix_entry;
extern const struct cmd_entry cmd_server_info_entry;
-extern const struct cmd_entry cmd_select_prompt_entry;
extern const struct cmd_entry cmd_set_buffer_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_show_buffer_entry;
extern const struct cmd_entry cmd_show_options_entry;
@@ -1183,8 +1193,8 @@ int server_msg_dispatch(struct client *);
/* server-fn.c */
void server_set_client_message(struct client *, const char *);
void server_clear_client_message(struct client *);
-void server_set_client_prompt(
- struct client *, const char *, void (*)(void *, char *), void *);
+void server_set_client_prompt(struct client *,
+ const char *, int (*)(void *, const char *), void *, int);
void server_clear_client_prompt(struct client *);
struct session *server_extract_session(
struct msg_command_data *, char *, char **);
@@ -1200,6 +1210,8 @@ void server_redraw_session(struct session *);
void server_status_session(struct session *);
void server_redraw_window(struct window *);
void server_status_window(struct window *);
+void server_lock(void);
+int server_unlock(const char *);
/* status.c */
void status_redraw(struct client *);
diff --git a/window-clock.c b/window-clock.c
index 9e075000..0462142d 100644
--- a/window-clock.c
+++ b/window-clock.c
@@ -1,4 +1,4 @@
-/* $Id: window-clock.c,v 1.2 2009-01-10 19:40:01 nicm Exp $ */
+/* $Id: window-clock.c,v 1.3 2009-01-11 00:48:42 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -41,6 +41,7 @@ const struct window_mode window_clock_mode = {
struct window_clock_mode_data {
struct screen screen;
+ time_t tim;
};
struct screen *
@@ -50,6 +51,7 @@ window_clock_init(struct window *w)
struct screen *s;
w->modedata = data = xmalloc(sizeof *data);
+ data->tim = time(NULL);
s = &data->screen;
screen_init(s, screen_size_x(&w->base), screen_size_y(&w->base), 0);
@@ -88,6 +90,17 @@ window_clock_key(struct window *w, unused struct client *c, unused int key)
void
window_clock_timer(struct window *w)
{
+ struct window_clock_mode_data *data = w->modedata;
+ struct tm *now, *then;
+ time_t t;
+
+ t = time(NULL);
+ now = gmtime(&t);
+ then = gmtime(&data->tim);
+ if (now->tm_min == then->tm_min)
+ return;
+ data->tim = t;
+
window_clock_draw_screen(w);
server_redraw_window(w);
}
@@ -96,141 +109,14 @@ void
window_clock_draw_screen(struct window *w)
{
struct window_clock_mode_data *data = w->modedata;
- struct screen *s = &data->screen;
struct screen_write_ctx ctx;
- struct grid_cell gc;
- char tim[64], *ptr;
- time_t t;
- u_int colour, i, j, x, y, idx;
- char 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 } },
- };
+ u_int colour;
+ int style;
colour = options_get_number(&w->options, "clock-mode-colour");
+ style = options_get_number(&w->options, "clock-mode-style");
- t = time(NULL);
- if (options_get_number(&w->options, "clock-mode-style") == 0)
- strftime(tim, sizeof tim, "%l:%M %p", localtime(&t));
- else
- strftime(tim, sizeof tim, "%H:%M", localtime(&t));
-
- screen_write_start(&ctx, s, NULL, NULL);
- 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);
- }
- screen_write_stop(&ctx);
- 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 (table[idx][j][i])
- gc.bg = colour;
- else
- gc.bg = 0;
- screen_write_putc(&ctx, &gc, ' ');
- }
- }
- x += 6;
- }
-
+ screen_write_start(&ctx, &data->screen, NULL, NULL);
+ clock_draw(&ctx, colour, style);
screen_write_stop(&ctx);
}