Zombie windows, requested by Will Maier.

This commit is contained in:
Nicholas Marriott 2008-06-29 07:04:31 +00:00
parent 09a4f6a62d
commit d90d646ca8
17 changed files with 254 additions and 55 deletions

17
CHANGES
View File

@ -1,3 +1,18 @@
29 June 2008
* Zombie windows. These are not closed when the child process dies. May be
set for a window with the new "remain-on-exit" option; the default setting
of this flag for new windows may be set with the "remain-by-default" session
option.
A window may be restarted with the respawn-window command:
respawn-window [-k] [command]
If -k is given, any existing process running in the window is killed;
if command is omitted, the same command as when the window was first
created is used.
27 June 2008 27 June 2008
* Handle nonexistent session or client to -t properly. * Handle nonexistent session or client to -t properly.
@ -577,4 +592,4 @@
(including mutt, emacs). No status bar yet and no key remapping or other (including mutt, emacs). No status bar yet and no key remapping or other
customisation. customisation.
$Id: CHANGES,v 1.145 2008-06-27 17:10:01 nicm Exp $ $Id: CHANGES,v 1.146 2008-06-29 07:04:28 nicm Exp $

View File

@ -1,4 +1,4 @@
# $Id: GNUmakefile,v 1.35 2008-06-25 20:43:13 nicm Exp $ # $Id: GNUmakefile,v 1.36 2008-06-29 07:04:29 nicm Exp $
.PHONY: clean .PHONY: clean
@ -29,6 +29,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-show-window-options.c cmd-command-prompt.c cmd-set-buffer.c \ cmd-show-window-options.c cmd-command-prompt.c cmd-set-buffer.c \
cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.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-list-commands.c cmd-move-window.c cmd-select-prompt.c \
cmd-respawn-window.c \
window-scroll.c window-more.c window-copy.c options.c paste.c \ window-scroll.c window-more.c window-copy.c options.c paste.c \
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.68 2008-06-25 20:43:13 nicm Exp $ # $Id: Makefile,v 1.69 2008-06-29 07:04:29 nicm Exp $
.SUFFIXES: .c .o .y .h .SUFFIXES: .c .o .y .h
.PHONY: clean update-index.html upload-index.html .PHONY: clean update-index.html upload-index.html
@ -33,6 +33,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-show-window-options.c cmd-command-prompt.c cmd-set-buffer.c \ cmd-show-window-options.c cmd-command-prompt.c cmd-set-buffer.c \
cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.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-list-commands.c cmd-move-window.c cmd-select-prompt.c \
cmd-respawn-window.c \
window-scroll.c window-more.c window-copy.c options.c paste.c \ window-scroll.c window-more.c window-copy.c options.c paste.c \
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c

4
TODO
View File

@ -49,12 +49,13 @@
-- For 0.4 -------------------------------------------------------------------- -- For 0.4 --------------------------------------------------------------------
- document zombie windows
- document buffer stuff - document buffer stuff
- document next/prev word - document next/prev word
- commands: save-buffer -b number filename - commands: save-buffer -b number filename
load-buffer -b number filename load-buffer -b number filename
copy-buffer -s src-session -t dst-session -a src-index -b dst-index copy-buffer -s src-session -t dst-session -a src-index -b dst-index
(from other session) (from other session)
-- For 0.5 -------------------------------------------------------------------- -- For 0.5 --------------------------------------------------------------------
@ -73,3 +74,4 @@
have a "edit-mode" option select which keymap have a "edit-mode" option select which keymap
- zombie windows: don't disappear when the command dies. new command - zombie windows: don't disappear when the command dies. new command
respawn-window [command] to restart; ommitting commands uses previous respawn-window [command] to restart; ommitting commands uses previous
- many more info displays for various things

View File

@ -1,4 +1,4 @@
/* $Id: cmd-generic.c,v 1.11 2008-06-20 08:36:20 nicm Exp $ */ /* $Id: cmd-generic.c,v 1.12 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -73,6 +73,13 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
if (argc != 1) if (argc != 1)
goto usage; goto usage;
data->arg = xstrdup(argv[0]); data->arg = xstrdup(argv[0]);
} else if (self->entry->flags & CMD_ZEROONEARG) {
if (argc == 0)
data->arg = NULL;
else if (argc == 1)
data->arg = xstrdup(argv[0]);
else
goto usage;
} else { } else {
if (argc != 0) if (argc != 0)
goto usage; goto usage;
@ -192,6 +199,13 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
if (argc != 1) if (argc != 1)
goto usage; goto usage;
data->arg = xstrdup(argv[0]); data->arg = xstrdup(argv[0]);
} else if (self->entry->flags & CMD_ZEROONEARG) {
if (argc == 0)
data->arg = NULL;
else if (argc == 1)
data->arg = xstrdup(argv[0]);
else
goto usage;
} else { } else {
if (argc != 0) if (argc != 0)
goto usage; goto usage;
@ -325,6 +339,13 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
if (argc != 1) if (argc != 1)
goto usage; goto usage;
data->arg = xstrdup(argv[0]); data->arg = xstrdup(argv[0]);
} else if (self->entry->flags & CMD_ZEROONEARG) {
if (argc == 0)
data->arg = NULL;
else if (argc == 1)
data->arg = xstrdup(argv[0]);
else
goto usage;
} else { } else {
if (argc != 0) if (argc != 0)
goto usage; goto usage;

View File

@ -1,4 +1,4 @@
/* $Id: cmd-list-windows.c,v 1.20 2008-06-05 21:25:00 nicm Exp $ */ /* $Id: cmd-list-windows.c,v 1.21 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -50,6 +50,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w; struct window *w;
u_int i; u_int i;
unsigned long long size; unsigned long long size;
const char *name;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return; return;
@ -65,9 +66,13 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
size += w->base.hsize * (sizeof *w->base.grid_colr); size += w->base.hsize * (sizeof *w->base.grid_colr);
size += w->base.hsize * (sizeof *w->base.grid_size); size += w->base.hsize * (sizeof *w->base.grid_size);
if (w->fd != -1)
name = ttyname(w->fd);
else
name = "";
ctx->print(ctx, ctx->print(ctx,
"%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]", "%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]",
wl->idx, w->name, w->base.title, ttyname(w->fd), wl->idx, w->name, w->base.title, name,
screen_size_x(&w->base), screen_size_y(&w->base), screen_size_x(&w->base), screen_size_y(&w->base),
w->base.hsize, w->base.hlimit, size); w->base.hsize, w->base.hlimit, size);
} }

74
cmd-respawn-window.c Normal file
View File

@ -0,0 +1,74 @@
/* $Id: cmd-respawn-window.c,v 1.1 2008-06-29 07:04:30 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 "tmux.h"
/*
* Respawn a window (restart the command). Kill existing if -k given.
*/
void cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw",
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
CMD_ZEROONEARG|CMD_KFLAG,
cmd_target_init,
cmd_target_parse,
cmd_respawn_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct session *s;
const char *env[] = { NULL, "TERM=screen", NULL };
char *cmd;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return;
if (wl->window->fd != -1 && !(data->flags & CMD_KFLAG)) {
ctx->error(ctx, "window still active: %s:%d", s->name, wl->idx);
return;
}
cmd = data->arg;
if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command");
if (window_spawn(wl->window, cmd, env) != 0) {
ctx->error(ctx, "respawn failed: %s:%d", s->name, wl->idx);
return;
}
screen_reset(&wl->window->base);
recalculate_sizes();
server_redraw_window(wl->window);
if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
}

View File

@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.36 2008-06-23 22:12:29 nicm Exp $ */ /* $Id: cmd-set-option.c,v 1.37 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -64,6 +64,7 @@ const struct set_option_entry set_option_table[NSETOPTION] = {
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "prefix", SET_OPTION_KEY, 0, 0, NULL }, { "prefix", SET_OPTION_KEY, 0, 0, NULL },
{ "remain-by-default", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL }, { "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
{ "status", SET_OPTION_FLAG, 0, 0, NULL }, { "status", SET_OPTION_FLAG, 0, 0, NULL },
{ "status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },

View File

@ -1,4 +1,4 @@
/* $Id: cmd-set-window-option.c,v 1.10 2008-06-18 22:21:51 nicm Exp $ */ /* $Id: cmd-set-window-option.c,v 1.11 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -218,6 +218,20 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
s->name, wl->idx, number); s->name, wl->idx, number);
recalculate_sizes(); recalculate_sizes();
} else if (strcmp(data->option, "remain-on-exit") == 0) {
if (flag == -1) {
ctx->error(ctx, "bad value: %s", data->value);
return;
}
if (flag == -2)
wl->window->flags ^= WINDOW_ZOMBIFY;
else {
if (flag)
wl->window->flags |= WINDOW_ZOMBIFY;
else
wl->window->flags &= ~WINDOW_ZOMBIFY;
}
} else { } else {
ctx->error(ctx, "unknown option: %s", data->option); ctx->error(ctx, "unknown option: %s", data->option);
return; return;

View File

@ -1,4 +1,4 @@
/* $Id: cmd-show-window-options.c,v 1.1 2008-06-16 06:10:02 nicm Exp $ */ /* $Id: cmd-show-window-options.c,v 1.2 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -60,6 +60,8 @@ cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "force-height %u", wl->window->limity); ctx->print(ctx, "force-height %u", wl->window->limity);
if (wl->window->flags & WINDOW_MONITOR) if (wl->window->flags & WINDOW_MONITOR)
ctx->print(ctx, "monitor-activity"); ctx->print(ctx, "monitor-activity");
if (wl->window->flags & WINDOW_ZOMBIFY)
ctx->print(ctx, "remain-on-exit");
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);

3
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.59 2008-06-27 17:10:01 nicm Exp $ */ /* $Id: cmd.c,v 1.60 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -54,6 +54,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_refresh_client_entry, &cmd_refresh_client_entry,
&cmd_rename_session_entry, &cmd_rename_session_entry,
&cmd_rename_window_entry, &cmd_rename_window_entry,
&cmd_respawn_window_entry,
&cmd_scroll_mode_entry, &cmd_scroll_mode_entry,
&cmd_select_prompt_entry, &cmd_select_prompt_entry,
&cmd_select_window_entry, &cmd_select_window_entry,

View File

@ -1,4 +1,4 @@
/* $Id: screen.c,v 1.62 2008-06-18 22:21:51 nicm Exp $ */ /* $Id: screen.c,v 1.63 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -156,6 +156,27 @@ screen_create(struct screen *s, u_int dx, u_int dy, u_int hlimit)
screen_clear_selection(s); screen_clear_selection(s);
} }
/* Reinitialise screen. */
void
screen_reset(struct screen *s)
{
s->cx = 0;
s->cy = 0;
s->rupper = 0;
s->rlower = s->dy - 1;
s->attr = SCREEN_DEFATTR;
s->colr = SCREEN_DEFCOLR;
s->mode = MODE_CURSOR|MODE_KCURSOR|MODE_KKEYPAD;
screen_display_fill_area(s, 0, 0,
screen_size_x(s), screen_size_y(s), ' ', 0, 0x88);
screen_clear_selection(s);
}
/* Resize screen. */ /* Resize screen. */
void void
screen_resize(struct screen *s, u_int sx, u_int sy) screen_resize(struct screen *s, u_int sx, u_int sy)

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.76 2008-06-23 07:41:21 nicm Exp $ */ /* $Id: server.c,v 1.77 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -263,7 +263,7 @@ server_fill_windows(struct pollfd **pfd)
u_int i; u_int i;
for (i = 0; i < ARRAY_LENGTH(&windows); i++) { for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
if ((w = ARRAY_ITEM(&windows, i)) == NULL) if ((w = ARRAY_ITEM(&windows, i)) == NULL || w->fd == -1)
(*pfd)->fd = -1; (*pfd)->fd = -1;
else { else {
(*pfd)->fd = w->fd; (*pfd)->fd = w->fd;
@ -284,7 +284,7 @@ server_handle_windows(struct pollfd **pfd)
u_int i; u_int i;
for (i = 0; i < ARRAY_LENGTH(&windows); i++) { for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
if ((w = ARRAY_ITEM(&windows, i)) != NULL) { if ((w = ARRAY_ITEM(&windows, i)) != NULL && w->fd != -1) {
log_debug("testing window %d (%d)", (*pfd)->fd, w->fd); log_debug("testing window %d (%d)", (*pfd)->fd, w->fd);
if (buffer_poll(*pfd, w->in, w->out) != 0) if (buffer_poll(*pfd, w->in, w->out) != 0)
server_lost_window(w); server_lost_window(w);
@ -629,6 +629,11 @@ server_lost_window(struct window *w)
log_debug("lost window %d", w->fd); log_debug("lost window %d", w->fd);
if (w->flags & WINDOW_ZOMBIFY) {
w->fd = -1;
return;
}
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i); s = ARRAY_ITEM(&sessions, i);
if (s == NULL) if (s == NULL)

View File

@ -1,4 +1,4 @@
/* $Id: session.c,v 1.39 2008-06-20 08:36:20 nicm Exp $ */ /* $Id: session.c,v 1.40 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -203,6 +203,10 @@ session_new(struct session *s, const char *name, const char *cmd, int idx)
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(&s->options, "history-limit");
if ((w = window_create(name, cmd, env, s->sx, s->sy, hlimit)) == NULL) if ((w = window_create(name, cmd, env, s->sx, s->sy, hlimit)) == NULL)
return (NULL); return (NULL);
if (options_get_number(&s->options, "remain-by-default"))
w->flags |= WINDOW_ZOMBIFY;
return (session_attach(s, w, idx)); return (session_attach(s, w, idx));
} }

3
tmux.c
View File

@ -1,4 +1,4 @@
/* $Id: tmux.c,v 1.69 2008-06-23 22:12:29 nicm Exp $ */ /* $Id: tmux.c,v 1.70 2008-06-29 07:04:30 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -222,6 +222,7 @@ main(int argc, char **argv)
options_set_number(&global_options, "status-interval", 15); options_set_number(&global_options, "status-interval", 15);
options_set_number(&global_options, "set-titles", 1); options_set_number(&global_options, "set-titles", 1);
options_set_number(&global_options, "buffer-limit", 9); options_set_number(&global_options, "buffer-limit", 9);
options_set_number(&global_options, "remain-by-default", 0);
if (cfg_file == NULL) { if (cfg_file == NULL) {
home = getenv("HOME"); home = getenv("HOME");

12
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.170 2008-06-25 20:43:14 nicm Exp $ */ /* $Id: tmux.h,v 1.171 2008-06-29 07:04:31 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -549,6 +549,7 @@ struct window_mode {
/* Window structure. */ /* Window structure. */
struct window { struct window {
char *name; char *name;
char *cmd;
int fd; int fd;
struct buffer *in; struct buffer *in;
@ -562,6 +563,7 @@ struct window {
#define WINDOW_ACTIVITY 0x4 #define WINDOW_ACTIVITY 0x4
#define WINDOW_MONITOR 0x8 #define WINDOW_MONITOR 0x8
#define WINDOW_AGGRESSIVE 0x10 #define WINDOW_AGGRESSIVE 0x10
#define WINDOW_ZOMBIFY 0x20
u_int limitx; u_int limitx;
u_int limity; u_int limity;
@ -764,6 +766,7 @@ struct cmd_entry {
#define CMD_KFLAG 0x4 #define CMD_KFLAG 0x4
#define CMD_DFLAG 0x8 #define CMD_DFLAG 0x8
#define CMD_ONEARG 0x10 #define CMD_ONEARG 0x10
#define CMD_ZEROONEARG 0x20
int flags; int flags;
void (*init)(struct cmd *, int); void (*init)(struct cmd *, int);
@ -821,7 +824,7 @@ struct set_option_entry {
const char **choices; const char **choices;
}; };
extern const struct set_option_entry set_option_table[]; extern const struct set_option_entry set_option_table[];
#define NSETOPTION 13 #define NSETOPTION 14
#ifdef NO_STRTONUM #ifdef NO_STRTONUM
/* strtonum.c */ /* strtonum.c */
@ -967,6 +970,7 @@ extern const struct cmd_entry cmd_previous_window_entry;
extern const struct cmd_entry cmd_refresh_client_entry; extern const struct cmd_entry cmd_refresh_client_entry;
extern const struct cmd_entry cmd_rename_session_entry; extern const struct cmd_entry cmd_rename_session_entry;
extern const struct cmd_entry cmd_rename_window_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_scroll_mode_entry;
extern const struct cmd_entry cmd_select_window_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_keys_entry;
@ -1171,6 +1175,7 @@ void screen_redraw_columns(struct screen_redraw_ctx *, u_int, u_int);
const char *screen_colourstring(u_char); const char *screen_colourstring(u_char);
u_char screen_stringcolour(const char *); u_char screen_stringcolour(const char *);
void screen_create(struct screen *, u_int, u_int, u_int); void screen_create(struct screen *, u_int, u_int, u_int);
void screen_reset(struct screen *);
void screen_destroy(struct screen *); void screen_destroy(struct screen *);
void screen_resize(struct screen *, u_int, u_int); void screen_resize(struct screen *, u_int, u_int);
void screen_expand_line(struct screen *, u_int, u_int); void screen_expand_line(struct screen *, u_int, u_int);
@ -1201,7 +1206,8 @@ void winlink_remove(struct winlinks *, struct winlink *);
struct winlink *winlink_next(struct winlinks *, struct winlink *); struct winlink *winlink_next(struct winlinks *, struct winlink *);
struct winlink *winlink_previous(struct winlinks *, struct winlink *); struct winlink *winlink_previous(struct winlinks *, struct winlink *);
struct window *window_create(const char *, struct window *window_create(const char *,
const char *, const char **, u_int, u_int, u_int); const char *, const char **, u_int, u_int, u_int);
int window_spawn(struct window *, const char *, const char **);
void window_destroy(struct window *); void window_destroy(struct window *);
int window_resize(struct window *, u_int, u_int); int window_resize(struct window *, u_int, u_int);
int window_set_mode(struct window *, const struct window_mode *); int window_set_mode(struct window *, const struct window_mode *);

View File

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.45 2008-06-20 17:31:48 nicm Exp $ */ /* $Id: window.c,v 1.46 2008-06-29 07:04:31 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -166,50 +166,25 @@ winlink_previous(unused struct winlinks *wwl, struct winlink *wl)
struct window * struct window *
window_create(const char *name, window_create(const char *name,
const char *cmd, const char **env, u_int sx, u_int sy, u_int hlimit) const char *cmd, const char **envp, u_int sx, u_int sy, u_int hlimit)
{ {
struct window *w; struct window *w;
struct winsize ws;
int fd, mode;
char *ptr, *copy; char *ptr, *copy;
const char **entry;
memset(&ws, 0, sizeof ws);
ws.ws_col = sx;
ws.ws_row = sy;
switch (forkpty(&fd, NULL, NULL, &ws)) {
case -1:
return (NULL);
case 0:
for (entry = env; *entry != NULL; entry++) {
if (putenv(*entry) != 0)
fatal("putenv failed");
}
sigreset();
log_debug("started child: cmd=%s; pid=%d", cmd, (int) getpid());
log_close();
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
fatal("execl failed");
}
if ((mode = fcntl(fd, F_GETFL)) == -1)
fatal("fcntl failed");
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed");
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed");
w = xmalloc(sizeof *w); w = xmalloc(sizeof *w);
w->fd = fd; w->cmd = NULL;
w->fd = -1;
w->in = buffer_create(BUFSIZ); w->in = buffer_create(BUFSIZ);
w->out = buffer_create(BUFSIZ); w->out = buffer_create(BUFSIZ);
w->mode = NULL; w->mode = NULL;
w->flags = 0; w->flags = 0;
w->limitx = w->limity = UINT_MAX; w->limitx = w->limity = UINT_MAX;
screen_create(&w->base, sx, sy, hlimit); screen_create(&w->base, sx, sy, hlimit);
w->screen = &w->base; w->screen = &w->base;
input_init(w); input_init(w);
if (name == NULL) { if (name == NULL) {
@ -238,9 +213,58 @@ window_create(const char *name,
ARRAY_ADD(&windows, w); ARRAY_ADD(&windows, w);
w->references = 0; w->references = 0;
if (window_spawn(w, cmd, envp) != 0) {
window_destroy(w);
return (NULL);
}
return (w); return (w);
} }
int
window_spawn(struct window *w, const char *cmd, const char **envp)
{
struct winsize ws;
int mode;
const char **envq;
if (w->fd != -1)
close(w->fd);
if (cmd != NULL) {
if (w->cmd != NULL)
xfree(w->cmd);
w->cmd = xstrdup(cmd);
}
memset(&ws, 0, sizeof ws);
ws.ws_col = screen_size_x(&w->base);
ws.ws_row = screen_size_y(&w->base);
switch (forkpty(&w->fd, NULL, NULL, &ws)) {
case -1:
return (1);
case 0:
for (envq = envp; *envq != NULL; envq++) {
if (putenv(*envq) != 0)
fatal("putenv failed");
}
sigreset();
log_debug("new child: cmd=%s; pid=%d", w->cmd, (int) getpid());
log_close();
execl(_PATH_BSHELL, "sh", "-c", w->cmd, (char *) NULL);
fatal("execl failed");
}
if ((mode = fcntl(w->fd, F_GETFL)) == -1)
fatal("fcntl failed");
if (fcntl(w->fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed");
if (fcntl(w->fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed");
return (0);
}
void void
window_destroy(struct window *w) window_destroy(struct window *w)
{ {
@ -252,7 +276,8 @@ window_destroy(struct window *w)
} }
ARRAY_REMOVE(&windows, i); ARRAY_REMOVE(&windows, i);
close(w->fd); if (w->fd != -1)
close(w->fd);
input_free(w); input_free(w);
@ -282,7 +307,7 @@ window_resize(struct window *w, u_int sx, u_int sy)
if (w->mode != NULL) if (w->mode != NULL)
w->mode->resize(w, sx, sy); w->mode->resize(w, sx, sy);
if (ioctl(w->fd, TIOCSWINSZ, &ws) == -1) if (w->fd != -1 && ioctl(w->fd, TIOCSWINSZ, &ws) == -1)
fatal("ioctl failed"); fatal("ioctl failed");
return (0); return (0);
} }