root/kern/subr_userconf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. userconf_init
  2. userconf_more
  3. userconf_hist_cmd
  4. userconf_hist_int
  5. userconf_hist_eoc
  6. userconf_pnum
  7. userconf_pdevnam
  8. userconf_pdev
  9. userconf_number
  10. userconf_device
  11. userconf_attr
  12. userconf_modify
  13. userconf_change
  14. userconf_disable
  15. userconf_enable
  16. userconf_help
  17. userconf_list
  18. userconf_show
  19. userconf_common_attr_val
  20. userconf_show_attr
  21. userconf_common_dev
  22. userconf_common_attr
  23. userconf_add_read
  24. userconf_add
  25. userconf_parse
  26. user_config

    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 }

/* [<][>][^][v][top][bottom][index][help] */