| 1 |  |  | /* $OpenBSD: cmd-respawn-window.c,v 1.30 2016/01/19 15:59:12 nicm Exp $ */ | 
    
    | 2 |  |  |  | 
    
    | 3 |  |  | /* | 
    
    | 4 |  |  |  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> | 
    
    | 5 |  |  |  * | 
    
    | 6 |  |  |  * Permission to use, copy, modify, and distribute this software for any | 
    
    | 7 |  |  |  * purpose with or without fee is hereby granted, provided that the above | 
    
    | 8 |  |  |  * copyright notice and this permission notice appear in all copies. | 
    
    | 9 |  |  |  * | 
    
    | 10 |  |  |  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
    
    | 11 |  |  |  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
    
    | 12 |  |  |  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 
    
    | 13 |  |  |  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
    
    | 14 |  |  |  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER | 
    
    | 15 |  |  |  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | 
    
    | 16 |  |  |  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
    
    | 17 |  |  |  */ | 
    
    | 18 |  |  |  | 
    
    | 19 |  |  | #include <sys/types.h> | 
    
    | 20 |  |  |  | 
    
    | 21 |  |  | #include <stdlib.h> | 
    
    | 22 |  |  | #include <unistd.h> | 
    
    | 23 |  |  |  | 
    
    | 24 |  |  | #include "tmux.h" | 
    
    | 25 |  |  |  | 
    
    | 26 |  |  | /* | 
    
    | 27 |  |  |  * Respawn a window (restart the command). Kill existing if -k given. | 
    
    | 28 |  |  |  */ | 
    
    | 29 |  |  |  | 
    
    | 30 |  |  | enum cmd_retval	 cmd_respawn_window_exec(struct cmd *, struct cmd_q *); | 
    
    | 31 |  |  |  | 
    
    | 32 |  |  | const struct cmd_entry cmd_respawn_window_entry = { | 
    
    | 33 |  |  | 	.name = "respawn-window", | 
    
    | 34 |  |  | 	.alias = "respawnw", | 
    
    | 35 |  |  |  | 
    
    | 36 |  |  | 	.args = { "kt:", 0, -1 }, | 
    
    | 37 |  |  | 	.usage = "[-k] " CMD_TARGET_WINDOW_USAGE " [command]", | 
    
    | 38 |  |  |  | 
    
    | 39 |  |  | 	.tflag = CMD_WINDOW, | 
    
    | 40 |  |  |  | 
    
    | 41 |  |  | 	.flags = 0, | 
    
    | 42 |  |  | 	.exec = cmd_respawn_window_exec | 
    
    | 43 |  |  | }; | 
    
    | 44 |  |  |  | 
    
    | 45 |  |  | enum cmd_retval | 
    
    | 46 |  |  | cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq) | 
    
    | 47 |  |  | { | 
    
    | 48 |  |  | 	struct args		*args = self->args; | 
    
    | 49 |  |  | 	struct session		*s = cmdq->state.tflag.s; | 
    
    | 50 |  |  | 	struct winlink		*wl = cmdq->state.tflag.wl; | 
    
    | 51 |  |  | 	struct window		*w = wl->window; | 
    
    | 52 |  |  | 	struct window_pane	*wp; | 
    
    | 53 |  |  | 	struct environ		*env; | 
    
    | 54 |  |  | 	const char		*path; | 
    
    | 55 |  |  | 	char		 	*cause; | 
    
    | 56 |  |  | 	struct environ_entry	*envent; | 
    
    | 57 |  |  |  | 
    
    | 58 |  |  | 	if (!args_has(self->args, 'k')) { | 
    
    | 59 |  |  | 		TAILQ_FOREACH(wp, &w->panes, entry) { | 
    
    | 60 |  |  | 			if (wp->fd == -1) | 
    
    | 61 |  |  | 				continue; | 
    
    | 62 |  |  | 			cmdq_error(cmdq, "window still active: %s:%d", s->name, | 
    
    | 63 |  |  | 			    wl->idx); | 
    
    | 64 |  |  | 			return (CMD_RETURN_ERROR); | 
    
    | 65 |  |  | 		} | 
    
    | 66 |  |  | 	} | 
    
    | 67 |  |  |  | 
    
    | 68 |  |  | 	env = environ_create(); | 
    
    | 69 |  |  | 	environ_copy(global_environ, env); | 
    
    | 70 |  |  | 	environ_copy(s->environ, env); | 
    
    | 71 |  |  | 	server_fill_environ(s, env); | 
    
    | 72 |  |  |  | 
    
    | 73 |  |  | 	wp = TAILQ_FIRST(&w->panes); | 
    
    | 74 |  |  | 	TAILQ_REMOVE(&w->panes, wp, entry); | 
    
    | 75 |  |  | 	layout_free(w); | 
    
    | 76 |  |  | 	window_destroy_panes(w); | 
    
    | 77 |  |  | 	TAILQ_INSERT_HEAD(&w->panes, wp, entry); | 
    
    | 78 |  |  | 	window_pane_resize(wp, w->sx, w->sy); | 
    
    | 79 |  |  |  | 
    
    | 80 |  |  | 	path = NULL; | 
    
    | 81 |  |  | 	if (cmdq->client != NULL && cmdq->client->session == NULL) | 
    
    | 82 |  |  | 		envent = environ_find(cmdq->client->environ, "PATH"); | 
    
    | 83 |  |  | 	else | 
    
    | 84 |  |  | 		envent = environ_find(s->environ, "PATH"); | 
    
    | 85 |  |  | 	if (envent != NULL) | 
    
    | 86 |  |  | 		path = envent->value; | 
    
    | 87 |  |  |  | 
    
    | 88 |  |  | 	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env, | 
    
    | 89 |  |  | 	    s->tio, &cause) != 0) { | 
    
    | 90 |  |  | 		cmdq_error(cmdq, "respawn window failed: %s", cause); | 
    
    | 91 |  |  | 		free(cause); | 
    
    | 92 |  |  | 		environ_free(env); | 
    
    | 93 |  |  | 		server_destroy_pane(wp, 0); | 
    
    | 94 |  |  | 		return (CMD_RETURN_ERROR); | 
    
    | 95 |  |  | 	} | 
    
    | 96 |  |  | 	layout_init(w, wp); | 
    
    | 97 |  |  | 	window_pane_reset_mode(wp); | 
    
    | 98 |  |  | 	screen_reinit(&wp->base); | 
    
    | 99 |  |  | 	input_init(wp); | 
    
    | 100 |  |  | 	window_set_active_pane(w, wp); | 
    
    | 101 |  |  |  | 
    
    | 102 |  |  | 	recalculate_sizes(); | 
    
    | 103 |  |  | 	server_redraw_window(w); | 
    
    | 104 |  |  |  | 
    
    | 105 |  |  | 	environ_free(env); | 
    
    | 106 |  |  | 	return (CMD_RETURN_NORMAL); | 
    
    | 107 |  |  | } |