1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021-2024 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 <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <wchar.h>
34
35 #include <bsddialog.h>
36 #include <bsddialog_theme.h>
37
38 #include "util.h"
39
40 #define NO_PRINT_VALUES(rv) \
41 (rv == BSDDIALOG_ERROR || rv == BSDDIALOG_CANCEL || rv == BSDDIALOG_ESC)
42
43 /* message */
infobox_builder(BUILDER_ARGS)44 int infobox_builder(BUILDER_ARGS)
45 {
46 if (argc > 0)
47 error_args(opt->name, argc, argv);
48
49 return (bsddialog_infobox(conf, text, rows, cols));
50 }
51
msgbox_builder(BUILDER_ARGS)52 int msgbox_builder(BUILDER_ARGS)
53 {
54 if (argc > 0)
55 error_args(opt->name, argc, argv);
56
57 return (bsddialog_msgbox(conf, text, rows, cols));
58 }
59
yesno_builder(BUILDER_ARGS)60 int yesno_builder(BUILDER_ARGS)
61 {
62 if (argc > 0)
63 error_args(opt->name, argc, argv);
64
65 return (bsddialog_yesno(conf, text, rows, cols));
66 }
67
68 /* textbox */
textbox_builder(BUILDER_ARGS)69 int textbox_builder(BUILDER_ARGS)
70 {
71 if (argc > 0)
72 error_args(opt->name, argc, argv);
73
74 return (bsddialog_textbox(conf, text, rows, cols));
75 }
76
77 /* bar */
gauge_builder(BUILDER_ARGS)78 int gauge_builder(BUILDER_ARGS)
79 {
80 int output;
81 unsigned int perc;
82
83 perc = 0;
84 if (argc == 1) {
85 perc = (u_int)strtoul(argv[0], NULL, 10);
86 perc = perc > 100 ? 100 : perc;
87 } else if (argc > 1) {
88 error_args(opt->name, argc - 1, argv + 1);
89 }
90
91 output = bsddialog_gauge(conf, text, rows, cols, perc, STDIN_FILENO,
92 "XXX", "EOF");
93
94 return (output);
95 }
96
mixedgauge_builder(BUILDER_ARGS)97 int mixedgauge_builder(BUILDER_ARGS)
98 {
99 int output, *minipercs;
100 unsigned int i, mainperc, nminibars;
101 const char **minilabels;
102
103 if (argc < 1)
104 exit_error(true, "%s missing <mainperc>", opt->name);
105 if (((argc-1) % 2) != 0)
106 exit_error(true,
107 "bad %s pair number [<minilabel> <miniperc>]", opt->name);
108
109 mainperc = (u_int)strtoul(argv[0], NULL, 10);
110 mainperc = mainperc > 100 ? 100 : mainperc;
111 argc--;
112 argv++;
113
114 nminibars = argc / 2;
115 if ((minilabels = calloc(nminibars, sizeof(char*))) == NULL)
116 exit_error(false, "Cannot allocate memory for minilabels");
117 if ((minipercs = calloc(nminibars, sizeof(int))) == NULL)
118 exit_error(false, "Cannot allocate memory for minipercs");
119
120 for (i = 0; i < nminibars; i++) {
121 minilabels[i] = argv[i * 2];
122 minipercs[i] = (int)strtol(argv[i * 2 + 1], NULL, 10);
123 }
124
125 output = bsddialog_mixedgauge(conf, text, rows, cols, mainperc,
126 nminibars, minilabels, minipercs);
127
128 return (output);
129 }
130
pause_builder(BUILDER_ARGS)131 int pause_builder(BUILDER_ARGS)
132 {
133 int output;
134 unsigned int secs;
135
136 if (argc == 0)
137 exit_error(true, "--pause missing <seconds>");
138 if (argc > 1)
139 error_args(opt->name, argc - 1, argv + 1);
140
141 secs = (u_int)strtoul(argv[0], NULL, 10);
142 output = bsddialog_pause(conf, text, rows, cols, &secs);
143
144 return (output);
145 }
146
rangebox_builder(BUILDER_ARGS)147 int rangebox_builder(BUILDER_ARGS)
148 {
149 int output, min, max, value;
150
151 if (argc < 2)
152 exit_error(true, "--rangebox missing <min> <max> [<init>]");
153 if (argc > 3)
154 error_args("--rangebox", argc - 3, argv + 3);
155
156 min = (int)strtol(argv[0], NULL, 10);
157 max = (int)strtol(argv[1], NULL, 10);
158
159 if (argc == 3) {
160 value = (int)strtol(argv[2], NULL, 10);
161 value = value < min ? min : value;
162 value = value > max ? max : value;
163 } else
164 value = min;
165
166 output = bsddialog_rangebox(conf, text, rows, cols, min, max, &value);
167 if (NO_PRINT_VALUES(output) == false)
168 dprintf(opt->output_fd, "%d", value);
169
170 return (output);
171 }
172
173 /* date and time */
date(BUILDER_ARGS)174 static int date(BUILDER_ARGS)
175 {
176 int rv;
177 unsigned int yy, mm, dd;
178 time_t cal;
179 struct tm *localtm;
180 char stringdate[1024];
181
182 time(&cal);
183 localtm = localtime(&cal);
184 yy = localtm->tm_year + 1900;
185 mm = localtm->tm_mon + 1;
186 dd = localtm->tm_mday;
187
188 if (argc > 3) {
189 error_args(opt->name, argc - 3, argv + 3);
190 } else if (argc == 3) {
191 /* lib checks/sets max and min */
192 dd = (u_int)strtoul(argv[0], NULL, 10);
193 mm = (u_int)strtoul(argv[1], NULL, 10);
194 yy = (u_int)strtoul(argv[2], NULL, 10);
195 }
196
197 if (strcmp(opt->name, "--datebox") == 0)
198 rv = bsddialog_datebox(conf, text, rows, cols, &yy, &mm, &dd);
199 else
200 rv = bsddialog_calendar(conf, text, rows, cols, &yy, &mm, &dd);
201 if (NO_PRINT_VALUES(rv))
202 return (rv);
203
204 if (opt->date_fmt != NULL) {
205 time(&cal);
206 localtm = localtime(&cal);
207 localtm->tm_year = yy - 1900;
208 localtm->tm_mon = mm - 1;
209 localtm->tm_mday = dd;
210 strftime(stringdate, 1024, opt->date_fmt, localtm);
211 dprintf(opt->output_fd, "%s", stringdate);
212 } else if (opt->bikeshed && ~dd & 1) {
213 dprintf(opt->output_fd, "%u/%u/%u", dd, mm, yy);
214 } else {
215 dprintf(opt->output_fd, "%02u/%02u/%u", dd, mm, yy);
216 }
217
218 return (rv);
219 }
220
calendar_builder(BUILDER_ARGS)221 int calendar_builder(BUILDER_ARGS)
222 {
223 /* Use height autosizing with rows = 2. Documented in bsddialog(1).
224 *
225 * f_dialog_calendar_size() in bsdconfig/share/dialog.subr:1352
226 * computes height 2 for `dialog --calendar', called by:
227 * 1) f_dialog_input_expire_password() in
228 * bsdconfig/usermgmt/share/user_input.subr:517 and
229 * 2) f_dialog_input_expire_account() in
230 * bsdconfig/usermgmt/share/user_input.subr:660.
231 *
232 * Then use height autosizing with 2 that is min height like dialog.
233 */
234 if (rows == 2)
235 rows = 0;
236
237 return (date(conf, text, rows, cols, argc, argv, opt));
238 }
239
datebox_builder(BUILDER_ARGS)240 int datebox_builder(BUILDER_ARGS)
241 {
242 return (date(conf, text, rows, cols, argc, argv, opt));
243 }
244
timebox_builder(BUILDER_ARGS)245 int timebox_builder(BUILDER_ARGS)
246 {
247 int output;
248 unsigned int hh, mm, ss;
249 time_t clock;
250 struct tm *localtm;
251 char stringtime[1024];
252
253 time(&clock);
254 localtm = localtime(&clock);
255 hh = localtm->tm_hour;
256 mm = localtm->tm_min;
257 ss = localtm->tm_sec;
258
259 if (argc > 3) {
260 error_args("--timebox", argc - 3, argv + 3);
261 } else if (argc == 3) {
262 hh = (u_int)strtoul(argv[0], NULL, 10);
263 mm = (u_int)strtoul(argv[1], NULL, 10);
264 ss = (u_int)strtoul(argv[2], NULL, 10);
265 }
266
267 output = bsddialog_timebox(conf, text, rows, cols, &hh, &mm, &ss);
268 if (NO_PRINT_VALUES(output))
269 return (output);
270
271 if (opt->time_fmt != NULL) {
272 time(&clock);
273 localtm = localtime(&clock);
274 localtm->tm_hour = hh;
275 localtm->tm_min = mm;
276 localtm->tm_sec = ss;
277 strftime(stringtime, 1024, opt->time_fmt, localtm);
278 dprintf(opt->output_fd, "%s", stringtime);
279 } else if (opt->bikeshed && ~ss & 1) {
280 dprintf(opt->output_fd, "%u:%u:%u", hh, mm, ss);
281 } else {
282 dprintf(opt->output_fd, "%02u:%02u:%02u", hh, mm, ss);
283 }
284
285 return (output);
286 }
287
288 /* menu */
289 static void
get_menu_items(int argc,char ** argv,bool setprefix,bool setdepth,bool setname,bool setdesc,bool setstatus,bool sethelp,unsigned int * nitems,struct bsddialog_menuitem ** items,int * focusitem,struct options * opt)290 get_menu_items(int argc, char **argv, bool setprefix, bool setdepth,
291 bool setname, bool setdesc, bool setstatus, bool sethelp,
292 unsigned int *nitems, struct bsddialog_menuitem **items, int *focusitem,
293 struct options *opt)
294 {
295 unsigned int i, j, sizeitem;
296
297 *focusitem = -1;
298
299 sizeitem = 0;
300 sizeitem += setprefix ? 1 : 0;
301 sizeitem += setdepth ? 1 : 0;
302 sizeitem += setname ? 1 : 0;
303 sizeitem += setdesc ? 1 : 0;
304 sizeitem += setstatus ? 1 : 0;
305 sizeitem += sethelp ? 1 : 0;
306 if ((argc % sizeitem) != 0)
307 exit_error(true, "%s bad arguments items number", opt->name);
308
309 *nitems = argc / sizeitem;
310 *items = calloc(*nitems, sizeof(struct bsddialog_menuitem));
311 if (items == NULL)
312 exit_error(false, "%s cannot allocate items", opt->name);
313
314 j = 0;
315 for (i = 0; i < *nitems; i++) {
316 (*items)[i].prefix = setprefix ? argv[j++] : "";
317 (*items)[i].depth = setdepth ?
318 (u_int)strtoul(argv[j++], NULL, 0) : 0;
319 (*items)[i].name = setname ? argv[j++] : "";
320 (*items)[i].desc = setdesc ? argv[j++] : "";
321 if (setstatus) {
322 if (strcasecmp(argv[j], "on") == 0)
323 (*items)[i].on = true;
324 else if (strcasecmp(argv[j], "off") == 0)
325 (*items)[i].on = false;
326 else
327 exit_error(true,
328 "\"%s\" (item %i) invalid status \"%s\"",
329 (*items)[i].name, i+1, argv[j]);
330 j++;
331 } else
332 (*items)[i].on = false;
333 (*items)[i].bottomdesc = sethelp ? argv[j++] : "";
334
335 if (opt->item_default != NULL && *focusitem == -1)
336 if (strcmp((*items)[i].name, opt->item_default) == 0)
337 *focusitem = i;
338 }
339 }
340
341 static void
print_menu_items(int output,int nitems,struct bsddialog_menuitem * items,int focusitem,struct options * opt)342 print_menu_items(int output, int nitems, struct bsddialog_menuitem *items,
343 int focusitem, struct options *opt)
344 {
345 bool sep, sepbefore, sepafter, sepsecond, toquote, ismenu, ischecklist;
346 int i;
347 char quotech;
348 const char *focusname, *sepstr;
349
350 ismenu = (strcmp(opt->name, "--menu") == 0) ? true : false;
351 ischecklist = (strcmp(opt->name, "--checklist") == 0) ? true : false;
352 sep = false;
353 quotech = opt->item_singlequote ? '\'' : '"';
354
355 if (NO_PRINT_VALUES(output))
356 return;
357
358 if (output == BSDDIALOG_HELP) {
359 dprintf(opt->output_fd, "HELP ");
360
361 if (focusitem >= 0) {
362 focusname = items[focusitem].name;
363 if (opt->item_bottomdesc &&
364 opt->help_print_item_name == false)
365 focusname = items[focusitem].bottomdesc;
366
367 toquote = false;
368 if (strchr(focusname, ' ') != NULL) {
369 toquote = opt->item_always_quote;
370 if (ismenu == false &&
371 opt->item_output_sepnl == false)
372 toquote = true;
373 }
374 if (toquote) {
375 dprintf(opt->output_fd, "%c%s%c",
376 quotech, focusname, quotech);
377 } else
378 dprintf(opt->output_fd, "%s", focusname);
379 }
380
381 if (ismenu || opt->help_print_items == false)
382 return;
383 sep = true;
384 }
385
386 sepbefore = false;
387 sepsecond = false;
388 if ((sepstr = opt->item_output_sep) == NULL) {
389 if (opt->item_output_sepnl)
390 sepstr = "\n";
391 else {
392 sepstr = " ";
393 sepsecond = true;
394 }
395 } else
396 sepbefore = true;
397
398 sepafter = false;
399 if (opt->item_output_sepnl) {
400 sepbefore = false;
401 sepafter = true;
402 }
403
404 for (i = 0; i < nitems; i++) {
405 if (items[i].on == false)
406 continue;
407
408 if (sep || sepbefore)
409 dprintf(opt->output_fd, "%s", sepstr);
410 sep = false;
411 if (sepsecond)
412 sep = true;
413
414 toquote = false;
415 if (strchr(items[i].name, ' ') != NULL) {
416 toquote = opt->item_always_quote;
417 if (ischecklist && opt->item_output_sepnl == false)
418 toquote = true;
419 }
420 if (toquote)
421 dprintf(opt->output_fd, "%c%s%c",
422 quotech, items[i].name, quotech);
423 else
424 dprintf(opt->output_fd, "%s", items[i].name);
425
426 if (sepafter)
427 dprintf(opt->output_fd, "%s", sepstr);
428 }
429 }
430
checklist_builder(BUILDER_ARGS)431 int checklist_builder(BUILDER_ARGS)
432 {
433 int output, focusitem;
434 unsigned int menurows, nitems;
435 struct bsddialog_menuitem *items;
436
437 if (argc < 1)
438 exit_error(true, "--checklist missing <menurows>");
439 menurows = (u_int)strtoul(argv[0], NULL, 10);
440
441 get_menu_items(argc-1, argv+1, opt->item_prefix, opt->item_depth, true,
442 true, true, opt->item_bottomdesc, &nitems, &items, &focusitem, opt);
443
444 output = bsddialog_checklist(conf, text, rows, cols, menurows, nitems,
445 items, &focusitem);
446
447 print_menu_items(output, nitems, items, focusitem, opt);
448 free(items);
449
450 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
451 output = BSDDIALOG_ITEM_HELP;
452
453 return (output);
454 }
455
menu_builder(BUILDER_ARGS)456 int menu_builder(BUILDER_ARGS)
457 {
458 int output, focusitem;
459 unsigned int menurows, nitems;
460 struct bsddialog_menuitem *items;
461
462 if (argc < 1)
463 exit_error(true, "--menu missing <menurows>");
464 menurows = (u_int)strtoul(argv[0], NULL, 10);
465
466 get_menu_items(argc-1, argv+1, opt->item_prefix, opt->item_depth, true,
467 true, false, opt->item_bottomdesc, &nitems, &items, &focusitem,
468 opt);
469
470 output = bsddialog_menu(conf, text, rows, cols, menurows, nitems,
471 items, &focusitem);
472
473 print_menu_items(output, nitems, items, focusitem, opt);
474 free(items);
475
476 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
477 output = BSDDIALOG_ITEM_HELP;
478
479 return (output);
480 }
481
radiolist_builder(BUILDER_ARGS)482 int radiolist_builder(BUILDER_ARGS)
483 {
484 int output, focusitem;
485 unsigned int menurows, nitems;
486 struct bsddialog_menuitem *items;
487
488 if (argc < 1)
489 exit_error(true, "--radiolist missing <menurows>");
490 menurows = (u_int)strtoul(argv[0], NULL, 10);
491
492 get_menu_items(argc-1, argv+1, opt->item_prefix, opt->item_depth, true,
493 true, true, opt->item_bottomdesc, &nitems, &items, &focusitem, opt);
494
495 output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
496 items, &focusitem);
497
498 print_menu_items(output, nitems, items, focusitem, opt);
499 free(items);
500
501 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
502 output = BSDDIALOG_ITEM_HELP;
503
504 return (output);
505 }
506
treeview_builder(BUILDER_ARGS)507 int treeview_builder(BUILDER_ARGS)
508 {
509 int output, focusitem;
510 unsigned int menurows, nitems;
511 struct bsddialog_menuitem *items;
512
513 if (argc < 1)
514 exit_error(true, "--treeview missing <menurows>");
515 menurows = (u_int)strtoul(argv[0], NULL, 10);
516
517 get_menu_items(argc-1, argv+1, opt->item_prefix, true, true, true, true,
518 opt->item_bottomdesc, &nitems, &items, &focusitem, opt);
519
520 conf->menu.no_name = true;
521 conf->menu.align_left = true;
522
523 output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
524 items, &focusitem);
525
526 print_menu_items(output, nitems, items, focusitem, opt);
527 free(items);
528
529 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
530 output = BSDDIALOG_ITEM_HELP;
531
532 return (output);
533 }
534
535 /* form */
strcols(const char * string)536 static unsigned int strcols(const char *string)
537 {
538 int w;
539 unsigned int ncol;
540 size_t charlen, mb_cur_max;
541 wchar_t wch;
542 mbstate_t mbs;
543
544 mb_cur_max = MB_CUR_MAX;
545 ncol = 0;
546 memset(&mbs, 0, sizeof(mbs));
547 while ((charlen = mbrlen(string, mb_cur_max, &mbs)) != 0 &&
548 charlen != (size_t)-1 && charlen != (size_t)-2) {
549 if (mbtowc(&wch, string, mb_cur_max) < 0)
550 return (0);
551 if ((w = wcwidth(wch)) > 0)
552 ncol += w;
553 string += charlen;
554 }
555
556 return (ncol);
557 }
558
559 static void
print_form_items(int output,int nitems,struct bsddialog_formitem * items,int focusitem,struct options * opt)560 print_form_items(int output, int nitems, struct bsddialog_formitem *items,
561 int focusitem, struct options *opt)
562 {
563 int i;
564 const char *helpname;
565
566 if (NO_PRINT_VALUES(output))
567 return;
568
569 if (output == BSDDIALOG_HELP) {
570 dprintf(opt->output_fd, "HELP");
571 if (focusitem >= 0) {
572 helpname = items[focusitem].label;
573 if (opt->item_bottomdesc &&
574 opt->help_print_item_name == false)
575 helpname = items[focusitem].bottomdesc;
576 dprintf(opt->output_fd, " %s", helpname);
577 }
578 if (opt->help_print_items == false)
579 return;
580 dprintf(opt->output_fd, "\n");
581 }
582
583 for (i = 0; i < nitems; i++) {
584 if (!(items[i].flags & BSDDIALOG_FIELDREADONLY))
585 dprintf(opt->output_fd, "%s\n", items[i].value);
586 free(items[i].value);
587 }
588 }
589
form_builder(BUILDER_ARGS)590 int form_builder(BUILDER_ARGS)
591 {
592 int output, fieldlen, focusitem;
593 unsigned int i, j, flags, formheight, nitems, sizeitem;
594 struct bsddialog_formitem *items;
595
596 if (argc < 1)
597 exit_error(true, "--form missing <formheight>");
598 formheight = (u_int)strtoul(argv[0], NULL, 10);
599
600 argc--;
601 argv++;
602 sizeitem = opt->item_bottomdesc ? 9 : 8;
603 if (argc % sizeitem != 0)
604 exit_error(true, "--form bad number of arguments items");
605
606 nitems = argc / sizeitem;
607 if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
608 exit_error(false, "cannot allocate memory for form items");
609 j = 0;
610 for (i = 0; i < nitems; i++) {
611 items[i].label = argv[j++];
612 items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10);
613 items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10);
614 items[i].init = argv[j++];
615 items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10);
616 items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10);
617
618 fieldlen = (int)strtol(argv[j++], NULL, 10);
619 if (fieldlen == 0)
620 items[i].fieldlen = strcols(items[i].init);
621 else
622 items[i].fieldlen = abs(fieldlen);
623
624 items[i].maxvaluelen = (u_int)strtoul(argv[j++], NULL, 10);
625 if (items[i].maxvaluelen == 0)
626 items[i].maxvaluelen = items[i].fieldlen;
627
628 flags = (fieldlen <= 0) ? BSDDIALOG_FIELDREADONLY : 0;
629 items[i].flags = flags;
630
631 items[i].bottomdesc = opt->item_bottomdesc ? argv[j++] : "";
632 }
633
634 focusitem = -1;
635 output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
636 items, &focusitem);
637 print_form_items(output, nitems, items, focusitem, opt);
638 free(items);
639
640 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
641 output = BSDDIALOG_ITEM_HELP;
642
643 return (output);
644 }
645
inputbox_builder(BUILDER_ARGS)646 int inputbox_builder(BUILDER_ARGS)
647 {
648 int output;
649 struct bsddialog_formitem item;
650
651 if (argc > 1)
652 error_args("--inputbox", argc - 1, argv + 1);
653
654 item.label = "";
655 item.ylabel = 0;
656 item.xlabel = 0;
657 item.init = argc > 0 ? argv[0] : "";
658 item.yfield = 0;
659 item.xfield = 0;
660 item.fieldlen = 1;
661 item.maxvaluelen = opt->max_input_form;
662 item.flags = BSDDIALOG_FIELDNOCOLOR;
663 item.flags |= BSDDIALOG_FIELDCURSOREND;
664 item.flags |= BSDDIALOG_FIELDEXTEND;
665 item.bottomdesc = "";
666
667 output = bsddialog_form(conf, text, rows, cols, 1, 1, &item, NULL);
668 print_form_items(output, 1, &item, -1, opt);
669
670 return (output);
671 }
672
mixedform_builder(BUILDER_ARGS)673 int mixedform_builder(BUILDER_ARGS)
674 {
675 int output, fieldlen, focusitem;
676 unsigned int i, j, formheight, nitems, sizeitem;
677 struct bsddialog_formitem *items;
678
679 if (argc < 1)
680 exit_error(true, "--mixedform missing <formheight>");
681 formheight = (u_int)strtoul(argv[0], NULL, 10);
682
683 argc--;
684 argv++;
685 sizeitem = opt->item_bottomdesc ? 10 : 9;
686 if (argc % sizeitem != 0)
687 exit_error(true, "--mixedform bad number of arguments items");
688
689 nitems = argc / sizeitem;
690 if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
691 exit_error(false, "cannot allocate memory for form items");
692 j = 0;
693 for (i = 0; i < nitems; i++) {
694 items[i].label = argv[j++];
695 items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10);
696 items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10);
697 items[i].init = argv[j++];
698 items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10);
699 items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10);
700 fieldlen = (int)strtol(argv[j++], NULL, 10);
701 if (fieldlen == 0)
702 items[i].fieldlen = strcols(items[i].init);
703 else
704 items[i].fieldlen = abs(fieldlen);
705 items[i].maxvaluelen = (u_int)strtoul(argv[j++], NULL, 10);
706 if (items[i].maxvaluelen == 0)
707 items[i].maxvaluelen = items[i].fieldlen;
708
709 items[i].flags = (u_int)strtoul(argv[j++], NULL, 10);
710 if (fieldlen <= 0)
711 items[i].flags |= BSDDIALOG_FIELDREADONLY;
712
713 items[i].bottomdesc = opt->item_bottomdesc ? argv[j++] : "";
714 }
715
716 focusitem = -1;
717 output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
718 items, &focusitem);
719 for (i = 0; i < nitems; i++) {
720 if ((int)strtol(argv[i * sizeitem + 6], NULL, 10) > 0)
721 items[i].flags &= ~ BSDDIALOG_FIELDREADONLY;
722 }
723 print_form_items(output, nitems, items, focusitem, opt);
724 free(items);
725
726 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
727 output = BSDDIALOG_ITEM_HELP;
728
729 return (output);
730 }
731
passwordbox_builder(BUILDER_ARGS)732 int passwordbox_builder(BUILDER_ARGS)
733 {
734 int output;
735 struct bsddialog_formitem item;
736
737 if (argc > 1)
738 error_args("--passwordbox", argc - 1, argv + 1);
739
740 item.label = "";
741 item.ylabel = 0;
742 item.xlabel = 0;
743 item.init = argc > 0 ? argv[0] : "";
744 item.yfield = 0;
745 item.xfield = 0;
746 item.fieldlen = 1;
747 item.maxvaluelen = opt->max_input_form;
748 item.flags = BSDDIALOG_FIELDHIDDEN;
749 item.flags |= BSDDIALOG_FIELDNOCOLOR;
750 item.flags |= BSDDIALOG_FIELDCURSOREND;
751 item.flags |= BSDDIALOG_FIELDEXTEND;
752 item.bottomdesc = "";
753
754 output = bsddialog_form(conf, text, rows, cols, 1, 1, &item, NULL);
755 print_form_items(output, 1, &item, -1, opt);
756
757 return (output);
758 }
759
passwordform_builder(BUILDER_ARGS)760 int passwordform_builder(BUILDER_ARGS)
761 {
762 int output, fieldlen, valuelen, focusitem;
763 unsigned int i, j, flags, formheight, nitems, sizeitem;
764 struct bsddialog_formitem *items;
765
766 if (argc < 1)
767 exit_error(true, "--passwordform missing <formheight>");
768 formheight = (u_int)strtoul(argv[0], NULL, 10);
769
770 argc--;
771 argv++;
772 sizeitem = opt->item_bottomdesc ? 9 : 8;
773 if (argc % sizeitem != 0)
774 exit_error(true, "--passwordform bad arguments items number");
775
776 flags = BSDDIALOG_FIELDHIDDEN;
777 nitems = argc / sizeitem;
778 if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
779 exit_error(false, "cannot allocate memory for form items");
780 j = 0;
781 for (i = 0; i < nitems; i++) {
782 items[i].label = argv[j++];
783 items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10);
784 items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10);
785 items[i].init = argv[j++];
786 items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10);
787 items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10);
788
789 fieldlen = (int)strtol(argv[j++], NULL, 10);
790 items[i].fieldlen = abs(fieldlen);
791
792 valuelen = (int)strtol(argv[j++], NULL, 10);
793 items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
794
795 flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
796 items[i].flags = flags;
797
798 items[i].bottomdesc = opt->item_bottomdesc ? argv[j++] : "";
799 }
800
801 focusitem = -1;
802 output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
803 items, &focusitem);
804 print_form_items(output, nitems, items, focusitem, opt);
805 free(items);
806
807 if (output == BSDDIALOG_HELP && opt->item_bottomdesc)
808 output = BSDDIALOG_ITEM_HELP;
809
810 return (output);
811 }
812