1 /* $NetBSD: subr_userconf.c,v 1.10.6.5 2005/11/10 14:09:45 skrll Exp $ */
4 * Copyright (c) 1996 Mats O Jansson <moj@stacken.kth.se>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Mats O Jansson.
18 * 4. The name of the author may not be used to endorse or promote
19 * products derived from this software without specific prior written
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * OpenBSD: subr_userconf.c,v 1.19 2000/01/08 23:23:37 d Exp
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: subr_userconf.c,v 1.10.6.5 2005/11/10 14:09:45 skrll Exp $");
40 #include "opt_userconf.h"
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
50 extern struct cfdata cfdata
[];
52 static int userconf_base
= 16; /* Base for "large" numbers */
53 static int userconf_maxdev
= -1; /* # of used device slots */
54 static int userconf_totdev
= -1; /* # of device slots */
56 static int userconf_maxlocnames
= -1; /* # of locnames */
58 static int userconf_cnt
= -1; /* Line counter for ... */
59 static int userconf_lines
= 12; /* ... # of lines per page */
60 static int userconf_histlen
= 0;
61 static int userconf_histcur
= 0;
62 static char userconf_history
[1024];
63 static int userconf_histsz
= sizeof(userconf_history
);
64 static char userconf_argbuf
[40]; /* Additional input */
65 static char userconf_cmdbuf
[40]; /* Command line */
66 static char userconf_histbuf
[40];
68 static int getsn(char *, int);
71 #define UC_DISABLE 'd'
76 static const char *userconf_cmds
[] = {
98 for (cf
= cfdata
; cf
->cf_name
; cf
++)
101 userconf_maxdev
= i
- 1;
102 userconf_totdev
= i
- 1;
111 if (userconf_cnt
!= -1) {
112 if (userconf_cnt
== userconf_lines
) {
113 printf("-- more --");
119 if (c
== 'q' || c
== 'Q')
126 userconf_hist_cmd(char cmd
)
128 userconf_histcur
= userconf_histlen
;
129 if (userconf_histcur
< userconf_histsz
) {
130 userconf_history
[userconf_histcur
] = cmd
;
136 userconf_hist_int(int val
)
138 snprintf(userconf_histbuf
, sizeof(userconf_histbuf
), " %d", val
);
139 if ((userconf_histcur
+ strlen(userconf_histbuf
)) < userconf_histsz
) {
140 memcpy(&userconf_history
[userconf_histcur
],
142 strlen(userconf_histbuf
));
143 userconf_histcur
= userconf_histcur
+ strlen(userconf_histbuf
);
148 userconf_hist_eoc(void)
150 if (userconf_histcur
< userconf_histsz
) {
151 userconf_history
[userconf_histcur
] = '\n';
153 userconf_histlen
= userconf_histcur
;
158 userconf_pnum(int val
)
160 if (val
> -2 && val
< 16) {
163 switch (userconf_base
) {
179 userconf_pdevnam(short dev
)
184 printf("%s", cd
->cf_name
);
185 switch (cd
->cf_fstate
) {
186 case FSTATE_NOTFOUND
:
187 case FSTATE_DNOTFOUND
:
188 printf("%d", cd
->cf_unit
);
204 userconf_pdev(short devno
)
207 const struct cfparent
*cfp
;
209 const struct cfiattrdata
*ia
;
210 const struct cflocdesc
*ld
;
213 if (devno
> userconf_maxdev
) {
214 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
220 printf("[%3d] ", devno
);
221 userconf_pdevnam(devno
);
226 else if (cfp
->cfp_parent
!= NULL
&& cfp
->cfp_unit
!= -1)
227 printf(" %s%d", cfp
->cfp_parent
, cfp
->cfp_unit
);
229 printf(" %s?", cfp
->cfp_parent
!= NULL
? cfp
->cfp_parent
231 switch (cd
->cf_fstate
) {
232 case FSTATE_NOTFOUND
:
236 case FSTATE_DNOTFOUND
:
246 ia
= cfiattr_lookup(cfp
->cfp_iattr
, 0);
250 for (i
= 0; i
< nld
; i
++) {
251 printf(" %s ", ld
[i
].cld_name
);
252 if (!ld
[i
].cld_defaultstr
253 || (l
[i
] != ld
[i
].cld_default
))
263 userconf_number(char *c
, int *val
)
276 if (*c
== 'x' || *c
== 'X') {
281 while (*c
!= '\n' && *c
!= '\t' && *c
!= ' ' && *c
!= '\0') {
284 if (cc
>= '0' && cc
<= '9')
286 else if (cc
>= 'a' && cc
<= 'f')
288 else if (cc
>= 'A' && cc
<= 'F')
295 num
= num
* base
+ cc
;
299 if (neg
&& num
> INT_MAX
) /* overflow */
301 *val
= neg
? - num
: num
;
306 userconf_device(char *cmd
, int *len
, short *unit
, short *state
)
308 short u
= 0, s
= FSTATE_FOUND
;
313 while (*c
>= 'a' && *c
<= 'z') {
321 while (*c
>= '0' && *c
<= '9') {
327 while (*c
== ' ' || *c
== '\t' || *c
== '\n')
341 userconf_modify(const struct cflocdesc
*item
, int *val
)
348 printf("%s [", item
->cld_name
);
349 if (item
->cld_defaultstr
&& (*val
== item
->cld_default
))
355 getsn(userconf_argbuf
, sizeof(userconf_argbuf
));
358 while (*c
== ' ' || *c
== '\t' || *c
== '\n') c
++;
362 if (item
->cld_defaultstr
) {
363 *val
= item
->cld_default
;
366 printf("No default\n");
367 } else if (userconf_number(c
, &a
) == 0) {
371 printf("Unknown argument\n");
380 userconf_change(int devno
)
386 const struct cfiattrdata
*ia
;
387 const struct cflocdesc
*ld
;
390 if (devno
<= userconf_maxdev
) {
392 userconf_pdev(devno
);
394 while (c
!= 'y' && c
!= 'Y' && c
!= 'n' && c
!= 'N') {
395 printf("change (y/n) ?");
400 if (c
== 'y' || c
== 'Y') {
402 /* XXX add cmd 'c' <devno> */
403 userconf_hist_cmd('c');
404 userconf_hist_int(devno
);
408 ia
= cfiattr_lookup(cd
->cf_pspec
->cfp_iattr
, 0);
413 for (ln
= 0; ln
< nld
; ln
++)
415 userconf_modify(&ld
[ln
], l
);
418 userconf_hist_int(*l
);
423 printf("[%3d] ", devno
);
424 userconf_pdevnam(devno
);
425 printf(" changed\n");
426 userconf_pdev(devno
);
433 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
438 userconf_disable(int devno
)
442 if (devno
<= userconf_maxdev
) {
443 switch (cfdata
[devno
].cf_fstate
) {
444 case FSTATE_NOTFOUND
:
445 cfdata
[devno
].cf_fstate
= FSTATE_DNOTFOUND
;
448 cfdata
[devno
].cf_fstate
= FSTATE_DSTAR
;
450 case FSTATE_DNOTFOUND
:
455 printf("Error unknown state\n");
459 printf("[%3d] ", devno
);
460 userconf_pdevnam(devno
);
464 /* XXX add cmd 'd' <devno> eoc */
465 userconf_hist_cmd('d');
466 userconf_hist_int(devno
);
469 printf(" disabled\n");
471 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
476 userconf_enable(int devno
)
480 if (devno
<= userconf_maxdev
) {
481 switch (cfdata
[devno
].cf_fstate
) {
482 case FSTATE_DNOTFOUND
:
483 cfdata
[devno
].cf_fstate
= FSTATE_NOTFOUND
;
486 cfdata
[devno
].cf_fstate
= FSTATE_STAR
;
488 case FSTATE_NOTFOUND
:
493 printf("Error unknown state\n");
497 printf("[%3d] ", devno
);
498 userconf_pdevnam(devno
);
502 /* XXX add cmd 'e' <devno> eoc */
503 userconf_hist_cmd('d');
504 userconf_hist_int(devno
);
507 printf(" enabled\n");
509 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
518 printf("command args description\n");
519 while (*userconf_cmds
[j
] != '\0') {
520 printf(userconf_cmds
[j
]);
521 k
= strlen(userconf_cmds
[j
]);
526 switch (*userconf_cmds
[j
+1]) {
528 printf("[count] number of lines before more");
531 printf("8|10|16 base on large numbers");
534 printf("devno|dev change devices");
537 printf("devno|dev disable devices");
540 printf("devno|dev enable devices");
543 printf("devno|dev find devices");
546 printf(" this message");
549 printf(" list configuration");
552 printf(" leave userconf");
555 printf(" don't know");
570 while (cfdata
[i
].cf_name
!= NULL
) {
580 userconf_common_dev(char *dev
, int len
, short unit
, short state
, char routine
)
592 while (cfdata
[i
].cf_name
!= NULL
) {
593 if (strlen(cfdata
[i
].cf_name
) == len
) {
596 * Ok, if device name is correct
597 * If state == FSTATE_FOUND, look for "dev"
598 * If state == FSTATE_STAR, look for "dev*"
599 * If state == FSTATE_NOTFOUND, look for "dev0"
601 if (strncasecmp(dev
, cfdata
[i
].cf_name
,
603 (state
== FSTATE_FOUND
||
604 (state
== FSTATE_STAR
&&
605 (cfdata
[i
].cf_fstate
== FSTATE_STAR
||
606 cfdata
[i
].cf_fstate
== FSTATE_DSTAR
)) ||
607 (state
== FSTATE_NOTFOUND
&&
608 cfdata
[i
].cf_unit
== unit
&&
609 (cfdata
[i
].cf_fstate
== FSTATE_NOTFOUND
||
610 cfdata
[i
].cf_fstate
== FSTATE_DNOTFOUND
)))) {
627 printf("Unknown routine /%c/\n",
647 userconf_add_read(char *prompt
, char field
, char *dev
, int len
, int *val
)
656 printf("%s ? ", prompt
);
658 getsn(userconf_argbuf
, sizeof(userconf_argbuf
));
661 while (*c
== ' ' || *c
== '\t' || *c
== '\n') c
++;
664 if (userconf_number(c
, &a
) == 0) {
665 if (a
> userconf_maxdev
) {
666 printf("Unknown devno (max is %d)\n",
668 } else if (strncasecmp(dev
,
669 cfdata
[a
].cf_name
, len
) != 0 &&
671 printf("Not same device type\n");
676 } else if (*c
== '?') {
677 userconf_common_dev(dev
, len
, 0,
678 FSTATE_FOUND
, UC_FIND
);
679 } else if (*c
== 'q' || *c
== 'Q') {
682 printf("Unknown argument\n");
692 userconf_parse(char *cmd
)
695 int i
= 0, j
= 0, k
, a
;
699 while (*c
== ' ' || *c
== '\t')
702 while (*c
!= ' ' && *c
!= '\t' && *c
!= '\n' && *c
!= '\0') {
708 while (*userconf_cmds
[j
] != '\0') {
709 if (strlen(userconf_cmds
[j
]) == i
) {
710 if (strncasecmp(v
, userconf_cmds
[j
], i
) == 0)
716 while (*c
== ' ' || *c
== '\t' || *c
== '\n')
721 printf("Unknown command, try help\n");
723 switch (*userconf_cmds
[k
+1]) {
726 printf("Argument expected\n");
727 else if (userconf_number(c
, &a
) == 0)
730 printf("Unknown argument\n");
734 printf("8|10|16 expected\n");
735 else if (userconf_number(c
, &a
) == 0) {
736 if (a
== 8 || a
== 10 || a
== 16) {
739 printf("8|10|16 expected\n");
742 printf("Unknown argument\n");
746 printf("DevNo or Dev expected\n");
747 else if (userconf_number(c
, &a
) == 0)
749 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
750 userconf_common_dev(c
, a
, unit
, state
, UC_CHANGE
);
752 printf("Unknown argument\n");
756 printf("Attr, DevNo or Dev expected\n");
757 else if (userconf_number(c
, &a
) == 0)
759 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
760 userconf_common_dev(c
, a
, unit
, state
, UC_DISABLE
);
762 printf("Unknown argument\n");
766 printf("Attr, DevNo or Dev expected\n");
767 else if (userconf_number(c
, &a
) == 0)
769 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
770 userconf_common_dev(c
, a
, unit
, state
, UC_ENABLE
);
772 printf("Unknown argument\n");
776 printf("DevNo or Dev expected\n");
777 else if (userconf_number(c
, &a
) == 0)
779 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
780 userconf_common_dev(c
, a
, unit
, state
, UC_FIND
);
782 printf("Unknown argument\n");
791 printf("Unknown argument\n");
794 /* XXX add cmd 'q' eoc */
795 userconf_hist_cmd('q');
800 printf("Unknown command\n");
807 extern void user_config(void);
812 char prompt
[] = "uc> ";
815 printf("userconf: configure system autoconfiguration:\n");
819 if (getsn(userconf_cmdbuf
, sizeof(userconf_cmdbuf
)) > 0 &&
820 userconf_parse(userconf_cmdbuf
))
823 printf("Continuing...\n");
827 * XXX shouldn't this be a common function?
830 getsn(char *cp
, int size
)
864 if (len
+ 1 >= size
|| c
< ' ') {