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