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