1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2021 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 <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
36 
37 #include <bsddialog.h>
38 #include <bsddialog_theme.h>
39 
40 #define BSDDIALOG_VERSION "0.0.1"
41 
42 enum OPTS {
43 	/* Common options */
44 	ASCII_LINES = '?' + 1,
45 	ASPECT_RATIO,
46 	BACKTITLE,
47 	BEGIN_X,
48 	BEGIN_Y,
49 	CANCEL_LABEL,
50 	CLEAR,
51 	COLORS,
52 	CR_WRAP,
53 	DATE_FORMAT,
54 	DEFAULTNO,
55 	DEFAULT_BUTTON,
56 	DEFAULT_ITEM,
57 	EXIT_LABEL,
58 	EXTRA_BUTTON,
59 	EXTRA_LABEL,
60 	HELP,
61 	HELP_BUTTON,
62 	HELP_LABEL,
63 	HELP_STATUS,
64 	HELP_TAGS,
65 	HFILE,
66 	HLINE,
67 	IGNORE,
68 	INSECURE,
69 	ITEM_HELP,
70 	ITEM_PREFIX,
71 	MAX_INPUT,
72 	NO_CANCEL,
73 	NOCANCEL,
74 	NO_COLLAPSE,
75 	NO_ITEMS,
76 	NO_LABEL,
77 	NO_LINES,
78 	NO_NL_EXPAND,
79 	NO_OK,
80 	NOOK,
81 	NO_TAGS,
82 	NO_SHADOW,
83 	OK_LABEL,
84 	OUTPUT_FD,
85 	OUTPUT_SEPARATOR,
86 	PRINT_MAXSIZE,
87 	PRINT_SIZE,
88 	PRINT_VERSION,
89 	QUOTED,
90 	SEPARATE_OUTPUT,
91 	SEPARATOR,
92 	SHADOW,
93 	SINGLE_QUOTED,
94 	SLEEP,
95 	STDERR,
96 	STDOUT,
97 	THEME,
98 	TIME_FORMAT,
99 	TITLE,
100 	TRIM,
101 	VERSION,
102 	YES_LABEL,
103 	/* Widgets */
104 	BUILDLIST,
105 	CHECKLIST,
106 	DATEBOX,
107 	FORM,
108 	GAUGE,
109 	INFOBOX,
110 	INPUTBOX,
111 	MENU,
112 	MIXEDFORM,
113 	MIXEDGAUGE,
114 	MSGBOX,
115 	PASSWORDBOX,
116 	PASSWORDFORM,
117 	PAUSE,
118 	RADIOLIST,
119 	RANGEBOX,
120 	TEXTBOX,
121 	TIMEBOX,
122 	TREEVIEW,
123 	YESNO,
124 };
125 
126 /* libbsddialog does not support NULL string for now */
127 static char *nostring = "";
128 /* Menus flags and options */
129 static bool item_prefix_flag, item_bottomdesc_flag, item_output_sepnl_flag;
130 static bool item_singlequote_flag, list_items_on_flag, item_tag_help_flag;
131 static bool item_always_quote_flag;
132 static char *item_output_sep_flag;
133 /* Time and calendar options */
134 static char *date_fmt_flag, *time_fmt_flag;
135 /* Forms */
136 static int max_input_form_flag;
137 /* General flags and options */
138 static int output_fd_flag;
139 
140 void usage(void);
141 /* widgets */
142 #define BUILDER_ARGS struct bsddialog_conf conf, char* text, int rows,         \
143 	int cols, int argc, char **argv, char *errbuf
144 int buildlist_builder(BUILDER_ARGS);
145 int checklist_builder(BUILDER_ARGS);
146 int datebox_builder(BUILDER_ARGS);
147 int form_builder(BUILDER_ARGS);
148 int gauge_builder(BUILDER_ARGS);
149 int infobox_builder(BUILDER_ARGS);
150 int inputbox_builder(BUILDER_ARGS);
151 int menu_builder(BUILDER_ARGS);
152 int mixedform_builder(BUILDER_ARGS);
153 int mixedgauge_builder(BUILDER_ARGS);
154 int msgbox_builder(BUILDER_ARGS);
155 int passwordbox_builder(BUILDER_ARGS);
156 int passwordform_builder(BUILDER_ARGS);
157 int pause_builder(BUILDER_ARGS);
158 int radiolist_builder(BUILDER_ARGS);
159 int rangebox_builder(BUILDER_ARGS);
160 int textbox_builder(BUILDER_ARGS);
161 int timebox_builder(BUILDER_ARGS);
162 int treeview_builder(BUILDER_ARGS);
163 int yesno_builder(BUILDER_ARGS);
164 
usage(void)165 void usage(void)
166 {
167 
168 	printf("usage: bsddialog --help\n"
169 	       "       bsddialog --version\n"
170 	       "       bsddialog [--<common-opts>] --<widget> <text> "
171 	       "<height> <width> [--<widget-opts>]\n");
172 	printf("\n");
173 	printf("Common Options:\n");
174 	printf("--ascii-lines, --aspect <ratio>, --backtitle <backtitle>, "
175 		"--begin-x <x>, --begin-y <y>, --cancel-label <string>, "
176 		"-clear, --colors, --date-format <format>, "
177 		"--default-button <label>, --defaultno, --default-item <name>,"
178 		"--exit-label <label>, --extra-button, --extra-label <label>,"
179 		"--hfile <filename>, --help-button, --help-label <label>, "
180 		"--help-status, --help-tags, --hline string, --ignore, "
181 		"--insecure, --item-help, --max-input <size>, --no-cancel, "
182 		"--nocancel, --no-label <label>, --no-items, --no-lines, "
183 		"--no-ok, --nook, --no-shadow, --no-tags, --ok-label <label>, "
184 		"--output-fd <fd>, --output-separator <sep>, --print-version, "
185 		"--print-size, --quoted, --print-maxsize, --shadow, "
186 		"--single-quoted, --separator <sep>, --separate-output, "
187 		"--sleep <secs>, --stderr, --stdout, "
188 		"--theme <blackwhite|bsddialog|dialog>, "
189 		"--time-format <format>, --title <title>, "
190 		"--yes-label <string>.\n");
191 	printf("\n");
192 	printf("Widgets:\n");
193 	printf("--buildlist <text> <rows> <cols> <menurows> [<name> <desc> "
194 		    "<on|off> ...]\n"
195 		"--checklist <text> <rows> <cols> <menurows> [<name> <desc> "
196 		    "<on|off> ...]\n"
197 		"--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n"
198 		"--form <text> <rows> <cols> <formrows> [<label> <ylabel> "
199 		    "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvalue> "
200 		    "...]\n"
201 		"--gauge <text> <rows> <cols> [<perc\\n> [<text> ...] XXX "
202 		    "...] EOF\n"
203 		"--infobox <text> <rows> <cols>\n"
204 		"--inputbox <text> <rows> <cols> [init]\n"
205 		"--menu <text> <rows> <cols> <menurows> [<name> <desc> ...]\n"
206 		"--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
207 		    "<xlabe> <init> <yfield> <xfield> <fieldlen> <maxvalue> "
208 		    "<0|1|2> ...]\n"
209 		"--mixedgauge <text> <rows> <cols> <mainperc> [<label> "
210 		    "<01234567|-perc> ...]\n"
211 		"--msgbox <text> <rows> <cols>\n"
212 		"--passwordbox <text> <rows> <cols> [init]\n"
213 		"--passwordform <text> <rows> <cols> <formrows> [<label> "
214 		    "<ylabel> <xlabe> <init> <yfield> <xfield> <fieldlen> "
215 		    "<maxvalue> ...]\n"
216 		"--pause <text> <rows> <cols> <secs>\n"
217 		"--radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
218 		    "<on|off> ...]\n"
219 		"--rangebox <text> <rows> <cols> <min> <max> <default>\n"
220 		"--textbox <file> <rows> <cols>\n"
221 		"--timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n"
222 		"--treeview <text> <rows> <cols> <menurows> [<depth> <name> "
223 		    "<desc> <on|off> ...]\n"
224 		"--yesno <text> <rows> <cols>\n");
225 
226 
227 }
228 
main(int argc,char * argv[argc])229 int main(int argc, char *argv[argc])
230 {
231 	char *text, *backtitle_flag, errorbuilder[1024];
232 	int input, rows, cols, output, getH, getW;
233 	int (*widgetbuilder)(BUILDER_ARGS) = NULL;
234 	bool ignore_flag, print_maxsize_flag;
235 	struct winsize ws;
236 	struct bsddialog_conf conf;
237 	enum bsddialog_default_theme theme_flag;
238 
239 	bsddialog_initconf(&conf);
240 
241 	backtitle_flag = NULL;
242 	theme_flag = -1;
243 	output_fd_flag = STDERR_FILENO;
244 	print_maxsize_flag = false;
245 	ignore_flag = false;
246 	errorbuilder[0] = '\0';
247 
248 	item_output_sepnl_flag = item_singlequote_flag = false;
249 	item_prefix_flag = item_bottomdesc_flag = false;
250 	list_items_on_flag = item_tag_help_flag = false;
251 	item_always_quote_flag = false;
252 	item_output_sep_flag = NULL;
253 
254 	date_fmt_flag = time_fmt_flag = NULL;
255 
256 	max_input_form_flag = 0;
257 
258 	/* options descriptor */
259 	struct option longopts[] = {
260 	    /* common options */
261 	    {"ascii-lines",     no_argument,       NULL, ASCII_LINES },
262 	    {"aspect",          required_argument, NULL, ASPECT_RATIO },
263 	    {"backtitle",       required_argument, NULL, BACKTITLE },
264 	    {"begin-x",         required_argument, NULL, BEGIN_X },
265 	    {"begin-y",         required_argument, NULL, BEGIN_Y },
266 	    {"cancel-label",    required_argument, NULL, CANCEL_LABEL },
267 	    {"clear",           no_argument,       NULL, CLEAR },
268 	    {"colors",          no_argument,       NULL, COLORS },
269 	    {"cr-wrap",         no_argument,       NULL, CR_WRAP },
270 	    {"date-format",     required_argument, NULL, DATE_FORMAT },
271 	    {"defaultno",       no_argument,       NULL, DEFAULTNO },
272 	    {"default-button",  required_argument, NULL, DEFAULT_BUTTON },
273 	    {"default-item",    required_argument, NULL, DEFAULT_ITEM },
274 	    {"exit-label",      required_argument, NULL, EXIT_LABEL },
275 	    {"extra-button",    no_argument,       NULL, EXTRA_BUTTON },
276 	    {"extra-label",     required_argument, NULL, EXTRA_LABEL },
277 	    {"help",            no_argument,       NULL, HELP },
278 	    {"help-button",     no_argument,       NULL, HELP_BUTTON },
279 	    {"help-label",      required_argument, NULL, HELP_LABEL },
280 	    {"help-status",     no_argument,       NULL, HELP_STATUS },
281 	    {"help-tags",       no_argument,       NULL, HELP_TAGS },
282 	    {"hfile",           required_argument, NULL, HFILE },
283 	    {"hline",           required_argument, NULL, HLINE },
284 	    {"ignore",          no_argument,       NULL, IGNORE },
285 	    {"insecure",        no_argument,       NULL, INSECURE },
286 	    {"item-help",       no_argument,       NULL, ITEM_HELP },
287 	    {"max-input",       required_argument, NULL, MAX_INPUT },
288 	    {"no-cancel",       no_argument,       NULL, NO_CANCEL },
289 	    {"nocancel",        no_argument,       NULL, NOCANCEL },
290 	    {"no-collapse",     no_argument,       NULL, NO_COLLAPSE },
291 	    {"no-items",        no_argument,       NULL, NO_ITEMS },
292 	    {"no-label",        required_argument, NULL, NO_LABEL },
293 	    {"no-lines",        no_argument,       NULL, NO_LINES },
294 	    {"no-nl-expand",    no_argument,       NULL, NO_NL_EXPAND },
295 	    {"no-ok",           no_argument,       NULL, NO_OK },
296 	    {"nook ",           no_argument,       NULL, NOOK },
297 	    {"no-tags",         no_argument,       NULL, NO_TAGS },
298 	    {"no-shadow",       no_argument,       NULL, NO_SHADOW },
299 	    {"ok-label",        required_argument, NULL, OK_LABEL },
300 	    {"output-fd",       required_argument, NULL, OUTPUT_FD },
301 	    {"separator",       required_argument, NULL, SEPARATOR },
302 	    {"output-separator",required_argument, NULL, OUTPUT_SEPARATOR },
303 	    {"print-maxsize",   no_argument,       NULL, PRINT_MAXSIZE },
304 	    {"print-size",      no_argument,       NULL, PRINT_SIZE },
305 	    {"print-version",   no_argument,       NULL, PRINT_VERSION },
306 	    {"quoted",          no_argument,       NULL, QUOTED },
307 	    {"separate-output", no_argument,       NULL, SEPARATE_OUTPUT },
308 	    {"shadow",          no_argument,       NULL, SHADOW },
309 	    {"single-quoted",   no_argument,       NULL, SINGLE_QUOTED },
310 	    {"sleep",           required_argument, NULL, SLEEP },
311 	    {"stderr",          no_argument,       NULL, STDERR },
312 	    {"stdout",          no_argument,       NULL, STDOUT },
313 	    {"theme_flag",      required_argument, NULL, THEME },
314 	    {"time-format",     required_argument, NULL, TIME_FORMAT },
315 	    {"title",           required_argument, NULL, TITLE },
316 	    {"trim",            no_argument,       NULL, TRIM },
317 	    {"version",         no_argument,       NULL, VERSION },
318 	    {"yes-label",       required_argument, NULL, YES_LABEL },
319 	    /* Widgets */
320 	    {"buildlist",    no_argument, NULL, BUILDLIST },
321 	    {"checklist",    no_argument, NULL, CHECKLIST },
322 	    {"datebox",      no_argument, NULL, DATEBOX },
323 	    {"form",         no_argument, NULL, FORM },
324 	    {"gauge",        no_argument, NULL, GAUGE },
325 	    {"infobox",      no_argument, NULL, INFOBOX },
326 	    {"inputbox",     no_argument, NULL, INPUTBOX },
327 	    {"menu",         no_argument, NULL, MENU },
328 	    {"mixedform",    no_argument, NULL, MIXEDFORM },
329 	    {"mixedgauge",   no_argument, NULL, MIXEDGAUGE },
330 	    {"msgbox",       no_argument, NULL, MSGBOX },
331 	    {"passwordbox",  no_argument, NULL, PASSWORDBOX },
332 	    {"passwordform", no_argument, NULL, PASSWORDFORM },
333 	    {"pause",        no_argument, NULL, PAUSE },
334 	    {"radiolist",    no_argument, NULL, RADIOLIST },
335 	    {"rangebox",     no_argument, NULL, RANGEBOX },
336 	    {"textbox",      no_argument, NULL, TEXTBOX },
337 	    {"timebox",      no_argument, NULL, TIMEBOX },
338 	    {"treeview",     no_argument, NULL, TREEVIEW },
339 	    {"yesno",        no_argument, NULL, YESNO },
340 	    /* END */
341 	    { NULL, 0, NULL, 0 }
342 	};
343 
344 	while ((input = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
345 		switch (input) {
346 		/* Common options */
347 		case ASCII_LINES:
348 			conf.ascii_lines = true;
349 			break;
350 		case ASPECT_RATIO:
351 			conf.aspect_ratio = atoi(optarg);
352 			if (conf.aspect_ratio < 1) {
353 				printf("Error: aspect cannot be < 1");
354 				return (BSDDIALOG_ERROR);
355 			}
356 			break;
357 		case BACKTITLE:
358 			backtitle_flag = optarg;
359 			break;
360 		case BEGIN_X:
361 			conf.x = atoi(optarg);
362 			if (conf.x < BSDDIALOG_CENTER) {
363 				printf("Error: --begin-x %d, cannot be < %d",
364 				    conf.x, BSDDIALOG_CENTER);
365 				return (BSDDIALOG_ERROR);
366 			}
367 			break;
368 		case BEGIN_Y:
369 			conf.y = atoi(optarg);
370 			if (conf.y < BSDDIALOG_CENTER) {
371 				printf("Error: --begin-y %d, cannot be < %d",
372 				    conf.y, BSDDIALOG_CENTER);
373 				return (BSDDIALOG_ERROR);
374 			}
375 			break;
376 		case CANCEL_LABEL:
377 			conf.button.cancel_label = optarg;
378 			break;
379 		case CLEAR:
380 			conf.clear = true;
381 			break;
382 		case COLORS:
383 			conf.text.colors = true;
384 			break;
385 		case CR_WRAP:
386 			conf.text.cr_wrap = true;
387 			break;
388 		case DATE_FORMAT:
389 			date_fmt_flag = optarg;
390 			break;
391 		case DEFAULT_BUTTON:
392 			conf.button.default_label = optarg;
393 			break;
394 		case DEFAULT_ITEM:
395 			conf.menu.default_item = optarg;
396 			break;
397 		case DEFAULTNO:
398 			conf.button.defaultno = true;
399 			break;
400 		case EXIT_LABEL:
401 			conf.button.exit_label = optarg;
402 			break;
403 		case EXTRA_BUTTON:
404 			conf.button.extra_button = true;
405 			break;
406 		case EXTRA_LABEL:
407 			conf.button.extra_label = optarg;
408 			break;
409 		case HELP:
410 			usage();
411 			return (BSDDIALOG_YESOK);
412 		case HELP_BUTTON:
413 			conf.button.help_button = true;
414 			break;
415 		case HELP_LABEL:
416 			conf.button.help_label = optarg;
417 			break;
418 		case HELP_STATUS:
419 			list_items_on_flag = true;
420 			break;
421 		case HELP_TAGS:
422 			item_tag_help_flag = true;
423 			break;
424 		case HFILE:
425 			conf.hfile = optarg;
426 			break;
427 		case HLINE:
428 			conf.hline = optarg;
429 			break;
430 		case IGNORE:
431 			ignore_flag = true;
432 			break;
433 		case INSECURE:
434 			conf.form.securech = '*';
435 			break;
436 		case ITEM_HELP:
437 			item_bottomdesc_flag = true;
438 			break;
439 		case MAX_INPUT:
440 			max_input_form_flag = atoi(optarg);
441 			break;
442 		case NO_ITEMS:
443 			conf.menu.no_desc = true;
444 			break;
445 		case ITEM_PREFIX:
446 			item_prefix_flag = true;
447 			break;
448 		case NOCANCEL:
449 		case NO_CANCEL:
450 			conf.button.no_cancel = true;
451 			break;
452 		case NO_COLLAPSE:
453 			conf.text.no_collapse = true;
454 			break;
455 		case NO_LABEL:
456 			conf.button.no_label = optarg;
457 			break;
458 		case NO_LINES:
459 			conf.no_lines = true;
460 			break;
461 		case NO_NL_EXPAND:
462 			conf.text.no_nl_expand = true;
463 			break;
464 		case NOOK:
465 		case NO_OK:
466 			conf.button.no_ok = true;
467 			break;
468 		case NO_TAGS:
469 			conf.menu.no_name = true;
470 			break;
471 		case NO_SHADOW:
472 			conf.shadow = false;
473 			break;
474 		case OK_LABEL:
475 			conf.button.ok_label = optarg;
476 			break;
477 		case OUTPUT_FD:
478 			output_fd_flag = atoi(optarg);
479 			break;
480 		case SEPARATOR:
481 		case OUTPUT_SEPARATOR:
482 			item_output_sep_flag = optarg;
483 			break;
484 		case QUOTED:
485 			item_always_quote_flag = true;
486 			break;
487 		case PRINT_MAXSIZE:
488 			print_maxsize_flag = true;
489 			break;
490 		case PRINT_SIZE:
491 			conf.get_height = &getH;;
492 			conf.get_width = &getW;
493 			break;
494 		case PRINT_VERSION:
495 			printf("bsddialog version %s\n", BSDDIALOG_VERSION);
496 			break;
497 		case SEPARATE_OUTPUT:
498 			item_output_sepnl_flag = true;
499 			break;
500 		case SHADOW:
501 			conf.shadow = true;
502 			break;
503 		case SINGLE_QUOTED:
504 			item_singlequote_flag = true;
505 			break;
506 		case SLEEP:
507 			conf.sleep = atoi(optarg);
508 			break;
509 		case STDERR:
510 			output_fd_flag = STDERR_FILENO;
511 			break;
512 		case STDOUT:
513 			output_fd_flag = STDOUT_FILENO;
514 			break;
515 		case THEME:
516 			if (strcmp(optarg, "bsddialog") == 0)
517 				theme_flag = BSDDIALOG_THEME_BSDDIALOG;
518 			else if (strcmp(optarg, "blackwhite") == 0)
519 				theme_flag = BSDDIALOG_THEME_BLACKWHITE;
520 			else if (strcmp(optarg, "dialog") == 0)
521 				theme_flag = BSDDIALOG_THEME_DIALOG;
522 			else {
523 				printf("Unknown theme, possible values: ");
524 				printf("blackwhite, bsddialog, dialog");
525 				return (BSDDIALOG_ERROR);
526 			}
527 			break;
528 		case TIME_FORMAT:
529 			time_fmt_flag = optarg;
530 			break;
531 		case TITLE:
532 			conf.title = optarg;
533 			break;
534 		case TRIM:
535 			conf.text.trim = true;
536 			break;
537 		case VERSION:
538 			printf("bsddialog %s (libbsddialog %s).\n",
539 			    BSDDIALOG_VERSION, LIBBSDDIALOG_VERSION);
540 			return (BSDDIALOG_YESOK);
541 		case YES_LABEL:
542 			conf.button.yes_label = optarg;
543 			break;
544 		/* Widgets */
545 		case BUILDLIST:
546 			widgetbuilder = buildlist_builder;
547 			break;
548 		case CHECKLIST:
549 			widgetbuilder = checklist_builder;
550 			break;
551 		case DATEBOX:
552 			widgetbuilder = datebox_builder;
553 			break;
554 		case FORM:
555 			widgetbuilder = form_builder;
556 			break;
557 		case GAUGE:
558 			widgetbuilder = gauge_builder;
559 			break;
560 		case INFOBOX:
561 			widgetbuilder = infobox_builder;
562 			break;
563 		case INPUTBOX:
564 			widgetbuilder = inputbox_builder;
565 			break;
566 		case MENU:
567 			widgetbuilder = menu_builder;
568 			break;
569 		case MIXEDFORM:
570 			widgetbuilder = mixedform_builder;
571 			break;
572 		case MIXEDGAUGE:
573 			widgetbuilder = mixedgauge_builder;
574 			break;
575 		case MSGBOX:
576 			widgetbuilder = msgbox_builder;
577 			break;
578 		case PAUSE:
579 			widgetbuilder = pause_builder;
580 			break;
581 		case PASSWORDBOX:
582 			widgetbuilder = passwordbox_builder;
583 			break;
584 		case PASSWORDFORM:
585 			widgetbuilder = passwordform_builder;
586 			break;
587 		case RADIOLIST:
588 			widgetbuilder = radiolist_builder;
589 			break;
590 		case RANGEBOX:
591 			widgetbuilder = rangebox_builder;
592 			break;
593 		case TEXTBOX:
594 			widgetbuilder = textbox_builder;
595 			break;
596 		case TIMEBOX:
597 			widgetbuilder = timebox_builder;
598 			break;
599 		case TREEVIEW:
600 			widgetbuilder = treeview_builder;
601 			break;
602 		case YESNO:
603 			widgetbuilder = yesno_builder;
604 			break;
605 		/* Error */
606 		default:
607 			if (ignore_flag == true)
608 				break;
609 			usage();
610 			return (BSDDIALOG_ERROR);
611 		}
612 	}
613 	argc -= optind;
614 	argv += optind;
615 
616 	if (print_maxsize_flag) {
617 		ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
618 		dprintf(output_fd_flag, "MaxSize: %d, %d\n", ws.ws_row, ws.ws_col);
619 		if (argc == 0)
620 			return (BSDDIALOG_YESOK);
621 	}
622 
623 	if (argc < 3) {
624 		usage();
625 		return (BSDDIALOG_ERROR);
626 	}
627 	text = argv[0];
628 	rows = atoi(argv[1]);
629 	cols = atoi(argv[2]);
630 	argc -= 3;
631 	argv += 3;
632 
633 	/* bsddialog terminal mode */
634 	if(bsddialog_init() != 0) {
635 		printf("Error: %s\n", bsddialog_geterror());
636 		return (BSDDIALOG_ERROR);
637 	}
638 
639 	if (theme_flag >= 0)
640 		bsddialog_set_default_theme(theme_flag);
641 
642 	if (backtitle_flag != NULL)
643 		bsddialog_backtitle(&conf, backtitle_flag);
644 
645 	output = BSDDIALOG_YESOK;
646 	if (widgetbuilder != NULL)
647 		output = widgetbuilder(conf, text, rows, cols, argc, argv,
648 		    errorbuilder);
649 
650 	bsddialog_end();
651 	/* end bsddialog terminal mode */
652 
653 	/* debug & devel */
654 	/*printf("[Debug] Exit status: %d ", output);
655 	switch (output) {
656 	case BSDDIALOG_ERROR: 	  printf("ERROR");    break;
657 	case BSDDIALOG_YESOK: 	  printf("YESOK");    break;
658 	case BSDDIALOG_NOCANCEL:  printf("NOCANCEL"); break;
659 	case BSDDIALOG_HELP: 	  printf("HELP");     break;
660 	case BSDDIALOG_EXTRA:     printf("EXTRA");    break;
661 	case BSDDIALOG_ITEM_HELP: printf("ITEM_HELP");break;
662 	case BSDDIALOG_ESC: 	  printf("ESC");      break;
663 	default: 		  printf("Unknow status! Bug!"); break;
664 	}
665 	printf("\n");*/
666 
667 	if (output == BSDDIALOG_ERROR) {
668 		if (errorbuilder[0] != '\0')
669 			printf("Error: %s\n", errorbuilder);
670 		else
671 			printf("Error: %s\n", bsddialog_geterror());
672 	}
673 
674 	if (conf.get_height != NULL && conf.get_width != NULL)
675 		dprintf(output_fd_flag, "Widget size: (%d - %d)\n",
676 		    *conf.get_height, *conf.get_width);
677 
678 	return (output);
679 }
680 
681 /* Widgets */
682 
gauge_builder(BUILDER_ARGS)683 int gauge_builder(BUILDER_ARGS)
684 {
685 	int output, perc;
686 
687 	if (argc > 0) {
688 		perc = argc > 0 ? atoi (argv[0]) : 0;
689 		perc = perc < 0 ? 0 : perc;
690 		perc = perc > 100 ? 100 : perc;
691 	}
692 	else
693 		perc = 0;
694 
695 	output = bsddialog_gauge(&conf, text, rows, cols, perc);
696 
697 	return (output);
698 }
699 
infobox_builder(BUILDER_ARGS)700 int infobox_builder(BUILDER_ARGS)
701 {
702 	int output;
703 
704 	output = bsddialog_infobox(&conf, text, rows, cols);
705 
706 	return (output);
707 }
708 
mixedgauge_builder(BUILDER_ARGS)709 int mixedgauge_builder(BUILDER_ARGS)
710 {
711 	int output, perc;
712 
713 	if (argc < 1 || (((argc-1) % 2) != 0) ) {
714 		strcpy(errbuf, "bad --mixedgauge arguments\n");
715 		return (BSDDIALOG_ERROR);
716 	}
717 
718 	perc = atoi(argv[0]);
719 	perc = perc < 0 ? 0 : perc;
720 	perc = perc > 100 ? 100 : perc;
721 
722 	output = bsddialog_mixedgauge(&conf, text, rows, cols, perc,
723 	    argc-1, argv + 1);
724 
725 	return (output);
726 }
727 
msgbox_builder(BUILDER_ARGS)728 int msgbox_builder(BUILDER_ARGS)
729 {
730 	int output;
731 
732 	output = bsddialog_msgbox(&conf, text, rows, cols);
733 
734 	return (output);
735 }
736 
pause_builder(BUILDER_ARGS)737 int pause_builder(BUILDER_ARGS)
738 {
739 	int output, sec;
740 
741 	if (argc < 1) {
742 		strcpy(errbuf, "not <seconds> argument for --pause\n");
743 		return (BSDDIALOG_ERROR);
744 	}
745 
746 	sec = atoi(argv[0]);
747 	output = bsddialog_pause(&conf, text, rows, cols, sec);
748 
749 	return (output);
750 }
751 
rangebox_builder(BUILDER_ARGS)752 int rangebox_builder(BUILDER_ARGS)
753 {
754 	int output, min, max, value;
755 
756 	if (argc < 2) {
757 		strcpy(errbuf, "usage --rangebox <text> <rows> <cols> <min> "
758 		    "<max> [<init>]\n");
759 		return (BSDDIALOG_ERROR);
760 	}
761 
762 	min = atoi(argv[0]);
763 	max = atoi(argv[1]);
764 
765 	if (argc > 2) {
766 		value = atoi(argv[2]);
767 		value = value < min ? min : value;
768 		value = value > max ? max : value;
769 	}
770 	else
771 		value = min;
772 
773 	output = bsddialog_rangebox(&conf, text, rows, cols, min, max, &value);
774 
775 	dprintf(output_fd_flag, "%d", value);
776 
777 	return (output);
778 }
779 
textbox_builder(BUILDER_ARGS)780 int textbox_builder(BUILDER_ARGS)
781 {
782 	int output;
783 
784 	output = bsddialog_textbox(&conf, text, rows, cols);
785 
786 	return (output);
787 }
788 
yesno_builder(BUILDER_ARGS)789 int yesno_builder(BUILDER_ARGS)
790 {
791 	int output;
792 
793 	output = bsddialog_yesno(&conf, text, rows, cols);
794 
795 	return (output);
796 }
797 
798 /* DATE and TIME */
datebox_builder(BUILDER_ARGS)799 int datebox_builder(BUILDER_ARGS)
800 {
801 	int output;
802 	unsigned int yy, mm, dd;
803 	time_t cal;
804 	struct tm *localtm;
805 	char stringdate[1024];
806 
807 	time(&cal);
808 	localtm = localtime(&cal);
809 	yy = localtm->tm_year + 1900;
810 	mm = localtm->tm_mon + 1;
811 	dd = localtm->tm_mday;
812 
813 	/* --calendar text h w [year month day] */
814 	if (argc == 3) {
815 		yy = atoi(argv[0]);
816 		mm = atoi(argv[1]);
817 		dd = atoi(argv[2]);
818 	}
819 
820 	output = bsddialog_datebox(&conf, text, rows, cols, &yy, &mm, &dd);
821 	if (output != BSDDIALOG_YESOK)
822 		return (output);
823 
824 	if (date_fmt_flag == NULL) {
825 		dprintf(output_fd_flag, "%u/%u/%u", yy, mm, dd);
826 	}
827 	else {
828 		time(&cal);
829 		localtm = localtime(&cal);
830 		localtm->tm_year = yy - 1900;
831 		localtm->tm_mon  = mm;
832 		localtm->tm_mday = dd;
833 		strftime(stringdate, 1024, date_fmt_flag, localtm);
834 		dprintf(output_fd_flag, "%s", stringdate);
835 	}
836 
837 	return (output);
838 }
839 
timebox_builder(BUILDER_ARGS)840 int timebox_builder(BUILDER_ARGS)
841 {
842 	int output;
843 	unsigned int hh, mm, ss;
844 	time_t clock;
845 	struct tm *localtm;
846 	char stringtime[1024];
847 
848 	time(&clock);
849 	localtm = localtime(&clock);
850 	hh = localtm->tm_hour;
851 	mm = localtm->tm_min;
852 	ss = localtm->tm_sec;
853 
854 	/* --timebox text h w [hour minute second] */
855 	if (argc == 3) {
856 		hh = atoi(argv[0]);
857 		mm = atoi(argv[1]);
858 		ss = atoi(argv[2]);
859 	}
860 
861 	output = bsddialog_timebox(&conf, text, rows, cols, &hh, &mm, &ss);
862 	if (output != BSDDIALOG_YESOK)
863 		return (output);
864 
865 	if (time_fmt_flag == NULL) {
866 		dprintf(output_fd_flag, "%u:%u:%u", hh, mm, ss);
867 	}
868 	else {
869 		time(&clock);
870 		localtm = localtime(&clock);
871 		localtm->tm_hour = hh;
872 		localtm->tm_min  = mm;
873 		localtm->tm_sec = ss;
874 		strftime(stringtime, 1024, time_fmt_flag, localtm);
875 		dprintf(output_fd_flag, "%s", stringtime);
876 	}
877 
878 	return (output);
879 }
880 
881 /* MENU */
882 static int
get_menu_items(char * errbuf,int argc,char ** argv,bool setprefix,bool setdepth,bool setname,bool setdesc,bool setstatus,bool sethelp,int * nitems,struct bsddialog_menuitem * items)883 get_menu_items(char *errbuf, int argc, char **argv, bool setprefix,
884     bool setdepth, bool setname, bool setdesc, bool setstatus, bool sethelp,
885     int *nitems, struct bsddialog_menuitem *items)
886 {
887 	int i, j, sizeitem;
888 
889 	sizeitem = 0;
890 	if (setprefix) sizeitem++;
891 	if (setdepth)  sizeitem++;
892 	if (setname)   sizeitem++;
893 	if (setdesc)   sizeitem++;
894 	if (setstatus) sizeitem++;
895 	if (sethelp)   sizeitem++;
896 	if ((argc % sizeitem) != 0) {
897 		strcpy(errbuf, "bad number of arguments for this menu\n");
898 		return (BSDDIALOG_ERROR);
899 	}
900 
901 	*nitems = argc / sizeitem;
902 	j = 0;
903 	for (i=0; i<*nitems; i++) {
904 		items[i].prefix = setprefix ? argv[j++] : nostring;
905 		items[i].depth = setdepth ? atoi(argv[j++]) : 0;
906 		items[i].name = setname ? argv[j++] : nostring;
907 		items[i].desc = setdesc ? argv[j++] : nostring;
908 		if (setstatus)
909 			items[i].on = strcmp(argv[j++], "on") == 0 ? true : false;
910 		else
911 			items[i].on = false;
912 		items[i].bottomdesc = sethelp ? argv[j++] : nostring;
913 	}
914 
915 	return (BSDDIALOG_YESOK);
916 }
917 
918 static void
print_menu_items(struct bsddialog_conf * conf,int output,int nitems,struct bsddialog_menuitem * items,int focusitem)919 print_menu_items(struct bsddialog_conf *conf, int output, int nitems,
920     struct bsddialog_menuitem *items, int focusitem)
921 {
922 	int i;
923 	bool sep, toquote;
924 	char *sepstr, quotech, *helpvalue;
925 
926 	sep = false;
927 	quotech = item_singlequote_flag ? '\'' : '"';
928 	sepstr = item_output_sep_flag != NULL ? item_output_sep_flag : " ";
929 
930 	if (output == BSDDIALOG_HELP && focusitem >= 0) {
931 		dprintf(output_fd_flag, "HELP ");
932 
933 		helpvalue = items[focusitem].name;
934 		if (item_bottomdesc_flag && item_tag_help_flag == false)
935 			helpvalue = items[focusitem].bottomdesc;
936 
937 		toquote = item_always_quote_flag || strchr(helpvalue, ' ') != NULL;
938 
939 		if (toquote)
940 			dprintf(output_fd_flag, "%c", quotech);
941 		dprintf(output_fd_flag, "%s", helpvalue);
942 		if (toquote)
943 			dprintf(output_fd_flag, "%c", quotech);
944 
945 		if (list_items_on_flag == false)
946 			return;
947 
948 		sep = true;
949 	}
950 
951 	if (output != BSDDIALOG_YESOK && list_items_on_flag == false)
952 		return;
953 
954 	for (i = 0; i < nitems; i++) {
955 		if (items[i].on == false)
956 			continue;
957 
958 		if (sep == true) {
959 			dprintf(output_fd_flag, "%s", sepstr);
960 			if (item_output_sepnl_flag)
961 				dprintf(output_fd_flag, "\n");
962 		}
963 		sep = true;
964 
965 		toquote = item_always_quote_flag || strchr(items[i].name, ' ') != NULL;
966 
967 		if (toquote)
968 			dprintf(output_fd_flag, "%c", quotech);
969 		dprintf(output_fd_flag, "%s", items[i].name);
970 		if (toquote)
971 			dprintf(output_fd_flag, "%c", quotech);
972 	}
973 }
974 
buildlist_builder(BUILDER_ARGS)975 int buildlist_builder(BUILDER_ARGS)
976 {
977 	int output, menurows, nitems, focusitem;
978 	struct bsddialog_menuitem items[1024];
979 
980 	if (argc < 1) {
981 		strcpy(errbuf, "<menurows> not provided");
982 		return (BSDDIALOG_ERROR);
983 	}
984 
985 	menurows = atoi(argv[0]);
986 
987 	output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
988 	    true, true, true, item_bottomdesc_flag, &nitems, items);
989 	if (output != 0)
990 		return (output);
991 
992 	output = bsddialog_buildlist(&conf, text, rows, cols, menurows, nitems,
993 	    items, &focusitem);
994 	if (output == BSDDIALOG_ERROR)
995 		return (BSDDIALOG_ERROR);
996 
997 	print_menu_items(&conf, output, nitems, items, focusitem);
998 
999 	return (output);
1000 }
1001 
checklist_builder(BUILDER_ARGS)1002 int checklist_builder(BUILDER_ARGS)
1003 {
1004 	int output, menurows, nitems, focusitem;
1005 	struct bsddialog_menuitem items[1024];
1006 
1007 	if (argc < 1) {
1008 		strcpy(errbuf, "<menurows> not provided");
1009 		return (BSDDIALOG_ERROR);
1010 	}
1011 
1012 	menurows = atoi(argv[0]);
1013 
1014 	output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
1015 	    true, true, true, item_bottomdesc_flag, &nitems, items);
1016 	if (output != 0)
1017 		return (output);
1018 
1019 	output = bsddialog_checklist(&conf, text, rows, cols, menurows, nitems,
1020 	    items, &focusitem);
1021 
1022 	print_menu_items(&conf, output, nitems, items, focusitem);
1023 
1024 	return (output);
1025 }
1026 
menu_builder(BUILDER_ARGS)1027 int menu_builder(BUILDER_ARGS)
1028 {
1029 	int output, menurows, nitems, focusitem;
1030 	struct bsddialog_menuitem items[1024];
1031 
1032 	if (argc < 1) {
1033 		strcpy(errbuf, "<menurows> not provided");
1034 		return (BSDDIALOG_ERROR);
1035 	}
1036 
1037 	menurows = atoi(argv[0]);
1038 
1039 	output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
1040 	    true, true, false, item_bottomdesc_flag, &nitems, items);
1041 	if (output != 0)
1042 		return (output);
1043 
1044 	output = bsddialog_menu(&conf, text, rows, cols, menurows, nitems,
1045 	    items, &focusitem);
1046 
1047 	print_menu_items(&conf, output, nitems, items, focusitem);
1048 
1049 	return (output);
1050 }
1051 
radiolist_builder(BUILDER_ARGS)1052 int radiolist_builder(BUILDER_ARGS)
1053 {
1054 	int output, menurows, nitems, focusitem;
1055 	struct bsddialog_menuitem items[1024];
1056 
1057 	if (argc < 1) {
1058 		strcpy(errbuf, "<menurows> not provided");
1059 		return (BSDDIALOG_ERROR);
1060 	}
1061 
1062 	menurows = atoi(argv[0]);
1063 
1064 	output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
1065 	    true, true, true, item_bottomdesc_flag, &nitems, items);
1066 	if (output != 0)
1067 		return (output);
1068 
1069 	output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
1070 	    items, &focusitem);
1071 
1072 	print_menu_items(&conf, output, nitems, items, focusitem);
1073 
1074 	return (output);
1075 }
1076 
treeview_builder(BUILDER_ARGS)1077 int treeview_builder(BUILDER_ARGS)
1078 {
1079 	int output, menurows, nitems, focusitem;
1080 	struct bsddialog_menuitem items[1024];
1081 
1082 	if (argc < 1) {
1083 		strcpy(errbuf, "<menurows> not provided");
1084 		return (BSDDIALOG_ERROR);
1085 	}
1086 
1087 	menurows = atoi(argv[0]);
1088 
1089 	output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, true,
1090 	    true, true, true, item_bottomdesc_flag, &nitems, items);
1091 	if (output != 0)
1092 		return (output);
1093 
1094 	conf.menu.no_name = true;
1095 	conf.menu.align_left = true;
1096 
1097 	output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
1098 	    items, &focusitem);
1099 
1100 	print_menu_items(&conf, output, nitems, items, focusitem);
1101 
1102 	return (output);
1103 }
1104 
1105 /* FORM */
1106 static void
print_form_items(struct bsddialog_conf * conf,int output,int nitems,struct bsddialog_formitem * items)1107 print_form_items(struct bsddialog_conf *conf, int output, int nitems,
1108     struct bsddialog_formitem *items)
1109 {
1110 	int i;
1111 
1112 	if (output == BSDDIALOG_ERROR)
1113 		return;
1114 
1115 	for (i=0; i < nitems; i++) {
1116 		dprintf(output_fd_flag, "%s\n", items[i].value);
1117 		free(items[i].value);
1118 	}
1119 }
1120 
form_builder(BUILDER_ARGS)1121 int form_builder(BUILDER_ARGS)
1122 {
1123 	int i, output, formheight, nitems, fieldlen, valuelen;
1124 	struct bsddialog_formitem items[1024];
1125 	unsigned int flags = 0;
1126 
1127 	if (argc < 1 || (((argc-1) % 8) != 0) ) {
1128 		strcpy(errbuf, "bad number of arguments for this form\n");
1129 		return (BSDDIALOG_ERROR);
1130 	}
1131 
1132 	formheight = atoi(argv[0]);
1133 
1134 	argc--;
1135 	argv++;
1136 
1137 	nitems = argc / 8;
1138 	for (i=0; i<nitems; i++) {
1139 		items[i].label	= argv[8*i];
1140 		items[i].ylabel = atoi(argv[8*i+1]);
1141 		items[i].xlabel = atoi(argv[8*i+2]);
1142 		items[i].init	= argv[8*i+3];
1143 		items[i].yfield	= atoi(argv[8*i+4]);
1144 		items[i].xfield	= atoi(argv[8*i+5]);
1145 
1146 		fieldlen = atoi(argv[8*i+6]);
1147 		items[i].fieldlen = abs(fieldlen);
1148 
1149 		valuelen = atoi(argv[8*i+7]);
1150 		items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
1151 
1152 		flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
1153 		items[i].flags = flags;
1154 	}
1155 
1156 	output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
1157 	    items);
1158 	print_form_items(&conf, output, nitems, items);
1159 
1160 	return (output);
1161 }
1162 
inputbox_builder(BUILDER_ARGS)1163 int inputbox_builder(BUILDER_ARGS)
1164 {
1165 	int output;
1166 	struct bsddialog_formitem item;
1167 
1168 	item.label	 = "";
1169 	item.ylabel	 = 0;
1170 	item.xlabel	 = 0;
1171 	item.init	 = argc > 0 ? argv[0] : "";
1172 	item.yfield	 = 1;
1173 	item.xfield	 = 1;
1174 	item.fieldlen    = cols > 4 ? cols-4 : 25;
1175 	item.maxvaluelen = max_input_form_flag > 0 ? max_input_form_flag : 2048;
1176 	item.flags	 = 0;
1177 
1178 	output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
1179 	print_form_items(&conf, output, 1, &item);
1180 
1181 	return (output);
1182 }
1183 
mixedform_builder(BUILDER_ARGS)1184 int mixedform_builder(BUILDER_ARGS)
1185 {
1186 	int i, output, formheight, nitems;
1187 	struct bsddialog_formitem items[1024];
1188 
1189 	if (argc < 1 || (((argc-1) % 9) != 0) ) {
1190 		strcpy(errbuf, "bad number of arguments for this form\n");
1191 		return (BSDDIALOG_ERROR);
1192 	}
1193 
1194 	formheight = atoi(argv[0]);
1195 
1196 	argc--;
1197 	argv++;
1198 
1199 	nitems = argc / 9;
1200 	for (i=0; i<nitems; i++) {
1201 		items[i].label	     = argv[9*i];
1202 		items[i].ylabel      = atoi(argv[9*i+1]);
1203 		items[i].xlabel      = atoi(argv[9*i+2]);
1204 		items[i].init	     = argv[9*i+3];
1205 		items[i].yfield	     = atoi(argv[9*i+4]);
1206 		items[i].xfield	     = atoi(argv[9*i+5]);
1207 		items[i].fieldlen    = atoi(argv[9*i+6]);
1208 		items[i].maxvaluelen = atoi(argv[9*i+7]);
1209 		items[i].flags       = atoi(argv[9*i+8]);
1210 	}
1211 
1212 	output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
1213 	    items);
1214 	print_form_items(&conf, output, nitems, items);
1215 
1216 	return (output);
1217 }
1218 
passwordbox_builder(BUILDER_ARGS)1219 int passwordbox_builder(BUILDER_ARGS)
1220 {
1221 	int output;
1222 	struct bsddialog_formitem item;
1223 
1224 	item.label	 = "";
1225 	item.ylabel	 = 0;
1226 	item.xlabel	 = 0;
1227 	item.init	 = argc > 0 ? argv[0] : "";
1228 	item.yfield	 = 1;
1229 	item.xfield	 = 1;
1230 	item.fieldlen	 = cols > 4 ? cols-4 : 25;
1231 	item.maxvaluelen = max_input_form_flag > 0 ? max_input_form_flag : 2048;
1232 	item.flags       = BSDDIALOG_FIELDHIDDEN;
1233 
1234 	output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
1235 	print_form_items(&conf, output, 1, &item);
1236 
1237 	return (output);
1238 }
1239 
passwordform_builder(BUILDER_ARGS)1240 int passwordform_builder(BUILDER_ARGS)
1241 {
1242 	int i, output, formheight, nitems, fieldlen, valuelen;
1243 	struct bsddialog_formitem items[1024];
1244 	unsigned int flags = BSDDIALOG_FIELDHIDDEN;
1245 
1246 	if (argc < 1 || (((argc-1) % 8) != 0) ) {
1247 		strcpy(errbuf, "bad number of arguments for this form\n");
1248 		return (BSDDIALOG_ERROR);
1249 	}
1250 
1251 	formheight = atoi(argv[0]);
1252 
1253 	argc--;
1254 	argv++;
1255 
1256 	nitems = argc / 8;
1257 	for (i=0; i<nitems; i++) {
1258 		items[i].label	= argv[8*i];
1259 		items[i].ylabel = atoi(argv[8*i+1]);
1260 		items[i].xlabel = atoi(argv[8*i+2]);
1261 		items[i].init	= argv[8*i+3];
1262 		items[i].yfield	= atoi(argv[8*i+4]);
1263 		items[i].xfield	= atoi(argv[8*i+5]);
1264 
1265 		fieldlen = atoi(argv[8*i+6]);
1266 		items[i].fieldlen = abs(fieldlen);
1267 
1268 		valuelen = atoi(argv[8*i+7]);
1269 		items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
1270 
1271 		flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
1272 		items[i].flags = flags;
1273 	}
1274 
1275 	output = bsddialog_form(&conf, text, rows, cols, formheight,
1276 	    nitems, items);
1277 	print_form_items(&conf, output, nitems, items);
1278 
1279 	return (output);
1280 }
1281