1 /* $OpenBSD: subr_userconf.c,v 1.43 2014/11/03 03:08:00 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1996-2001 Mats O Jansson <moj@stacken.kth.se> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/device.h> 32 #include <sys/malloc.h> 33 #include <sys/time.h> 34 35 #include <dev/cons.h> 36 37 extern char *locnames[]; 38 extern short locnamp[]; 39 extern short cfroots[]; 40 extern int cfroots_size; 41 extern int pv_size; 42 extern short pv[]; 43 extern struct timezone tz; 44 extern char *pdevnames[]; 45 extern int pdevnames_size; 46 extern struct pdevinit pdevinit[]; 47 48 int userconf_base = 16; /* Base for "large" numbers */ 49 int userconf_maxdev = -1; /* # of used device slots */ 50 int userconf_totdev = -1; /* # of device slots */ 51 int userconf_maxlocnames = -1; /* # of locnames */ 52 int userconf_cnt = -1; /* Line counter for ... */ 53 int userconf_lines = 12; /* ... # of lines per page */ 54 int userconf_histlen = 0; 55 int userconf_histcur = 0; 56 char userconf_history[1024]; 57 int userconf_histsz = sizeof(userconf_history); 58 char userconf_argbuf[40]; /* Additional input */ 59 char userconf_cmdbuf[40]; /* Command line */ 60 char userconf_histbuf[40]; 61 62 void userconf_init(void); 63 int userconf_more(void); 64 void userconf_modify(char *, int *); 65 void userconf_hist_cmd(char); 66 void userconf_hist_int(int); 67 void userconf_hist_eoc(void); 68 void userconf_pnum(int); 69 void userconf_pdevnam(short); 70 void userconf_pdev(short); 71 int userconf_number(char *, int *); 72 int userconf_device(char *, int *, short *, short *); 73 int userconf_attr(char *, int *); 74 void userconf_modify(char *, int *); 75 void userconf_change(int); 76 void userconf_disable(int); 77 void userconf_enable(int); 78 void userconf_help(void); 79 void userconf_list(void); 80 void userconf_show(void); 81 void userconf_common_attr_val(short, int *, char); 82 void userconf_show_attr(char *); 83 void userconf_common_dev(char *, int, short, short, char); 84 void userconf_common_attr(char *, int, char); 85 void userconf_add_read(char *, char, char *, int, int *); 86 void userconf_add(char *, int, short, short); 87 int userconf_parse(char *); 88 89 #define UC_CHANGE 'c' 90 #define UC_DISABLE 'd' 91 #define UC_ENABLE 'e' 92 #define UC_FIND 'f' 93 #define UC_SHOW 's' 94 95 char *userconf_cmds[] = { 96 "add", "a", 97 "base", "b", 98 "change", "c", 99 #if defined(DDB) 100 "ddb", "D", 101 #endif 102 "disable", "d", 103 "enable", "e", 104 "exit", "q", 105 "find", "f", 106 "help", "h", 107 "list", "l", 108 "lines", "L", 109 "quit", "q", 110 "show", "s", 111 "timezone", "t", 112 "verbose", "v", 113 "?", "h", 114 "", "", 115 }; 116 117 void 118 userconf_init(void) 119 { 120 int i = 0; 121 struct cfdata *cd; 122 int ln; 123 124 while (cfdata[i].cf_attach != 0) { 125 userconf_maxdev = i; 126 userconf_totdev = i; 127 128 cd = &cfdata[i]; 129 ln = cd->cf_locnames; 130 while (locnamp[ln] != -1) { 131 if (locnamp[ln] > userconf_maxlocnames) 132 userconf_maxlocnames = locnamp[ln]; 133 ln++; 134 } 135 i++; 136 } 137 138 while (cfdata[i].cf_attach == 0) { 139 userconf_totdev = i; 140 i++; 141 } 142 userconf_totdev = userconf_totdev - 1; 143 } 144 145 int 146 userconf_more(void) 147 { 148 int quit = 0; 149 char c = '\0'; 150 151 if (userconf_cnt != -1) { 152 if (userconf_cnt == userconf_lines) { 153 printf("--- more ---"); 154 c = cngetc(); 155 userconf_cnt = 0; 156 printf("\r \r"); 157 } 158 userconf_cnt++; 159 if (c == 'q' || c == 'Q') 160 quit = 1; 161 } 162 return (quit); 163 } 164 165 void 166 userconf_hist_cmd(char cmd) 167 { 168 userconf_histcur = userconf_histlen; 169 if (userconf_histcur < userconf_histsz) { 170 userconf_history[userconf_histcur] = cmd; 171 userconf_histcur++; 172 } 173 } 174 175 void 176 userconf_hist_int(int val) 177 { 178 snprintf(userconf_histbuf, sizeof userconf_histbuf, " %d",val); 179 if (userconf_histcur + strlen(userconf_histbuf) < userconf_histsz) { 180 bcopy(userconf_histbuf, 181 &userconf_history[userconf_histcur], 182 strlen(userconf_histbuf)); 183 userconf_histcur = userconf_histcur + strlen(userconf_histbuf); 184 } 185 } 186 187 void 188 userconf_hist_eoc(void) 189 { 190 if (userconf_histcur < userconf_histsz) { 191 userconf_history[userconf_histcur] = '\n'; 192 userconf_histcur++; 193 userconf_histlen = userconf_histcur; 194 } 195 } 196 197 void 198 userconf_pnum(int val) 199 { 200 if (val > -2 && val < 16) { 201 printf("%d",val); 202 return; 203 } 204 205 switch (userconf_base) { 206 case 8: 207 printf("0%o",val); 208 break; 209 case 10: 210 printf("%d",val); 211 break; 212 case 16: 213 default: 214 printf("0x%x",val); 215 break; 216 } 217 } 218 219 void 220 userconf_pdevnam(short dev) 221 { 222 struct cfdata *cd; 223 224 cd = &cfdata[dev]; 225 printf("%s", cd->cf_driver->cd_name); 226 switch (cd->cf_fstate) { 227 case FSTATE_NOTFOUND: 228 case FSTATE_DNOTFOUND: 229 printf("%d", cd->cf_unit); 230 break; 231 case FSTATE_FOUND: 232 printf("*FOUND*"); 233 break; 234 case FSTATE_STAR: 235 case FSTATE_DSTAR: 236 printf("*"); 237 break; 238 default: 239 printf("*UNKNOWN*"); 240 break; 241 } 242 } 243 244 void 245 userconf_pdev(short devno) 246 { 247 struct cfdata *cd; 248 short *p; 249 int *l; 250 int ln; 251 char c; 252 253 if (devno > userconf_maxdev && devno <= userconf_totdev) { 254 printf("%3d free slot (for add)\n", devno); 255 return; 256 } 257 258 if (devno > userconf_totdev && 259 devno <= userconf_totdev+pdevnames_size) { 260 printf("%3d %s count %d", devno, 261 pdevnames[devno-userconf_totdev-1], 262 abs(pdevinit[devno-userconf_totdev-1].pdev_count)); 263 if (pdevinit[devno-userconf_totdev-1].pdev_count < 1) 264 printf(" disable"); 265 printf(" (pseudo device)\n"); 266 return; 267 } 268 269 if (devno > userconf_maxdev) { 270 printf("Unknown devno (max is %d)\n", userconf_maxdev); 271 return; 272 } 273 274 cd = &cfdata[devno]; 275 276 printf("%3d ", devno); 277 userconf_pdevnam(devno); 278 printf(" at"); 279 c = ' '; 280 p = cd->cf_parents; 281 if (*p == -1) 282 printf(" root"); 283 while (*p != -1) { 284 printf("%c", c); 285 userconf_pdevnam(*p++); 286 c = '|'; 287 } 288 switch (cd->cf_fstate) { 289 case FSTATE_NOTFOUND: 290 case FSTATE_FOUND: 291 case FSTATE_STAR: 292 break; 293 case FSTATE_DNOTFOUND: 294 case FSTATE_DSTAR: 295 printf(" disable"); 296 break; 297 default: 298 printf(" ???"); 299 break; 300 } 301 l = cd->cf_loc; 302 ln = cd->cf_locnames; 303 while (locnamp[ln] != -1) { 304 printf(" %s ", locnames[locnamp[ln]]); 305 ln++; 306 userconf_pnum(*l++); 307 } 308 printf(" flags 0x%x\n", cd->cf_flags); 309 } 310 311 int 312 userconf_number(char *c, int *val) 313 { 314 u_int num = 0; 315 int neg = 0; 316 int base = 10; 317 318 if (*c == '-') { 319 neg = 1; 320 c++; 321 } 322 if (*c == '0') { 323 base = 8; 324 c++; 325 if (*c == 'x' || *c == 'X') { 326 base = 16; 327 c++; 328 } 329 } 330 while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') { 331 u_char cc = *c; 332 333 if (cc >= '0' && cc <= '9') 334 cc = cc - '0'; 335 else if (cc >= 'a' && cc <= 'f') 336 cc = cc - 'a' + 10; 337 else if (cc >= 'A' && cc <= 'F') 338 cc = cc - 'A' + 10; 339 else 340 return (-1); 341 342 if (cc > base) 343 return (-1); 344 num = num * base + cc; 345 c++; 346 } 347 348 if (neg && num > INT_MAX) /* overflow */ 349 return (1); 350 *val = neg ? - num : num; 351 return (0); 352 } 353 354 int 355 userconf_device(char *cmd, int *len, short *unit, short *state) 356 { 357 short u = 0, s = FSTATE_FOUND; 358 int l = 0; 359 char *c; 360 361 c = cmd; 362 while (*c >= 'a' && *c <= 'z') { 363 l++; 364 c++; 365 } 366 if (*c == '*') { 367 s = FSTATE_STAR; 368 c++; 369 } else { 370 while (*c >= '0' && *c <= '9') { 371 s = FSTATE_NOTFOUND; 372 u = u*10 + *c - '0'; 373 c++; 374 } 375 } 376 while (*c == ' ' || *c == '\t' || *c == '\n') 377 c++; 378 379 if (*c == '\0') { 380 *len = l; 381 *unit = u; 382 *state = s; 383 return(0); 384 } 385 386 return(-1); 387 } 388 389 int 390 userconf_attr(char *cmd, int *val) 391 { 392 char *c; 393 short attr = -1, i = 0, l = 0; 394 395 c = cmd; 396 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 397 c++; 398 l++; 399 } 400 401 while (i <= userconf_maxlocnames) { 402 if (strlen(locnames[i]) == l) { 403 if (strncasecmp(cmd, locnames[i], l) == 0) 404 attr = i; 405 } 406 i++; 407 } 408 409 if (attr == -1) { 410 return (-1); 411 } 412 413 *val = attr; 414 415 return(0); 416 } 417 418 void 419 userconf_modify(char *item, int *val) 420 { 421 int ok = 0; 422 int a; 423 char *c; 424 int i; 425 426 while (!ok) { 427 printf("%s [", item); 428 userconf_pnum(*val); 429 printf("] ? "); 430 431 i = getsn(userconf_argbuf, sizeof(userconf_argbuf)); 432 433 c = userconf_argbuf; 434 while (*c == ' ' || *c == '\t' || *c == '\n') c++; 435 436 if (*c != '\0') { 437 if (userconf_number(c, &a) == 0) { 438 *val = a; 439 ok = 1; 440 } else { 441 printf("Unknown argument\n"); 442 } 443 } else { 444 ok = 1; 445 } 446 } 447 } 448 449 void 450 userconf_change(int devno) 451 { 452 struct cfdata *cd; 453 char c = '\0'; 454 int *l; 455 int ln; 456 457 if (devno <= userconf_maxdev) { 458 userconf_pdev(devno); 459 460 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 461 printf("change (y/n) ?"); 462 c = cngetc(); 463 printf("\n"); 464 } 465 466 if (c == 'y' || c == 'Y') { 467 int share = 0, i, *lk, lklen; 468 469 /* XXX add cmd 'c' <devno> */ 470 userconf_hist_cmd('c'); 471 userconf_hist_int(devno); 472 473 cd = &cfdata[devno]; 474 l = cd->cf_loc; 475 ln = cd->cf_locnames; 476 477 /* 478 * Search for some other driver sharing this 479 * locator table. if one does, we may need to 480 * replace the locators with a malloc'd copy. 481 */ 482 for (i = 0; cfdata[i].cf_driver; i++) 483 if (i != devno && cfdata[i].cf_loc == l) 484 share = 1; 485 if (share) { 486 for (i = 0; locnamp[ln+i] != -1 ; i++) 487 ; 488 lk = l = mallocarray(i, sizeof(int), 489 M_TEMP, M_NOWAIT); 490 if (lk == NULL) { 491 printf("out of memory.\n"); 492 return; 493 } 494 lklen = i * sizeof(int); 495 bcopy(cd->cf_loc, l, lklen); 496 } 497 498 while (locnamp[ln] != -1) { 499 userconf_modify(locnames[locnamp[ln]], l); 500 501 /* XXX add *l */ 502 userconf_hist_int(*l); 503 504 ln++; 505 l++; 506 } 507 userconf_modify("flags", &cd->cf_flags); 508 userconf_hist_int(cd->cf_flags); 509 510 if (share) { 511 if (memcmp(cd->cf_loc, lk, lklen)) 512 cd->cf_loc = lk; 513 else 514 free(lk, M_TEMP, lklen); 515 } 516 517 printf("%3d ", devno); 518 userconf_pdevnam(devno); 519 printf(" changed\n"); 520 userconf_pdev(devno); 521 } 522 return; 523 } 524 525 if (devno > userconf_maxdev && devno <= userconf_totdev) { 526 printf("%3d can't change free slot\n", devno); 527 return; 528 } 529 530 if (devno > userconf_totdev && 531 devno <= userconf_totdev+pdevnames_size) { 532 userconf_pdev(devno); 533 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 534 printf("change (y/n) ?"); 535 c = cngetc(); 536 printf("\n"); 537 } 538 539 if (c == 'y' || c == 'Y') { 540 /* XXX add cmd 'c' <devno> */ 541 userconf_hist_cmd('c'); 542 userconf_hist_int(devno); 543 544 userconf_modify("count", 545 &pdevinit[devno-userconf_totdev-1].pdev_count); 546 userconf_hist_int(pdevinit[devno-userconf_totdev-1].pdev_count); 547 548 printf("%3d %s changed\n", devno, 549 pdevnames[devno-userconf_totdev-1]); 550 userconf_pdev(devno); 551 552 /* XXX add eoc */ 553 userconf_hist_eoc(); 554 } 555 return; 556 } 557 558 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 559 } 560 561 void 562 userconf_disable(int devno) 563 { 564 int done = 0; 565 566 if (devno <= userconf_maxdev) { 567 switch (cfdata[devno].cf_fstate) { 568 case FSTATE_NOTFOUND: 569 cfdata[devno].cf_fstate = FSTATE_DNOTFOUND; 570 break; 571 case FSTATE_STAR: 572 cfdata[devno].cf_fstate = FSTATE_DSTAR; 573 break; 574 case FSTATE_DNOTFOUND: 575 case FSTATE_DSTAR: 576 done = 1; 577 break; 578 default: 579 printf("Error unknown state\n"); 580 break; 581 } 582 583 printf("%3d ", devno); 584 userconf_pdevnam(devno); 585 if (done) { 586 printf(" already"); 587 } else { 588 /* XXX add cmd 'd' <devno> eoc */ 589 userconf_hist_cmd('d'); 590 userconf_hist_int(devno); 591 userconf_hist_eoc(); 592 } 593 printf(" disabled\n"); 594 595 return; 596 } 597 598 if (devno > userconf_maxdev && devno <= userconf_totdev) { 599 printf("%3d can't disable free slot\n", devno); 600 return; 601 } 602 603 if (devno > userconf_totdev && 604 devno <= userconf_totdev+pdevnames_size) { 605 printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]); 606 if (pdevinit[devno-userconf_totdev-1].pdev_count < 1) { 607 printf(" already "); 608 } else { 609 pdevinit[devno-userconf_totdev-1].pdev_count *= -1; 610 /* XXX add cmd 'd' <devno> eoc */ 611 userconf_hist_cmd('d'); 612 userconf_hist_int(devno); 613 userconf_hist_eoc(); 614 } 615 printf(" disabled\n"); 616 return; 617 } 618 619 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 620 } 621 622 void 623 userconf_enable(int devno) 624 { 625 int done = 0; 626 627 if (devno <= userconf_maxdev) { 628 switch (cfdata[devno].cf_fstate) { 629 case FSTATE_DNOTFOUND: 630 cfdata[devno].cf_fstate = FSTATE_NOTFOUND; 631 break; 632 case FSTATE_DSTAR: 633 cfdata[devno].cf_fstate = FSTATE_STAR; 634 break; 635 case FSTATE_NOTFOUND: 636 case FSTATE_STAR: 637 done = 1; 638 break; 639 default: 640 printf("Error unknown state\n"); 641 break; 642 } 643 644 printf("%3d ", devno); 645 userconf_pdevnam(devno); 646 if (done) { 647 printf(" already"); 648 } else { 649 /* XXX add cmd 'e' <devno> eoc */ 650 userconf_hist_cmd('e'); 651 userconf_hist_int(devno); 652 userconf_hist_eoc(); 653 } 654 printf(" enabled\n"); 655 return; 656 } 657 658 if (devno > userconf_maxdev && devno <= userconf_totdev) { 659 printf("%3d can't enable free slot\n", devno); 660 return; 661 } 662 663 if (devno > userconf_totdev && 664 devno <= userconf_totdev+pdevnames_size) { 665 printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]); 666 if (pdevinit[devno-userconf_totdev-1].pdev_count > 0) { 667 printf(" already"); 668 } else { 669 pdevinit[devno-userconf_totdev-1].pdev_count *= -1; 670 /* XXX add cmd 'e' <devno> eoc */ 671 userconf_hist_cmd('e'); 672 userconf_hist_int(devno); 673 userconf_hist_eoc(); 674 } 675 printf(" enabled\n"); 676 return; 677 } 678 679 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 680 } 681 682 void 683 userconf_help(void) 684 { 685 int j = 0, k; 686 687 printf("command args description\n"); 688 while (*userconf_cmds[j] != '\0') { 689 printf("%s", userconf_cmds[j]); 690 k = strlen(userconf_cmds[j]); 691 while (k < 10) { 692 printf(" "); 693 k++; 694 } 695 switch (*userconf_cmds[j+1]) { 696 case 'L': 697 printf("[count] number of lines before more"); 698 break; 699 case 'a': 700 printf("dev add a device"); 701 break; 702 case 'b': 703 printf("8|10|16 base on large numbers"); 704 break; 705 case 'c': 706 printf("devno|dev change devices"); 707 break; 708 #if defined(DDB) 709 case 'D': 710 printf(" enter ddb"); 711 break; 712 #endif 713 case 'd': 714 printf("attr val|devno|dev disable devices"); 715 break; 716 case 'e': 717 printf("attr val|devno|dev enable devices"); 718 break; 719 case 'f': 720 printf("devno|dev find devices"); 721 break; 722 case 'h': 723 printf(" this message"); 724 break; 725 case 'l': 726 printf(" list configuration"); 727 break; 728 case 'q': 729 printf(" leave UKC"); 730 break; 731 case 's': 732 printf("[attr [val]] " 733 "show attributes (or devices with an attribute)"); 734 break; 735 case 't': 736 printf("[mins [dst]] set timezone/dst"); 737 break; 738 case 'v': 739 printf(" toggle verbose booting"); 740 break; 741 default: 742 printf(" don't know"); 743 break; 744 } 745 printf("\n"); 746 j += 2; 747 } 748 } 749 750 void 751 userconf_list(void) 752 { 753 int i = 0; 754 755 userconf_cnt = 0; 756 757 while (i <= (userconf_totdev+pdevnames_size)) { 758 if (userconf_more()) 759 break; 760 userconf_pdev(i++); 761 } 762 763 userconf_cnt = -1; 764 } 765 766 void 767 userconf_show(void) 768 { 769 int i = 0; 770 771 userconf_cnt = 0; 772 773 while (i <= userconf_maxlocnames) { 774 if (userconf_more()) 775 break; 776 printf("%s\n", locnames[i++]); 777 } 778 779 userconf_cnt = -1; 780 } 781 782 void 783 userconf_common_attr_val(short attr, int *val, char routine) 784 { 785 struct cfdata *cd; 786 int *l; 787 int ln; 788 int i = 0, quit = 0; 789 790 userconf_cnt = 0; 791 792 while (i <= userconf_maxdev) { 793 cd = &cfdata[i]; 794 l = cd->cf_loc; 795 ln = cd->cf_locnames; 796 while (locnamp[ln] != -1) { 797 if (locnamp[ln] == attr) { 798 if (val == NULL) { 799 quit = userconf_more(); 800 userconf_pdev(i); 801 } else { 802 if (*val == *l) { 803 quit = userconf_more(); 804 switch (routine) { 805 case UC_ENABLE: 806 userconf_enable(i); 807 break; 808 case UC_DISABLE: 809 userconf_disable(i); 810 break; 811 case UC_SHOW: 812 userconf_pdev(i); 813 break; 814 default: 815 printf("Unknown routine /%c/\n", 816 routine); 817 break; 818 } 819 } 820 } 821 } 822 if (quit) 823 break; 824 ln++; 825 l++; 826 } 827 if (quit) 828 break; 829 i++; 830 } 831 832 userconf_cnt = -1; 833 } 834 835 void 836 userconf_show_attr(char *cmd) 837 { 838 char *c; 839 short attr = -1, i = 0, l = 0; 840 int a; 841 842 c = cmd; 843 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 844 c++; 845 l++; 846 } 847 while (*c == ' ' || *c == '\t' || *c == '\n') { 848 c++; 849 } 850 while (i <= userconf_maxlocnames) { 851 if (strlen(locnames[i]) == l) { 852 if (strncasecmp(cmd, locnames[i], l) == 0) { 853 attr = i; 854 } 855 } 856 i++; 857 } 858 859 if (attr == -1) { 860 printf("Unknown attribute\n"); 861 return; 862 } 863 864 if (*c == '\0') { 865 userconf_common_attr_val(attr, NULL, UC_SHOW); 866 } else { 867 if (userconf_number(c, &a) == 0) { 868 userconf_common_attr_val(attr, &a, UC_SHOW); 869 } else { 870 printf("Unknown argument\n"); 871 } 872 } 873 } 874 875 void 876 userconf_common_dev(char *dev, int len, short unit, short state, char routine) 877 { 878 int i = 0; 879 880 switch (routine) { 881 case UC_CHANGE: 882 break; 883 default: 884 userconf_cnt = 0; 885 break; 886 } 887 888 while (cfdata[i].cf_attach != 0) { 889 if (strlen(cfdata[i].cf_driver->cd_name) == len) { 890 891 /* 892 * Ok, if device name is correct 893 * If state == FSTATE_FOUND, look for "dev" 894 * If state == FSTATE_STAR, look for "dev*" 895 * If state == FSTATE_NOTFOUND, look for "dev0" 896 */ 897 if (strncasecmp(dev, cfdata[i].cf_driver->cd_name, 898 len) == 0 && 899 (state == FSTATE_FOUND || 900 (state == FSTATE_STAR && 901 (cfdata[i].cf_fstate == FSTATE_STAR || 902 cfdata[i].cf_fstate == FSTATE_DSTAR)) || 903 (state == FSTATE_NOTFOUND && 904 cfdata[i].cf_unit == unit && 905 (cfdata[i].cf_fstate == FSTATE_NOTFOUND || 906 cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) { 907 if (userconf_more()) 908 break; 909 switch (routine) { 910 case UC_CHANGE: 911 userconf_change(i); 912 break; 913 case UC_ENABLE: 914 userconf_enable(i); 915 break; 916 case UC_DISABLE: 917 userconf_disable(i); 918 break; 919 case UC_FIND: 920 userconf_pdev(i); 921 break; 922 default: 923 printf("Unknown routine /%c/\n", 924 routine); 925 break; 926 } 927 } 928 } 929 i++; 930 } 931 932 for (i = 0; i < pdevnames_size; i++) { 933 if (strncasecmp(dev, pdevnames[i], len) == 0 && 934 state == FSTATE_FOUND) { 935 switch(routine) { 936 case UC_CHANGE: 937 userconf_change(userconf_totdev+1+i); 938 break; 939 case UC_ENABLE: 940 userconf_enable(userconf_totdev+1+i); 941 break; 942 case UC_DISABLE: 943 userconf_disable(userconf_totdev+1+i); 944 break; 945 case UC_FIND: 946 userconf_pdev(userconf_totdev+1+i); 947 break; 948 default: 949 printf("Unknown pseudo routine /%c/\n",routine); 950 break; 951 } 952 } 953 } 954 955 switch (routine) { 956 case UC_CHANGE: 957 break; 958 default: 959 userconf_cnt = -1; 960 break; 961 } 962 } 963 964 void 965 userconf_common_attr(char *cmd, int attr, char routine) 966 { 967 char *c; 968 short l = 0; 969 int a; 970 971 c = cmd; 972 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 973 c++; 974 l++; 975 } 976 while (*c == ' ' || *c == '\t' || *c == '\n') 977 c++; 978 979 if (*c == '\0') { 980 printf("Value missing for attribute\n"); 981 return; 982 } 983 984 if (userconf_number(c, &a) == 0) { 985 userconf_common_attr_val(attr, &a, routine); 986 } else { 987 printf("Unknown argument\n"); 988 } 989 } 990 991 void 992 userconf_add_read(char *prompt, char field, char *dev, int len, int *val) 993 { 994 int ok = 0; 995 int a; 996 char *c; 997 int i; 998 999 *val = -1; 1000 1001 while (!ok) { 1002 printf("%s ? ", prompt); 1003 1004 i = getsn(userconf_argbuf, sizeof(userconf_argbuf)); 1005 1006 c = userconf_argbuf; 1007 while (*c == ' ' || *c == '\t' || *c == '\n') 1008 c++; 1009 1010 if (*c != '\0') { 1011 if (userconf_number(c, &a) == 0) { 1012 if (a > userconf_maxdev) { 1013 printf("Unknown devno (max is %d)\n", 1014 userconf_maxdev); 1015 } else if (strncasecmp(dev, 1016 cfdata[a].cf_driver->cd_name, len) != 0 && 1017 field == 'a') { 1018 printf("Not same device type\n"); 1019 } else { 1020 *val = a; 1021 ok = 1; 1022 } 1023 } else if (*c == '?') { 1024 userconf_common_dev(dev, len, 0, 1025 FSTATE_FOUND, UC_FIND); 1026 } else if (*c == 'q' || *c == 'Q') { 1027 ok = 1; 1028 } else { 1029 printf("Unknown argument\n"); 1030 } 1031 } else { 1032 ok = 1; 1033 } 1034 } 1035 } 1036 1037 void 1038 userconf_add(char *dev, int len, short unit, short state) 1039 { 1040 int i = 0, found = 0; 1041 struct cfdata new; 1042 int val, max_unit, star_unit, orig; 1043 1044 memset(&new, 0, sizeof(struct cfdata)); 1045 1046 if (userconf_maxdev == userconf_totdev) { 1047 printf("No more space for new devices.\n"); 1048 return; 1049 } 1050 1051 if (state == FSTATE_FOUND) { 1052 printf("Device not complete number or * is missing\n"); 1053 return; 1054 } 1055 1056 for (i = 0; cfdata[i].cf_driver; i++) 1057 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1058 strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0) 1059 found = 1; 1060 1061 if (!found) { 1062 printf("No device of this type exists.\n"); 1063 return; 1064 } 1065 1066 userconf_add_read("Clone Device (DevNo, 'q' or '?')", 1067 'a', dev, len, &val); 1068 1069 if (val != -1) { 1070 orig = val; 1071 new = cfdata[val]; 1072 new.cf_unit = unit; 1073 new.cf_fstate = state; 1074 userconf_add_read("Insert before Device (DevNo, 'q' or '?')", 1075 'i', dev, len, &val); 1076 } 1077 1078 if (val != -1) { 1079 /* XXX add cmd 'a' <orig> <val> eoc */ 1080 userconf_hist_cmd('a'); 1081 userconf_hist_int(orig); 1082 userconf_hist_int(unit); 1083 userconf_hist_int(state); 1084 userconf_hist_int(val); 1085 userconf_hist_eoc(); 1086 1087 /* Insert the new record */ 1088 for (i = userconf_maxdev; val <= i; i--) 1089 cfdata[i+1] = cfdata[i]; 1090 cfdata[val] = new; 1091 1092 /* Fix indexs in pv */ 1093 for (i = 0; i < pv_size; i++) { 1094 if (pv[i] != -1 && pv[i] >= val) 1095 pv[i]++; 1096 } 1097 1098 /* Fix indexs in cfroots */ 1099 for (i = 0; i < cfroots_size; i++) { 1100 if (cfroots[i] != -1 && cfroots[i] >= val) 1101 cfroots[i]++; 1102 } 1103 1104 userconf_maxdev++; 1105 1106 max_unit = -1; 1107 1108 /* Find max unit number of the device type */ 1109 1110 i = 0; 1111 while (cfdata[i].cf_attach != 0) { 1112 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1113 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1114 len) == 0) { 1115 switch (cfdata[i].cf_fstate) { 1116 case FSTATE_NOTFOUND: 1117 case FSTATE_DNOTFOUND: 1118 if (cfdata[i].cf_unit > max_unit) 1119 max_unit = cfdata[i].cf_unit; 1120 break; 1121 default: 1122 break; 1123 } 1124 } 1125 i++; 1126 } 1127 1128 /* 1129 * For all * entries set unit number to max+1, and update 1130 * cf_starunit1 if necessary. 1131 */ 1132 max_unit++; 1133 star_unit = -1; 1134 1135 i = 0; 1136 while (cfdata[i].cf_attach != 0) { 1137 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1138 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1139 len) == 0) { 1140 switch (cfdata[i].cf_fstate) { 1141 case FSTATE_NOTFOUND: 1142 case FSTATE_DNOTFOUND: 1143 if (cfdata[i].cf_unit > star_unit) 1144 star_unit = cfdata[i].cf_unit; 1145 break; 1146 default: 1147 break; 1148 } 1149 } 1150 i++; 1151 } 1152 star_unit++; 1153 1154 i = 0; 1155 while (cfdata[i].cf_attach != 0) { 1156 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1157 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1158 len) == 0) { 1159 switch (cfdata[i].cf_fstate) { 1160 case FSTATE_STAR: 1161 case FSTATE_DSTAR: 1162 cfdata[i].cf_unit = max_unit; 1163 if (cfdata[i].cf_starunit1 < star_unit) 1164 cfdata[i].cf_starunit1 = 1165 star_unit; 1166 break; 1167 default: 1168 break; 1169 } 1170 } 1171 i++; 1172 } 1173 userconf_pdev(val); 1174 } 1175 1176 /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags, 1177 cf_parents, cf_locnames, and cf_locnames */ 1178 } 1179 1180 int 1181 userconf_parse(char *cmd) 1182 { 1183 char *c, *v; 1184 int i = 0, j = 0, k, a; 1185 short unit, state; 1186 1187 c = cmd; 1188 while (*c == ' ' || *c == '\t') 1189 c++; 1190 v = c; 1191 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 1192 c++; 1193 i++; 1194 } 1195 1196 k = -1; 1197 while (*userconf_cmds[j] != '\0') { 1198 if (strlen(userconf_cmds[j]) == i) { 1199 if (strncasecmp(v, userconf_cmds[j], i) == 0) 1200 k = j; 1201 } 1202 j += 2; 1203 } 1204 1205 while (*c == ' ' || *c == '\t' || *c == '\n') 1206 c++; 1207 1208 if (k == -1) { 1209 if (*v != '\n') 1210 printf("Unknown command, try help\n"); 1211 } else { 1212 switch (*userconf_cmds[k+1]) { 1213 case 'L': 1214 if (*c == '\0') 1215 printf("Argument expected\n"); 1216 else if (userconf_number(c, &a) == 0) 1217 userconf_lines = a; 1218 else 1219 printf("Unknown argument\n"); 1220 break; 1221 case 'a': 1222 if (*c == '\0') 1223 printf("Dev expected\n"); 1224 else if (userconf_device(c, &a, &unit, &state) == 0) 1225 userconf_add(c, a, unit, state); 1226 else 1227 printf("Unknown argument\n"); 1228 break; 1229 case 'b': 1230 if (*c == '\0') 1231 printf("8|10|16 expected\n"); 1232 else if (userconf_number(c, &a) == 0) { 1233 if (a == 8 || a == 10 || a == 16) { 1234 userconf_base = a; 1235 } else { 1236 printf("8|10|16 expected\n"); 1237 } 1238 } else 1239 printf("Unknown argument\n"); 1240 break; 1241 case 'c': 1242 if (*c == '\0') 1243 printf("DevNo or Dev expected\n"); 1244 else if (userconf_number(c, &a) == 0) 1245 userconf_change(a); 1246 else if (userconf_device(c, &a, &unit, &state) == 0) 1247 userconf_common_dev(c, a, unit, state, UC_CHANGE); 1248 else 1249 printf("Unknown argument\n"); 1250 break; 1251 #if defined(DDB) 1252 case 'D': 1253 Debugger(); 1254 break; 1255 #endif 1256 case 'd': 1257 if (*c == '\0') 1258 printf("Attr, DevNo or Dev expected\n"); 1259 else if (userconf_attr(c, &a) == 0) 1260 userconf_common_attr(c, a, UC_DISABLE); 1261 else if (userconf_number(c, &a) == 0) 1262 userconf_disable(a); 1263 else if (userconf_device(c, &a, &unit, &state) == 0) 1264 userconf_common_dev(c, a, unit, state, UC_DISABLE); 1265 else 1266 printf("Unknown argument\n"); 1267 break; 1268 case 'e': 1269 if (*c == '\0') 1270 printf("Attr, DevNo or Dev expected\n"); 1271 else if (userconf_attr(c, &a) == 0) 1272 userconf_common_attr(c, a, UC_ENABLE); 1273 else if (userconf_number(c, &a) == 0) 1274 userconf_enable(a); 1275 else if (userconf_device(c, &a, &unit, &state) == 0) 1276 userconf_common_dev(c, a, unit, state, UC_ENABLE); 1277 else 1278 printf("Unknown argument\n"); 1279 break; 1280 case 'f': 1281 if (*c == '\0') 1282 printf("DevNo or Dev expected\n"); 1283 else if (userconf_number(c, &a) == 0) 1284 userconf_pdev(a); 1285 else if (userconf_device(c, &a, &unit, &state) == 0) 1286 userconf_common_dev(c, a, unit, state, UC_FIND); 1287 else 1288 printf("Unknown argument\n"); 1289 break; 1290 case 'h': 1291 userconf_help(); 1292 break; 1293 case 'l': 1294 if (*c == '\0') 1295 userconf_list(); 1296 else 1297 printf("Unknown argument\n"); 1298 break; 1299 case 'q': 1300 /* XXX add cmd 'q' eoc */ 1301 userconf_hist_cmd('q'); 1302 userconf_hist_eoc(); 1303 return(-1); 1304 break; 1305 case 's': 1306 if (*c == '\0') 1307 userconf_show(); 1308 else 1309 userconf_show_attr(c); 1310 break; 1311 case 't': 1312 if (*c == '\0' || userconf_number(c, &a) == 0) { 1313 if (*c != '\0') { 1314 tz.tz_minuteswest = a; 1315 while (*c != '\n' && *c != '\t' && 1316 *c != ' ' && *c != '\0') 1317 c++; 1318 while (*c == '\t' || *c == ' ') 1319 c++; 1320 if (*c != '\0' && 1321 userconf_number(c, &a) == 0) 1322 tz.tz_dsttime = a; 1323 userconf_hist_cmd('t'); 1324 userconf_hist_int(tz.tz_minuteswest); 1325 userconf_hist_int(tz.tz_dsttime); 1326 userconf_hist_eoc(); 1327 } 1328 printf("timezone = %d, dst = %d\n", 1329 tz.tz_minuteswest, tz.tz_dsttime); 1330 } else 1331 printf("Unknown argument\n"); 1332 break; 1333 case 'v': 1334 autoconf_verbose = !autoconf_verbose; 1335 printf("autoconf verbose %sabled\n", 1336 autoconf_verbose ? "en" : "dis"); 1337 break; 1338 default: 1339 printf("Unknown command\n"); 1340 break; 1341 } 1342 } 1343 return(0); 1344 } 1345 1346 void 1347 user_config(void) 1348 { 1349 userconf_init(); 1350 printf("User Kernel Config\n"); 1351 1352 cnpollc(1); 1353 while (1) { 1354 printf("UKC> "); 1355 if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 && 1356 userconf_parse(userconf_cmdbuf)) 1357 break; 1358 } 1359 cnpollc(0); 1360 1361 printf("Continuing...\n"); 1362 } 1363