GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/config/ukcutil.c Lines: 0 720 0.0 %
Date: 2017-11-07 Branches: 0 547 0.0 %

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