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 */ 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 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 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 */ 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 */ 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 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 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 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 */ 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 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 240 int datebox_builder(BUILDER_ARGS) 241 { 242 return (date(conf, text, rows, cols, argc, argv, opt)); 243 } 244 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 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 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 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 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 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 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 */ 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 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 dprintf(opt->output_fd, "%s\n", items[i].value); 585 free(items[i].value); 586 } 587 } 588 589 int form_builder(BUILDER_ARGS) 590 { 591 int output, fieldlen, focusitem; 592 unsigned int i, j, flags, formheight, nitems, sizeitem; 593 struct bsddialog_formitem *items; 594 595 if (argc < 1) 596 exit_error(true, "--form missing <formheight>"); 597 formheight = (u_int)strtoul(argv[0], NULL, 10); 598 599 argc--; 600 argv++; 601 sizeitem = opt->item_bottomdesc ? 9 : 8; 602 if (argc % sizeitem != 0) 603 exit_error(true, "--form bad number of arguments items"); 604 605 nitems = argc / sizeitem; 606 if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL) 607 exit_error(false, "cannot allocate memory for form items"); 608 j = 0; 609 for (i = 0; i < nitems; i++) { 610 items[i].label = argv[j++]; 611 items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10); 612 items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10); 613 items[i].init = argv[j++]; 614 items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10); 615 items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10); 616 617 fieldlen = (int)strtol(argv[j++], NULL, 10); 618 if (fieldlen == 0) 619 items[i].fieldlen = strcols(items[i].init); 620 else 621 items[i].fieldlen = abs(fieldlen); 622 623 items[i].maxvaluelen = (u_int)strtoul(argv[j++], NULL, 10); 624 if (items[i].maxvaluelen == 0) 625 items[i].maxvaluelen = items[i].fieldlen; 626 627 flags = (fieldlen <= 0) ? BSDDIALOG_FIELDREADONLY : 0; 628 items[i].flags = flags; 629 630 items[i].bottomdesc = opt->item_bottomdesc ? argv[j++] : ""; 631 } 632 633 focusitem = -1; 634 output = bsddialog_form(conf, text, rows, cols, formheight, nitems, 635 items, &focusitem); 636 print_form_items(output, nitems, items, focusitem, opt); 637 free(items); 638 639 if (output == BSDDIALOG_HELP && opt->item_bottomdesc) 640 output = BSDDIALOG_ITEM_HELP; 641 642 return (output); 643 } 644 645 int inputbox_builder(BUILDER_ARGS) 646 { 647 int output; 648 struct bsddialog_formitem item; 649 650 if (argc > 1) 651 error_args("--inputbox", argc - 1, argv + 1); 652 653 item.label = ""; 654 item.ylabel = 0; 655 item.xlabel = 0; 656 item.init = argc > 0 ? argv[0] : ""; 657 item.yfield = 0; 658 item.xfield = 0; 659 item.fieldlen = 1; 660 item.maxvaluelen = opt->max_input_form; 661 item.flags = BSDDIALOG_FIELDNOCOLOR; 662 item.flags |= BSDDIALOG_FIELDCURSOREND; 663 item.flags |= BSDDIALOG_FIELDEXTEND; 664 item.bottomdesc = ""; 665 666 output = bsddialog_form(conf, text, rows, cols, 1, 1, &item, NULL); 667 print_form_items(output, 1, &item, -1, opt); 668 669 return (output); 670 } 671 672 int mixedform_builder(BUILDER_ARGS) 673 { 674 int output, fieldlen, focusitem; 675 unsigned int i, j, formheight, nitems, sizeitem; 676 struct bsddialog_formitem *items; 677 678 if (argc < 1) 679 exit_error(true, "--mixedform missing <formheight>"); 680 formheight = (u_int)strtoul(argv[0], NULL, 10); 681 682 argc--; 683 argv++; 684 sizeitem = opt->item_bottomdesc ? 10 : 9; 685 if (argc % sizeitem != 0) 686 exit_error(true, "--mixedform bad number of arguments items"); 687 688 nitems = argc / sizeitem; 689 if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL) 690 exit_error(false, "cannot allocate memory for form items"); 691 j = 0; 692 for (i = 0; i < nitems; i++) { 693 items[i].label = argv[j++]; 694 items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10); 695 items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10); 696 items[i].init = argv[j++]; 697 items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10); 698 items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10); 699 fieldlen = (int)strtol(argv[j++], NULL, 10); 700 if (fieldlen == 0) 701 items[i].fieldlen = strcols(items[i].init); 702 else 703 items[i].fieldlen = abs(fieldlen); 704 items[i].maxvaluelen = (u_int)strtoul(argv[j++], NULL, 10); 705 if (items[i].maxvaluelen == 0) 706 items[i].maxvaluelen = items[i].fieldlen; 707 708 items[i].flags = (u_int)strtoul(argv[j++], NULL, 10); 709 if (fieldlen <= 0) 710 items[i].flags |= BSDDIALOG_FIELDREADONLY; 711 712 items[i].bottomdesc = opt->item_bottomdesc ? argv[j++] : ""; 713 } 714 715 focusitem = -1; 716 output = bsddialog_form(conf, text, rows, cols, formheight, nitems, 717 items, &focusitem); 718 print_form_items(output, nitems, items, focusitem, opt); 719 free(items); 720 721 if (output == BSDDIALOG_HELP && opt->item_bottomdesc) 722 output = BSDDIALOG_ITEM_HELP; 723 724 return (output); 725 } 726 727 int passwordbox_builder(BUILDER_ARGS) 728 { 729 int output; 730 struct bsddialog_formitem item; 731 732 if (argc > 1) 733 error_args("--passwordbox", argc - 1, argv + 1); 734 735 item.label = ""; 736 item.ylabel = 0; 737 item.xlabel = 0; 738 item.init = argc > 0 ? argv[0] : ""; 739 item.yfield = 0; 740 item.xfield = 0; 741 item.fieldlen = 1; 742 item.maxvaluelen = opt->max_input_form; 743 item.flags = BSDDIALOG_FIELDHIDDEN; 744 item.flags |= BSDDIALOG_FIELDNOCOLOR; 745 item.flags |= BSDDIALOG_FIELDCURSOREND; 746 item.flags |= BSDDIALOG_FIELDEXTEND; 747 item.bottomdesc = ""; 748 749 output = bsddialog_form(conf, text, rows, cols, 1, 1, &item, NULL); 750 print_form_items(output, 1, &item, -1, opt); 751 752 return (output); 753 } 754 755 int passwordform_builder(BUILDER_ARGS) 756 { 757 int output, fieldlen, valuelen, focusitem; 758 unsigned int i, j, flags, formheight, nitems, sizeitem; 759 struct bsddialog_formitem *items; 760 761 if (argc < 1) 762 exit_error(true, "--passwordform missing <formheight>"); 763 formheight = (u_int)strtoul(argv[0], NULL, 10); 764 765 argc--; 766 argv++; 767 sizeitem = opt->item_bottomdesc ? 9 : 8; 768 if (argc % sizeitem != 0) 769 exit_error(true, "--passwordform bad arguments items number"); 770 771 flags = BSDDIALOG_FIELDHIDDEN; 772 nitems = argc / sizeitem; 773 if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL) 774 exit_error(false, "cannot allocate memory for form items"); 775 j = 0; 776 for (i = 0; i < nitems; i++) { 777 items[i].label = argv[j++]; 778 items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10); 779 items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10); 780 items[i].init = argv[j++]; 781 items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10); 782 items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10); 783 784 fieldlen = (int)strtol(argv[j++], NULL, 10); 785 items[i].fieldlen = abs(fieldlen); 786 787 valuelen = (int)strtol(argv[j++], NULL, 10); 788 items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen; 789 790 flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0); 791 items[i].flags = flags; 792 793 items[i].bottomdesc = opt->item_bottomdesc ? argv[j++] : ""; 794 } 795 796 focusitem = -1; 797 output = bsddialog_form(conf, text, rows, cols, formheight, nitems, 798 items, &focusitem); 799 print_form_items(output, nitems, items, focusitem, opt); 800 free(items); 801 802 if (output == BSDDIALOG_HELP && opt->item_bottomdesc) 803 output = BSDDIALOG_ITEM_HELP; 804 805 return (output); 806 } 807