Server locking. set-password and lock-server commands, plus automatic locking.

This commit is contained in:
Nicholas Marriott 2009-01-11 00:48:42 +00:00
parent ee0a7cda88
commit e3feb067a5
21 changed files with 778 additions and 278 deletions

View File

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

View File

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

View File

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

7
TODO
View File

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

View File

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

160
clock.c Normal file
View File

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

View File

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

55
cmd-lock-server.c Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

169
cmd-set-password.c Normal file
View File

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

8
cmd.c
View File

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

View File

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

View File

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

124
server.c
View File

@ -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);
@ -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;
@ -312,10 +318,6 @@ 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;
@ -336,19 +338,53 @@ server_check_redraw(struct client *c)
}
}
if (c->flags & CLIENT_REDRAW) {
if (server_locked)
server_do_redraw_locked(c);
else
server_do_redraw_client(c);
c->flags |= CLIENT_STATUS;
}
if (c->flags & CLIENT_STATUS) {
if (c->message_string != NULL)
status_message_redraw(c);
else if (c->prompt_string != NULL)
status_prompt_redraw(c);
else
status_redraw(c);
}
c->tty.flags |= flags;
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;
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.
* 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)
@ -366,22 +402,33 @@ server_check_redraw(struct client *c)
screen_redraw_start_client(&ctx, c);
screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s));
screen_redraw_stop(&ctx);
c->flags |= CLIENT_STATUS;
}
if (c->flags & CLIENT_STATUS) {
if (c->message_string != NULL)
status_message_redraw(c);
else if (c->prompt_string != NULL)
status_prompt_redraw(c);
else
status_redraw(c);
}
/* 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;
c->tty.flags |= flags;
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");
c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS);
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. */
@ -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. */

View File

@ -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,14 +609,14 @@ 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);
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);
if (c->prompt_callback(c->prompt_data, NULL) == 0)
server_clear_client_prompt(c);
break;
default:

89
tmux.c
View File

@ -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,6 +319,16 @@ main(int argc, char **argv)
}
options_set_string(&global_options, "default-path", "%s", cwd);
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;
@ -319,18 +337,25 @@ main(int argc, char **argv)
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)
if (client_init(rpath, &cctx, start_server, flags) != 0)
exit(1);
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_write_server2(&cctx,
MSG_COMMAND, &data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
client_fill_session(&cmddata);
client_write_server2(&cctx, MSG_COMMAND,
&cmddata, sizeof cmddata, BUFFER_OUT(b), BUFFER_USED(b));
}
buffer_destroy(b);
for (;;) {

36
tmux.h
View File

@ -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_ERROR,
MSG_PRINT,
MSG_EXIT,
MSG_EXITING,
MSG_EXITED,
MSG_DETACH,
MSG_ERROR,
MSG_EXIT,
MSG_EXITED,
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 *);

View File

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