1 /* $NetBSD: subr_userconf.c,v 1.18 2005/12/11 12:24:30 christos 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.
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
28 * OpenBSD: subr_userconf.c,v 1.19 2000/01/08 23:23:37 d Exp
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: subr_userconf.c,v 1.18 2005/12/11 12:24:30 christos Exp $");
34 #include "opt_userconf.h"
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
44 extern struct cfdata cfdata
[];
46 static int userconf_base
= 16; /* Base for "large" numbers */
47 static int userconf_maxdev
= -1; /* # of used device slots */
48 static int userconf_totdev
= -1; /* # of device slots */
50 static int userconf_maxlocnames
= -1; /* # of locnames */
52 static int userconf_cnt
= -1; /* Line counter for ... */
53 static int userconf_lines
= 12; /* ... # of lines per page */
54 static int userconf_histlen
= 0;
55 static int userconf_histcur
= 0;
56 static char userconf_history
[1024];
57 static int userconf_histsz
= sizeof(userconf_history
);
58 static char userconf_argbuf
[40]; /* Additional input */
59 static char userconf_cmdbuf
[40]; /* Command line */
60 static char userconf_histbuf
[40];
62 static int getsn(char *, int);
65 #define UC_DISABLE 'd'
70 static const char *userconf_cmds
[] = {
92 for (cf
= cfdata
; cf
->cf_name
; cf
++)
95 userconf_maxdev
= i
- 1;
96 userconf_totdev
= i
- 1;
105 if (userconf_cnt
!= -1) {
106 if (userconf_cnt
== userconf_lines
) {
107 printf("-- more --");
113 if (c
== 'q' || c
== 'Q')
120 userconf_hist_cmd(char cmd
)
122 userconf_histcur
= userconf_histlen
;
123 if (userconf_histcur
< userconf_histsz
) {
124 userconf_history
[userconf_histcur
] = cmd
;
130 userconf_hist_int(int val
)
132 snprintf(userconf_histbuf
, sizeof(userconf_histbuf
), " %d", val
);
133 if ((userconf_histcur
+ strlen(userconf_histbuf
)) < userconf_histsz
) {
134 memcpy(&userconf_history
[userconf_histcur
],
136 strlen(userconf_histbuf
));
137 userconf_histcur
= userconf_histcur
+ strlen(userconf_histbuf
);
142 userconf_hist_eoc(void)
144 if (userconf_histcur
< userconf_histsz
) {
145 userconf_history
[userconf_histcur
] = '\n';
147 userconf_histlen
= userconf_histcur
;
152 userconf_pnum(int val
)
154 if (val
> -2 && val
< 16) {
157 switch (userconf_base
) {
173 userconf_pdevnam(short dev
)
178 printf("%s", cd
->cf_name
);
179 switch (cd
->cf_fstate
) {
180 case FSTATE_NOTFOUND
:
181 case FSTATE_DNOTFOUND
:
182 printf("%d", cd
->cf_unit
);
198 userconf_pdev(short devno
)
201 const struct cfparent
*cfp
;
203 const struct cfiattrdata
*ia
;
204 const struct cflocdesc
*ld
;
207 if (devno
> userconf_maxdev
) {
208 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
214 printf("[%3d] ", devno
);
215 userconf_pdevnam(devno
);
220 else if (cfp
->cfp_parent
!= NULL
&& cfp
->cfp_unit
!= -1)
221 printf(" %s%d", cfp
->cfp_parent
, cfp
->cfp_unit
);
223 printf(" %s?", cfp
->cfp_parent
!= NULL
? cfp
->cfp_parent
225 switch (cd
->cf_fstate
) {
226 case FSTATE_NOTFOUND
:
230 case FSTATE_DNOTFOUND
:
240 ia
= cfiattr_lookup(cfp
->cfp_iattr
, 0);
244 for (i
= 0; i
< nld
; i
++) {
245 printf(" %s ", ld
[i
].cld_name
);
246 if (!ld
[i
].cld_defaultstr
247 || (l
[i
] != ld
[i
].cld_default
))
257 userconf_number(char *c
, int *val
)
270 if (*c
== 'x' || *c
== 'X') {
275 while (*c
!= '\n' && *c
!= '\t' && *c
!= ' ' && *c
!= '\0') {
278 if (cc
>= '0' && cc
<= '9')
280 else if (cc
>= 'a' && cc
<= 'f')
282 else if (cc
>= 'A' && cc
<= 'F')
289 num
= num
* base
+ cc
;
293 if (neg
&& num
> INT_MAX
) /* overflow */
295 *val
= neg
? - num
: num
;
300 userconf_device(char *cmd
, int *len
, short *unit
, short *state
)
302 short u
= 0, s
= FSTATE_FOUND
;
307 while (*c
>= 'a' && *c
<= 'z') {
315 while (*c
>= '0' && *c
<= '9') {
321 while (*c
== ' ' || *c
== '\t' || *c
== '\n')
335 userconf_modify(const struct cflocdesc
*item
, int *val
)
342 printf("%s [", item
->cld_name
);
343 if (item
->cld_defaultstr
&& (*val
== item
->cld_default
))
349 getsn(userconf_argbuf
, sizeof(userconf_argbuf
));
352 while (*c
== ' ' || *c
== '\t' || *c
== '\n') c
++;
356 if (item
->cld_defaultstr
) {
357 *val
= item
->cld_default
;
360 printf("No default\n");
361 } else if (userconf_number(c
, &a
) == 0) {
365 printf("Unknown argument\n");
374 userconf_change(int devno
)
380 const struct cfiattrdata
*ia
;
381 const struct cflocdesc
*ld
;
384 if (devno
<= userconf_maxdev
) {
386 userconf_pdev(devno
);
388 while (c
!= 'y' && c
!= 'Y' && c
!= 'n' && c
!= 'N') {
389 printf("change (y/n) ?");
394 if (c
== 'y' || c
== 'Y') {
396 /* XXX add cmd 'c' <devno> */
397 userconf_hist_cmd('c');
398 userconf_hist_int(devno
);
402 ia
= cfiattr_lookup(cd
->cf_pspec
->cfp_iattr
, 0);
407 for (ln
= 0; ln
< nld
; ln
++)
409 userconf_modify(&ld
[ln
], l
);
412 userconf_hist_int(*l
);
417 printf("[%3d] ", devno
);
418 userconf_pdevnam(devno
);
419 printf(" changed\n");
420 userconf_pdev(devno
);
427 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
432 userconf_disable(int devno
)
436 if (devno
<= userconf_maxdev
) {
437 switch (cfdata
[devno
].cf_fstate
) {
438 case FSTATE_NOTFOUND
:
439 cfdata
[devno
].cf_fstate
= FSTATE_DNOTFOUND
;
442 cfdata
[devno
].cf_fstate
= FSTATE_DSTAR
;
444 case FSTATE_DNOTFOUND
:
449 printf("Error unknown state\n");
453 printf("[%3d] ", devno
);
454 userconf_pdevnam(devno
);
458 /* XXX add cmd 'd' <devno> eoc */
459 userconf_hist_cmd('d');
460 userconf_hist_int(devno
);
463 printf(" disabled\n");
465 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
470 userconf_enable(int devno
)
474 if (devno
<= userconf_maxdev
) {
475 switch (cfdata
[devno
].cf_fstate
) {
476 case FSTATE_DNOTFOUND
:
477 cfdata
[devno
].cf_fstate
= FSTATE_NOTFOUND
;
480 cfdata
[devno
].cf_fstate
= FSTATE_STAR
;
482 case FSTATE_NOTFOUND
:
487 printf("Error unknown state\n");
491 printf("[%3d] ", devno
);
492 userconf_pdevnam(devno
);
496 /* XXX add cmd 'e' <devno> eoc */
497 userconf_hist_cmd('d');
498 userconf_hist_int(devno
);
501 printf(" enabled\n");
503 printf("Unknown devno (max is %d)\n", userconf_maxdev
);
512 printf("command args description\n");
513 while (*userconf_cmds
[j
] != '\0') {
514 printf(userconf_cmds
[j
]);
515 k
= strlen(userconf_cmds
[j
]);
520 switch (*userconf_cmds
[j
+1]) {
522 printf("[count] number of lines before more");
525 printf("8|10|16 base on large numbers");
528 printf("devno|dev change devices");
531 printf("devno|dev disable devices");
534 printf("devno|dev enable devices");
537 printf("devno|dev find devices");
540 printf(" this message");
543 printf(" list configuration");
546 printf(" leave userconf");
549 printf(" don't know");
564 while (cfdata
[i
].cf_name
!= NULL
) {
574 userconf_common_dev(char *dev
, int len
, short unit
, short state
, char routine
)
586 while (cfdata
[i
].cf_name
!= NULL
) {
587 if (strlen(cfdata
[i
].cf_name
) == len
) {
590 * Ok, if device name is correct
591 * If state == FSTATE_FOUND, look for "dev"
592 * If state == FSTATE_STAR, look for "dev*"
593 * If state == FSTATE_NOTFOUND, look for "dev0"
595 if (strncasecmp(dev
, cfdata
[i
].cf_name
,
597 (state
== FSTATE_FOUND
||
598 (state
== FSTATE_STAR
&&
599 (cfdata
[i
].cf_fstate
== FSTATE_STAR
||
600 cfdata
[i
].cf_fstate
== FSTATE_DSTAR
)) ||
601 (state
== FSTATE_NOTFOUND
&&
602 cfdata
[i
].cf_unit
== unit
&&
603 (cfdata
[i
].cf_fstate
== FSTATE_NOTFOUND
||
604 cfdata
[i
].cf_fstate
== FSTATE_DNOTFOUND
)))) {
621 printf("Unknown routine /%c/\n",
641 userconf_add_read(char *prompt
, char field
, char *dev
, int len
, int *val
)
650 printf("%s ? ", prompt
);
652 getsn(userconf_argbuf
, sizeof(userconf_argbuf
));
655 while (*c
== ' ' || *c
== '\t' || *c
== '\n') c
++;
658 if (userconf_number(c
, &a
) == 0) {
659 if (a
> userconf_maxdev
) {
660 printf("Unknown devno (max is %d)\n",
662 } else if (strncasecmp(dev
,
663 cfdata
[a
].cf_name
, len
) != 0 &&
665 printf("Not same device type\n");
670 } else if (*c
== '?') {
671 userconf_common_dev(dev
, len
, 0,
672 FSTATE_FOUND
, UC_FIND
);
673 } else if (*c
== 'q' || *c
== 'Q') {
676 printf("Unknown argument\n");
686 userconf_parse(char *cmd
)
689 int i
= 0, j
= 0, k
, a
;
693 while (*c
== ' ' || *c
== '\t')
696 while (*c
!= ' ' && *c
!= '\t' && *c
!= '\n' && *c
!= '\0') {
702 while (*userconf_cmds
[j
] != '\0') {
703 if (strlen(userconf_cmds
[j
]) == i
) {
704 if (strncasecmp(v
, userconf_cmds
[j
], i
) == 0)
710 while (*c
== ' ' || *c
== '\t' || *c
== '\n')
715 printf("Unknown command, try help\n");
717 switch (*userconf_cmds
[k
+1]) {
720 printf("Argument expected\n");
721 else if (userconf_number(c
, &a
) == 0)
724 printf("Unknown argument\n");
728 printf("8|10|16 expected\n");
729 else if (userconf_number(c
, &a
) == 0) {
730 if (a
== 8 || a
== 10 || a
== 16) {
733 printf("8|10|16 expected\n");
736 printf("Unknown argument\n");
740 printf("DevNo or Dev expected\n");
741 else if (userconf_number(c
, &a
) == 0)
743 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
744 userconf_common_dev(c
, a
, unit
, state
, UC_CHANGE
);
746 printf("Unknown argument\n");
750 printf("Attr, DevNo or Dev expected\n");
751 else if (userconf_number(c
, &a
) == 0)
753 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
754 userconf_common_dev(c
, a
, unit
, state
, UC_DISABLE
);
756 printf("Unknown argument\n");
760 printf("Attr, DevNo or Dev expected\n");
761 else if (userconf_number(c
, &a
) == 0)
763 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
764 userconf_common_dev(c
, a
, unit
, state
, UC_ENABLE
);
766 printf("Unknown argument\n");
770 printf("DevNo or Dev expected\n");
771 else if (userconf_number(c
, &a
) == 0)
773 else if (userconf_device(c
, &a
, &unit
, &state
) == 0)
774 userconf_common_dev(c
, a
, unit
, state
, UC_FIND
);
776 printf("Unknown argument\n");
785 printf("Unknown argument\n");
788 /* XXX add cmd 'q' eoc */
789 userconf_hist_cmd('q');
794 printf("Unknown command\n");
801 extern void user_config(void);
806 char prompt
[] = "uc> ";
809 printf("userconf: configure system autoconfiguration:\n");
813 if (getsn(userconf_cmdbuf
, sizeof(userconf_cmdbuf
)) > 0 &&
814 userconf_parse(userconf_cmdbuf
))
817 printf("Continuing...\n");
821 * XXX shouldn't this be a common function?
824 getsn(char *cp
, int size
)
858 if (len
+ 1 >= size
|| c
< ' ') {