1 /* $OpenBSD: subr_userconf.c,v 1.36 2009/06/02 12:46:33 deraadt 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", devno, 261 pdevnames[devno-userconf_totdev-1], 262 abs(pdevinit[devno-userconf_totdev-1].pdev_count)); 263 if (pdevinit[devno-userconf_totdev-1].pdev_count < 1) 264 printf(" disable"); 265 printf(" (pseudo device)\n"); 266 return; 267 } 268 269 if (devno > userconf_maxdev) { 270 printf("Unknown devno (max is %d)\n", userconf_maxdev); 271 return; 272 } 273 274 cd = &cfdata[devno]; 275 276 printf("%3d ", devno); 277 userconf_pdevnam(devno); 278 printf(" at"); 279 c = ' '; 280 p = cd->cf_parents; 281 if (*p == -1) 282 printf(" root"); 283 while (*p != -1) { 284 printf("%c", c); 285 userconf_pdevnam(*p++); 286 c = '|'; 287 } 288 switch (cd->cf_fstate) { 289 case FSTATE_NOTFOUND: 290 case FSTATE_FOUND: 291 case FSTATE_STAR: 292 break; 293 case FSTATE_DNOTFOUND: 294 case FSTATE_DSTAR: 295 printf(" disable"); 296 break; 297 default: 298 printf(" ???"); 299 break; 300 } 301 l = cd->cf_loc; 302 ln = cd->cf_locnames; 303 while (locnamp[ln] != -1) { 304 printf(" %s ", locnames[locnamp[ln]]); 305 ln++; 306 userconf_pnum(*l++); 307 } 308 printf(" flags 0x%x\n", cd->cf_flags); 309 } 310 311 int 312 userconf_number(char *c, int *val) 313 { 314 u_int num = 0; 315 int neg = 0; 316 int base = 10; 317 318 if (*c == '-') { 319 neg = 1; 320 c++; 321 } 322 if (*c == '0') { 323 base = 8; 324 c++; 325 if (*c == 'x' || *c == 'X') { 326 base = 16; 327 c++; 328 } 329 } 330 while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') { 331 u_char cc = *c; 332 333 if (cc >= '0' && cc <= '9') 334 cc = cc - '0'; 335 else if (cc >= 'a' && cc <= 'f') 336 cc = cc - 'a' + 10; 337 else if (cc >= 'A' && cc <= 'F') 338 cc = cc - 'A' + 10; 339 else 340 return (-1); 341 342 if (cc > base) 343 return (-1); 344 num = num * base + cc; 345 c++; 346 } 347 348 if (neg && num > INT_MAX) /* overflow */ 349 return (1); 350 *val = neg ? - num : num; 351 return (0); 352 } 353 354 int 355 userconf_device(char *cmd, int *len, short *unit, short *state) 356 { 357 short u = 0, s = FSTATE_FOUND; 358 int l = 0; 359 char *c; 360 361 c = cmd; 362 while (*c >= 'a' && *c <= 'z') { 363 l++; 364 c++; 365 } 366 if (*c == '*') { 367 s = FSTATE_STAR; 368 c++; 369 } else { 370 while (*c >= '0' && *c <= '9') { 371 s = FSTATE_NOTFOUND; 372 u = u*10 + *c - '0'; 373 c++; 374 } 375 } 376 while (*c == ' ' || *c == '\t' || *c == '\n') 377 c++; 378 379 if (*c == '\0') { 380 *len = l; 381 *unit = u; 382 *state = s; 383 return(0); 384 } 385 386 return(-1); 387 } 388 389 int 390 userconf_attr(char *cmd, int *val) 391 { 392 char *c; 393 short attr = -1, i = 0, l = 0; 394 395 c = cmd; 396 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 397 c++; 398 l++; 399 } 400 401 while (i <= userconf_maxlocnames) { 402 if (strlen(locnames[i]) == l) { 403 if (strncasecmp(cmd, locnames[i], l) == 0) 404 attr = i; 405 } 406 i++; 407 } 408 409 if (attr == -1) { 410 return (-1); 411 } 412 413 *val = attr; 414 415 return(0); 416 } 417 418 void 419 userconf_modify(char *item, int *val) 420 { 421 int ok = 0; 422 int a; 423 char *c; 424 int i; 425 426 while (!ok) { 427 printf("%s [", item); 428 userconf_pnum(*val); 429 printf("] ? "); 430 431 i = getsn(userconf_argbuf, sizeof(userconf_argbuf)); 432 433 c = userconf_argbuf; 434 while (*c == ' ' || *c == '\t' || *c == '\n') c++; 435 436 if (*c != '\0') { 437 if (userconf_number(c, &a) == 0) { 438 *val = a; 439 ok = 1; 440 } else { 441 printf("Unknown argument\n"); 442 } 443 } else { 444 ok = 1; 445 } 446 } 447 } 448 449 void 450 userconf_change(int devno) 451 { 452 struct cfdata *cd; 453 char c = '\0'; 454 int *l; 455 int ln; 456 457 if (devno <= userconf_maxdev) { 458 userconf_pdev(devno); 459 460 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 461 printf("change (y/n) ?"); 462 c = cngetc(); 463 printf("\n"); 464 } 465 466 if (c == 'y' || c == 'Y') { 467 int share = 0, i, *lk; 468 469 /* XXX add cmd 'c' <devno> */ 470 userconf_hist_cmd('c'); 471 userconf_hist_int(devno); 472 473 cd = &cfdata[devno]; 474 l = cd->cf_loc; 475 ln = cd->cf_locnames; 476 477 /* 478 * Search for some other driver sharing this 479 * locator table. if one does, we may need to 480 * replace the locators with a malloc'd copy. 481 */ 482 for (i = 0; cfdata[i].cf_driver; i++) 483 if (i != devno && cfdata[i].cf_loc == l) 484 share = 1; 485 if (share) { 486 for (i = 0; locnamp[ln+i] != -1 ; i++) 487 ; 488 lk = l = (int *)malloc(sizeof(int) * i, 489 M_TEMP, M_NOWAIT); 490 if (lk == NULL) { 491 printf("out of memory.\n"); 492 return; 493 } 494 bcopy(cd->cf_loc, l, sizeof(int) * i); 495 } 496 497 while (locnamp[ln] != -1) { 498 userconf_modify(locnames[locnamp[ln]], l); 499 500 /* XXX add *l */ 501 userconf_hist_int(*l); 502 503 ln++; 504 l++; 505 } 506 userconf_modify("flags", &cd->cf_flags); 507 userconf_hist_int(cd->cf_flags); 508 509 if (share) { 510 if (bcmp(cd->cf_loc, lk, sizeof(int) * i)) 511 cd->cf_loc = lk; 512 else 513 free(lk, M_TEMP); 514 } 515 516 printf("%3d ", devno); 517 userconf_pdevnam(devno); 518 printf(" changed\n"); 519 userconf_pdev(devno); 520 } 521 return; 522 } 523 524 if (devno > userconf_maxdev && devno <= userconf_totdev) { 525 printf("%3d can't change free slot\n", devno); 526 return; 527 } 528 529 if (devno > userconf_totdev && 530 devno <= userconf_totdev+pdevnames_size) { 531 userconf_pdev(devno); 532 while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { 533 printf("change (y/n) ?"); 534 c = cngetc(); 535 printf("\n"); 536 } 537 538 if (c == 'y' || c == 'Y') { 539 /* XXX add cmd 'c' <devno> */ 540 userconf_hist_cmd('c'); 541 userconf_hist_int(devno); 542 543 userconf_modify("count", 544 &pdevinit[devno-userconf_totdev-1].pdev_count); 545 userconf_hist_int(pdevinit[devno-userconf_totdev-1].pdev_count); 546 547 printf("%3d %s changed\n", devno, 548 pdevnames[devno-userconf_totdev-1]); 549 userconf_pdev(devno); 550 551 /* XXX add eoc */ 552 userconf_hist_eoc(); 553 } 554 return; 555 } 556 557 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 558 } 559 560 void 561 userconf_disable(int devno) 562 { 563 int done = 0; 564 565 if (devno <= userconf_maxdev) { 566 switch (cfdata[devno].cf_fstate) { 567 case FSTATE_NOTFOUND: 568 cfdata[devno].cf_fstate = FSTATE_DNOTFOUND; 569 break; 570 case FSTATE_STAR: 571 cfdata[devno].cf_fstate = FSTATE_DSTAR; 572 break; 573 case FSTATE_DNOTFOUND: 574 case FSTATE_DSTAR: 575 done = 1; 576 break; 577 default: 578 printf("Error unknown state\n"); 579 break; 580 } 581 582 printf("%3d ", devno); 583 userconf_pdevnam(devno); 584 if (done) { 585 printf(" already"); 586 } else { 587 /* XXX add cmd 'd' <devno> eoc */ 588 userconf_hist_cmd('d'); 589 userconf_hist_int(devno); 590 userconf_hist_eoc(); 591 } 592 printf(" disabled\n"); 593 594 return; 595 } 596 597 if (devno > userconf_maxdev && devno <= userconf_totdev) { 598 printf("%3d can't disable free slot\n", devno); 599 return; 600 } 601 602 if (devno > userconf_totdev && 603 devno <= userconf_totdev+pdevnames_size) { 604 printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]); 605 if (pdevinit[devno-userconf_totdev-1].pdev_count < 1) { 606 printf(" already "); 607 } else { 608 pdevinit[devno-userconf_totdev-1].pdev_count *= -1; 609 /* XXX add cmd 'd' <devno> eoc */ 610 userconf_hist_cmd('d'); 611 userconf_hist_int(devno); 612 userconf_hist_eoc(); 613 } 614 printf(" disabled\n"); 615 return; 616 } 617 618 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 619 } 620 621 void 622 userconf_enable(int devno) 623 { 624 int done = 0; 625 626 if (devno <= userconf_maxdev) { 627 switch (cfdata[devno].cf_fstate) { 628 case FSTATE_DNOTFOUND: 629 cfdata[devno].cf_fstate = FSTATE_NOTFOUND; 630 break; 631 case FSTATE_DSTAR: 632 cfdata[devno].cf_fstate = FSTATE_STAR; 633 break; 634 case FSTATE_NOTFOUND: 635 case FSTATE_STAR: 636 done = 1; 637 break; 638 default: 639 printf("Error unknown state\n"); 640 break; 641 } 642 643 printf("%3d ", devno); 644 userconf_pdevnam(devno); 645 if (done) { 646 printf(" already"); 647 } else { 648 /* XXX add cmd 'e' <devno> eoc */ 649 userconf_hist_cmd('e'); 650 userconf_hist_int(devno); 651 userconf_hist_eoc(); 652 } 653 printf(" enabled\n"); 654 return; 655 } 656 657 if (devno > userconf_maxdev && devno <= userconf_totdev) { 658 printf("%3d can't enable free slot\n", devno); 659 return; 660 } 661 662 if (devno > userconf_totdev && 663 devno <= userconf_totdev+pdevnames_size) { 664 printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]); 665 if (pdevinit[devno-userconf_totdev-1].pdev_count > 0) { 666 printf(" already"); 667 } else { 668 pdevinit[devno-userconf_totdev-1].pdev_count *= -1; 669 /* XXX add cmd 'e' <devno> eoc */ 670 userconf_hist_cmd('e'); 671 userconf_hist_int(devno); 672 userconf_hist_eoc(); 673 } 674 printf(" enabled\n"); 675 return; 676 } 677 678 printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size); 679 } 680 681 void 682 userconf_help(void) 683 { 684 int j = 0, k; 685 686 printf("command args description\n"); 687 while (*userconf_cmds[j] != '\0') { 688 printf(userconf_cmds[j]); 689 k = strlen(userconf_cmds[j]); 690 while (k < 10) { 691 printf(" "); 692 k++; 693 } 694 switch (*userconf_cmds[j+1]) { 695 case 'L': 696 printf("[count] number of lines before more"); 697 break; 698 case 'a': 699 printf("dev add a device"); 700 break; 701 case 'b': 702 printf("8|10|16 base on large numbers"); 703 break; 704 case 'c': 705 printf("devno|dev change devices"); 706 break; 707 #if defined(DDB) 708 case 'D': 709 printf(" enter ddb"); 710 break; 711 #endif 712 case 'd': 713 printf("attr val|devno|dev disable devices"); 714 break; 715 case 'e': 716 printf("attr val|devno|dev enable devices"); 717 break; 718 case 'f': 719 printf("devno|dev find devices"); 720 break; 721 case 'h': 722 printf(" this message"); 723 break; 724 case 'l': 725 printf(" list configuration"); 726 break; 727 case 'q': 728 printf(" leave UKC"); 729 break; 730 case 's': 731 printf("[attr [val]] " 732 "show attributes (or devices with an attribute)"); 733 break; 734 case 't': 735 printf("[mins [dst]] set timezone/dst"); 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, int *val, char routine) 783 { 784 struct cfdata *cd; 785 int *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 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(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 != 0) { 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 int 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) == 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, int *val) 992 { 993 int ok = 0; 994 int 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) == 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 i = 0, found = 0; 1040 struct cfdata new; 1041 int val, max_unit, star_unit, orig; 1042 1043 bzero(&new, sizeof(struct cfdata)); 1044 1045 if (userconf_maxdev == userconf_totdev) { 1046 printf("No more space for new devices.\n"); 1047 return; 1048 } 1049 1050 if (state == FSTATE_FOUND) { 1051 printf("Device not complete number or * is missing\n"); 1052 return; 1053 } 1054 1055 for (i = 0; cfdata[i].cf_driver; i++) 1056 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1057 strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0) 1058 found = 1; 1059 1060 if (!found) { 1061 printf("No device of this type exists.\n"); 1062 return; 1063 } 1064 1065 userconf_add_read("Clone Device (DevNo, 'q' or '?')", 1066 'a', dev, len, &val); 1067 1068 if (val != -1) { 1069 orig = val; 1070 new = cfdata[val]; 1071 new.cf_unit = unit; 1072 new.cf_fstate = state; 1073 userconf_add_read("Insert before Device (DevNo, 'q' or '?')", 1074 'i', dev, len, &val); 1075 } 1076 1077 if (val != -1) { 1078 /* XXX add cmd 'a' <orig> <val> eoc */ 1079 userconf_hist_cmd('a'); 1080 userconf_hist_int(orig); 1081 userconf_hist_int(unit); 1082 userconf_hist_int(state); 1083 userconf_hist_int(val); 1084 userconf_hist_eoc(); 1085 1086 /* Insert the new record */ 1087 for (i = userconf_maxdev; val <= i; i--) 1088 cfdata[i+1] = cfdata[i]; 1089 cfdata[val] = new; 1090 1091 /* Fix indexs in pv */ 1092 for (i = 0; i < pv_size; i++) { 1093 if (pv[i] != -1 && pv[i] >= val) 1094 pv[i]++; 1095 } 1096 1097 /* Fix indexs in cfroots */ 1098 for (i = 0; i < cfroots_size; i++) { 1099 if (cfroots[i] != -1 && cfroots[i] >= val) 1100 cfroots[i]++; 1101 } 1102 1103 userconf_maxdev++; 1104 1105 max_unit = -1; 1106 1107 /* Find max unit number of the device type */ 1108 1109 i = 0; 1110 while (cfdata[i].cf_attach != 0) { 1111 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1112 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1113 len) == 0) { 1114 switch (cfdata[i].cf_fstate) { 1115 case FSTATE_NOTFOUND: 1116 case FSTATE_DNOTFOUND: 1117 if (cfdata[i].cf_unit > max_unit) 1118 max_unit = cfdata[i].cf_unit; 1119 break; 1120 default: 1121 break; 1122 } 1123 } 1124 i++; 1125 } 1126 1127 /* 1128 * For all * entries set unit number to max+1, and update 1129 * cf_starunit1 if necessary. 1130 */ 1131 max_unit++; 1132 star_unit = -1; 1133 1134 i = 0; 1135 while (cfdata[i].cf_attach != 0) { 1136 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1137 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1138 len) == 0) { 1139 switch (cfdata[i].cf_fstate) { 1140 case FSTATE_NOTFOUND: 1141 case FSTATE_DNOTFOUND: 1142 if (cfdata[i].cf_unit > star_unit) 1143 star_unit = cfdata[i].cf_unit; 1144 break; 1145 default: 1146 break; 1147 } 1148 } 1149 i++; 1150 } 1151 star_unit++; 1152 1153 i = 0; 1154 while (cfdata[i].cf_attach != 0) { 1155 if (strlen(cfdata[i].cf_driver->cd_name) == len && 1156 strncasecmp(dev, cfdata[i].cf_driver->cd_name, 1157 len) == 0) { 1158 switch (cfdata[i].cf_fstate) { 1159 case FSTATE_STAR: 1160 case FSTATE_DSTAR: 1161 cfdata[i].cf_unit = max_unit; 1162 if (cfdata[i].cf_starunit1 < star_unit) 1163 cfdata[i].cf_starunit1 = 1164 star_unit; 1165 break; 1166 default: 1167 break; 1168 } 1169 } 1170 i++; 1171 } 1172 userconf_pdev(val); 1173 } 1174 1175 /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags, 1176 cf_parents, cf_locnames, cf_locnames and cf_ivstubs */ 1177 } 1178 1179 int 1180 userconf_parse(char *cmd) 1181 { 1182 char *c, *v; 1183 int i = 0, j = 0, k, a; 1184 short unit, state; 1185 1186 c = cmd; 1187 while (*c == ' ' || *c == '\t') 1188 c++; 1189 v = c; 1190 while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') { 1191 c++; 1192 i++; 1193 } 1194 1195 k = -1; 1196 while (*userconf_cmds[j] != '\0') { 1197 if (strlen(userconf_cmds[j]) == i) { 1198 if (strncasecmp(v, userconf_cmds[j], i) == 0) 1199 k = j; 1200 } 1201 j += 2; 1202 } 1203 1204 while (*c == ' ' || *c == '\t' || *c == '\n') 1205 c++; 1206 1207 if (k == -1) { 1208 if (*v != '\n') 1209 printf("Unknown command, try help\n"); 1210 } else { 1211 switch (*userconf_cmds[k+1]) { 1212 case 'L': 1213 if (*c == '\0') 1214 printf("Argument expected\n"); 1215 else if (userconf_number(c, &a) == 0) 1216 userconf_lines = a; 1217 else 1218 printf("Unknown argument\n"); 1219 break; 1220 case 'a': 1221 if (*c == '\0') 1222 printf("Dev expected\n"); 1223 else if (userconf_device(c, &a, &unit, &state) == 0) 1224 userconf_add(c, a, unit, state); 1225 else 1226 printf("Unknown argument\n"); 1227 break; 1228 case 'b': 1229 if (*c == '\0') 1230 printf("8|10|16 expected\n"); 1231 else if (userconf_number(c, &a) == 0) { 1232 if (a == 8 || a == 10 || a == 16) { 1233 userconf_base = a; 1234 } else { 1235 printf("8|10|16 expected\n"); 1236 } 1237 } else 1238 printf("Unknown argument\n"); 1239 break; 1240 case 'c': 1241 if (*c == '\0') 1242 printf("DevNo or Dev expected\n"); 1243 else if (userconf_number(c, &a) == 0) 1244 userconf_change(a); 1245 else if (userconf_device(c, &a, &unit, &state) == 0) 1246 userconf_common_dev(c, a, unit, state, UC_CHANGE); 1247 else 1248 printf("Unknown argument\n"); 1249 break; 1250 #if defined(DDB) 1251 case 'D': 1252 Debugger(); 1253 break; 1254 #endif 1255 case 'd': 1256 if (*c == '\0') 1257 printf("Attr, DevNo or Dev expected\n"); 1258 else if (userconf_attr(c, &a) == 0) 1259 userconf_common_attr(c, a, UC_DISABLE); 1260 else if (userconf_number(c, &a) == 0) 1261 userconf_disable(a); 1262 else if (userconf_device(c, &a, &unit, &state) == 0) 1263 userconf_common_dev(c, a, unit, state, UC_DISABLE); 1264 else 1265 printf("Unknown argument\n"); 1266 break; 1267 case 'e': 1268 if (*c == '\0') 1269 printf("Attr, DevNo or Dev expected\n"); 1270 else if (userconf_attr(c, &a) == 0) 1271 userconf_common_attr(c, a, UC_ENABLE); 1272 else if (userconf_number(c, &a) == 0) 1273 userconf_enable(a); 1274 else if (userconf_device(c, &a, &unit, &state) == 0) 1275 userconf_common_dev(c, a, unit, state, UC_ENABLE); 1276 else 1277 printf("Unknown argument\n"); 1278 break; 1279 case 'f': 1280 if (*c == '\0') 1281 printf("DevNo or Dev expected\n"); 1282 else if (userconf_number(c, &a) == 0) 1283 userconf_pdev(a); 1284 else if (userconf_device(c, &a, &unit, &state) == 0) 1285 userconf_common_dev(c, a, unit, state, UC_FIND); 1286 else 1287 printf("Unknown argument\n"); 1288 break; 1289 case 'h': 1290 userconf_help(); 1291 break; 1292 case 'l': 1293 if (*c == '\0') 1294 userconf_list(); 1295 else 1296 printf("Unknown argument\n"); 1297 break; 1298 case 'q': 1299 /* XXX add cmd 'q' eoc */ 1300 userconf_hist_cmd('q'); 1301 userconf_hist_eoc(); 1302 return(-1); 1303 break; 1304 case 's': 1305 if (*c == '\0') 1306 userconf_show(); 1307 else 1308 userconf_show_attr(c); 1309 break; 1310 case 't': 1311 if (*c == '\0' || userconf_number(c, &a) == 0) { 1312 if (*c != '\0') { 1313 tz.tz_minuteswest = a; 1314 while (*c != '\n' && *c != '\t' && 1315 *c != ' ' && *c != '\0') 1316 c++; 1317 while (*c == '\t' || *c == ' ') 1318 c++; 1319 if (*c != '\0' && 1320 userconf_number(c, &a) == 0) 1321 tz.tz_dsttime = a; 1322 userconf_hist_cmd('t'); 1323 userconf_hist_int(tz.tz_minuteswest); 1324 userconf_hist_int(tz.tz_dsttime); 1325 userconf_hist_eoc(); 1326 } 1327 printf("timezone = %d, dst = %d\n", 1328 tz.tz_minuteswest, tz.tz_dsttime); 1329 } else 1330 printf("Unknown argument\n"); 1331 break; 1332 case 'v': 1333 autoconf_verbose = !autoconf_verbose; 1334 printf("autoconf verbose %sabled\n", 1335 autoconf_verbose ? "en" : "dis"); 1336 break; 1337 default: 1338 printf("Unknown command\n"); 1339 break; 1340 } 1341 } 1342 return(0); 1343 } 1344 1345 void 1346 user_config(void) 1347 { 1348 userconf_init(); 1349 printf("User Kernel Config\n"); 1350 1351 while (1) { 1352 printf("UKC> "); 1353 if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 && 1354 userconf_parse(userconf_cmdbuf)) 1355 break; 1356 } 1357 printf("Continuing...\n"); 1358 } 1359