Annotation of src/usr.bin/tmux/cmd-set-option.c, Revision 1.34
1.34 ! nicm 1: /* $OpenBSD: cmd-set-option.c,v 1.33 2010/02/04 18:20:16 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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:
24: #include "tmux.h"
25:
26: /*
27: * Set an option.
28: */
29:
30: int cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
31:
1.27 nicm 32: const char *cmd_set_option_print(
33: const struct set_option_entry *, struct options_entry *);
34: void cmd_set_option_string(struct cmd_ctx *,
35: struct options *, const struct set_option_entry *, char *, int);
36: void cmd_set_option_number(struct cmd_ctx *,
1.28 nicm 37: struct options *, const struct set_option_entry *, char *);
1.27 nicm 38: void cmd_set_option_keys(struct cmd_ctx *,
1.28 nicm 39: struct options *, const struct set_option_entry *, char *);
1.27 nicm 40: void cmd_set_option_colour(struct cmd_ctx *,
1.28 nicm 41: struct options *, const struct set_option_entry *, char *);
1.27 nicm 42: void cmd_set_option_attributes(struct cmd_ctx *,
1.28 nicm 43: struct options *, const struct set_option_entry *, char *);
1.27 nicm 44: void cmd_set_option_flag(struct cmd_ctx *,
1.28 nicm 45: struct options *, const struct set_option_entry *, char *);
1.27 nicm 46: void cmd_set_option_choice(struct cmd_ctx *,
1.28 nicm 47: struct options *, const struct set_option_entry *, char *);
1.27 nicm 48:
1.1 nicm 49: const struct cmd_entry cmd_set_option_entry = {
50: "set-option", "set",
1.29 nicm 51: "[-agsuw] [-t target-session|target-window] option [value]",
52: CMD_ARG12, "agsuw",
1.1 nicm 53: NULL,
1.14 nicm 54: cmd_target_parse,
1.1 nicm 55: cmd_set_option_exec,
1.14 nicm 56: cmd_target_free,
57: cmd_target_print
1.1 nicm 58: };
59:
1.27 nicm 60: const char *set_option_mode_keys_list[] = {
61: "emacs", "vi", NULL
62: };
63: const char *set_option_clock_mode_style_list[] = {
64: "12", "24", NULL
65: };
1.1 nicm 66: const char *set_option_status_keys_list[] = {
67: "emacs", "vi", NULL
68: };
1.8 nicm 69: const char *set_option_status_justify_list[] = {
70: "left", "centre", "right", NULL
71: };
1.1 nicm 72: const char *set_option_bell_action_list[] = {
73: "none", "any", "current", NULL
74: };
1.27 nicm 75:
1.29 nicm 76: const struct set_option_entry set_option_table[] = {
1.31 nicm 77: { "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.29 nicm 78: { "quiet", SET_OPTION_FLAG, 0, 0, NULL },
1.30 nicm 79: { NULL, 0, 0, 0, NULL }
1.29 nicm 80: };
81:
1.27 nicm 82: const struct set_option_entry set_session_option_table[] = {
1.15 nicm 83: { "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.1 nicm 84: { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list },
85: { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
86: { "default-command", SET_OPTION_STRING, 0, 0, NULL },
87: { "default-path", SET_OPTION_STRING, 0, 0, NULL },
1.17 nicm 88: { "default-shell", SET_OPTION_STRING, 0, 0, NULL },
1.4 nicm 89: { "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
1.16 nicm 90: { "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
1.33 nicm 91: { "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
1.16 nicm 92: { "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
1.1 nicm 93: { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
94: { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
95: { "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.20 nicm 96: { "lock-command", SET_OPTION_STRING, 0, 0, NULL },
1.21 nicm 97: { "lock-server", SET_OPTION_FLAG, 0, 0, NULL },
1.1 nicm 98: { "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
99: { "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
100: { "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.26 nicm 101: { "message-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.22 nicm 102: { "mouse-select-pane", SET_OPTION_FLAG, 0, 0, NULL },
1.32 nicm 103: { "pane-active-border-bg", SET_OPTION_COLOUR, 0, 0, NULL },
104: { "pane-active-border-fg", SET_OPTION_COLOUR, 0, 0, NULL },
105: { "pane-border-bg", SET_OPTION_COLOUR, 0, 0, NULL },
106: { "pane-border-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.19 nicm 107: { "prefix", SET_OPTION_KEYS, 0, 0, NULL },
1.1 nicm 108: { "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
109: { "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
110: { "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
1.18 nicm 111: { "set-titles-string", SET_OPTION_STRING, 0, 0, NULL },
1.1 nicm 112: { "status", SET_OPTION_FLAG, 0, 0, NULL },
113: { "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
114: { "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
115: { "status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
116: { "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
1.28 nicm 117: { "status-justify",
1.8 nicm 118: SET_OPTION_CHOICE, 0, 0, set_option_status_justify_list },
1.1 nicm 119: { "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list },
120: { "status-left", SET_OPTION_STRING, 0, 0, NULL },
1.12 nicm 121: { "status-left-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
122: { "status-left-bg", SET_OPTION_COLOUR, 0, 0, NULL },
123: { "status-left-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.1 nicm 124: { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
125: { "status-right", SET_OPTION_STRING, 0, 0, NULL },
1.12 nicm 126: { "status-right-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
127: { "status-right-bg", SET_OPTION_COLOUR, 0, 0, NULL },
128: { "status-right-fg", SET_OPTION_COLOUR, 0, 0, NULL },
1.1 nicm 129: { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
1.28 nicm 130: { "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
1.10 nicm 131: { "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
1.13 nicm 132: { "update-environment", SET_OPTION_STRING, 0, 0, NULL },
1.7 nicm 133: { "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
1.28 nicm 134: { "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
1.7 nicm 135: { "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
1.6 nicm 136: { NULL, 0, 0, 0, NULL }
1.1 nicm 137: };
138:
1.27 nicm 139: const struct set_option_entry set_window_option_table[] = {
140: { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL },
1.34 ! nicm 141: { "alternate-screen", SET_OPTION_FLAG, 0, 0, NULL },
1.27 nicm 142: { "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL },
143: { "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL },
144: { "clock-mode-style",
145: SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list },
146: { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
147: { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
148: { "main-pane-height", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
149: { "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
150: { "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
151: { "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL },
152: { "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL },
153: { "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list },
154: { "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL },
155: { "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL },
156: { "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
157: { "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
158: { "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL },
159: { "utf8", SET_OPTION_FLAG, 0, 0, NULL },
160: { "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
161: { "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
162: { "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
163: { "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL },
164: { "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL },
165: { "window-status-current-format", SET_OPTION_STRING, 0, 0, NULL },
166: { "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
167: { "window-status-format", SET_OPTION_STRING, 0, 0, NULL },
168: { "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
169: { NULL, 0, 0, 0, NULL }
170: };
171:
1.1 nicm 172: int
173: cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
174: {
1.14 nicm 175: struct cmd_target_data *data = self->data;
1.27 nicm 176: const struct set_option_entry *table;
1.1 nicm 177: struct session *s;
1.27 nicm 178: struct winlink *wl;
1.1 nicm 179: struct client *c;
180: struct options *oo;
1.6 nicm 181: const struct set_option_entry *entry, *opt;
1.24 nicm 182: struct jobs *jobs;
183: struct job *job, *nextjob;
1.1 nicm 184: u_int i;
1.24 nicm 185: int try_again;
1.1 nicm 186:
1.29 nicm 187: if (cmd_check_flag(data->chflags, 's')) {
188: oo = &global_options;
189: table = set_option_table;
190: } else if (cmd_check_flag(data->chflags, 'w')) {
1.27 nicm 191: table = set_window_option_table;
192: if (cmd_check_flag(data->chflags, 'g'))
193: oo = &global_w_options;
194: else {
195: wl = cmd_find_window(ctx, data->target, NULL);
196: if (wl == NULL)
197: return (-1);
198: oo = &wl->window->options;
199: }
200: } else {
201: table = set_session_option_table;
202: if (cmd_check_flag(data->chflags, 'g'))
203: oo = &global_s_options;
204: else {
205: s = cmd_find_session(ctx, data->target);
206: if (s == NULL)
207: return (-1);
208: oo = &s->options;
209: }
1.1 nicm 210: }
211:
1.14 nicm 212: if (*data->arg == '\0') {
1.1 nicm 213: ctx->error(ctx, "invalid option");
214: return (-1);
215: }
216:
217: entry = NULL;
1.27 nicm 218: for (opt = table; opt->name != NULL; opt++) {
1.14 nicm 219: if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
1.1 nicm 220: continue;
221: if (entry != NULL) {
1.14 nicm 222: ctx->error(ctx, "ambiguous option: %s", data->arg);
1.1 nicm 223: return (-1);
224: }
1.6 nicm 225: entry = opt;
1.1 nicm 226:
227: /* Bail now if an exact match. */
1.14 nicm 228: if (strcmp(entry->name, data->arg) == 0)
1.1 nicm 229: break;
230: }
231: if (entry == NULL) {
1.14 nicm 232: ctx->error(ctx, "unknown option: %s", data->arg);
1.1 nicm 233: return (-1);
234: }
235:
1.25 nicm 236: if (cmd_check_flag(data->chflags, 'u')) {
237: if (cmd_check_flag(data->chflags, 'g')) {
1.1 nicm 238: ctx->error(ctx,
239: "can't unset global option: %s", entry->name);
240: return (-1);
241: }
1.14 nicm 242: if (data->arg2 != NULL) {
1.1 nicm 243: ctx->error(ctx,
244: "value passed to unset option: %s", entry->name);
245: return (-1);
246: }
247:
248: options_remove(oo, entry->name);
249: ctx->info(ctx, "unset option: %s", entry->name);
250: } else {
251: switch (entry->type) {
252: case SET_OPTION_STRING:
1.27 nicm 253: cmd_set_option_string(ctx, oo, entry,
1.25 nicm 254: data->arg2, cmd_check_flag(data->chflags, 'a'));
1.1 nicm 255: break;
256: case SET_OPTION_NUMBER:
1.27 nicm 257: cmd_set_option_number(ctx, oo, entry, data->arg2);
1.1 nicm 258: break;
1.19 nicm 259: case SET_OPTION_KEYS:
1.27 nicm 260: cmd_set_option_keys(ctx, oo, entry, data->arg2);
1.1 nicm 261: break;
262: case SET_OPTION_COLOUR:
1.27 nicm 263: cmd_set_option_colour(ctx, oo, entry, data->arg2);
1.1 nicm 264: break;
265: case SET_OPTION_ATTRIBUTES:
1.27 nicm 266: cmd_set_option_attributes(ctx, oo, entry, data->arg2);
1.1 nicm 267: break;
268: case SET_OPTION_FLAG:
1.27 nicm 269: cmd_set_option_flag(ctx, oo, entry, data->arg2);
1.1 nicm 270: break;
271: case SET_OPTION_CHOICE:
1.27 nicm 272: cmd_set_option_choice(ctx, oo, entry, data->arg2);
1.1 nicm 273: break;
274: }
275: }
276:
277: recalculate_sizes();
1.27 nicm 278: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
279: c = ARRAY_ITEM(&clients, i);
280: if (c != NULL && c->session != NULL)
281: server_redraw_client(c);
282: }
1.24 nicm 283:
1.28 nicm 284: /*
1.24 nicm 285: * Special-case: kill all persistent jobs if status-left, status-right
286: * or set-titles-string have changed. Persistent jobs are only used by
287: * the status line at the moment so this works XXX.
288: */
289: if (strcmp(entry->name, "status-left") == 0 ||
290: strcmp(entry->name, "status-right") == 0 ||
1.27 nicm 291: strcmp(entry->name, "set-titles-string") == 0 ||
292: strcmp(entry->name, "window-status-format") == 0) {
1.24 nicm 293: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
294: c = ARRAY_ITEM(&clients, i);
295: if (c == NULL || c->session == NULL)
296: continue;
297:
298: jobs = &c->status_jobs;
299: do {
1.28 nicm 300: try_again = 0;
1.24 nicm 301: job = RB_ROOT(jobs);
302: while (job != NULL) {
303: nextjob = RB_NEXT(jobs, jobs, job);
304: if (job->flags & JOB_PERSIST) {
305: job_remove(jobs, job);
306: try_again = 1;
307: break;
308: }
309: job = nextjob;
310: }
311: } while (try_again);
1.1 nicm 312: server_redraw_client(c);
1.23 nicm 313: }
1.1 nicm 314: }
315:
316: return (0);
1.27 nicm 317: }
318:
319: const char *
320: cmd_set_option_print(
321: const struct set_option_entry *entry, struct options_entry *o)
322: {
323: static char out[BUFSIZ];
324: const char *s;
325: struct keylist *keylist;
326: u_int i;
327:
328: *out = '\0';
329: switch (entry->type) {
330: case SET_OPTION_STRING:
331: xsnprintf(out, sizeof out, "\"%s\"", o->str);
332: break;
333: case SET_OPTION_NUMBER:
334: xsnprintf(out, sizeof out, "%lld", o->num);
335: break;
336: case SET_OPTION_KEYS:
337: keylist = o->data;
338: for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
339: strlcat(out, key_string_lookup_key(
340: ARRAY_ITEM(keylist, i)), sizeof out);
341: if (i != ARRAY_LENGTH(keylist) - 1)
342: strlcat(out, ",", sizeof out);
343: }
344: break;
345: case SET_OPTION_COLOUR:
346: s = colour_tostring(o->num);
347: xsnprintf(out, sizeof out, "%s", s);
348: break;
349: case SET_OPTION_ATTRIBUTES:
350: s = attributes_tostring(o->num);
351: xsnprintf(out, sizeof out, "%s", s);
352: break;
353: case SET_OPTION_FLAG:
354: if (o->num)
355: strlcpy(out, "on", sizeof out);
356: else
357: strlcpy(out, "off", sizeof out);
358: break;
359: case SET_OPTION_CHOICE:
360: s = entry->choices[o->num];
361: xsnprintf(out, sizeof out, "%s", s);
362: break;
363: }
364: return (out);
365: }
366:
367: void
368: cmd_set_option_string(struct cmd_ctx *ctx, struct options *oo,
369: const struct set_option_entry *entry, char *value, int append)
370: {
371: struct options_entry *o;
372: char *oldvalue, *newvalue;
373:
374: if (value == NULL) {
375: ctx->error(ctx, "empty value");
376: return;
377: }
378:
379: if (append) {
380: oldvalue = options_get_string(oo, entry->name);
381: xasprintf(&newvalue, "%s%s", oldvalue, value);
382: } else
383: newvalue = value;
1.28 nicm 384:
1.27 nicm 385: o = options_set_string(oo, entry->name, "%s", newvalue);
386: ctx->info(ctx,
387: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
388:
389: if (newvalue != value)
390: xfree(newvalue);
391: }
392:
393: void
394: cmd_set_option_number(struct cmd_ctx *ctx, struct options *oo,
395: const struct set_option_entry *entry, char *value)
396: {
397: struct options_entry *o;
398: long long number;
399: const char *errstr;
400:
401: if (value == NULL) {
402: ctx->error(ctx, "empty value");
403: return;
404: }
405:
406: number = strtonum(value, entry->minimum, entry->maximum, &errstr);
407: if (errstr != NULL) {
408: ctx->error(ctx, "value is %s: %s", errstr, value);
409: return;
410: }
411:
412: o = options_set_number(oo, entry->name, number);
413: ctx->info(ctx,
414: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
415: }
416:
417: void
418: cmd_set_option_keys(struct cmd_ctx *ctx, struct options *oo,
419: const struct set_option_entry *entry, char *value)
420: {
421: struct options_entry *o;
422: struct keylist *keylist;
423: char *copyvalue, *ptr, *str;
424: int key;
425:
426: if (value == NULL) {
427: ctx->error(ctx, "empty value");
428: return;
429: }
430:
431: keylist = xmalloc(sizeof *keylist);
432: ARRAY_INIT(keylist);
433:
434: ptr = copyvalue = xstrdup(value);
435: while ((str = strsep(&ptr, ",")) != NULL) {
436: if ((key = key_string_lookup_string(str)) == KEYC_NONE) {
437: xfree(keylist);
438: ctx->error(ctx, "unknown key: %s", str);
439: xfree(copyvalue);
440: return;
441: }
442: ARRAY_ADD(keylist, key);
443: }
444: xfree(copyvalue);
445:
446: o = options_set_data(oo, entry->name, keylist, xfree);
447: ctx->info(ctx,
448: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
449: }
450:
451: void
452: cmd_set_option_colour(struct cmd_ctx *ctx, struct options *oo,
453: const struct set_option_entry *entry, char *value)
454: {
455: struct options_entry *o;
456: int colour;
457:
458: if (value == NULL) {
459: ctx->error(ctx, "empty value");
460: return;
461: }
462:
463: if ((colour = colour_fromstring(value)) == -1) {
464: ctx->error(ctx, "bad colour: %s", value);
465: return;
466: }
467:
468: o = options_set_number(oo, entry->name, colour);
469: ctx->info(ctx,
470: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
471: }
472:
473: void
474: cmd_set_option_attributes(struct cmd_ctx *ctx, struct options *oo,
475: const struct set_option_entry *entry, char *value)
476: {
477: struct options_entry *o;
478: int attr;
479:
480: if (value == NULL) {
481: ctx->error(ctx, "empty value");
482: return;
483: }
484:
485: if ((attr = attributes_fromstring(value)) == -1) {
486: ctx->error(ctx, "bad attributes: %s", value);
487: return;
488: }
489:
490: o = options_set_number(oo, entry->name, attr);
491: ctx->info(ctx,
492: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
493: }
494:
495: void
496: cmd_set_option_flag(struct cmd_ctx *ctx, struct options *oo,
497: const struct set_option_entry *entry, char *value)
498: {
499: struct options_entry *o;
500: int flag;
501:
502: if (value == NULL || *value == '\0')
503: flag = !options_get_number(oo, entry->name);
504: else {
505: if ((value[0] == '1' && value[1] == '\0') ||
506: strcasecmp(value, "on") == 0 ||
507: strcasecmp(value, "yes") == 0)
508: flag = 1;
509: else if ((value[0] == '0' && value[1] == '\0') ||
510: strcasecmp(value, "off") == 0 ||
511: strcasecmp(value, "no") == 0)
512: flag = 0;
513: else {
514: ctx->error(ctx, "bad value: %s", value);
515: return;
516: }
517: }
518:
519: o = options_set_number(oo, entry->name, flag);
520: ctx->info(ctx,
521: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
522: }
523:
524: void
525: cmd_set_option_choice(struct cmd_ctx *ctx, struct options *oo,
526: const struct set_option_entry *entry, char *value)
527: {
528: struct options_entry *o;
529: const char **choicep;
530: int n, choice = -1;
531:
532: if (value == NULL) {
533: ctx->error(ctx, "empty value");
534: return;
535: }
536:
537: n = 0;
538: for (choicep = entry->choices; *choicep != NULL; choicep++) {
539: n++;
540: if (strncmp(*choicep, value, strlen(value)) != 0)
541: continue;
542:
543: if (choice != -1) {
544: ctx->error(ctx, "ambiguous option value: %s", value);
545: return;
546: }
547: choice = n - 1;
548: }
549: if (choice == -1) {
550: ctx->error(ctx, "unknown option value: %s", value);
551: return;
552: }
553:
554: o = options_set_number(oo, entry->name, choice);
555: ctx->info(ctx,
556: "set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
1.1 nicm 557: }