diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2008-06-29 07:04:31 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2008-06-29 07:04:31 +0000 |
commit | d90d646ca8e7ff6f97e9d11a2d746e217c7a3dcc (patch) | |
tree | e4830af4b33734b903a866103a01eebf83c2a1f1 /window.c | |
parent | 09a4f6a62d6a2337fc0d801827385c2b13e691be (diff) | |
download | rtmux-d90d646ca8e7ff6f97e9d11a2d746e217c7a3dcc.tar.gz rtmux-d90d646ca8e7ff6f97e9d11a2d746e217c7a3dcc.tar.bz2 rtmux-d90d646ca8e7ff6f97e9d11a2d746e217c7a3dcc.zip |
Zombie windows, requested by Will Maier.
Diffstat (limited to 'window.c')
-rw-r--r-- | window.c | 95 |
1 files changed, 60 insertions, 35 deletions
@@ -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); } |