The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_userconf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f91a2b2e52799d520d15e1cb4b387633


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.