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