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