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 if (!(items[i].flags & BSDDIALOG_FIELDREADONLY)) 585 dprintf(opt->output_fd, "%s\n", items[i].value); 586 free(items[i].value); 587 } 588 } 589 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 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 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 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 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