summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2008-06-29 07:04:31 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2008-06-29 07:04:31 +0000
commitd90d646ca8e7ff6f97e9d11a2d746e217c7a3dcc (patch)
treee4830af4b33734b903a866103a01eebf83c2a1f1
parent09a4f6a62d6a2337fc0d801827385c2b13e691be (diff)
Zombie windows, requested by Will Maier.
-rw-r--r--CHANGES17
-rw-r--r--GNUmakefile3
-rw-r--r--Makefile3
-rw-r--r--TODO4
-rw-r--r--cmd-generic.c23
-rw-r--r--cmd-list-windows.c9
-rw-r--r--cmd-respawn-window.c74
-rw-r--r--cmd-set-option.c3
-rw-r--r--cmd-set-window-option.c16
-rw-r--r--cmd-show-window-options.c4
-rw-r--r--cmd.c3
-rw-r--r--screen.c23
-rw-r--r--server.c11
-rw-r--r--session.c6
-rw-r--r--tmux.c3
-rw-r--r--tmux.h12
-rw-r--r--window.c95
17 files changed, 254 insertions, 55 deletions
diff --git a/CHANGES b/CHANGES
index 9a1e7c8d..4ad3e010 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
* 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
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 $
diff --git a/GNUmakefile b/GNUmakefile
index 9667c202..24f6f28c 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -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
@@ -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-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 \
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
diff --git a/Makefile b/Makefile
index 13c4bc3e..c8abee11 100644
--- a/Makefile
+++ b/Makefile
@@ -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
.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-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 \
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
diff --git a/TODO b/TODO
index 967b5cb9..e4e8c846 100644
--- a/TODO
+++ b/TODO
@@ -49,12 +49,13 @@
-- For 0.4 --------------------------------------------------------------------
+- document zombie windows
- document buffer stuff
- document next/prev word
- commands: save-buffer -b number filename
load-buffer -b number filename
copy-buffer -s src-session -t dst-session -a src-index -b dst-index
- (from other session)
+ (from other session)
-- For 0.5 --------------------------------------------------------------------
@@ -73,3 +74,4 @@
have a "edit-mode" option select which keymap
- zombie windows: don't disappear when the command dies. new command
respawn-window [command] to restart; ommitting commands uses previous
+- many more info displays for various things
diff --git a/cmd-generic.c b/cmd-generic.c
index 3ede0cf6..49bb14b2 100644
--- a/cmd-generic.c
+++ b/cmd-generic.c
@@ -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>
@@ -73,6 +73,13 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
if (argc != 1)
goto usage;
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 {
if (argc != 0)
goto usage;
@@ -192,6 +199,13 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
if (argc != 1)
goto usage;
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 {
if (argc != 0)
goto usage;
@@ -325,6 +339,13 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
if (argc != 1)
goto usage;
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 {
if (argc != 0)
goto usage;
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index 19a2fc5d..ec839e14 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -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>
@@ -50,6 +50,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w;
u_int i;
unsigned long long size;
+ const char *name;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
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_size);
+ if (w->fd != -1)
+ name = ttyname(w->fd);
+ else
+ name = "";
ctx->print(ctx,
"%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),
w->base.hsize, w->base.hlimit, size);
}
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
new file mode 100644
index 00000000..0b3cb0de
--- /dev/null
+++ b/cmd-respawn-window.c
@@ -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);
+}
diff --git a/cmd-set-option.c b/cmd-set-option.c
index d3a2c8a2..a980e8c9 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -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>
@@ -64,6 +64,7 @@ const struct set_option_entry set_option_table[NSETOPTION] = {
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, SHRT_MAX, 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 },
{ "status", SET_OPTION_FLAG, 0, 0, NULL },
{ "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
diff --git a/cmd-set-window-option.c b/cmd-set-window-option.c
index ec3f0582..d7742b91 100644
--- a/cmd-set-window-option.c
+++ b/cmd-set-window-option.c
@@ -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>
@@ -218,6 +218,20 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
s->name, wl->idx, number);
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 {
ctx->error(ctx, "unknown option: %s", data->option);
return;
diff --git a/cmd-show-window-options.c b/cmd-show-window-options.c
index 1f4db81a..abd4078b 100644
--- a/cmd-show-window-options.c
+++ b/cmd-show-window-options.c
@@ -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>
@@ -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);
if (wl->window->flags & WINDOW_MONITOR)
ctx->print(ctx, "monitor-activity");
+ if (wl->window->flags & WINDOW_ZOMBIFY)
+ ctx->print(ctx, "remain-on-exit");
if (ctx->cmdclient != NULL)
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
diff --git a/cmd.c b/cmd.c
index 0fa4808c..afac3092 100644
--- a/cmd.c
+++ b/cmd.c
@@ -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>
@@ -54,6 +54,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_refresh_client_entry,
&cmd_rename_session_entry,
&cmd_rename_window_entry,
+ &cmd_respawn_window_entry,
&cmd_scroll_mode_entry,
&cmd_select_prompt_entry,
&cmd_select_window_entry,
diff --git a/screen.c b/screen.c
index 825803a7..ca253906 100644
--- a/screen.c
+++ b/screen.c
@@ -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>
@@ -156,6 +156,27 @@ screen_create(struct screen *s, u_int dx, u_int dy, u_int hlimit)
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. */
void
screen_resize(struct screen *s, u_int sx, u_int sy)
diff --git a/server.c b/server.c
index 8e596299..ca14803c 100644
--- a/server.c
+++ b/server.c
@@ -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>
@@ -263,7 +263,7 @@ server_fill_windows(struct pollfd **pfd)
u_int 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;
else {
(*pfd)->fd = w->fd;
@@ -284,7 +284,7 @@ server_handle_windows(struct pollfd **pfd)
u_int 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);
if (buffer_poll(*pfd, w->in, w->out) != 0)
server_lost_window(w);
@@ -629,6 +629,11 @@ server_lost_window(struct window *w)
log_debug("lost window %d", w->fd);
+ if (w->flags & WINDOW_ZOMBIFY) {
+ w->fd = -1;
+ return;
+ }
+
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL)
diff --git a/session.c b/session.c
index 67609172..5d3f79ea 100644
--- a/session.c
+++ b/session.c
@@ -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>
@@ -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");
if ((w = window_create(name, cmd, env, s->sx, s->sy, hlimit)) == NULL)
return (NULL);
+
+ if (options_get_number(&s->options, "remain-by-default"))
+ w->flags |= WINDOW_ZOMBIFY;
+
return (session_attach(s, w, idx));
}
diff --git a/tmux.c b/tmux.c
index 392a1279..6525a755 100644
--- a/tmux.c
+++ b/tmux.c
@@ -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>
@@ -222,6 +222,7 @@ main(int argc, char **argv)
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, "remain-by-default", 0);
if (cfg_file == NULL) {
home = getenv("HOME");
diff --git a/tmux.h b/tmux.h
index 15d5cb8e..ee3cf7bf 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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>
@@ -549,6 +549,7 @@ struct window_mode {
/* Window structure. */
struct window {
char *name;
+ char *cmd;
int fd;
struct buffer *in;
@@ -562,6 +563,7 @@ struct window {
#define WINDOW_ACTIVITY 0x4
#define WINDOW_MONITOR 0x8
#define WINDOW_AGGRESSIVE 0x10
+#define WINDOW_ZOMBIFY 0x20
u_int limitx;
u_int limity;
@@ -764,6 +766,7 @@ struct cmd_entry {
#define CMD_KFLAG 0x4
#define CMD_DFLAG 0x8
#define CMD_ONEARG 0x10
+#define CMD_ZEROONEARG 0x20
int flags;
void (*init)(struct cmd *, int);
@@ -821,7 +824,7 @@ struct set_option_entry {
const char **choices;
};
extern const struct set_option_entry set_option_table[];
-#define NSETOPTION 13
+#define NSETOPTION 14
#ifdef NO_STRTONUM
/* 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_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_window_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);
u_char screen_stringcolour(const char *);
void screen_create(struct screen *, u_int, u_int, u_int);
+void screen_reset(struct screen *);
void screen_destroy(struct screen *);
void screen_resize(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_previous(struct winlinks *, struct winlink *);
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 *);
int window_resize(struct window *, u_int, u_int);
int window_set_mode(struct window *, const struct window_mode *);
diff --git a/window.c b/window.c
index 2e5d7134..ac404d4e 100644
--- a/window.c
+++ b/window.c
@@ -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>
@@ -166,50 +166,25 @@ winlink_previous(unused struct winlinks *wwl, struct winlink *wl)
struct window *
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 winsize ws;
- int fd, mode;
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->fd = fd;
+ w->cmd = NULL;
+
+ w->fd = -1;
w->in = buffer_create(BUFSIZ);
w->out = buffer_create(BUFSIZ);
+
w->mode = NULL;
w->flags = 0;
+
w->limitx = w->limity = UINT_MAX;
screen_create(&w->base, sx, sy, hlimit);
w->screen = &w->base;
+
input_init(w);
if (name == NULL) {
@@ -238,9 +213,58 @@ window_create(const char *name,
ARRAY_ADD(&windows, w);
w->references = 0;
+ if (window_spawn(w, cmd, envp) != 0) {
+ window_destroy(w);
+ return (NULL);
+ }
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
window_destroy(struct window *w)
{
@@ -252,7 +276,8 @@ window_destroy(struct window *w)
}
ARRAY_REMOVE(&windows, i);
- close(w->fd);
+ if (w->fd != -1)
+ close(w->fd);
input_free(w);
@@ -282,7 +307,7 @@ window_resize(struct window *w, u_int sx, u_int sy)
if (w->mode != NULL)
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");
return (0);
}