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