mirror of
https://github.com/tmux/tmux.git
synced 2024-12-12 17:38:48 +00:00
Server locking. set-password and lock-server commands, plus automatic locking.
This commit is contained in:
parent
ee0a7cda88
commit
e3feb067a5
9
CHANGES
9
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
|
||||
|
10
GNUmakefile
10
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))
|
||||
|
6
Makefile
6
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
|
||||
|
7
TODO
7
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
|
||||
|
3
client.c
3
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>
|
||||
|
160
clock.c
Normal file
160
clock.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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
55
cmd-lock-server.c
Normal 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);
|
||||
}
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
169
cmd-set-password.c
Normal 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
8
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);
|
||||
}
|
||||
|
||||
|
69
server-fn.c
69
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);
|
||||
}
|
||||
|
30
server-msg.c
30
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);
|
||||
}
|
||||
|
124
server.c
124
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);
|
||||
@ -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. */
|
||||
|
22
status.c
22
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,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
89
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,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
36
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_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 *);
|
||||
|
152
window-clock.c
152
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user