1 /* $OpenBSD: subr_userconf.c,v 1.34 2005/12/09 09:09:52 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 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 (pseudo device)\n", devno, 261 pdevnames[devno-userconf_totdev-1], 262 pdevinit[devno-userconf_totdev-1].pdev_count); 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, int *val) 310 { 311 u_int 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 > INT_MAX) /* overflow */ 346 return (1); 347 *val = neg ? - num : num; 348 return (0); 349 } 350 351 int 352 userconf_device(char *cmd, int *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, int *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, int *val) 417 { 418 int ok = 0; 419 int 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) == 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 int *l; 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, *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 = (int *)malloc(sizeof(int) * i, 486 M_TEMP, M_NOWAIT); 487 if (lk == NULL) { 488 printf("out of memory.\n"); 489 return; 490 } 491 bcopy(cd->cf_loc, l, sizeof(int) * i); 492 } 493 494 while (locnamp[ln] != -1) { 495 userconf_modify(locnames[locnamp[ln]], l); 496 497 /* XXX add *l */ 498 userconf_hist_int(*l); 499 500 ln++; 501 l++; 502 } 503 userconf_modify("flags", &cd->cf_flags); 504 userconf_hist_int(cd->cf_flags); 505 506 if (share) { 507 if (bcmp(cd->cf_loc, lk, sizeof(int) * i)) 508 cd->cf_loc = lk; 509 else 510 free(lk, M_TEMP); 511 } 512 513 printf("%3d ", devno); 514 userconf_pdevnam(devno); 515 printf(" changed\n"); 516 userconf_pdev(devno); 517 } 518 return; 519 } 520 521 if (devno > userconf_maxdev && devno <= userconf_totdev) { 522 printf("%3d can't change free slot\n", devno); 523 return; 524 } 525 526 if (devno > userconf_totdev && 527 devno <= userconf_totdev+pdevnames_size) { 528 userconf_pdev(devno); 529 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 530 printf("change (y/n) ?"); 531 c = cngetc(); 532 printf("\n"); 533 } 534 535 if (c == 'y' || c == 'Y') { 536 /* XXX add cmd 'c' <devno> */ 537 userconf_hist_cmd('c'); 538 userconf_hist_int(devno); 539 540 userconf_modify("count", 541 &pdevinit[devno-userconf_totdev-1].pdev_count); 542 userconf_hist_int(pdevinit[devno-userconf_totdev-1].pdev_count); 543 544 printf("%3d %s changed\n", devno, 545 pdevnames[devno-userconf_totdev-1]); 546 userconf_pdev(devno); 547 548 /* XXX add eoc */ 549 userconf_hist_eoc(); 550 } 551 return; 552 } 553 554 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 555 } 556 557 void 558 userconf_disable(int devno) 559 { 560 int done = 0; 561 562 if (devno <= userconf_maxdev) { 563 switch (cfdata[devno].cf_fstate) { 564 case FSTATE_NOTFOUND: 565 cfdata[devno].cf_fstate = FSTATE_DNOTFOUND; 566 break; 567 case FSTATE_STAR: 568 cfdata[devno].cf_fstate = FSTATE_DSTAR; 569 break; 570 case FSTATE_DNOTFOUND: 571 case FSTATE_DSTAR: 572 done = 1; 573 break; 574 default: 575 printf("Error unknown state\n"); 576 break; 577 } 578 579 printf("%3d ", devno); 580 userconf_pdevnam(devno); 581 if (done) { 582 printf(" already"); 583 } else { 584 /* XXX add cmd 'd' <devno> eoc */ 585 userconf_hist_cmd('d'); 586 userconf_hist_int(devno); 587 userconf_hist_eoc(); 588 } 589 printf(" disabled\n"); 590 591 return; 592 } 593 594 if (devno > userconf_maxdev && devno <= userconf_totdev) { 595 printf("%3d can't disable free slot\n", devno); 596 return; 597 } 598 599 if (devno > userconf_totdev && 600 devno <= userconf_totdev+pdevnames_size) { 601 printf("%3d %s can't disable pseudo device\n", devno, 602 pdevnames[devno-userconf_totdev-1]); 603 return; 604 } 605 606 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 607 } 608 609 void 610 userconf_enable(int devno) 611 { 612 int done = 0; 613 614 if (devno <= userconf_maxdev) { 615 switch (cfdata[devno].cf_fstate) { 616 case FSTATE_DNOTFOUND: 617 cfdata[devno].cf_fstate = FSTATE_NOTFOUND; 618 break; 619 case FSTATE_DSTAR: 620 cfdata[devno].cf_fstate = FSTATE_STAR; 621 break; 622 case FSTATE_NOTFOUND: 623 case FSTATE_STAR: 624 done = 1; 625 break; 626 default: 627 printf("Error unknown state\n"); 628 break; 629 } 630 631 printf("%3d ", devno); 632 userconf_pdevnam(devno); 633 if (done) { 634 printf(" already"); 635 } else { 636 /* XXX add cmd 'e' <devno> eoc */ 637 userconf_hist_cmd('e'); 638 userconf_hist_int(devno); 639 userconf_hist_eoc(); 640 } 641 printf(" enabled\n"); 642 return; 643 } 644 645 if (devno > userconf_maxdev && devno <= userconf_totdev) { 646 printf("%3d can't enable free slot\n", devno); 647 return; 648 } 649 650 if (devno > userconf_totdev && 651 devno <= userconf_totdev+pdevnames_size) { 652 printf("%3d %s can't enable pseudo device\n", devno, 653 pdevnames[devno-userconf_totdev-1]); 654 return; 655 } 656 657 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 658 } 659 660 void 661 userconf_help(void) 662 { 663 int j = 0, k; 664 665 printf("command args description\n"); 666 while (*userconf_cmds[j] != '\0') { 667 printf(userconf_cmds[j]); 668 k = strlen(userconf_cmds[j]); 669 while (k < 10) { 670 printf(" "); 671 k++; 672 } 673 switch (*userconf_cmds[j+1]) { 674 case 'L': 675 printf("[count] number of lines before more"); 676 break; 677 case 'a': 678 printf("dev add a device"); 679 break; 680 case 'b': 681 printf("8|10|16 base on large numbers"); 682 break; 683 case 'c': 684 printf("devno|dev change devices"); 685 break; 686 #if defined(DDB) 687 case 'D': 688 printf(" enter ddb"); 689 break; 690 #endif 691 case 'd': 692 printf("attr val|devno|dev disable devices"); 693 break; 694 case 'e': 695 printf("attr val|devno|dev enable devices"); 696 break; 697 case 'f': 698 printf("devno|dev find devices"); 699 break; 700 case 'h': 701 printf(" this message"); 702 break; 703 case 'l': 704 printf(" list configuration"); 705 break; 706 case 'q': 707 printf(" leave UKC"); 708 break; 709 case 's': 710 printf("[attr [val]] " 711 "show attributes (or devices with an attribute)"); 712 break; 713 case 't': 714 printf("[mins [dst]] set timezone/dst"); 715 break; 716 case 'v': 717 printf(" toggle verbose booting"); 718 break; 719 default: 720 printf(" don't know"); 721 break; 722 } 723 printf("\n"); 724 j += 2; 725 } 726 } 727 728 void 729 userconf_list(void) 730 { 731 int i = 0; 732 733 userconf_cnt = 0; 734 735 while (i <= (userconf_totdev+pdevnames_size)) { 736 if (userconf_more()) 737 break; 738 userconf_pdev(i++); 739 } 740 741 userconf_cnt = -1; 742 } 743 744 void 745 userconf_show(void) 746 { 747 int i = 0; 748 749 userconf_cnt = 0; 750 751 while (i <= userconf_maxlocnames) { 752 if (userconf_more()) 753 break; 754 printf("%s\n", locnames[i++]); 755 } 756 757 userconf_cnt = -1; 758 } 759 760 void 761 userconf_common_attr_val(short attr, int *val, char routine) 762 { 763 struct cfdata *cd; 764 int *l; 765 int ln; 766 int i = 0, quit = 0; 767 768 userconf_cnt = 0; 769 770 while (i <= userconf_maxdev) { 771 cd = &cfdata[i]; 772 l = cd->cf_loc; 773 ln = cd->cf_locnames; 774 while (locnamp[ln] != -1) { 775 if (locnamp[ln] == attr) { 776 if (val == NULL) { 777 quit = userconf_more(); 778 userconf_pdev(i); 779 } else { 780 if (*val == *l) { 781 quit = userconf_more(); 782 switch (routine) { 783 case UC_ENABLE: 784 userconf_enable(i); 785 break; 786 case UC_DISABLE: 787 userconf_disable(i); 788 break; 789 case UC_SHOW: 790 userconf_pdev(i); 791 break; 792 default: 793 printf("Unknown routine /%c/\n", 794 routine); 795 break; 796 } 797 } 798 } 799 } 800 if (quit) 801 break; 802 ln++; 803 l++; 804 } 805 if (quit) 806 break; 807 i++; 808 } 809 810 userconf_cnt = -1; 811 } 812 813 void 814 userconf_show_attr(char *cmd) 815 { 816 char *c; 817 short attr = -1, i = 0, l = 0; 818 int a; 819 820 c = cmd; 821 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 822 c++; 823 l++; 824 } 825 while (*c == ' ' || *c == '\t' || *c == '\n') { 826 c++; 827 } 828 while (i <= userconf_maxlocnames) { 829 if (strlen(locnames[i]) == l) { 830 if (strncasecmp(cmd, locnames[i], l) == 0) { 831 attr = i; 832 } 833 } 834 i++; 835 } 836 837 if (attr == -1) { 838 printf("Unknown attribute\n"); 839 return; 840 } 841 842 if (*c == '\0') { 843 userconf_common_attr_val(attr, NULL, UC_SHOW); 844 } else { 845 if (userconf_number(c, &a) == 0) { 846 userconf_common_attr_val(attr, &a, UC_SHOW); 847 } else { 848 printf("Unknown argument\n"); 849 } 850 } 851 } 852 853 void 854 userconf_common_dev(char *dev, int len, short unit, short state, char routine) 855 { 856 int i = 0; 857 858 switch (routine) { 859 case UC_CHANGE: 860 break; 861 default: 862 userconf_cnt = 0; 863 break; 864 } 865 866 while (cfdata[i].cf_attach != 0) { 867 if (strlen(cfdata[i].cf_driver->cd_name) == len) { 868 869 /* 870 * Ok, if device name is correct 871 * If state == FSTATE_FOUND, look for "dev" 872 * If state == FSTATE_STAR, look for "dev*" 873 * If state == FSTATE_NOTFOUND, look for "dev0" 874 */ 875 if (strncasecmp(dev, cfdata[i].cf_driver->cd_name, 876 len) == 0 && 877 (state == FSTATE_FOUND || 878 (state == FSTATE_STAR && 879 (cfdata[i].cf_fstate == FSTATE_STAR || 880 cfdata[i].cf_fstate == FSTATE_DSTAR)) || 881 (state == FSTATE_NOTFOUND && 882 cfdata[i].cf_unit == unit && 883 (cfdata[i].cf_fstate == FSTATE_NOTFOUND || 884 cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) { 885 if (userconf_more()) 886 break; 887 switch (routine) { 888 case UC_CHANGE: 889 userconf_change(i); 890 break; 891 case UC_ENABLE: 892 userconf_enable(i); 893 break; 894 case UC_DISABLE: 895 userconf_disable(i); 896 break; 897 case UC_FIND: 898 userconf_pdev(i); 899 break; 900 default: 901 printf("Unknown routine /%c/\n", 902 routine); 903 break; 904 } 905 } 906 } 907 i++; 908 } 909 910 for (i = 0; i < pdevnames_size; i++) { 911 if (strncasecmp(dev, pdevnames[i], len) == 0 && 912 state == FSTATE_FOUND) { 913 switch(routine) { 914 case UC_CHANGE: 915 userconf_change(userconf_totdev+1+i); 916 break; 917 case UC_ENABLE: 918 userconf_enable(userconf_totdev+1+i); 919 break; 920 case UC_DISABLE: 921 userconf_disable(userconf_totdev+1+i); 922 break; 923 case UC_FIND: 924 userconf_pdev(userconf_totdev+1+i); 925 break; 926 default: 927 printf("Unknown pseudo routine /%c/\n",routine); 928 break; 929 } 930 } 931 } 932 933 switch (routine) { 934 case UC_CHANGE: 935 break; 936 default: 937 userconf_cnt = -1; 938 break; 939 } 940 } 941 942 void 943 userconf_common_attr(char *cmd, int attr, char routine) 944 { 945 char *c; 946 short l = 0; 947 int a; 948 949 c = cmd; 950 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 951 c++; 952 l++; 953 } 954 while (*c == ' ' || *c == '\t' || *c == '\n') 955 c++; 956 957 if (*c == '\0') { 958 printf("Value missing for attribute\n"); 959 return; 960 } 961 962 if (userconf_number(c, &a) == 0) { 963 userconf_common_attr_val(attr, &a, routine); 964 } else { 965 printf("Unknown argument\n"); 966 } 967 } 968 969 void 970 userconf_add_read(char *prompt, char field, char *dev, int len, int *val) 971 { 972 int ok = 0; 973 int a; 974 char *c; 975 int i; 976 977 *val = -1; 978 979 while (!ok) { 980 printf("%s ? ", prompt); 981 982 i = getsn(userconf_argbuf, sizeof(userconf_argbuf)); 983 984 c = userconf_argbuf; 985 while (*c == ' ' || *c == '\t' || *c == '\n') 986 c++; 987 988 if (*c != '\0') { 989 if (userconf_number(c, &a) == 0) { 990 if (a > userconf_maxdev) { 991 printf("Unknown devno (max is %d)\n", 992 userconf_maxdev); 993 } else if (strncasecmp(dev, 994 cfdata[a].cf_driver->cd_name, len) != 0 && 995 field == 'a') { 996 printf("Not same device type\n"); 997 } else { 998 *val = a; 999 ok = 1; 1000 } 1001 } else if (*c == '?') { 1002 userconf_common_dev(dev, len, 0, 1003 FSTATE_FOUND, UC_FIND); 1004 } else if (*c == 'q' || *c == 'Q') { 1005 ok = 1; 1006 } else { 1007 printf("Unknown argument\n"); 1008 } 1009 } else { 1010 ok = 1; 1011 } 1012 } 1013 } 1014 1015 void 1016 userconf_add(char *dev, int len, short unit, short state) 1017 { 1018 int i = 0, found = 0; 1019 struct cfdata new; 1020 int val, max_unit, star_unit, orig; 1021 1022 bzero(&new, sizeof(struct cfdata)); 1023 1024 if (userconf_maxdev == userconf_totdev) { 1025 printf("No more space for new devices.\n"); 1026 return; 1027 } 1028 1029 if (state == FSTATE_FOUND) { 1030 printf("Device not complete number or * is missing\n"); 1031 return; 1032 } 1033 1034 for (i = 0; cfdata[i].cf_driver; i++) 1035 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1036 strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0) 1037 found = 1; 1038 1039 if (!found) { 1040 printf("No device of this type exists.\n"); 1041 return; 1042 } 1043 1044 userconf_add_read("Clone Device (DevNo, 'q' or '?')", 1045 'a', dev, len, &val); 1046 1047 if (val != -1) { 1048 orig = val; 1049 new = cfdata[val]; 1050 new.cf_unit = unit; 1051 new.cf_fstate = state; 1052 userconf_add_read("Insert before Device (DevNo, 'q' or '?')", 1053 'i', dev, len, &val); 1054 } 1055 1056 if (val != -1) { 1057 /* XXX add cmd 'a' <orig> <val> eoc */ 1058 userconf_hist_cmd('a'); 1059 userconf_hist_int(orig); 1060 userconf_hist_int(unit); 1061 userconf_hist_int(state); 1062 userconf_hist_int(val); 1063 userconf_hist_eoc(); 1064 1065 /* Insert the new record */ 1066 for (i = userconf_maxdev; val <= i; i--) 1067 cfdata[i+1] = cfdata[i]; 1068 cfdata[val] = new; 1069 1070 /* Fix indexs in pv */ 1071 for (i = 0; i < pv_size; i++) { 1072 if (pv[i] != -1 && pv[i] >= val) 1073 pv[i]++; 1074 } 1075 1076 /* Fix indexs in cfroots */ 1077 for (i = 0; i < cfroots_size; i++) { 1078 if (cfroots[i] != -1 && cfroots[i] >= val) 1079 cfroots[i]++; 1080 } 1081 1082 userconf_maxdev++; 1083 1084 max_unit = -1; 1085 1086 /* Find max unit number of the device type */ 1087 1088 i = 0; 1089 while (cfdata[i].cf_attach != 0) { 1090 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1091 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1092 len) == 0) { 1093 switch (cfdata[i].cf_fstate) { 1094 case FSTATE_NOTFOUND: 1095 case FSTATE_DNOTFOUND: 1096 if (cfdata[i].cf_unit > max_unit) 1097 max_unit = cfdata[i].cf_unit; 1098 break; 1099 default: 1100 break; 1101 } 1102 } 1103 i++; 1104 } 1105 1106 /* 1107 * For all * entries set unit number to max+1, and update 1108 * cf_starunit1 if necessary. 1109 */ 1110 max_unit++; 1111 star_unit = -1; 1112 1113 i = 0; 1114 while (cfdata[i].cf_attach != 0) { 1115 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1116 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1117 len) == 0) { 1118 switch (cfdata[i].cf_fstate) { 1119 case FSTATE_NOTFOUND: 1120 case FSTATE_DNOTFOUND: 1121 if (cfdata[i].cf_unit > star_unit) 1122 star_unit = cfdata[i].cf_unit; 1123 break; 1124 default: 1125 break; 1126 } 1127 } 1128 i++; 1129 } 1130 star_unit++; 1131 1132 i = 0; 1133 while (cfdata[i].cf_attach != 0) { 1134 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1135 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1136 len) == 0) { 1137 switch (cfdata[i].cf_fstate) { 1138 case FSTATE_STAR: 1139 case FSTATE_DSTAR: 1140 cfdata[i].cf_unit = max_unit; 1141 if (cfdata[i].cf_starunit1 < star_unit) 1142 cfdata[i].cf_starunit1 = 1143 star_unit; 1144 break; 1145 default: 1146 break; 1147 } 1148 } 1149 i++; 1150 } 1151 userconf_pdev(val); 1152 } 1153 1154 /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags, 1155 cf_parents, cf_locnames, cf_locnames and cf_ivstubs */ 1156 } 1157 1158 int 1159 userconf_parse(char *cmd) 1160 { 1161 char *c, *v; 1162 int i = 0, j = 0, k, a; 1163 short unit, state; 1164 1165 c = cmd; 1166 while (*c == ' ' || *c == '\t') 1167 c++; 1168 v = c; 1169 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 1170 c++; 1171 i++; 1172 } 1173 1174 k = -1; 1175 while (*userconf_cmds[j] != '\0') { 1176 if (strlen(userconf_cmds[j]) == i) { 1177 if (strncasecmp(v, userconf_cmds[j], i) == 0) 1178 k = j; 1179 } 1180 j += 2; 1181 } 1182 1183 while (*c == ' ' || *c == '\t' || *c == '\n') 1184 c++; 1185 1186 if (k == -1) { 1187 if (*v != '\n') 1188 printf("Unknown command, try help\n"); 1189 } else { 1190 switch (*userconf_cmds[k+1]) { 1191 case 'L': 1192 if (*c == '\0') 1193 printf("Argument expected\n"); 1194 else if (userconf_number(c, &a) == 0) 1195 userconf_lines = a; 1196 else 1197 printf("Unknown argument\n"); 1198 break; 1199 case 'a': 1200 if (*c == '\0') 1201 printf("Dev expected\n"); 1202 else if (userconf_device(c, &a, &unit, &state) == 0) 1203 userconf_add(c, a, unit, state); 1204 else 1205 printf("Unknown argument\n"); 1206 break; 1207 case 'b': 1208 if (*c == '\0') 1209 printf("8|10|16 expected\n"); 1210 else if (userconf_number(c, &a) == 0) { 1211 if (a == 8 || a == 10 || a == 16) { 1212 userconf_base = a; 1213 } else { 1214 printf("8|10|16 expected\n"); 1215 } 1216 } else 1217 printf("Unknown argument\n"); 1218 break; 1219 case 'c': 1220 if (*c == '\0') 1221 printf("DevNo or Dev expected\n"); 1222 else if (userconf_number(c, &a) == 0) 1223 userconf_change(a); 1224 else if (userconf_device(c, &a, &unit, &state) == 0) 1225 userconf_common_dev(c, a, unit, state, UC_CHANGE); 1226 else 1227 printf("Unknown argument\n"); 1228 break; 1229 #if defined(DDB) 1230 case 'D': 1231 Debugger(); 1232 break; 1233 #endif 1234 case 'd': 1235 if (*c == '\0') 1236 printf("Attr, DevNo or Dev expected\n"); 1237 else if (userconf_attr(c, &a) == 0) 1238 userconf_common_attr(c, a, UC_DISABLE); 1239 else if (userconf_number(c, &a) == 0) 1240 userconf_disable(a); 1241 else if (userconf_device(c, &a, &unit, &state) == 0) 1242 userconf_common_dev(c, a, unit, state, UC_DISABLE); 1243 else 1244 printf("Unknown argument\n"); 1245 break; 1246 case 'e': 1247 if (*c == '\0') 1248 printf("Attr, DevNo or Dev expected\n"); 1249 else if (userconf_attr(c, &a) == 0) 1250 userconf_common_attr(c, a, UC_ENABLE); 1251 else if (userconf_number(c, &a) == 0) 1252 userconf_enable(a); 1253 else if (userconf_device(c, &a, &unit, &state) == 0) 1254 userconf_common_dev(c, a, unit, state, UC_ENABLE); 1255 else 1256 printf("Unknown argument\n"); 1257 break; 1258 case 'f': 1259 if (*c == '\0') 1260 printf("DevNo or Dev expected\n"); 1261 else if (userconf_number(c, &a) == 0) 1262 userconf_pdev(a); 1263 else if (userconf_device(c, &a, &unit, &state) == 0) 1264 userconf_common_dev(c, a, unit, state, UC_FIND); 1265 else 1266 printf("Unknown argument\n"); 1267 break; 1268 case 'h': 1269 userconf_help(); 1270 break; 1271 case 'l': 1272 if (*c == '\0') 1273 userconf_list(); 1274 else 1275 printf("Unknown argument\n"); 1276 break; 1277 case 'q': 1278 /* XXX add cmd 'q' eoc */ 1279 userconf_hist_cmd('q'); 1280 userconf_hist_eoc(); 1281 return(-1); 1282 break; 1283 case 's': 1284 if (*c == '\0') 1285 userconf_show(); 1286 else 1287 userconf_show_attr(c); 1288 break; 1289 case 't': 1290 if (*c == '\0' || userconf_number(c, &a) == 0) { 1291 if (*c != '\0') { 1292 tz.tz_minuteswest = a; 1293 while (*c != '\n' && *c != '\t' && 1294 *c != ' ' && *c != '\0') 1295 c++; 1296 while (*c == '\t' || *c == ' ') 1297 c++; 1298 if (*c != '\0' && 1299 userconf_number(c, &a) == 0) 1300 tz.tz_dsttime = a; 1301 userconf_hist_cmd('t'); 1302 userconf_hist_int(tz.tz_minuteswest); 1303 userconf_hist_int(tz.tz_dsttime); 1304 userconf_hist_eoc(); 1305 } 1306 printf("timezone = %d, dst = %d\n", 1307 tz.tz_minuteswest, tz.tz_dsttime); 1308 } else 1309 printf("Unknown argument\n"); 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 while (1) { 1331 printf("UKC> "); 1332 if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 && 1333 userconf_parse(userconf_cmdbuf)) 1334 break; 1335 } 1336 printf("Continuing...\n"); 1337 } 1338