1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/ioctl.h>
29 
30 #include <getopt.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 
36 #include <bsddialog.h>
37 #include <bsddialog_theme.h>
38 
39 #include "util.h"
40 
41 enum OPTS {
42 	/* Options */
43 	ALTERNATE_SCREEN = '?' + 1,
44 	AND_DIALOG,
45 	ASCII_LINES,
46 	BACKTITLE,
47 	BEGIN_X,
48 	BEGIN_Y,
49 	BIKESHED,
50 	CANCEL_EXIT_CODE,
51 	CANCEL_LABEL,
52 	CLEAR_DIALOG,
53 	CLEAR_SCREEN,
54 	COLUMNS_PER_ROW,
55 	CR_WRAP,
56 	DATEBOX_FORMAT,
57 	DATE_FORMAT,
58 	DEFAULT_BUTTON,
59 	DEFAULT_ITEM,
60 	DEFAULT_NO,
61 	DISABLE_ESC,
62 	ERROR_EXIT_CODE,
63 	ESC_EXIT_CODE,
64 	EXIT_LABEL,
65 	EXTRA_BUTTON,
66 	EXTRA_EXIT_CODE,
67 	EXTRA_LABEL,
68 	HELP_BUTTON,
69 	HELP_EXIT_CODE,
70 	HELP_LABEL,
71 	HELP_PRINT_ITEMS,
72 	HELP_PRINT_NAME,
73 	HFILE,
74 	HLINE,
75 	HMSG,
76 	IGNORE,
77 	INSECURE,
78 	ITEM_BOTTOM_DESC,
79 	ITEM_DEPTH,
80 	ITEM_PREFIX,
81 	LEFT1_BUTTON,
82 	LEFT1_EXIT_CODE,
83 	LEFT2_BUTTON,
84 	LEFT2_EXIT_CODE,
85 	LEFT3_BUTTON,
86 	LEFT3_EXIT_CODE,
87 	LOAD_THEME,
88 	MAX_INPUT,
89 	NO_CANCEL,
90 	NO_DESCRIPTIONS,
91 	NO_LINES,
92 	NO_NAMES,
93 	NO_OK,
94 	NO_SHADOW,
95 	NORMAL_SCREEN,
96 	OK_EXIT_CODE,
97 	OK_LABEL,
98 	OUTPUT_FD,
99 	OUTPUT_SEPARATOR,
100 	PRINT_MAXSIZE,
101 	PRINT_SIZE,
102 	PRINT_VERSION,
103 	QUOTED,
104 	RIGHT1_BUTTON,
105 	RIGHT1_EXIT_CODE,
106 	RIGHT2_BUTTON,
107 	RIGHT2_EXIT_CODE,
108 	RIGHT3_BUTTON,
109 	RIGHT3_EXIT_CODE,
110 	SAVE_THEME,
111 	SEPARATE_OUTPUT,
112 	SHADOW,
113 	SINGLE_QUOTED,
114 	SLEEP,
115 	STDERR,
116 	STDOUT,
117 	SWITCH_BUTTONS,
118 	TAB_ESCAPE,
119 	TAB_LEN,
120 	TEXT_ESCAPE,
121 	TEXT_UNCHANGED,
122 	THEME,
123 	TIMEOUT_EXIT_CODE,
124 	TIME_FORMAT,
125 	TITLE,
126 	/* Dialogs */
127 	CALENDAR,
128 	CHECKLIST,
129 	DATEBOX,
130 	FORM,
131 	GAUGE,
132 	INFOBOX,
133 	INPUTBOX,
134 	MENU,
135 	MIXEDFORM,
136 	MIXEDGAUGE,
137 	MSGBOX,
138 	PASSWORDBOX,
139 	PASSWORDFORM,
140 	PAUSE,
141 	RADIOLIST,
142 	RANGEBOX,
143 	TEXTBOX,
144 	TIMEBOX,
145 	TREEVIEW,
146 	YESNO
147 };
148 
149 /* options descriptor */
150 static struct option longopts[] = {
151 	/* Options */
152 	{"alternate-screen",  no_argument,       NULL, ALTERNATE_SCREEN},
153 	{"and-dialog",        no_argument,       NULL, AND_DIALOG},
154 	{"and-widget",        no_argument,       NULL, AND_DIALOG},
155 	{"ascii-lines",       no_argument,       NULL, ASCII_LINES},
156 	{"backtitle",         required_argument, NULL, BACKTITLE},
157 	{"begin-x",           required_argument, NULL, BEGIN_X},
158 	{"begin-y",           required_argument, NULL, BEGIN_Y},
159 	{"bikeshed",          no_argument,       NULL, BIKESHED},
160 	{"cancel-exit-code",  required_argument, NULL, CANCEL_EXIT_CODE},
161 	{"cancel-label",      required_argument, NULL, CANCEL_LABEL},
162 	{"clear",             no_argument,       NULL, CLEAR_SCREEN},
163 	{"clear-dialog",      no_argument,       NULL, CLEAR_DIALOG},
164 	{"clear-screen",      no_argument,       NULL, CLEAR_SCREEN},
165 	{"colors",            no_argument,       NULL, TEXT_ESCAPE},
166 	{"columns-per-row",   required_argument, NULL, COLUMNS_PER_ROW},
167 	{"cr-wrap",           no_argument,       NULL, CR_WRAP},
168 	{"datebox-format",    required_argument, NULL, DATEBOX_FORMAT},
169 	{"date-format",       required_argument, NULL, DATE_FORMAT},
170 	{"defaultno",         no_argument,       NULL, DEFAULT_NO},
171 	{"default-button",    required_argument, NULL, DEFAULT_BUTTON},
172 	{"default-item",      required_argument, NULL, DEFAULT_ITEM},
173 	{"default-no",        no_argument,       NULL, DEFAULT_NO},
174 	{"disable-esc",       no_argument,       NULL, DISABLE_ESC},
175 	{"error-exit-code",   required_argument, NULL, ERROR_EXIT_CODE},
176 	{"esc-exit-code",     required_argument, NULL, ESC_EXIT_CODE},
177 	{"exit-label",        required_argument, NULL, EXIT_LABEL},
178 	{"extra-button",      no_argument,       NULL, EXTRA_BUTTON},
179 	{"extra-exit-code",   required_argument, NULL, EXTRA_EXIT_CODE},
180 	{"extra-label",       required_argument, NULL, EXTRA_LABEL},
181 	{"help-button",       no_argument,       NULL, HELP_BUTTON},
182 	{"help-exit-code",    required_argument, NULL, HELP_EXIT_CODE},
183 	{"help-label",        required_argument, NULL, HELP_LABEL},
184 	{"help-print-items",  no_argument,       NULL, HELP_PRINT_ITEMS},
185 	{"help-print-name",   no_argument,       NULL, HELP_PRINT_NAME},
186 	{"help-status",       no_argument,       NULL, HELP_PRINT_ITEMS},
187 	{"help-tags",         no_argument,       NULL, HELP_PRINT_NAME},
188 	{"hfile",             required_argument, NULL, HFILE},
189 	{"hline",             required_argument, NULL, HLINE},
190 	{"hmsg",              required_argument, NULL, HMSG},
191 	{"ignore",            no_argument,       NULL, IGNORE},
192 	{"insecure",          no_argument,       NULL, INSECURE},
193 	{"item-bottom-desc",  no_argument,       NULL, ITEM_BOTTOM_DESC},
194 	{"item-depth",        no_argument,       NULL, ITEM_DEPTH},
195 	{"item-help",         no_argument,       NULL, ITEM_BOTTOM_DESC},
196 	{"item-prefix",       no_argument,       NULL, ITEM_PREFIX},
197 	{"keep-tite",         no_argument,       NULL, ALTERNATE_SCREEN},
198 	{"left1-button",      required_argument, NULL, LEFT1_BUTTON},
199 	{"left1-exit-code",   required_argument, NULL, LEFT1_EXIT_CODE},
200 	{"left2-button",      required_argument, NULL, LEFT2_BUTTON},
201 	{"left2-exit-code",   required_argument, NULL, LEFT2_EXIT_CODE},
202 	{"left3-button",      required_argument, NULL, LEFT3_BUTTON},
203 	{"left3-exit-code",   required_argument, NULL, LEFT3_EXIT_CODE},
204 	{"load-theme",        required_argument, NULL, LOAD_THEME},
205 	{"max-input",         required_argument, NULL, MAX_INPUT},
206 	{"no-cancel",         no_argument,       NULL, NO_CANCEL},
207 	{"nocancel",          no_argument,       NULL, NO_CANCEL},
208 	{"no-descriptions",   no_argument,       NULL, NO_DESCRIPTIONS},
209 	{"no-items",          no_argument,       NULL, NO_DESCRIPTIONS},
210 	{"no-label",          required_argument, NULL, CANCEL_LABEL},
211 	{"no-lines",          no_argument,       NULL, NO_LINES},
212 	{"no-names",          no_argument,       NULL, NO_NAMES},
213 	{"no-ok",             no_argument,       NULL, NO_OK},
214 	{"nook",              no_argument,       NULL, NO_OK},
215 	{"no-shadow",         no_argument,       NULL, NO_SHADOW},
216 	{"no-tags",           no_argument,       NULL, NO_NAMES},
217 	{"normal-screen",     no_argument,       NULL, NORMAL_SCREEN},
218 	{"ok-exit-code",      required_argument, NULL, OK_EXIT_CODE},
219 	{"ok-label",          required_argument, NULL, OK_LABEL},
220 	{"output-fd",         required_argument, NULL, OUTPUT_FD},
221 	{"output-separator",  required_argument, NULL, OUTPUT_SEPARATOR},
222 	{"print-maxsize",     no_argument,       NULL, PRINT_MAXSIZE},
223 	{"print-size",        no_argument,       NULL, PRINT_SIZE},
224 	{"print-version",     no_argument,       NULL, PRINT_VERSION},
225 	{"quoted",            no_argument,       NULL, QUOTED},
226 	{"right1-button",     required_argument, NULL, RIGHT1_BUTTON},
227 	{"right1-exit-code",  required_argument, NULL, RIGHT1_EXIT_CODE},
228 	{"right2-button",     required_argument, NULL, RIGHT2_BUTTON},
229 	{"right2-exit-code",  required_argument, NULL, RIGHT2_EXIT_CODE},
230 	{"right3-button",     required_argument, NULL, RIGHT3_BUTTON},
231 	{"right3-exit-code",  required_argument, NULL, RIGHT3_EXIT_CODE},
232 	{"save-theme",        required_argument, NULL, SAVE_THEME},
233 	{"separate-output",   no_argument,       NULL, SEPARATE_OUTPUT},
234 	{"separator",         required_argument, NULL, OUTPUT_SEPARATOR},
235 	{"shadow",            no_argument,       NULL, SHADOW},
236 	{"single-quoted",     no_argument,       NULL, SINGLE_QUOTED},
237 	{"sleep",             required_argument, NULL, SLEEP},
238 	{"stderr",            no_argument,       NULL, STDERR},
239 	{"stdout",            no_argument,       NULL, STDOUT},
240 	{"switch-buttons",    no_argument,       NULL, SWITCH_BUTTONS},
241 	{"tab-escape",        no_argument,       NULL, TAB_ESCAPE},
242 	{"tab-len",           required_argument, NULL, TAB_LEN},
243 	{"text-escape",       no_argument,       NULL, TEXT_ESCAPE},
244 	{"text-unchanged",    no_argument,       NULL, TEXT_UNCHANGED},
245 	{"theme",             required_argument, NULL, THEME},
246 	{"timeout-exit-code", required_argument, NULL, TIMEOUT_EXIT_CODE},
247 	{"time-format",       required_argument, NULL, TIME_FORMAT},
248 	{"title",             required_argument, NULL, TITLE},
249 	{"yes-label",         required_argument, NULL, OK_LABEL},
250 	/* Dialogs */
251 	{"calendar",     no_argument, NULL, CALENDAR},
252 	{"checklist",    no_argument, NULL, CHECKLIST},
253 	{"datebox",      no_argument, NULL, DATEBOX},
254 	{"form",         no_argument, NULL, FORM},
255 	{"gauge",        no_argument, NULL, GAUGE},
256 	{"infobox",      no_argument, NULL, INFOBOX},
257 	{"inputbox",     no_argument, NULL, INPUTBOX},
258 	{"menu",         no_argument, NULL, MENU},
259 	{"mixedform",    no_argument, NULL, MIXEDFORM},
260 	{"mixedgauge",   no_argument, NULL, MIXEDGAUGE},
261 	{"msgbox",       no_argument, NULL, MSGBOX},
262 	{"passwordbox",  no_argument, NULL, PASSWORDBOX},
263 	{"passwordform", no_argument, NULL, PASSWORDFORM},
264 	{"pause",        no_argument, NULL, PAUSE},
265 	{"radiolist",    no_argument, NULL, RADIOLIST},
266 	{"rangebox",     no_argument, NULL, RANGEBOX},
267 	{"textbox",      no_argument, NULL, TEXTBOX},
268 	{"timebox",      no_argument, NULL, TIMEBOX},
269 	{"treeview",     no_argument, NULL, TREEVIEW},
270 	{"yesno",        no_argument, NULL, YESNO},
271 	/* END */
272 	{ NULL, 0, NULL, 0}
273 };
274 
275 void usage(void)
276 {
277 	printf("usage: bsddialog --help | --version\n");
278 	printf("       bsddialog [--<opt>] --<dialog> <text> <rows> <cols> "
279 	    "[<arg>] [--<opt>]\n");
280 	printf("       bsddialog ... --<dialog1> ... [--and-dialog --<dialog2> "
281 	    "...] ...\n");
282 	printf("\n");
283 
284 	printf("Options:\n");
285 	printf(" --alternate-screen, --ascii-lines, --backtitle <backtitle>,"
286 	    " --begin-x <x>,\n --begin-y <y>, --bikeshed,"
287 	    " --cancel-exit-code <retval>, --cancel-label <label>,\n"
288 	    " --clear-dialog, --clear-screen, --columns-per-row <columns>,"
289 	    " --cr-wrap,\n --datebox-format d/m/y|m/d/y|y/m/d,"
290 	    " --date-format <format>,\n --default-button <label>,"
291 	    " --default-item <name>, --default-no, --disable-esc,\n"
292 	    " --error-exit-code <retval>, --esc-exit-code <retval>,"
293 	    " --exit-label <label>,\n --extra-button,"
294 	    " --extra-exit-code <retval>, --extra-label <label>,\n"
295 	    " --left1-button <label>, --left1-exit-code <retval>,"
296 	    " --left2-button <label>,\n --left2-exit-code <retval>,"
297 	    " --left3-button <label>, --left3-exit-code <retval>,\n"
298 	    " --help-button, --help-exit-code <retval>, --help-label <label>,\n"
299 	    " --help-print-items, --help-print-name, --hfile <file>,"
300 	    " --hline <string>,\n --hmsg <string>, --ignore, --insecure,"
301 	    " --item-bottom-desc, --item-depth,\n --item-prefix,"
302 	    " --load-theme <file>, --max-input <size>, --no-cancel,\n"
303 	    " --no-descriptions, --no-label <label>, --no-lines, --no-names,"
304 	    " --no-ok,\n --no-shadow, --normal-screen, --ok-exit-code <retval>,"
305 	    " --ok-label <label>,\n --output-fd <fd>, --output-separator <sep>,"
306 	    " --print-maxsize, --print-size,\n --print-version, --quoted,"
307 	    " --right1-button <label>,\n --right1-exit-code <retval>,"
308 	    " --right2-button <label>,\n --right2-exit-code <retval>,"
309 	    " --right3-button <label>,\n --right3-exit-code <retval>,"
310 	    " --save-theme <file>, --separate-output,\n --separator <sep>,"
311 	    " --shadow, --single-quoted, --sleep <secs>, --stderr,\n --stdout,"
312 	    " --switch-buttons, --tab-escape, --tab-len <spaces>,"
313 	    " --text-escape,\n --text-unchanged, --theme 3d|blackwhite|flat,"
314 	    " --timeout-exit-code <retval>,\n --time-format <format>,"
315 	    " --title <title>, --yes-label <label>.");
316 	printf("\n\n");
317 
318 	printf("Dialogs:\n");
319 	printf(" --calendar <text> <rows> <cols> [<dd> <mm> <yy>]\n");
320 	printf(" --checklist <text> <rows> <cols> <menurows> [<name> <desc> "
321 	    "on|off] ...\n");
322 	printf(" --datebox <text> <rows> <cols> [<dd> <mm> <yy>]\n");
323 	printf(" --form <text> <rows> <cols> <formrows> [<label> <ylabel> "
324 	    "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters>] "
325 	    "...\n");
326 	printf(" --gauge <text> <rows> <cols> [<perc>]\n");
327 	printf(" --infobox <text> <rows> <cols>\n");
328 	printf(" --inputbox <text> <rows> <cols> [<init>]\n");
329 	printf(" --menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n");
330 	printf(" --mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
331 	    "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters> "
332 	    "0|1|2] ...\n");
333 	printf(" --mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> "
334 	    "<miniperc>] ...\n");
335 	printf(" --msgbox <text> <rows> <cols>\n");
336 	printf(" --passwordbox <text> <rows> <cols> [<init>]\n");
337 	printf(" --passwordform <text> <rows> <cols> <formrows> [<label> "
338 	    "<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> "
339 	    "<maxletters>] ...\n");
340 	printf(" --pause <text> <rows> <cols> <secs>\n");
341 	printf(" --radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
342 	    "on|off] ...\n");
343 	printf(" --rangebox <text> <rows> <cols> <min> <max> [<init>]\n");
344 	printf(" --textbox <file> <rows> <cols>\n");
345 	printf(" --timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n");
346 	printf(" --treeview <text> <rows> <cols> <menurows> [<depth> <name> "
347 	    "<desc> on|off] ...\n");
348 	printf(" --yesno <text> <rows> <cols>\n");
349 	printf("\n");
350 
351 	printf("See 'man 1 bsddialog' for more information.\n");
352 }
353 
354 int
355 parseargs(int argc, char **argv, struct bsddialog_conf *conf,
356     struct options *opt)
357 {
358 	int arg, parsed, i;
359 	struct winsize ws;
360 
361 	bsddialog_initconf(conf);
362 	conf->key.enable_esc = true;
363 	conf->button.always_active = true;
364 
365 	memset(opt, 0, sizeof(struct options));
366 	opt->theme = -1;
367 	opt->output_fd = STDERR_FILENO;
368 	opt->max_input_form = 2048;
369 	opt->mandatory_dialog = true;
370 
371 	for (i = 0; i < argc; i++) {
372 		if (strcmp(argv[i], "--and-dialog") == 0 ||
373 		    strcmp(argv[i], "--and-widget") == 0) {
374 			argc = i + 1;
375 			break;
376 		}
377 	}
378 	parsed = argc;
379 	while ((arg = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
380 		switch (arg) {
381 		/* Options */
382 		case ALTERNATE_SCREEN:
383 			opt->screen_mode = "smcup";
384 			break;
385 		case AND_DIALOG:
386 			if (opt->dialogbuilder == NULL)
387 				exit_error(true,"--and-dialog without "
388 				    "previous --<dialog>");
389 			break;
390 		case ASCII_LINES:
391 			conf->ascii_lines = true;
392 			break;
393 		case BACKTITLE:
394 			opt->backtitle = optarg;
395 			if (conf->y == BSDDIALOG_CENTER)
396 				conf->auto_topmargin = 2;
397 			break;
398 		case BEGIN_X:
399 			conf->x = (int)strtol(optarg, NULL, 10);
400 			if (conf->x < BSDDIALOG_CENTER)
401 				exit_error(false, "--begin-x %d is < %d",
402 				    conf->x, BSDDIALOG_CENTER);
403 			break;
404 		case BEGIN_Y:
405 			conf->y = (int)strtol(optarg, NULL, 10);
406 			if (conf->y < BSDDIALOG_CENTER)
407 				exit_error(false, "--begin-y %d is < %d",
408 				    conf->y, BSDDIALOG_CENTER);
409 			conf->auto_topmargin = 0;
410 			break;
411 		case BIKESHED:
412 			opt->bikeshed = true;
413 			break;
414 		case CANCEL_EXIT_CODE:
415 			set_exit_code(BSDDIALOG_CANCEL,
416 			    (int)strtol(optarg, NULL, 10));
417 			break;
418 		case CANCEL_LABEL:
419 			conf->button.cancel_label = optarg;
420 			break;
421 		case CLEAR_DIALOG:
422 			conf->clear = true;
423 			break;
424 		case CLEAR_SCREEN:
425 			opt->mandatory_dialog = false;
426 			opt->clearscreen = true;
427 			break;
428 		case COLUMNS_PER_ROW:
429 			conf->text.cols_per_row =
430 			    (u_int)strtoul(optarg, NULL, 10);
431 			break;
432 		case CR_WRAP:
433 			opt->cr_wrap = true;
434 			break;
435 		case DATEBOX_FORMAT:
436 			if (strcasecmp(optarg, "d/m/y") == 0)
437 				conf->date.format = "d/m/y";
438 			else if (strcasecmp(optarg, "m/d/y") == 0)
439 				conf->date.format = "m/d/y";
440 			else if (strcasecmp(optarg, "y/m/d") == 0)
441 				conf->date.format = "y/m/d";
442 			else
443 				exit_error(true,
444 				    "date format \"%s\" is invalid", optarg);
445 			break;
446 		case DATE_FORMAT:
447 			opt->date_fmt = optarg;
448 			break;
449 		case DEFAULT_BUTTON:
450 			conf->button.default_label = optarg;
451 			break;
452 		case DEFAULT_ITEM:
453 			opt->item_default = optarg;
454 			break;
455 		case DEFAULT_NO:
456 			conf->button.default_cancel = true;
457 			break;
458 		case DISABLE_ESC:
459 			conf->key.enable_esc = false;
460 			break;
461 		case ERROR_EXIT_CODE:
462 			set_exit_code(BSDDIALOG_ERROR,
463 			    (int)strtol(optarg, NULL, 10));
464 			break;
465 		case ESC_EXIT_CODE:
466 			set_exit_code(BSDDIALOG_ESC,
467 			    (int)strtol(optarg, NULL, 10));
468 			break;
469 		case EXIT_LABEL:
470 			conf->button.ok_label = optarg;
471 			break;
472 		case EXTRA_BUTTON:
473 			conf->button.with_extra = true;
474 			break;
475 		case EXTRA_EXIT_CODE:
476 			set_exit_code(BSDDIALOG_EXTRA,
477 			    (int)strtol(optarg, NULL, 10));
478 			break;
479 		case EXTRA_LABEL:
480 			conf->button.extra_label = optarg;
481 			break;
482 		case HELP_BUTTON:
483 			conf->button.with_help = true;
484 			break;
485 		case HELP_EXIT_CODE:
486 			i = (int)strtol(optarg, NULL, 10);
487 			set_exit_code(BSDDIALOG_HELP, i);
488 			/* _TEM_HELP follows _HELP */
489 			set_exit_code(BSDDIALOG_ITEM_HELP, i);
490 			break;
491 		case HELP_LABEL:
492 			conf->button.help_label = optarg;
493 			break;
494 		case HELP_PRINT_ITEMS:
495 			opt->help_print_items = true;
496 			break;
497 		case HELP_PRINT_NAME:
498 			opt->help_print_item_name = true;
499 			break;
500 		case HFILE:
501 			conf->key.f1_file = optarg;
502 			break;
503 		case HLINE:
504 			if (optarg[0] != '\0')
505 				conf->bottomtitle = optarg;
506 			break;
507 		case HMSG:
508 			conf->key.f1_message = optarg;
509 			break;
510 		case IGNORE:
511 			opt->ignore = true;
512 			break;
513 		case INSECURE:
514 			conf->form.securech = '*';
515 			break;
516 		case ITEM_BOTTOM_DESC:
517 			opt->item_bottomdesc = true;
518 			break;
519 		case ITEM_DEPTH:
520 			opt->item_depth = true;
521 			break;
522 		case ITEM_PREFIX:
523 			opt->item_prefix = true;
524 			break;
525 		case LEFT1_BUTTON:
526 			conf->button.left1_label = optarg;
527 			break;
528 		case LEFT1_EXIT_CODE:
529 			set_exit_code(BSDDIALOG_LEFT1,
530 			    (int)strtol(optarg, NULL, 10));
531 			break;
532 		case LEFT2_BUTTON:
533 			conf->button.left2_label = optarg;
534 			break;
535 		case LEFT2_EXIT_CODE:
536 			set_exit_code(BSDDIALOG_LEFT2,
537 			    (int)strtol(optarg, NULL, 10));
538 			break;
539 		case LEFT3_BUTTON:
540 			conf->button.left3_label = optarg;
541 			break;
542 		case LEFT3_EXIT_CODE:
543 			set_exit_code(BSDDIALOG_LEFT3,
544 			    (int)strtol(optarg, NULL, 10));
545 			break;
546 		case LOAD_THEME:
547 			opt->loadthemefile = optarg;
548 			break;
549 		case MAX_INPUT:
550 			opt->max_input_form = (u_int)strtoul(optarg, NULL, 10);
551 			break;
552 		case NO_CANCEL:
553 			conf->button.without_cancel = true;
554 			break;
555 		case NO_DESCRIPTIONS:
556 			conf->menu.no_desc = true;
557 			break;
558 		case NO_LINES:
559 			conf->no_lines = true;
560 			break;
561 		case NO_NAMES:
562 			conf->menu.no_name = true;
563 			break;
564 		case NO_OK:
565 			conf->button.without_ok = true;
566 			break;
567 		case NO_SHADOW:
568 			conf->shadow = false;
569 			break;
570 		case NORMAL_SCREEN:
571 			opt->screen_mode = "rmcup";
572 			break;
573 		case OK_EXIT_CODE:
574 			set_exit_code(BSDDIALOG_OK,
575 			    (int)strtol(optarg, NULL, 10));
576 			break;
577 		case OK_LABEL:
578 			conf->button.ok_label = optarg;
579 			break;
580 		case OUTPUT_FD:
581 			opt->output_fd = (int)strtol(optarg, NULL, 10);
582 			break;
583 		case OUTPUT_SEPARATOR:
584 			opt->item_output_sep = optarg;
585 			break;
586 		case QUOTED:
587 			opt->item_always_quote = true;
588 			break;
589 		case PRINT_MAXSIZE:
590 			opt->mandatory_dialog = false;
591 			ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
592 			dprintf(opt->output_fd, "MaxSize: %d, %d\n",
593 			    ws.ws_row, ws.ws_col);
594 			break;
595 		case PRINT_SIZE:
596 			conf->get_height = &opt->getH;
597 			conf->get_width = &opt->getW;
598 			break;
599 		case PRINT_VERSION:
600 			opt->mandatory_dialog = false;
601 			dprintf(opt->output_fd, "Version: %s\n",
602 			    LIBBSDDIALOG_VERSION);
603 			break;
604 		case RIGHT1_BUTTON:
605 			conf->button.right1_label = optarg;
606 			break;
607 		case RIGHT1_EXIT_CODE:
608 			set_exit_code(BSDDIALOG_RIGHT1,
609 			    (int)strtol(optarg, NULL, 10));
610 			break;
611 		case RIGHT2_BUTTON:
612 			conf->button.right2_label = optarg;
613 			break;
614 		case RIGHT2_EXIT_CODE:
615 			set_exit_code(BSDDIALOG_RIGHT2,
616 			    (int)strtol(optarg, NULL, 10));
617 			break;
618 		case RIGHT3_BUTTON:
619 			conf->button.right3_label = optarg;
620 			break;
621 		case RIGHT3_EXIT_CODE:
622 			set_exit_code(BSDDIALOG_RIGHT3,
623 			    (int)strtol(optarg, NULL, 10));
624 			break;
625 		case SAVE_THEME:
626 			opt->mandatory_dialog = false;
627 			opt->savethemefile = optarg;
628 			break;
629 		case SEPARATE_OUTPUT:
630 			opt->item_output_sepnl = true;
631 			break;
632 		case SHADOW:
633 			conf->shadow = true;
634 			break;
635 		case SINGLE_QUOTED:
636 			opt->item_singlequote = true;
637 			break;
638 		case SLEEP:
639 			conf->sleep = (u_int)strtoul(optarg, NULL, 10);
640 			break;
641 		case STDERR:
642 			opt->output_fd = STDERR_FILENO;
643 			break;
644 		case STDOUT:
645 			opt->output_fd = STDOUT_FILENO;
646 			break;
647 		case SWITCH_BUTTONS:
648 			conf->button.always_active = false;
649 			break;
650 		case TAB_ESCAPE:
651 			opt->tab_escape = true;
652 			break;
653 		case TAB_LEN:
654 			conf->text.tablen = (u_int)strtoul(optarg, NULL, 10);
655 			break;
656 		case TEXT_ESCAPE:
657 			conf->text.escape = true;
658 			break;
659 		case TEXT_UNCHANGED:
660 			opt->text_unchanged = true;
661 			break;
662 		case THEME:
663 			if (strcasecmp(optarg, "blackwhite") == 0)
664 				opt->theme = BSDDIALOG_THEME_BLACKWHITE;
665 			else if (strcasecmp(optarg, "flat") == 0)
666 				opt->theme = BSDDIALOG_THEME_FLAT;
667 			else if (strcasecmp(optarg, "3d") == 0)
668 				opt->theme = BSDDIALOG_THEME_3D;
669 			else
670 				exit_error(true,
671 				    "--theme: \"%s\" is unknown", optarg);
672 			break;
673 		case TIMEOUT_EXIT_CODE:
674 			set_exit_code(BSDDIALOG_TIMEOUT,
675 			    (int)strtol(optarg, NULL, 10));
676 			break;
677 		case TIME_FORMAT:
678 			opt->time_fmt = optarg;
679 			break;
680 		case TITLE:
681 			conf->title = optarg;
682 			break;
683 		/* Dialogs */
684 		case CALENDAR:
685 			if (opt->dialogbuilder != NULL)
686 				exit_error(true, "%s and --calendar without "
687 				    "--and-dialog", opt->name);
688 			opt->name = "--calendar";
689 			opt->dialogbuilder = calendar_builder;
690 			break;
691 		case CHECKLIST:
692 			if (opt->dialogbuilder != NULL)
693 				exit_error(true, "%s and --checklist without "
694 				    "--and-dialog", opt->name);
695 			opt->name = "--checklist";
696 			opt->dialogbuilder = checklist_builder;
697 			conf->auto_downmargin = 1;
698 			break;
699 		case DATEBOX:
700 			if (opt->dialogbuilder != NULL)
701 				exit_error(true, "%s and --datebox without "
702 				    "--and-dialog", opt->name);
703 			opt->name = "--datebox";
704 			opt->dialogbuilder = datebox_builder;
705 			break;
706 		case FORM:
707 			if (opt->dialogbuilder != NULL)
708 				exit_error(true, "%s and --form without "
709 				    "--and-dialog", opt->name);
710 			opt->name = "--form";
711 			opt->dialogbuilder = form_builder;
712 			conf->auto_downmargin = 1;
713 			break;
714 		case GAUGE:
715 			if (opt->dialogbuilder != NULL)
716 				exit_error(true, "%s and --gauge without "
717 				    "--and-dialog", opt->name);
718 			opt->name = "--gauge";
719 			opt->dialogbuilder = gauge_builder;
720 			break;
721 		case INFOBOX:
722 			if (opt->dialogbuilder != NULL)
723 				exit_error(true, "%s and --infobox without "
724 				    "--and-dialog", opt->name);
725 			opt->name = "--infobox";
726 			opt->dialogbuilder = infobox_builder;
727 			break;
728 		case INPUTBOX:
729 			if (opt->dialogbuilder != NULL)
730 				exit_error(true, "%s and --inputbox without "
731 				    "--and-dialog", opt->name);
732 			opt->name = "--inputbox";
733 			opt->dialogbuilder = inputbox_builder;
734 			conf->auto_downmargin = 1;
735 			break;
736 		case MENU:
737 			if (opt->dialogbuilder != NULL)
738 				exit_error(true, "%s and --menu without "
739 				    "--and-dialog", opt->name);
740 			opt->name = "--menu";
741 			opt->dialogbuilder = menu_builder;
742 			conf->auto_downmargin = 1;
743 			break;
744 		case MIXEDFORM:
745 			if (opt->dialogbuilder != NULL)
746 				exit_error(true, "%s and --mixedform without "
747 				    "--and-dialog", opt->name);
748 			opt->name = "--mixedform";
749 			opt->dialogbuilder = mixedform_builder;
750 			conf->auto_downmargin = 1;
751 			break;
752 		case MIXEDGAUGE:
753 			if (opt->dialogbuilder != NULL)
754 				exit_error(true, "%s and --mixedgauge without "
755 				    "--and-dialog", opt->name);
756 			opt->name = "--mixedgauge";
757 			opt->dialogbuilder = mixedgauge_builder;
758 			break;
759 		case MSGBOX:
760 			if (opt->dialogbuilder != NULL)
761 				exit_error(true, "%s and --msgbox without "
762 				    "--and-dialog", opt->name);
763 			opt->name = "--";
764 			opt->dialogbuilder = msgbox_builder;
765 			break;
766 		case PAUSE:
767 			if (opt->dialogbuilder != NULL)
768 				exit_error(true, "%s and --pause without "
769 				    "--and-dialog", opt->name);
770 			opt->name = "--pause";
771 			opt->dialogbuilder = pause_builder;
772 			break;
773 		case PASSWORDBOX:
774 			if (opt->dialogbuilder != NULL)
775 				exit_error(true, "%s and --passwordbox without "
776 				    "--and-dialog", opt->name);
777 			opt->name = "--passwordbox";
778 			opt->dialogbuilder = passwordbox_builder;
779 			conf->auto_downmargin = 1;
780 			break;
781 		case PASSWORDFORM:
782 			if (opt->dialogbuilder != NULL)
783 				exit_error(true, "%s and --passwordform "
784 				    "without --and-dialog", opt->name);
785 			opt->name = "--passwordform";
786 			opt->dialogbuilder = passwordform_builder;
787 			conf->auto_downmargin = 1;
788 			break;
789 		case RADIOLIST:
790 			if (opt->dialogbuilder != NULL)
791 				exit_error(true, "%s and --radiolist without "
792 				    "--and-dialog", opt->name);
793 			opt->name = "--radiolist";
794 			opt->dialogbuilder = radiolist_builder;
795 			conf->auto_downmargin = 1;
796 			break;
797 		case RANGEBOX:
798 			if (opt->dialogbuilder != NULL)
799 				exit_error(true, "%s and --rangebox without "
800 				    "--and-dialog", opt->name);
801 			opt->name = "--rangebox";
802 			opt->dialogbuilder = rangebox_builder;
803 			break;
804 		case TEXTBOX:
805 			if (opt->dialogbuilder != NULL)
806 				exit_error(true, "%s and --textbox without "
807 				    "--and-dialog", opt->name);
808 			opt->name = "--textbox";
809 			opt->dialogbuilder = textbox_builder;
810 			break;
811 		case TIMEBOX:
812 			if (opt->dialogbuilder != NULL)
813 				exit_error(true, "%s and --timebox without "
814 				    "--and-dialog", opt->name);
815 			opt->name = "--timebox";
816 			opt->dialogbuilder = timebox_builder;
817 			break;
818 		case TREEVIEW:
819 			if (opt->dialogbuilder != NULL)
820 				exit_error(true, "%s and --treeview without "
821 				    "--and-dialog", opt->name);
822 			opt->name = "--treeview";
823 			opt->dialogbuilder = treeview_builder;
824 			conf->auto_downmargin = 1;
825 			break;
826 		case YESNO:
827 			if (opt->dialogbuilder != NULL)
828 				exit_error(true, "%s and --yesno without "
829 				    "--and-dialog", opt->name);
830 			opt->name = "--yesno";
831 			opt->dialogbuilder = yesno_builder;
832 			break;
833 		default: /* Error */
834 			if (opt->ignore == true)
835 				break;
836 			exit_error(true, "--ignore to continue");
837 		}
838 	}
839 
840 	return (parsed);
841 }
842