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