1 /* $OpenBSD: subr_userconf.c,v 1.33 2003/06/02 21:14:47 maja 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() 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() 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(cmd) 167 char cmd; 168 { 169 userconf_histcur = userconf_histlen; 170 if (userconf_histcur < userconf_histsz) { 171 userconf_history[userconf_histcur] = cmd; 172 userconf_histcur++; 173 } 174 } 175 176 void 177 userconf_hist_int(val) 178 int val; 179 { 180 snprintf(userconf_histbuf, sizeof userconf_histbuf, " %d",val); 181 if (userconf_histcur + strlen(userconf_histbuf) < userconf_histsz) { 182 bcopy(userconf_histbuf, 183 &userconf_history[userconf_histcur], 184 strlen(userconf_histbuf)); 185 userconf_histcur = userconf_histcur + strlen(userconf_histbuf); 186 } 187 } 188 189 void 190 userconf_hist_eoc() 191 { 192 if (userconf_histcur < userconf_histsz) { 193 userconf_history[userconf_histcur] = '\n'; 194 userconf_histcur++; 195 userconf_histlen = userconf_histcur; 196 } 197 } 198 199 void 200 userconf_pnum(val) 201 int val; 202 { 203 if (val > -2 && val < 16) { 204 printf("%d",val); 205 return; 206 } 207 208 switch (userconf_base) { 209 case 8: 210 printf("0%o",val); 211 break; 212 case 10: 213 printf("%d",val); 214 break; 215 case 16: 216 default: 217 printf("0x%x",val); 218 break; 219 } 220 } 221 222 void 223 userconf_pdevnam(dev) 224 short dev; 225 { 226 struct cfdata *cd; 227 228 cd = &cfdata[dev]; 229 printf("%s", cd->cf_driver->cd_name); 230 switch (cd->cf_fstate) { 231 case FSTATE_NOTFOUND: 232 case FSTATE_DNOTFOUND: 233 printf("%d", cd->cf_unit); 234 break; 235 case FSTATE_FOUND: 236 printf("*FOUND*"); 237 break; 238 case FSTATE_STAR: 239 case FSTATE_DSTAR: 240 printf("*"); 241 break; 242 default: 243 printf("*UNKNOWN*"); 244 break; 245 } 246 } 247 248 void 249 userconf_pdev(devno) 250 short devno; 251 { 252 struct cfdata *cd; 253 short *p; 254 int *l; 255 int ln; 256 char c; 257 258 if (devno > userconf_maxdev && devno <= userconf_totdev) { 259 printf("%3d free slot (for add)\n", devno); 260 return; 261 } 262 263 if (devno > userconf_totdev && 264 devno <= userconf_totdev+pdevnames_size) { 265 printf("%3d %s count %d (pseudo device)\n", devno, 266 pdevnames[devno-userconf_totdev-1], 267 pdevinit[devno-userconf_totdev-1].pdev_count); 268 return; 269 } 270 271 if (devno > userconf_maxdev) { 272 printf("Unknown devno (max is %d)\n", userconf_maxdev); 273 return; 274 } 275 276 cd = &cfdata[devno]; 277 278 printf("%3d ", devno); 279 userconf_pdevnam(devno); 280 printf(" at"); 281 c = ' '; 282 p = cd->cf_parents; 283 if (*p == -1) 284 printf(" root"); 285 while (*p != -1) { 286 printf("%c", c); 287 userconf_pdevnam(*p++); 288 c = '|'; 289 } 290 switch (cd->cf_fstate) { 291 case FSTATE_NOTFOUND: 292 case FSTATE_FOUND: 293 case FSTATE_STAR: 294 break; 295 case FSTATE_DNOTFOUND: 296 case FSTATE_DSTAR: 297 printf(" disable"); 298 break; 299 default: 300 printf(" ???"); 301 break; 302 } 303 l = cd->cf_loc; 304 ln = cd->cf_locnames; 305 while (locnamp[ln] != -1) { 306 printf(" %s ", locnames[locnamp[ln]]); 307 ln++; 308 userconf_pnum(*l++); 309 } 310 printf(" flags 0x%x\n", cd->cf_flags); 311 } 312 313 int 314 userconf_number(c, val) 315 char *c; 316 int *val; 317 { 318 u_int num = 0; 319 int neg = 0; 320 int base = 10; 321 322 if (*c == '-') { 323 neg = 1; 324 c++; 325 } 326 if (*c == '0') { 327 base = 8; 328 c++; 329 if (*c == 'x' || *c == 'X') { 330 base = 16; 331 c++; 332 } 333 } 334 while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') { 335 u_char cc = *c; 336 337 if (cc >= '0' && cc <= '9') 338 cc = cc - '0'; 339 else if (cc >= 'a' && cc <= 'f') 340 cc = cc - 'a' + 10; 341 else if (cc >= 'A' && cc <= 'F') 342 cc = cc - 'A' + 10; 343 else 344 return (-1); 345 346 if (cc > base) 347 return (-1); 348 num = num * base + cc; 349 c++; 350 } 351 352 if (neg && num > INT_MAX) /* overflow */ 353 return (1); 354 *val = neg ? - num : num; 355 return (0); 356 } 357 358 int 359 userconf_device(cmd, len, unit, state) 360 char *cmd; 361 int *len; 362 short *unit, *state; 363 { 364 short u = 0, s = FSTATE_FOUND; 365 int l = 0; 366 char *c; 367 368 c = cmd; 369 while (*c >= 'a' && *c <= 'z') { 370 l++; 371 c++; 372 } 373 if (*c == '*') { 374 s = FSTATE_STAR; 375 c++; 376 } else { 377 while (*c >= '0' && *c <= '9') { 378 s = FSTATE_NOTFOUND; 379 u = u*10 + *c - '0'; 380 c++; 381 } 382 } 383 while (*c == ' ' || *c == '\t' || *c == '\n') 384 c++; 385 386 if (*c == '\0') { 387 *len = l; 388 *unit = u; 389 *state = s; 390 return(0); 391 } 392 393 return(-1); 394 } 395 396 int 397 userconf_attr(cmd, val) 398 char *cmd; 399 int *val; 400 { 401 char *c; 402 short attr = -1, i = 0, l = 0; 403 404 c = cmd; 405 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 406 c++; 407 l++; 408 } 409 410 while (i <= userconf_maxlocnames) { 411 if (strlen(locnames[i]) == l) { 412 if (strncasecmp(cmd, locnames[i], l) == 0) 413 attr = i; 414 } 415 i++; 416 } 417 418 if (attr == -1) { 419 return (-1); 420 } 421 422 *val = attr; 423 424 return(0); 425 } 426 427 void 428 userconf_modify(item, val) 429 char *item; 430 int *val; 431 { 432 int ok = 0; 433 int a; 434 char *c; 435 int i; 436 437 while (!ok) { 438 printf("%s [", item); 439 userconf_pnum(*val); 440 printf("] ? "); 441 442 i = getsn(userconf_argbuf, sizeof(userconf_argbuf)); 443 444 c = userconf_argbuf; 445 while (*c == ' ' || *c == '\t' || *c == '\n') c++; 446 447 if (*c != '\0') { 448 if (userconf_number(c, &a) == 0) { 449 *val = a; 450 ok = 1; 451 } else { 452 printf("Unknown argument\n"); 453 } 454 } else { 455 ok = 1; 456 } 457 } 458 } 459 460 void 461 userconf_change(devno) 462 int devno; 463 { 464 struct cfdata *cd; 465 char c = '\0'; 466 int *l; 467 int ln; 468 469 if (devno <= userconf_maxdev) { 470 userconf_pdev(devno); 471 472 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 473 printf("change (y/n) ?"); 474 c = cngetc(); 475 printf("\n"); 476 } 477 478 if (c == 'y' || c == 'Y') { 479 int share = 0, i, *lk; 480 481 /* XXX add cmd 'c' <devno> */ 482 userconf_hist_cmd('c'); 483 userconf_hist_int(devno); 484 485 cd = &cfdata[devno]; 486 l = cd->cf_loc; 487 ln = cd->cf_locnames; 488 489 /* 490 * Search for some other driver sharing this 491 * locator table. if one does, we may need to 492 * replace the locators with a malloc'd copy. 493 */ 494 for (i = 0; cfdata[i].cf_driver; i++) 495 if (i != devno && cfdata[i].cf_loc == l) 496 share = 1; 497 if (share) { 498 for (i = 0; locnamp[ln+i] != -1 ; i++) 499 ; 500 lk = l = (int *)malloc(sizeof(int) * i, 501 M_TEMP, M_NOWAIT); 502 if (lk == NULL) { 503 printf("out of memory.\n"); 504 return; 505 } 506 bcopy(cd->cf_loc, l, sizeof(int) * i); 507 } 508 509 while (locnamp[ln] != -1) { 510 userconf_modify(locnames[locnamp[ln]], l); 511 512 /* XXX add *l */ 513 userconf_hist_int(*l); 514 515 ln++; 516 l++; 517 } 518 userconf_modify("flags", &cd->cf_flags); 519 userconf_hist_int(cd->cf_flags); 520 521 if (share) { 522 if (bcmp(cd->cf_loc, lk, sizeof(int) * i)) 523 cd->cf_loc = lk; 524 else 525 free(lk, M_TEMP); 526 } 527 528 printf("%3d ", devno); 529 userconf_pdevnam(devno); 530 printf(" changed\n"); 531 userconf_pdev(devno); 532 } 533 return; 534 } 535 536 if (devno > userconf_maxdev && devno <= userconf_totdev) { 537 printf("%3d can't change free slot\n", devno); 538 return; 539 } 540 541 if (devno > userconf_totdev && 542 devno <= userconf_totdev+pdevnames_size) { 543 userconf_pdev(devno); 544 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 545 printf("change (y/n) ?"); 546 c = cngetc(); 547 printf("\n"); 548 } 549 550 if (c == 'y' || c == 'Y') { 551 /* XXX add cmd 'c' <devno> */ 552 userconf_hist_cmd('c'); 553 userconf_hist_int(devno); 554 555 userconf_modify("count", 556 &pdevinit[devno-userconf_totdev-1].pdev_count); 557 userconf_hist_int(pdevinit[devno-userconf_totdev-1].pdev_count); 558 559 printf("%3d %s changed\n", devno, 560 pdevnames[devno-userconf_totdev-1]); 561 userconf_pdev(devno); 562 563 /* XXX add eoc */ 564 userconf_hist_eoc(); 565 } 566 return; 567 } 568 569 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 570 } 571 572 void 573 userconf_disable(devno) 574 int devno; 575 { 576 int done = 0; 577 578 if (devno <= userconf_maxdev) { 579 switch (cfdata[devno].cf_fstate) { 580 case FSTATE_NOTFOUND: 581 cfdata[devno].cf_fstate = FSTATE_DNOTFOUND; 582 break; 583 case FSTATE_STAR: 584 cfdata[devno].cf_fstate = FSTATE_DSTAR; 585 break; 586 case FSTATE_DNOTFOUND: 587 case FSTATE_DSTAR: 588 done = 1; 589 break; 590 default: 591 printf("Error unknown state\n"); 592 break; 593 } 594 595 printf("%3d ", devno); 596 userconf_pdevnam(devno); 597 if (done) { 598 printf(" already"); 599 } else { 600 /* XXX add cmd 'd' <devno> eoc */ 601 userconf_hist_cmd('d'); 602 userconf_hist_int(devno); 603 userconf_hist_eoc(); 604 } 605 printf(" disabled\n"); 606 607 return; 608 } 609 610 if (devno > userconf_maxdev && devno <= userconf_totdev) { 611 printf("%3d can't disable free slot\n", devno); 612 return; 613 } 614 615 if (devno > userconf_totdev && 616 devno <= userconf_totdev+pdevnames_size) { 617 printf("%3d %s can't disable pseudo device\n", devno, 618 pdevnames[devno-userconf_totdev-1]); 619 return; 620 } 621 622 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 623 } 624 625 void 626 userconf_enable(devno) 627 int devno; 628 { 629 int done = 0; 630 631 if (devno <= userconf_maxdev) { 632 switch (cfdata[devno].cf_fstate) { 633 case FSTATE_DNOTFOUND: 634 cfdata[devno].cf_fstate = FSTATE_NOTFOUND; 635 break; 636 case FSTATE_DSTAR: 637 cfdata[devno].cf_fstate = FSTATE_STAR; 638 break; 639 case FSTATE_NOTFOUND: 640 case FSTATE_STAR: 641 done = 1; 642 break; 643 default: 644 printf("Error unknown state\n"); 645 break; 646 } 647 648 printf("%3d ", devno); 649 userconf_pdevnam(devno); 650 if (done) { 651 printf(" already"); 652 } else { 653 /* XXX add cmd 'e' <devno> eoc */ 654 userconf_hist_cmd('e'); 655 userconf_hist_int(devno); 656 userconf_hist_eoc(); 657 } 658 printf(" enabled\n"); 659 return; 660 } 661 662 if (devno > userconf_maxdev && devno <= userconf_totdev) { 663 printf("%3d can't enable free slot\n", devno); 664 return; 665 } 666 667 if (devno > userconf_totdev && 668 devno <= userconf_totdev+pdevnames_size) { 669 printf("%3d %s can't enable pseudo device\n", devno, 670 pdevnames[devno-userconf_totdev-1]); 671 return; 672 } 673 674 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 675 } 676 677 void 678 userconf_help() 679 { 680 int j = 0, k; 681 682 printf("command args description\n"); 683 while (*userconf_cmds[j] != '\0') { 684 printf(userconf_cmds[j]); 685 k = strlen(userconf_cmds[j]); 686 while (k < 10) { 687 printf(" "); 688 k++; 689 } 690 switch (*userconf_cmds[j+1]) { 691 case 'L': 692 printf("[count] number of lines before more"); 693 break; 694 case 'a': 695 printf("dev add a device"); 696 break; 697 case 'b': 698 printf("8|10|16 base on large numbers"); 699 break; 700 case 'c': 701 printf("devno|dev change devices"); 702 break; 703 #if defined(DDB) 704 case 'D': 705 printf(" enter ddb"); 706 break; 707 #endif 708 case 'd': 709 printf("attr val|devno|dev disable devices"); 710 break; 711 case 'e': 712 printf("attr val|devno|dev enable devices"); 713 break; 714 case 'f': 715 printf("devno|dev find devices"); 716 break; 717 case 'h': 718 printf(" this message"); 719 break; 720 case 'l': 721 printf(" list configuration"); 722 break; 723 case 'q': 724 printf(" leave UKC"); 725 break; 726 case 's': 727 printf("[attr [val]] " 728 "show attributes (or devices with an attribute)"); 729 break; 730 case 't': 731 printf("[mins [dst]] set timezone/dst"); 732 break; 733 case 'v': 734 printf(" toggle verbose booting"); 735 break; 736 default: 737 printf(" don't know"); 738 break; 739 } 740 printf("\n"); 741 j += 2; 742 } 743 } 744 745 void 746 userconf_list() 747 { 748 int i = 0; 749 750 userconf_cnt = 0; 751 752 while (i <= (userconf_totdev+pdevnames_size)) { 753 if (userconf_more()) 754 break; 755 userconf_pdev(i++); 756 } 757 758 userconf_cnt = -1; 759 } 760 761 void 762 userconf_show() 763 { 764 int i = 0; 765 766 userconf_cnt = 0; 767 768 while (i <= userconf_maxlocnames) { 769 if (userconf_more()) 770 break; 771 printf("%s\n", locnames[i++]); 772 } 773 774 userconf_cnt = -1; 775 } 776 777 void 778 userconf_common_attr_val(attr, val, routine) 779 short attr; 780 int *val; 781 char routine; 782 { 783 struct cfdata *cd; 784 int *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(cmd) 835 char *cmd; 836 { 837 char *c; 838 short attr = -1, i = 0, l = 0; 839 int 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) == 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(dev, len, unit, state, routine) 876 char *dev; 877 int len; 878 short unit, state; 879 char routine; 880 { 881 int i = 0; 882 883 switch (routine) { 884 case UC_CHANGE: 885 break; 886 default: 887 userconf_cnt = 0; 888 break; 889 } 890 891 while (cfdata[i].cf_attach != 0) { 892 if (strlen(cfdata[i].cf_driver->cd_name) == len) { 893 894 /* 895 * Ok, if device name is correct 896 * If state == FSTATE_FOUND, look for "dev" 897 * If state == FSTATE_STAR, look for "dev*" 898 * If state == FSTATE_NOTFOUND, look for "dev0" 899 */ 900 if (strncasecmp(dev, cfdata[i].cf_driver->cd_name, 901 len) == 0 && 902 (state == FSTATE_FOUND || 903 (state == FSTATE_STAR && 904 (cfdata[i].cf_fstate == FSTATE_STAR || 905 cfdata[i].cf_fstate == FSTATE_DSTAR)) || 906 (state == FSTATE_NOTFOUND && 907 cfdata[i].cf_unit == unit && 908 (cfdata[i].cf_fstate == FSTATE_NOTFOUND || 909 cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) { 910 if (userconf_more()) 911 break; 912 switch (routine) { 913 case UC_CHANGE: 914 userconf_change(i); 915 break; 916 case UC_ENABLE: 917 userconf_enable(i); 918 break; 919 case UC_DISABLE: 920 userconf_disable(i); 921 break; 922 case UC_FIND: 923 userconf_pdev(i); 924 break; 925 default: 926 printf("Unknown routine /%c/\n", 927 routine); 928 break; 929 } 930 } 931 } 932 i++; 933 } 934 935 for (i = 0; i < pdevnames_size; i++) { 936 if (strncasecmp(dev, pdevnames[i], len) == 0 && 937 state == FSTATE_FOUND) { 938 switch(routine) { 939 case UC_CHANGE: 940 userconf_change(userconf_totdev+1+i); 941 break; 942 case UC_ENABLE: 943 userconf_enable(userconf_totdev+1+i); 944 break; 945 case UC_DISABLE: 946 userconf_disable(userconf_totdev+1+i); 947 break; 948 case UC_FIND: 949 userconf_pdev(userconf_totdev+1+i); 950 break; 951 default: 952 printf("Unknown pseudo routine /%c/\n",routine); 953 break; 954 } 955 } 956 } 957 958 switch (routine) { 959 case UC_CHANGE: 960 break; 961 default: 962 userconf_cnt = -1; 963 break; 964 } 965 } 966 967 void 968 userconf_common_attr(cmd, attr, routine) 969 char *cmd; 970 int attr; 971 char routine; 972 { 973 char *c; 974 short l = 0; 975 int a; 976 977 c = cmd; 978 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 979 c++; 980 l++; 981 } 982 while (*c == ' ' || *c == '\t' || *c == '\n') 983 c++; 984 985 if (*c == '\0') { 986 printf("Value missing for attribute\n"); 987 return; 988 } 989 990 if (userconf_number(c, &a) == 0) { 991 userconf_common_attr_val(attr, &a, routine); 992 } else { 993 printf("Unknown argument\n"); 994 } 995 } 996 997 void 998 userconf_add_read(prompt, field, dev, len, val) 999 char *prompt; 1000 char field; 1001 char *dev; 1002 int len; 1003 int *val; 1004 { 1005 int ok = 0; 1006 int a; 1007 char *c; 1008 int i; 1009 1010 *val = -1; 1011 1012 while (!ok) { 1013 printf("%s ? ", prompt); 1014 1015 i = getsn(userconf_argbuf, sizeof(userconf_argbuf)); 1016 1017 c = userconf_argbuf; 1018 while (*c == ' ' || *c == '\t' || *c == '\n') 1019 c++; 1020 1021 if (*c != '\0') { 1022 if (userconf_number(c, &a) == 0) { 1023 if (a > userconf_maxdev) { 1024 printf("Unknown devno (max is %d)\n", 1025 userconf_maxdev); 1026 } else if (strncasecmp(dev, 1027 cfdata[a].cf_driver->cd_name, len) != 0 && 1028 field == 'a') { 1029 printf("Not same device type\n"); 1030 } else { 1031 *val = a; 1032 ok = 1; 1033 } 1034 } else if (*c == '?') { 1035 userconf_common_dev(dev, len, 0, 1036 FSTATE_FOUND, UC_FIND); 1037 } else if (*c == 'q' || *c == 'Q') { 1038 ok = 1; 1039 } else { 1040 printf("Unknown argument\n"); 1041 } 1042 } else { 1043 ok = 1; 1044 } 1045 } 1046 } 1047 1048 void 1049 userconf_add(dev, len, unit, state) 1050 char *dev; 1051 int len; 1052 short unit, state; 1053 { 1054 int i = 0, found = 0; 1055 struct cfdata new; 1056 int val, max_unit, star_unit, orig; 1057 1058 bzero(&new, sizeof(struct cfdata)); 1059 1060 if (userconf_maxdev == userconf_totdev) { 1061 printf("No more space for new devices.\n"); 1062 return; 1063 } 1064 1065 if (state == FSTATE_FOUND) { 1066 printf("Device not complete number or * is missing\n"); 1067 return; 1068 } 1069 1070 for (i = 0; cfdata[i].cf_driver; i++) 1071 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1072 strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0) 1073 found = 1; 1074 1075 if (!found) { 1076 printf("No device of this type exists.\n"); 1077 return; 1078 } 1079 1080 userconf_add_read("Clone Device (DevNo, 'q' or '?')", 1081 'a', dev, len, &val); 1082 1083 if (val != -1) { 1084 orig = val; 1085 new = cfdata[val]; 1086 new.cf_unit = unit; 1087 new.cf_fstate = state; 1088 userconf_add_read("Insert before Device (DevNo, 'q' or '?')", 1089 'i', dev, len, &val); 1090 } 1091 1092 if (val != -1) { 1093 /* XXX add cmd 'a' <orig> <val> eoc */ 1094 userconf_hist_cmd('a'); 1095 userconf_hist_int(orig); 1096 userconf_hist_int(unit); 1097 userconf_hist_int(state); 1098 userconf_hist_int(val); 1099 userconf_hist_eoc(); 1100 1101 /* Insert the new record */ 1102 for (i = userconf_maxdev; val <= i; i--) 1103 cfdata[i+1] = cfdata[i]; 1104 cfdata[val] = new; 1105 1106 /* Fix indexs in pv */ 1107 for (i = 0; i < pv_size; i++) { 1108 if (pv[i] != -1 && pv[i] >= val) 1109 pv[i]++; 1110 } 1111 1112 /* Fix indexs in cfroots */ 1113 for (i = 0; i < cfroots_size; i++) { 1114 if (cfroots[i] != -1 && cfroots[i] >= val) 1115 cfroots[i]++; 1116 } 1117 1118 userconf_maxdev++; 1119 1120 max_unit = -1; 1121 1122 /* Find max unit number of the device type */ 1123 1124 i = 0; 1125 while (cfdata[i].cf_attach != 0) { 1126 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1127 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1128 len) == 0) { 1129 switch (cfdata[i].cf_fstate) { 1130 case FSTATE_NOTFOUND: 1131 case FSTATE_DNOTFOUND: 1132 if (cfdata[i].cf_unit > max_unit) 1133 max_unit = cfdata[i].cf_unit; 1134 break; 1135 default: 1136 break; 1137 } 1138 } 1139 i++; 1140 } 1141 1142 /* 1143 * For all * entries set unit number to max+1, and update 1144 * cf_starunit1 if necessary. 1145 */ 1146 max_unit++; 1147 star_unit = -1; 1148 1149 i = 0; 1150 while (cfdata[i].cf_attach != 0) { 1151 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1152 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1153 len) == 0) { 1154 switch (cfdata[i].cf_fstate) { 1155 case FSTATE_NOTFOUND: 1156 case FSTATE_DNOTFOUND: 1157 if (cfdata[i].cf_unit > star_unit) 1158 star_unit = cfdata[i].cf_unit; 1159 break; 1160 default: 1161 break; 1162 } 1163 } 1164 i++; 1165 } 1166 star_unit++; 1167 1168 i = 0; 1169 while (cfdata[i].cf_attach != 0) { 1170 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1171 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1172 len) == 0) { 1173 switch (cfdata[i].cf_fstate) { 1174 case FSTATE_STAR: 1175 case FSTATE_DSTAR: 1176 cfdata[i].cf_unit = max_unit; 1177 if (cfdata[i].cf_starunit1 < star_unit) 1178 cfdata[i].cf_starunit1 = 1179 star_unit; 1180 break; 1181 default: 1182 break; 1183 } 1184 } 1185 i++; 1186 } 1187 userconf_pdev(val); 1188 } 1189 1190 /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags, 1191 cf_parents, cf_locnames, cf_locnames and cf_ivstubs */ 1192 } 1193 1194 int 1195 userconf_parse(cmd) 1196 char *cmd; 1197 { 1198 char *c, *v; 1199 int i = 0, j = 0, k, a; 1200 short unit, state; 1201 1202 c = cmd; 1203 while (*c == ' ' || *c == '\t') 1204 c++; 1205 v = c; 1206 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 1207 c++; 1208 i++; 1209 } 1210 1211 k = -1; 1212 while (*userconf_cmds[j] != '\0') { 1213 if (strlen(userconf_cmds[j]) == i) { 1214 if (strncasecmp(v, userconf_cmds[j], i) == 0) 1215 k = j; 1216 } 1217 j += 2; 1218 } 1219 1220 while (*c == ' ' || *c == '\t' || *c == '\n') 1221 c++; 1222 1223 if (k == -1) { 1224 if (*v != '\n') 1225 printf("Unknown command, try help\n"); 1226 } else { 1227 switch (*userconf_cmds[k+1]) { 1228 case 'L': 1229 if (*c == '\0') 1230 printf("Argument expected\n"); 1231 else if (userconf_number(c, &a) == 0) 1232 userconf_lines = a; 1233 else 1234 printf("Unknown argument\n"); 1235 break; 1236 case 'a': 1237 if (*c == '\0') 1238 printf("Dev expected\n"); 1239 else if (userconf_device(c, &a, &unit, &state) == 0) 1240 userconf_add(c, a, unit, state); 1241 else 1242 printf("Unknown argument\n"); 1243 break; 1244 case 'b': 1245 if (*c == '\0') 1246 printf("8|10|16 expected\n"); 1247 else if (userconf_number(c, &a) == 0) { 1248 if (a == 8 || a == 10 || a == 16) { 1249 userconf_base = a; 1250 } else { 1251 printf("8|10|16 expected\n"); 1252 } 1253 } else 1254 printf("Unknown argument\n"); 1255 break; 1256 case 'c': 1257 if (*c == '\0') 1258 printf("DevNo or Dev expected\n"); 1259 else if (userconf_number(c, &a) == 0) 1260 userconf_change(a); 1261 else if (userconf_device(c, &a, &unit, &state) == 0) 1262 userconf_common_dev(c, a, unit, state, UC_CHANGE); 1263 else 1264 printf("Unknown argument\n"); 1265 break; 1266 #if defined(DDB) 1267 case 'D': 1268 Debugger(); 1269 break; 1270 #endif 1271 case 'd': 1272 if (*c == '\0') 1273 printf("Attr, DevNo or Dev expected\n"); 1274 else if (userconf_attr(c, &a) == 0) 1275 userconf_common_attr(c, a, UC_DISABLE); 1276 else if (userconf_number(c, &a) == 0) 1277 userconf_disable(a); 1278 else if (userconf_device(c, &a, &unit, &state) == 0) 1279 userconf_common_dev(c, a, unit, state, UC_DISABLE); 1280 else 1281 printf("Unknown argument\n"); 1282 break; 1283 case 'e': 1284 if (*c == '\0') 1285 printf("Attr, DevNo or Dev expected\n"); 1286 else if (userconf_attr(c, &a) == 0) 1287 userconf_common_attr(c, a, UC_ENABLE); 1288 else if (userconf_number(c, &a) == 0) 1289 userconf_enable(a); 1290 else if (userconf_device(c, &a, &unit, &state) == 0) 1291 userconf_common_dev(c, a, unit, state, UC_ENABLE); 1292 else 1293 printf("Unknown argument\n"); 1294 break; 1295 case 'f': 1296 if (*c == '\0') 1297 printf("DevNo or Dev expected\n"); 1298 else if (userconf_number(c, &a) == 0) 1299 userconf_pdev(a); 1300 else if (userconf_device(c, &a, &unit, &state) == 0) 1301 userconf_common_dev(c, a, unit, state, UC_FIND); 1302 else 1303 printf("Unknown argument\n"); 1304 break; 1305 case 'h': 1306 userconf_help(); 1307 break; 1308 case 'l': 1309 if (*c == '\0') 1310 userconf_list(); 1311 else 1312 printf("Unknown argument\n"); 1313 break; 1314 case 'q': 1315 /* XXX add cmd 'q' eoc */ 1316 userconf_hist_cmd('q'); 1317 userconf_hist_eoc(); 1318 return(-1); 1319 break; 1320 case 's': 1321 if (*c == '\0') 1322 userconf_show(); 1323 else 1324 userconf_show_attr(c); 1325 break; 1326 case 't': 1327 if (*c == '\0' || userconf_number(c, &a) == 0) { 1328 if (*c != '\0') { 1329 tz.tz_minuteswest = a; 1330 while (*c != '\n' && *c != '\t' && 1331 *c != ' ' && *c != '\0') 1332 c++; 1333 while (*c == '\t' || *c == ' ') 1334 c++; 1335 if (*c != '\0' && 1336 userconf_number(c, &a) == 0) 1337 tz.tz_dsttime = a; 1338 userconf_hist_cmd('t'); 1339 userconf_hist_int(tz.tz_minuteswest); 1340 userconf_hist_int(tz.tz_dsttime); 1341 userconf_hist_eoc(); 1342 } 1343 printf("timezone = %d, dst = %d\n", 1344 tz.tz_minuteswest, tz.tz_dsttime); 1345 } else 1346 printf("Unknown argument\n"); 1347 break; 1348 case 'v': 1349 autoconf_verbose = !autoconf_verbose; 1350 printf("autoconf verbose %sabled\n", 1351 autoconf_verbose ? "en" : "dis"); 1352 break; 1353 default: 1354 printf("Unknown command\n"); 1355 break; 1356 } 1357 } 1358 return(0); 1359 } 1360 1361 void 1362 user_config() 1363 { 1364 userconf_init(); 1365 printf("User Kernel Config\n"); 1366 1367 while (1) { 1368 printf("UKC> "); 1369 if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 && 1370 userconf_parse(userconf_cmdbuf)) 1371 break; 1372 } 1373 printf("Continuing...\n"); 1374 } 1375