Annotation of sys/kern/subr_userconf.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: subr_userconf.c,v 1.34 2005/12/09 09:09:52 jsg Exp $ */
2:
3: /*
4: * Copyright (c) 1996-2001 Mats O Jansson <moj@stacken.kth.se>
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: #include <sys/param.h>
30: #include <sys/systm.h>
31: #include <sys/device.h>
32: #include <sys/malloc.h>
33: #include <sys/time.h>
34:
35: #include <dev/cons.h>
36:
37: extern char *locnames[];
38: extern short locnamp[];
39: extern short cfroots[];
40: extern int cfroots_size;
41: extern int pv_size;
42: extern short pv[];
43: extern struct timezone tz;
44: extern char *pdevnames[];
45: extern int pdevnames_size;
46: extern struct pdevinit pdevinit[];
47:
48: int userconf_base = 16; /* Base for "large" numbers */
49: int userconf_maxdev = -1; /* # of used device slots */
50: int userconf_totdev = -1; /* # of device slots */
51: int userconf_maxlocnames = -1; /* # of locnames */
52: int userconf_cnt = -1; /* Line counter for ... */
53: int userconf_lines = 12; /* ... # of lines per page */
54: int userconf_histlen = 0;
55: int userconf_histcur = 0;
56: char userconf_history[1024];
57: int userconf_histsz = sizeof(userconf_history);
58: char userconf_argbuf[40]; /* Additional input */
59: char userconf_cmdbuf[40]; /* Command line */
60: char userconf_histbuf[40];
61:
62: void userconf_init(void);
63: int userconf_more(void);
64: void userconf_modify(char *, int *);
65: void userconf_hist_cmd(char);
66: void userconf_hist_int(int);
67: void userconf_hist_eoc(void);
68: void userconf_pnum(int);
69: void userconf_pdevnam(short);
70: void userconf_pdev(short);
71: int userconf_number(char *, int *);
72: int userconf_device(char *, int *, short *, short *);
73: int userconf_attr(char *, int *);
74: void userconf_modify(char *, int *);
75: void userconf_change(int);
76: void userconf_disable(int);
77: void userconf_enable(int);
78: void userconf_help(void);
79: void userconf_list(void);
80: void userconf_show(void);
81: void userconf_common_attr_val(short, int *, char);
82: void userconf_show_attr(char *);
83: void userconf_common_dev(char *, int, short, short, char);
84: void userconf_common_attr(char *, int, char);
85: void userconf_add_read(char *, char, char *, int, int *);
86: void userconf_add(char *, int, short, short);
87: int userconf_parse(char *);
88:
89: #define UC_CHANGE 'c'
90: #define UC_DISABLE 'd'
91: #define UC_ENABLE 'e'
92: #define UC_FIND 'f'
93: #define UC_SHOW 's'
94:
95: char *userconf_cmds[] = {
96: "add", "a",
97: "base", "b",
98: "change", "c",
99: #if defined(DDB)
100: "ddb", "D",
101: #endif
102: "disable", "d",
103: "enable", "e",
104: "exit", "q",
105: "find", "f",
106: "help", "h",
107: "list", "l",
108: "lines", "L",
109: "quit", "q",
110: "show", "s",
111: "timezone", "t",
112: "verbose", "v",
113: "?", "h",
114: "", "",
115: };
116:
117: void
118: userconf_init(void)
119: {
120: int i = 0;
121: struct cfdata *cd;
122: int ln;
123:
124: while (cfdata[i].cf_attach != 0) {
125: userconf_maxdev = i;
126: userconf_totdev = i;
127:
128: cd = &cfdata[i];
129: ln = cd->cf_locnames;
130: while (locnamp[ln] != -1) {
131: if (locnamp[ln] > userconf_maxlocnames)
132: userconf_maxlocnames = locnamp[ln];
133: ln++;
134: }
135: i++;
136: }
137:
138: while (cfdata[i].cf_attach == 0) {
139: userconf_totdev = i;
140: i++;
141: }
142: userconf_totdev = userconf_totdev - 1;
143: }
144:
145: int
146: userconf_more(void)
147: {
148: int quit = 0;
149: char c = '\0';
150:
151: if (userconf_cnt != -1) {
152: if (userconf_cnt == userconf_lines) {
153: printf("--- more ---");
154: c = cngetc();
155: userconf_cnt = 0;
156: printf("\r \r");
157: }
158: userconf_cnt++;
159: if (c == 'q' || c == 'Q')
160: quit = 1;
161: }
162: return (quit);
163: }
164:
165: void
166: userconf_hist_cmd(char cmd)
167: {
168: userconf_histcur = userconf_histlen;
169: if (userconf_histcur < userconf_histsz) {
170: userconf_history[userconf_histcur] = cmd;
171: userconf_histcur++;
172: }
173: }
174:
175: void
176: userconf_hist_int(int val)
177: {
178: snprintf(userconf_histbuf, sizeof userconf_histbuf, " %d",val);
179: if (userconf_histcur + strlen(userconf_histbuf) < userconf_histsz) {
180: bcopy(userconf_histbuf,
181: &userconf_history[userconf_histcur],
182: strlen(userconf_histbuf));
183: userconf_histcur = userconf_histcur + strlen(userconf_histbuf);
184: }
185: }
186:
187: void
188: userconf_hist_eoc(void)
189: {
190: if (userconf_histcur < userconf_histsz) {
191: userconf_history[userconf_histcur] = '\n';
192: userconf_histcur++;
193: userconf_histlen = userconf_histcur;
194: }
195: }
196:
197: void
198: userconf_pnum(int val)
199: {
200: if (val > -2 && val < 16) {
201: printf("%d",val);
202: return;
203: }
204:
205: switch (userconf_base) {
206: case 8:
207: printf("0%o",val);
208: break;
209: case 10:
210: printf("%d",val);
211: break;
212: case 16:
213: default:
214: printf("0x%x",val);
215: break;
216: }
217: }
218:
219: void
220: userconf_pdevnam(short dev)
221: {
222: struct cfdata *cd;
223:
224: cd = &cfdata[dev];
225: printf("%s", cd->cf_driver->cd_name);
226: switch (cd->cf_fstate) {
227: case FSTATE_NOTFOUND:
228: case FSTATE_DNOTFOUND:
229: printf("%d", cd->cf_unit);
230: break;
231: case FSTATE_FOUND:
232: printf("*FOUND*");
233: break;
234: case FSTATE_STAR:
235: case FSTATE_DSTAR:
236: printf("*");
237: break;
238: default:
239: printf("*UNKNOWN*");
240: break;
241: }
242: }
243:
244: void
245: userconf_pdev(short devno)
246: {
247: struct cfdata *cd;
248: short *p;
249: int *l;
250: int ln;
251: char c;
252:
253: if (devno > userconf_maxdev && devno <= userconf_totdev) {
254: printf("%3d free slot (for add)\n", devno);
255: return;
256: }
257:
258: if (devno > userconf_totdev &&
259: devno <= userconf_totdev+pdevnames_size) {
260: printf("%3d %s count %d (pseudo device)\n", devno,
261: pdevnames[devno-userconf_totdev-1],
262: pdevinit[devno-userconf_totdev-1].pdev_count);
263: return;
264: }
265:
266: if (devno > userconf_maxdev) {
267: printf("Unknown devno (max is %d)\n", userconf_maxdev);
268: return;
269: }
270:
271: cd = &cfdata[devno];
272:
273: printf("%3d ", devno);
274: userconf_pdevnam(devno);
275: printf(" at");
276: c = ' ';
277: p = cd->cf_parents;
278: if (*p == -1)
279: printf(" root");
280: while (*p != -1) {
281: printf("%c", c);
282: userconf_pdevnam(*p++);
283: c = '|';
284: }
285: switch (cd->cf_fstate) {
286: case FSTATE_NOTFOUND:
287: case FSTATE_FOUND:
288: case FSTATE_STAR:
289: break;
290: case FSTATE_DNOTFOUND:
291: case FSTATE_DSTAR:
292: printf(" disable");
293: break;
294: default:
295: printf(" ???");
296: break;
297: }
298: l = cd->cf_loc;
299: ln = cd->cf_locnames;
300: while (locnamp[ln] != -1) {
301: printf(" %s ", locnames[locnamp[ln]]);
302: ln++;
303: userconf_pnum(*l++);
304: }
305: printf(" flags 0x%x\n", cd->cf_flags);
306: }
307:
308: int
309: userconf_number(char *c, int *val)
310: {
311: u_int num = 0;
312: int neg = 0;
313: int base = 10;
314:
315: if (*c == '-') {
316: neg = 1;
317: c++;
318: }
319: if (*c == '0') {
320: base = 8;
321: c++;
322: if (*c == 'x' || *c == 'X') {
323: base = 16;
324: c++;
325: }
326: }
327: while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') {
328: u_char cc = *c;
329:
330: if (cc >= '0' && cc <= '9')
331: cc = cc - '0';
332: else if (cc >= 'a' && cc <= 'f')
333: cc = cc - 'a' + 10;
334: else if (cc >= 'A' && cc <= 'F')
335: cc = cc - 'A' + 10;
336: else
337: return (-1);
338:
339: if (cc > base)
340: return (-1);
341: num = num * base + cc;
342: c++;
343: }
344:
345: if (neg && num > INT_MAX) /* overflow */
346: return (1);
347: *val = neg ? - num : num;
348: return (0);
349: }
350:
351: int
352: userconf_device(char *cmd, int *len, short *unit, short *state)
353: {
354: short u = 0, s = FSTATE_FOUND;
355: int l = 0;
356: char *c;
357:
358: c = cmd;
359: while (*c >= 'a' && *c <= 'z') {
360: l++;
361: c++;
362: }
363: if (*c == '*') {
364: s = FSTATE_STAR;
365: c++;
366: } else {
367: while (*c >= '0' && *c <= '9') {
368: s = FSTATE_NOTFOUND;
369: u = u*10 + *c - '0';
370: c++;
371: }
372: }
373: while (*c == ' ' || *c == '\t' || *c == '\n')
374: c++;
375:
376: if (*c == '\0') {
377: *len = l;
378: *unit = u;
379: *state = s;
380: return(0);
381: }
382:
383: return(-1);
384: }
385:
386: int
387: userconf_attr(char *cmd, int *val)
388: {
389: char *c;
390: short attr = -1, i = 0, l = 0;
391:
392: c = cmd;
393: while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
394: c++;
395: l++;
396: }
397:
398: while (i <= userconf_maxlocnames) {
399: if (strlen(locnames[i]) == l) {
400: if (strncasecmp(cmd, locnames[i], l) == 0)
401: attr = i;
402: }
403: i++;
404: }
405:
406: if (attr == -1) {
407: return (-1);
408: }
409:
410: *val = attr;
411:
412: return(0);
413: }
414:
415: void
416: userconf_modify(char *item, int *val)
417: {
418: int ok = 0;
419: int a;
420: char *c;
421: int i;
422:
423: while (!ok) {
424: printf("%s [", item);
425: userconf_pnum(*val);
426: printf("] ? ");
427:
428: i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
429:
430: c = userconf_argbuf;
431: while (*c == ' ' || *c == '\t' || *c == '\n') c++;
432:
433: if (*c != '\0') {
434: if (userconf_number(c, &a) == 0) {
435: *val = a;
436: ok = 1;
437: } else {
438: printf("Unknown argument\n");
439: }
440: } else {
441: ok = 1;
442: }
443: }
444: }
445:
446: void
447: userconf_change(int devno)
448: {
449: struct cfdata *cd;
450: char c = '\0';
451: int *l;
452: int ln;
453:
454: if (devno <= userconf_maxdev) {
455: userconf_pdev(devno);
456:
457: while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
458: printf("change (y/n) ?");
459: c = cngetc();
460: printf("\n");
461: }
462:
463: if (c == 'y' || c == 'Y') {
464: int share = 0, i, *lk;
465:
466: /* XXX add cmd 'c' <devno> */
467: userconf_hist_cmd('c');
468: userconf_hist_int(devno);
469:
470: cd = &cfdata[devno];
471: l = cd->cf_loc;
472: ln = cd->cf_locnames;
473:
474: /*
475: * Search for some other driver sharing this
476: * locator table. if one does, we may need to
477: * replace the locators with a malloc'd copy.
478: */
479: for (i = 0; cfdata[i].cf_driver; i++)
480: if (i != devno && cfdata[i].cf_loc == l)
481: share = 1;
482: if (share) {
483: for (i = 0; locnamp[ln+i] != -1 ; i++)
484: ;
485: lk = l = (int *)malloc(sizeof(int) * i,
486: M_TEMP, M_NOWAIT);
487: if (lk == NULL) {
488: printf("out of memory.\n");
489: return;
490: }
491: bcopy(cd->cf_loc, l, sizeof(int) * i);
492: }
493:
494: while (locnamp[ln] != -1) {
495: userconf_modify(locnames[locnamp[ln]], l);
496:
497: /* XXX add *l */
498: userconf_hist_int(*l);
499:
500: ln++;
501: l++;
502: }
503: userconf_modify("flags", &cd->cf_flags);
504: userconf_hist_int(cd->cf_flags);
505:
506: if (share) {
507: if (bcmp(cd->cf_loc, lk, sizeof(int) * i))
508: cd->cf_loc = lk;
509: else
510: free(lk, M_TEMP);
511: }
512:
513: printf("%3d ", devno);
514: userconf_pdevnam(devno);
515: printf(" changed\n");
516: userconf_pdev(devno);
517: }
518: return;
519: }
520:
521: if (devno > userconf_maxdev && devno <= userconf_totdev) {
522: printf("%3d can't change free slot\n", devno);
523: return;
524: }
525:
526: if (devno > userconf_totdev &&
527: devno <= userconf_totdev+pdevnames_size) {
528: userconf_pdev(devno);
529: while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
530: printf("change (y/n) ?");
531: c = cngetc();
532: printf("\n");
533: }
534:
535: if (c == 'y' || c == 'Y') {
536: /* XXX add cmd 'c' <devno> */
537: userconf_hist_cmd('c');
538: userconf_hist_int(devno);
539:
540: userconf_modify("count",
541: &pdevinit[devno-userconf_totdev-1].pdev_count);
542: userconf_hist_int(pdevinit[devno-userconf_totdev-1].pdev_count);
543:
544: printf("%3d %s changed\n", devno,
545: pdevnames[devno-userconf_totdev-1]);
546: userconf_pdev(devno);
547:
548: /* XXX add eoc */
549: userconf_hist_eoc();
550: }
551: return;
552: }
553:
554: printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
555: }
556:
557: void
558: userconf_disable(int devno)
559: {
560: int done = 0;
561:
562: if (devno <= userconf_maxdev) {
563: switch (cfdata[devno].cf_fstate) {
564: case FSTATE_NOTFOUND:
565: cfdata[devno].cf_fstate = FSTATE_DNOTFOUND;
566: break;
567: case FSTATE_STAR:
568: cfdata[devno].cf_fstate = FSTATE_DSTAR;
569: break;
570: case FSTATE_DNOTFOUND:
571: case FSTATE_DSTAR:
572: done = 1;
573: break;
574: default:
575: printf("Error unknown state\n");
576: break;
577: }
578:
579: printf("%3d ", devno);
580: userconf_pdevnam(devno);
581: if (done) {
582: printf(" already");
583: } else {
584: /* XXX add cmd 'd' <devno> eoc */
585: userconf_hist_cmd('d');
586: userconf_hist_int(devno);
587: userconf_hist_eoc();
588: }
589: printf(" disabled\n");
590:
591: return;
592: }
593:
594: if (devno > userconf_maxdev && devno <= userconf_totdev) {
595: printf("%3d can't disable free slot\n", devno);
596: return;
597: }
598:
599: if (devno > userconf_totdev &&
600: devno <= userconf_totdev+pdevnames_size) {
601: printf("%3d %s can't disable pseudo device\n", devno,
602: pdevnames[devno-userconf_totdev-1]);
603: return;
604: }
605:
606: printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
607: }
608:
609: void
610: userconf_enable(int devno)
611: {
612: int done = 0;
613:
614: if (devno <= userconf_maxdev) {
615: switch (cfdata[devno].cf_fstate) {
616: case FSTATE_DNOTFOUND:
617: cfdata[devno].cf_fstate = FSTATE_NOTFOUND;
618: break;
619: case FSTATE_DSTAR:
620: cfdata[devno].cf_fstate = FSTATE_STAR;
621: break;
622: case FSTATE_NOTFOUND:
623: case FSTATE_STAR:
624: done = 1;
625: break;
626: default:
627: printf("Error unknown state\n");
628: break;
629: }
630:
631: printf("%3d ", devno);
632: userconf_pdevnam(devno);
633: if (done) {
634: printf(" already");
635: } else {
636: /* XXX add cmd 'e' <devno> eoc */
637: userconf_hist_cmd('e');
638: userconf_hist_int(devno);
639: userconf_hist_eoc();
640: }
641: printf(" enabled\n");
642: return;
643: }
644:
645: if (devno > userconf_maxdev && devno <= userconf_totdev) {
646: printf("%3d can't enable free slot\n", devno);
647: return;
648: }
649:
650: if (devno > userconf_totdev &&
651: devno <= userconf_totdev+pdevnames_size) {
652: printf("%3d %s can't enable pseudo device\n", devno,
653: pdevnames[devno-userconf_totdev-1]);
654: return;
655: }
656:
657: printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
658: }
659:
660: void
661: userconf_help(void)
662: {
663: int j = 0, k;
664:
665: printf("command args description\n");
666: while (*userconf_cmds[j] != '\0') {
667: printf(userconf_cmds[j]);
668: k = strlen(userconf_cmds[j]);
669: while (k < 10) {
670: printf(" ");
671: k++;
672: }
673: switch (*userconf_cmds[j+1]) {
674: case 'L':
675: printf("[count] number of lines before more");
676: break;
677: case 'a':
678: printf("dev add a device");
679: break;
680: case 'b':
681: printf("8|10|16 base on large numbers");
682: break;
683: case 'c':
684: printf("devno|dev change devices");
685: break;
686: #if defined(DDB)
687: case 'D':
688: printf(" enter ddb");
689: break;
690: #endif
691: case 'd':
692: printf("attr val|devno|dev disable devices");
693: break;
694: case 'e':
695: printf("attr val|devno|dev enable devices");
696: break;
697: case 'f':
698: printf("devno|dev find devices");
699: break;
700: case 'h':
701: printf(" this message");
702: break;
703: case 'l':
704: printf(" list configuration");
705: break;
706: case 'q':
707: printf(" leave UKC");
708: break;
709: case 's':
710: printf("[attr [val]] "
711: "show attributes (or devices with an attribute)");
712: break;
713: case 't':
714: printf("[mins [dst]] set timezone/dst");
715: break;
716: case 'v':
717: printf(" toggle verbose booting");
718: break;
719: default:
720: printf(" don't know");
721: break;
722: }
723: printf("\n");
724: j += 2;
725: }
726: }
727:
728: void
729: userconf_list(void)
730: {
731: int i = 0;
732:
733: userconf_cnt = 0;
734:
735: while (i <= (userconf_totdev+pdevnames_size)) {
736: if (userconf_more())
737: break;
738: userconf_pdev(i++);
739: }
740:
741: userconf_cnt = -1;
742: }
743:
744: void
745: userconf_show(void)
746: {
747: int i = 0;
748:
749: userconf_cnt = 0;
750:
751: while (i <= userconf_maxlocnames) {
752: if (userconf_more())
753: break;
754: printf("%s\n", locnames[i++]);
755: }
756:
757: userconf_cnt = -1;
758: }
759:
760: void
761: userconf_common_attr_val(short attr, int *val, char routine)
762: {
763: struct cfdata *cd;
764: int *l;
765: int ln;
766: int i = 0, quit = 0;
767:
768: userconf_cnt = 0;
769:
770: while (i <= userconf_maxdev) {
771: cd = &cfdata[i];
772: l = cd->cf_loc;
773: ln = cd->cf_locnames;
774: while (locnamp[ln] != -1) {
775: if (locnamp[ln] == attr) {
776: if (val == NULL) {
777: quit = userconf_more();
778: userconf_pdev(i);
779: } else {
780: if (*val == *l) {
781: quit = userconf_more();
782: switch (routine) {
783: case UC_ENABLE:
784: userconf_enable(i);
785: break;
786: case UC_DISABLE:
787: userconf_disable(i);
788: break;
789: case UC_SHOW:
790: userconf_pdev(i);
791: break;
792: default:
793: printf("Unknown routine /%c/\n",
794: routine);
795: break;
796: }
797: }
798: }
799: }
800: if (quit)
801: break;
802: ln++;
803: l++;
804: }
805: if (quit)
806: break;
807: i++;
808: }
809:
810: userconf_cnt = -1;
811: }
812:
813: void
814: userconf_show_attr(char *cmd)
815: {
816: char *c;
817: short attr = -1, i = 0, l = 0;
818: int a;
819:
820: c = cmd;
821: while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
822: c++;
823: l++;
824: }
825: while (*c == ' ' || *c == '\t' || *c == '\n') {
826: c++;
827: }
828: while (i <= userconf_maxlocnames) {
829: if (strlen(locnames[i]) == l) {
830: if (strncasecmp(cmd, locnames[i], l) == 0) {
831: attr = i;
832: }
833: }
834: i++;
835: }
836:
837: if (attr == -1) {
838: printf("Unknown attribute\n");
839: return;
840: }
841:
842: if (*c == '\0') {
843: userconf_common_attr_val(attr, NULL, UC_SHOW);
844: } else {
845: if (userconf_number(c, &a) == 0) {
846: userconf_common_attr_val(attr, &a, UC_SHOW);
847: } else {
848: printf("Unknown argument\n");
849: }
850: }
851: }
852:
853: void
854: userconf_common_dev(char *dev, int len, short unit, short state, char routine)
855: {
856: int i = 0;
857:
858: switch (routine) {
859: case UC_CHANGE:
860: break;
861: default:
862: userconf_cnt = 0;
863: break;
864: }
865:
866: while (cfdata[i].cf_attach != 0) {
867: if (strlen(cfdata[i].cf_driver->cd_name) == len) {
868:
869: /*
870: * Ok, if device name is correct
871: * If state == FSTATE_FOUND, look for "dev"
872: * If state == FSTATE_STAR, look for "dev*"
873: * If state == FSTATE_NOTFOUND, look for "dev0"
874: */
875: if (strncasecmp(dev, cfdata[i].cf_driver->cd_name,
876: len) == 0 &&
877: (state == FSTATE_FOUND ||
878: (state == FSTATE_STAR &&
879: (cfdata[i].cf_fstate == FSTATE_STAR ||
880: cfdata[i].cf_fstate == FSTATE_DSTAR)) ||
881: (state == FSTATE_NOTFOUND &&
882: cfdata[i].cf_unit == unit &&
883: (cfdata[i].cf_fstate == FSTATE_NOTFOUND ||
884: cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) {
885: if (userconf_more())
886: break;
887: switch (routine) {
888: case UC_CHANGE:
889: userconf_change(i);
890: break;
891: case UC_ENABLE:
892: userconf_enable(i);
893: break;
894: case UC_DISABLE:
895: userconf_disable(i);
896: break;
897: case UC_FIND:
898: userconf_pdev(i);
899: break;
900: default:
901: printf("Unknown routine /%c/\n",
902: routine);
903: break;
904: }
905: }
906: }
907: i++;
908: }
909:
910: for (i = 0; i < pdevnames_size; i++) {
911: if (strncasecmp(dev, pdevnames[i], len) == 0 &&
912: state == FSTATE_FOUND) {
913: switch(routine) {
914: case UC_CHANGE:
915: userconf_change(userconf_totdev+1+i);
916: break;
917: case UC_ENABLE:
918: userconf_enable(userconf_totdev+1+i);
919: break;
920: case UC_DISABLE:
921: userconf_disable(userconf_totdev+1+i);
922: break;
923: case UC_FIND:
924: userconf_pdev(userconf_totdev+1+i);
925: break;
926: default:
927: printf("Unknown pseudo routine /%c/\n",routine);
928: break;
929: }
930: }
931: }
932:
933: switch (routine) {
934: case UC_CHANGE:
935: break;
936: default:
937: userconf_cnt = -1;
938: break;
939: }
940: }
941:
942: void
943: userconf_common_attr(char *cmd, int attr, char routine)
944: {
945: char *c;
946: short l = 0;
947: int a;
948:
949: c = cmd;
950: while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
951: c++;
952: l++;
953: }
954: while (*c == ' ' || *c == '\t' || *c == '\n')
955: c++;
956:
957: if (*c == '\0') {
958: printf("Value missing for attribute\n");
959: return;
960: }
961:
962: if (userconf_number(c, &a) == 0) {
963: userconf_common_attr_val(attr, &a, routine);
964: } else {
965: printf("Unknown argument\n");
966: }
967: }
968:
969: void
970: userconf_add_read(char *prompt, char field, char *dev, int len, int *val)
971: {
972: int ok = 0;
973: int a;
974: char *c;
975: int i;
976:
977: *val = -1;
978:
979: while (!ok) {
980: printf("%s ? ", prompt);
981:
982: i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
983:
984: c = userconf_argbuf;
985: while (*c == ' ' || *c == '\t' || *c == '\n')
986: c++;
987:
988: if (*c != '\0') {
989: if (userconf_number(c, &a) == 0) {
990: if (a > userconf_maxdev) {
991: printf("Unknown devno (max is %d)\n",
992: userconf_maxdev);
993: } else if (strncasecmp(dev,
994: cfdata[a].cf_driver->cd_name, len) != 0 &&
995: field == 'a') {
996: printf("Not same device type\n");
997: } else {
998: *val = a;
999: ok = 1;
1000: }
1001: } else if (*c == '?') {
1002: userconf_common_dev(dev, len, 0,
1003: FSTATE_FOUND, UC_FIND);
1004: } else if (*c == 'q' || *c == 'Q') {
1005: ok = 1;
1006: } else {
1007: printf("Unknown argument\n");
1008: }
1009: } else {
1010: ok = 1;
1011: }
1012: }
1013: }
1014:
1015: void
1016: userconf_add(char *dev, int len, short unit, short state)
1017: {
1018: int i = 0, found = 0;
1019: struct cfdata new;
1020: int val, max_unit, star_unit, orig;
1021:
1022: bzero(&new, sizeof(struct cfdata));
1023:
1024: if (userconf_maxdev == userconf_totdev) {
1025: printf("No more space for new devices.\n");
1026: return;
1027: }
1028:
1029: if (state == FSTATE_FOUND) {
1030: printf("Device not complete number or * is missing\n");
1031: return;
1032: }
1033:
1034: for (i = 0; cfdata[i].cf_driver; i++)
1035: if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1036: strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0)
1037: found = 1;
1038:
1039: if (!found) {
1040: printf("No device of this type exists.\n");
1041: return;
1042: }
1043:
1044: userconf_add_read("Clone Device (DevNo, 'q' or '?')",
1045: 'a', dev, len, &val);
1046:
1047: if (val != -1) {
1048: orig = val;
1049: new = cfdata[val];
1050: new.cf_unit = unit;
1051: new.cf_fstate = state;
1052: userconf_add_read("Insert before Device (DevNo, 'q' or '?')",
1053: 'i', dev, len, &val);
1054: }
1055:
1056: if (val != -1) {
1057: /* XXX add cmd 'a' <orig> <val> eoc */
1058: userconf_hist_cmd('a');
1059: userconf_hist_int(orig);
1060: userconf_hist_int(unit);
1061: userconf_hist_int(state);
1062: userconf_hist_int(val);
1063: userconf_hist_eoc();
1064:
1065: /* Insert the new record */
1066: for (i = userconf_maxdev; val <= i; i--)
1067: cfdata[i+1] = cfdata[i];
1068: cfdata[val] = new;
1069:
1070: /* Fix indexs in pv */
1071: for (i = 0; i < pv_size; i++) {
1072: if (pv[i] != -1 && pv[i] >= val)
1073: pv[i]++;
1074: }
1075:
1076: /* Fix indexs in cfroots */
1077: for (i = 0; i < cfroots_size; i++) {
1078: if (cfroots[i] != -1 && cfroots[i] >= val)
1079: cfroots[i]++;
1080: }
1081:
1082: userconf_maxdev++;
1083:
1084: max_unit = -1;
1085:
1086: /* Find max unit number of the device type */
1087:
1088: i = 0;
1089: while (cfdata[i].cf_attach != 0) {
1090: if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1091: strncasecmp(dev, cfdata[i].cf_driver->cd_name,
1092: len) == 0) {
1093: switch (cfdata[i].cf_fstate) {
1094: case FSTATE_NOTFOUND:
1095: case FSTATE_DNOTFOUND:
1096: if (cfdata[i].cf_unit > max_unit)
1097: max_unit = cfdata[i].cf_unit;
1098: break;
1099: default:
1100: break;
1101: }
1102: }
1103: i++;
1104: }
1105:
1106: /*
1107: * For all * entries set unit number to max+1, and update
1108: * cf_starunit1 if necessary.
1109: */
1110: max_unit++;
1111: star_unit = -1;
1112:
1113: i = 0;
1114: while (cfdata[i].cf_attach != 0) {
1115: if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1116: strncasecmp(dev, cfdata[i].cf_driver->cd_name,
1117: len) == 0) {
1118: switch (cfdata[i].cf_fstate) {
1119: case FSTATE_NOTFOUND:
1120: case FSTATE_DNOTFOUND:
1121: if (cfdata[i].cf_unit > star_unit)
1122: star_unit = cfdata[i].cf_unit;
1123: break;
1124: default:
1125: break;
1126: }
1127: }
1128: i++;
1129: }
1130: star_unit++;
1131:
1132: i = 0;
1133: while (cfdata[i].cf_attach != 0) {
1134: if (strlen(cfdata[i].cf_driver->cd_name) == len &&
1135: strncasecmp(dev, cfdata[i].cf_driver->cd_name,
1136: len) == 0) {
1137: switch (cfdata[i].cf_fstate) {
1138: case FSTATE_STAR:
1139: case FSTATE_DSTAR:
1140: cfdata[i].cf_unit = max_unit;
1141: if (cfdata[i].cf_starunit1 < star_unit)
1142: cfdata[i].cf_starunit1 =
1143: star_unit;
1144: break;
1145: default:
1146: break;
1147: }
1148: }
1149: i++;
1150: }
1151: userconf_pdev(val);
1152: }
1153:
1154: /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags,
1155: cf_parents, cf_locnames, cf_locnames and cf_ivstubs */
1156: }
1157:
1158: int
1159: userconf_parse(char *cmd)
1160: {
1161: char *c, *v;
1162: int i = 0, j = 0, k, a;
1163: short unit, state;
1164:
1165: c = cmd;
1166: while (*c == ' ' || *c == '\t')
1167: c++;
1168: v = c;
1169: while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
1170: c++;
1171: i++;
1172: }
1173:
1174: k = -1;
1175: while (*userconf_cmds[j] != '\0') {
1176: if (strlen(userconf_cmds[j]) == i) {
1177: if (strncasecmp(v, userconf_cmds[j], i) == 0)
1178: k = j;
1179: }
1180: j += 2;
1181: }
1182:
1183: while (*c == ' ' || *c == '\t' || *c == '\n')
1184: c++;
1185:
1186: if (k == -1) {
1187: if (*v != '\n')
1188: printf("Unknown command, try help\n");
1189: } else {
1190: switch (*userconf_cmds[k+1]) {
1191: case 'L':
1192: if (*c == '\0')
1193: printf("Argument expected\n");
1194: else if (userconf_number(c, &a) == 0)
1195: userconf_lines = a;
1196: else
1197: printf("Unknown argument\n");
1198: break;
1199: case 'a':
1200: if (*c == '\0')
1201: printf("Dev expected\n");
1202: else if (userconf_device(c, &a, &unit, &state) == 0)
1203: userconf_add(c, a, unit, state);
1204: else
1205: printf("Unknown argument\n");
1206: break;
1207: case 'b':
1208: if (*c == '\0')
1209: printf("8|10|16 expected\n");
1210: else if (userconf_number(c, &a) == 0) {
1211: if (a == 8 || a == 10 || a == 16) {
1212: userconf_base = a;
1213: } else {
1214: printf("8|10|16 expected\n");
1215: }
1216: } else
1217: printf("Unknown argument\n");
1218: break;
1219: case 'c':
1220: if (*c == '\0')
1221: printf("DevNo or Dev expected\n");
1222: else if (userconf_number(c, &a) == 0)
1223: userconf_change(a);
1224: else if (userconf_device(c, &a, &unit, &state) == 0)
1225: userconf_common_dev(c, a, unit, state, UC_CHANGE);
1226: else
1227: printf("Unknown argument\n");
1228: break;
1229: #if defined(DDB)
1230: case 'D':
1231: Debugger();
1232: break;
1233: #endif
1234: case 'd':
1235: if (*c == '\0')
1236: printf("Attr, DevNo or Dev expected\n");
1237: else if (userconf_attr(c, &a) == 0)
1238: userconf_common_attr(c, a, UC_DISABLE);
1239: else if (userconf_number(c, &a) == 0)
1240: userconf_disable(a);
1241: else if (userconf_device(c, &a, &unit, &state) == 0)
1242: userconf_common_dev(c, a, unit, state, UC_DISABLE);
1243: else
1244: printf("Unknown argument\n");
1245: break;
1246: case 'e':
1247: if (*c == '\0')
1248: printf("Attr, DevNo or Dev expected\n");
1249: else if (userconf_attr(c, &a) == 0)
1250: userconf_common_attr(c, a, UC_ENABLE);
1251: else if (userconf_number(c, &a) == 0)
1252: userconf_enable(a);
1253: else if (userconf_device(c, &a, &unit, &state) == 0)
1254: userconf_common_dev(c, a, unit, state, UC_ENABLE);
1255: else
1256: printf("Unknown argument\n");
1257: break;
1258: case 'f':
1259: if (*c == '\0')
1260: printf("DevNo or Dev expected\n");
1261: else if (userconf_number(c, &a) == 0)
1262: userconf_pdev(a);
1263: else if (userconf_device(c, &a, &unit, &state) == 0)
1264: userconf_common_dev(c, a, unit, state, UC_FIND);
1265: else
1266: printf("Unknown argument\n");
1267: break;
1268: case 'h':
1269: userconf_help();
1270: break;
1271: case 'l':
1272: if (*c == '\0')
1273: userconf_list();
1274: else
1275: printf("Unknown argument\n");
1276: break;
1277: case 'q':
1278: /* XXX add cmd 'q' eoc */
1279: userconf_hist_cmd('q');
1280: userconf_hist_eoc();
1281: return(-1);
1282: break;
1283: case 's':
1284: if (*c == '\0')
1285: userconf_show();
1286: else
1287: userconf_show_attr(c);
1288: break;
1289: case 't':
1290: if (*c == '\0' || userconf_number(c, &a) == 0) {
1291: if (*c != '\0') {
1292: tz.tz_minuteswest = a;
1293: while (*c != '\n' && *c != '\t' &&
1294: *c != ' ' && *c != '\0')
1295: c++;
1296: while (*c == '\t' || *c == ' ')
1297: c++;
1298: if (*c != '\0' &&
1299: userconf_number(c, &a) == 0)
1300: tz.tz_dsttime = a;
1301: userconf_hist_cmd('t');
1302: userconf_hist_int(tz.tz_minuteswest);
1303: userconf_hist_int(tz.tz_dsttime);
1304: userconf_hist_eoc();
1305: }
1306: printf("timezone = %d, dst = %d\n",
1307: tz.tz_minuteswest, tz.tz_dsttime);
1308: } else
1309: printf("Unknown argument\n");
1310: break;
1311: case 'v':
1312: autoconf_verbose = !autoconf_verbose;
1313: printf("autoconf verbose %sabled\n",
1314: autoconf_verbose ? "en" : "dis");
1315: break;
1316: default:
1317: printf("Unknown command\n");
1318: break;
1319: }
1320: }
1321: return(0);
1322: }
1323:
1324: void
1325: user_config(void)
1326: {
1327: userconf_init();
1328: printf("User Kernel Config\n");
1329:
1330: while (1) {
1331: printf("UKC> ");
1332: if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 &&
1333: userconf_parse(userconf_cmdbuf))
1334: break;
1335: }
1336: printf("Continuing...\n");
1337: }
CVSweb