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