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