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