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