1 /* $OpenBSD: cmd-show-options.c,v 1.49 2019/04/30 18:02:03 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 <stdlib.h> 22 #include <string.h> 23 #include <vis.h> 24 25 #include "tmux.h" 26 27 /* 28 * Show options. 29 */ 30 31 static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *); 32 33 static void cmd_show_options_print(struct cmd *, struct cmdq_item *, 34 struct options_entry *, int); 35 static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *, 36 struct options *); 37 38 const struct cmd_entry cmd_show_options_entry = { 39 .name = "show-options", 40 .alias = "show", 41 42 .args = { "gHqst:vw", 0, 1 }, 43 .usage = "[-gHqsvw] [-t target-session|target-window] [option]", 44 45 .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL }, 46 47 .flags = CMD_AFTERHOOK, 48 .exec = cmd_show_options_exec 49 }; 50 51 const struct cmd_entry cmd_show_window_options_entry = { 52 .name = "show-window-options", 53 .alias = "showw", 54 55 .args = { "gvt:", 0, 1 }, 56 .usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]", 57 58 .target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL }, 59 60 .flags = CMD_AFTERHOOK, 61 .exec = cmd_show_options_exec 62 }; 63 64 const struct cmd_entry cmd_show_hooks_entry = { 65 .name = "show-hooks", 66 .alias = NULL, 67 68 .args = { "gt:", 0, 1 }, 69 .usage = "[-g] " CMD_TARGET_SESSION_USAGE, 70 71 .target = { 't', CMD_FIND_SESSION, 0 }, 72 73 .flags = CMD_AFTERHOOK, 74 .exec = cmd_show_options_exec 75 }; 76 77 static enum cmd_retval 78 cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) 79 { 80 struct args *args = self->args; 81 struct cmd_find_state *fs = &item->target; 82 struct client *c = cmd_find_client(item, NULL, 1); 83 struct session *s = item->target.s; 84 struct winlink *wl = item->target.wl; 85 struct options *oo; 86 enum options_table_scope scope; 87 char *argument, *name = NULL, *cause; 88 const char *target; 89 int window, idx, ambiguous; 90 struct options_entry *o; 91 92 window = (self->entry == &cmd_show_window_options_entry); 93 if (args->argc == 0) { 94 scope = options_scope_from_flags(args, window, fs, &oo, &cause); 95 return (cmd_show_options_all(self, item, oo)); 96 } 97 argument = format_single(item, args->argv[0], c, s, wl, NULL); 98 99 name = options_match(argument, &idx, &ambiguous); 100 if (name == NULL) { 101 if (args_has(args, 'q')) 102 goto fail; 103 if (ambiguous) 104 cmdq_error(item, "ambiguous option: %s", argument); 105 else 106 cmdq_error(item, "invalid option: %s", argument); 107 goto fail; 108 } 109 if (*name == '@') 110 scope = options_scope_from_flags(args, window, fs, &oo, &cause); 111 else { 112 if (options_get_only(global_options, name) != NULL) 113 scope = OPTIONS_TABLE_SERVER; 114 else if (options_get_only(global_s_options, name) != NULL) 115 scope = OPTIONS_TABLE_SESSION; 116 else if (options_get_only(global_w_options, name) != NULL) 117 scope = OPTIONS_TABLE_WINDOW; 118 else { 119 scope = OPTIONS_TABLE_NONE; 120 xasprintf(&cause, "unknown option: %s", argument); 121 } 122 if (scope == OPTIONS_TABLE_SERVER) 123 oo = global_options; 124 else if (scope == OPTIONS_TABLE_SESSION) { 125 if (args_has(self->args, 'g')) 126 oo = global_s_options; 127 else if (s == NULL) { 128 target = args_get(args, 't'); 129 if (target != NULL) { 130 cmdq_error(item, "no such session: %s", 131 target); 132 } else 133 cmdq_error(item, "no current session"); 134 goto fail; 135 } else 136 oo = s->options; 137 } else if (scope == OPTIONS_TABLE_WINDOW) { 138 if (args_has(self->args, 'g')) 139 oo = global_w_options; 140 else if (wl == NULL) { 141 target = args_get(args, 't'); 142 if (target != NULL) { 143 cmdq_error(item, "no such window: %s", 144 target); 145 } else 146 cmdq_error(item, "no current window"); 147 goto fail; 148 } else 149 oo = wl->window->options; 150 } 151 } 152 if (scope == OPTIONS_TABLE_NONE) { 153 if (args_has(args, 'q')) 154 goto fail; 155 cmdq_error(item, "%s", cause); 156 free(cause); 157 goto fail; 158 } 159 o = options_get_only(oo, name); 160 if (o != NULL) 161 cmd_show_options_print(self, item, o, idx); 162 163 free(name); 164 free(argument); 165 return (CMD_RETURN_NORMAL); 166 167 fail: 168 free(name); 169 free(argument); 170 return (CMD_RETURN_ERROR); 171 } 172 173 static void 174 cmd_show_options_print(struct cmd *self, struct cmdq_item *item, 175 struct options_entry *o, int idx) 176 { 177 struct options_array_item *a; 178 const char *name = options_name(o); 179 char *value, *tmp = NULL, *escaped; 180 181 if (idx != -1) { 182 xasprintf(&tmp, "%s[%d]", name, idx); 183 name = tmp; 184 } else { 185 if (options_isarray(o)) { 186 a = options_array_first(o); 187 if (a == NULL) { 188 if (!args_has(self->args, 'v')) 189 cmdq_print(item, "%s", name); 190 return; 191 } 192 while (a != NULL) { 193 idx = options_array_item_index(a); 194 cmd_show_options_print(self, item, o, idx); 195 a = options_array_next(a); 196 } 197 return; 198 } 199 } 200 201 value = options_tostring(o, idx, 0); 202 if (args_has(self->args, 'v')) 203 cmdq_print(item, "%s", value); 204 else if (options_isstring(o)) { 205 utf8_stravis(&escaped, value, VIS_OCTAL|VIS_TAB|VIS_NL|VIS_DQ); 206 cmdq_print(item, "%s \"%s\"", name, escaped); 207 free(escaped); 208 } else 209 cmdq_print(item, "%s %s", name, value); 210 free(value); 211 212 free(tmp); 213 } 214 215 static enum cmd_retval 216 cmd_show_options_all(struct cmd *self, struct cmdq_item *item, 217 struct options *oo) 218 { 219 struct options_entry *o; 220 struct options_array_item *a; 221 u_int idx; 222 const struct options_table_entry *oe; 223 224 o = options_first(oo); 225 while (o != NULL) { 226 oe = options_table_entry(o); 227 if ((self->entry != &cmd_show_hooks_entry && 228 !args_has(self->args, 'H') && 229 oe != NULL && 230 (oe->flags & OPTIONS_TABLE_IS_HOOK)) || 231 (self->entry == &cmd_show_hooks_entry && 232 (oe == NULL || 233 (~oe->flags & OPTIONS_TABLE_IS_HOOK)))) { 234 o = options_next(o); 235 continue; 236 } 237 if (!options_isarray(o)) 238 cmd_show_options_print(self, item, o, -1); 239 else if ((a = options_array_first(o)) == NULL) { 240 if (!args_has(self->args, 'v')) 241 cmdq_print(item, "%s", options_name(o)); 242 } else { 243 while (a != NULL) { 244 idx = options_array_item_index(a); 245 cmd_show_options_print(self, item, o, idx); 246 a = options_array_next(a); 247 } 248 } 249 o = options_next(o); 250 } 251 return (CMD_RETURN_NORMAL); 252 } 253