1 /* $OpenBSD: cmd-new-window.c,v 1.74 2018/05/03 16:56:59 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2007 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 <errno.h> 22 #include <fcntl.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "tmux.h" 28 29 /* 30 * Create a new window. 31 */ 32 33 #define NEW_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}" 34 35 static enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmdq_item *); 36 37 const struct cmd_entry cmd_new_window_entry = { 38 .name = "new-window", 39 .alias = "neww", 40 41 .args = { "ac:dF:kn:Pt:", 0, -1 }, 42 .usage = "[-adkP] [-c start-directory] [-F format] [-n window-name] " 43 CMD_TARGET_WINDOW_USAGE " [command]", 44 45 .target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX }, 46 47 .flags = 0, 48 .exec = cmd_new_window_exec 49 }; 50 51 static enum cmd_retval 52 cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) 53 { 54 struct args *args = self->args; 55 struct cmd_find_state *current = &item->shared->current; 56 struct session *s = item->target.s; 57 struct winlink *wl = item->target.wl; 58 struct client *c = cmd_find_client(item, NULL, 1); 59 int idx = item->target.idx; 60 const char *cmd, *path, *template, *tmp; 61 char **argv, *cause, *cp, *cwd, *name; 62 int argc, detached; 63 struct environ_entry *envent; 64 struct cmd_find_state fs; 65 66 if (args_has(args, 'a') && wl != NULL) { 67 if ((idx = winlink_shuffle_up(s, wl)) == -1) { 68 cmdq_error(item, "no free window indexes"); 69 return (CMD_RETURN_ERROR); 70 } 71 } 72 detached = args_has(args, 'd'); 73 74 if (args->argc == 0) { 75 cmd = options_get_string(s->options, "default-command"); 76 if (cmd != NULL && *cmd != '\0') { 77 argc = 1; 78 argv = (char **)&cmd; 79 } else { 80 argc = 0; 81 argv = NULL; 82 } 83 } else { 84 argc = args->argc; 85 argv = args->argv; 86 } 87 88 path = NULL; 89 if (item->client != NULL && item->client->session == NULL) 90 envent = environ_find(item->client->environ, "PATH"); 91 else 92 envent = environ_find(s->environ, "PATH"); 93 if (envent != NULL) 94 path = envent->value; 95 96 if ((tmp = args_get(args, 'c')) != NULL) 97 cwd = format_single(item, tmp, c, s, NULL, NULL); 98 else if (item->client != NULL && item->client->session == NULL) 99 cwd = xstrdup(item->client->cwd); 100 else 101 cwd = xstrdup(s->cwd); 102 103 if ((tmp = args_get(args, 'n')) != NULL) 104 name = format_single(item, tmp, c, s, NULL, NULL); 105 else 106 name = NULL; 107 108 wl = NULL; 109 if (idx != -1) 110 wl = winlink_find_by_index(&s->windows, idx); 111 if (wl != NULL && args_has(args, 'k')) { 112 /* 113 * Can't use session_detach as it will destroy session if this 114 * makes it empty. 115 */ 116 notify_session_window("window-unlinked", s, wl->window); 117 wl->flags &= ~WINLINK_ALERTFLAGS; 118 winlink_stack_remove(&s->lastw, wl); 119 winlink_remove(&s->windows, wl); 120 121 /* Force select/redraw if current. */ 122 if (wl == s->curw) { 123 detached = 0; 124 s->curw = NULL; 125 } 126 } 127 128 if (idx == -1) 129 idx = -1 - options_get_number(s->options, "base-index"); 130 wl = session_new(s, name, argc, argv, path, cwd, idx, 131 &cause); 132 if (wl == NULL) { 133 cmdq_error(item, "create window failed: %s", cause); 134 free(cause); 135 goto error; 136 } 137 if (!detached) { 138 session_select(s, wl->idx); 139 cmd_find_from_winlink(current, wl, 0); 140 server_redraw_session_group(s); 141 } else 142 server_status_session_group(s); 143 144 if (args_has(args, 'P')) { 145 if ((template = args_get(args, 'F')) == NULL) 146 template = NEW_WINDOW_TEMPLATE; 147 cp = format_single(item, template, c, s, wl, NULL); 148 cmdq_print(item, "%s", cp); 149 free(cp); 150 } 151 152 cmd_find_from_winlink(&fs, wl, 0); 153 hooks_insert(s->hooks, item, &fs, "after-new-window"); 154 155 free(name); 156 free(cwd); 157 return (CMD_RETURN_NORMAL); 158 159 error: 160 free(name); 161 free(cwd); 162 return (CMD_RETURN_ERROR); 163 } 164