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