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