xref: /plan9/sys/src/cmd/cwfs/config.c (revision 01a344a29f2ff35133953eaef092a50fc8c3163b)
1*01a344a2SDavid du Colombier #include "all.h"
2*01a344a2SDavid du Colombier #include "io.h"
3*01a344a2SDavid du Colombier 
4*01a344a2SDavid du Colombier static void	dowormcopy(void);
5*01a344a2SDavid du Colombier static int	dodevcopy(void);
6*01a344a2SDavid du Colombier 
7*01a344a2SDavid du Colombier struct {
8*01a344a2SDavid du Colombier 	char*	icharp;
9*01a344a2SDavid du Colombier 	char*	charp;
10*01a344a2SDavid du Colombier 	int	error;
11*01a344a2SDavid du Colombier 	int	newconf;	/* clear before start */
12*01a344a2SDavid du Colombier 	int	modconf;	/* write back when done */
13*01a344a2SDavid du Colombier 	int	nextiter;
14*01a344a2SDavid du Colombier 	int	lastiter;
15*01a344a2SDavid du Colombier 	int	diriter;
16*01a344a2SDavid du Colombier 	Device*	lastcw;
17*01a344a2SDavid du Colombier 	Device*	devlist;
18*01a344a2SDavid du Colombier } f;
19*01a344a2SDavid du Colombier 
20*01a344a2SDavid du Colombier static Device* confdev;
21*01a344a2SDavid du Colombier static int copyworm = 0, copydev = 0;
22*01a344a2SDavid du Colombier static char *src, *dest;
23*01a344a2SDavid du Colombier 
24*01a344a2SDavid du Colombier static int resetparams;
25*01a344a2SDavid du Colombier 
26*01a344a2SDavid du Colombier Fspar fspar[] = {
27*01a344a2SDavid du Colombier 	{ "blocksize",	RBUFSIZE, },
28*01a344a2SDavid du Colombier 	{ "daddrbits",	sizeof(Off)*8, },
29*01a344a2SDavid du Colombier 	{ "indirblks",	NIBLOCK, },
30*01a344a2SDavid du Colombier 	{ "dirblks",	NDBLOCK, },
31*01a344a2SDavid du Colombier 	{ "namelen",	NAMELEN, },
32*01a344a2SDavid du Colombier 	{ nil, 0, },
33*01a344a2SDavid du Colombier };
34*01a344a2SDavid du Colombier 
35*01a344a2SDavid du Colombier int
devcmpr(Device * d1,Device * d2)36*01a344a2SDavid du Colombier devcmpr(Device *d1, Device *d2)
37*01a344a2SDavid du Colombier {
38*01a344a2SDavid du Colombier 	while (d1 != d2) {
39*01a344a2SDavid du Colombier 		if(d1 == nil || d2 == nil || d1->type != d2->type)
40*01a344a2SDavid du Colombier 			return 1;
41*01a344a2SDavid du Colombier 
42*01a344a2SDavid du Colombier 		switch(d1->type) {
43*01a344a2SDavid du Colombier 		default:
44*01a344a2SDavid du Colombier 			print("can't compare dev: %Z\n", d1);
45*01a344a2SDavid du Colombier 			panic("devcmp");
46*01a344a2SDavid du Colombier 			return 1;
47*01a344a2SDavid du Colombier 
48*01a344a2SDavid du Colombier 		case Devmcat:
49*01a344a2SDavid du Colombier 		case Devmlev:
50*01a344a2SDavid du Colombier 		case Devmirr:
51*01a344a2SDavid du Colombier 			d1 = d1->cat.first;
52*01a344a2SDavid du Colombier 			d2 = d2->cat.first;
53*01a344a2SDavid du Colombier 			while(d1 && d2) {
54*01a344a2SDavid du Colombier 				if(devcmpr(d1, d2))
55*01a344a2SDavid du Colombier 					return 1;
56*01a344a2SDavid du Colombier 				d1 = d1->link;
57*01a344a2SDavid du Colombier 				d2 = d2->link;
58*01a344a2SDavid du Colombier 			}
59*01a344a2SDavid du Colombier 			break;
60*01a344a2SDavid du Colombier 
61*01a344a2SDavid du Colombier 		case Devnone:
62*01a344a2SDavid du Colombier 			return 0;
63*01a344a2SDavid du Colombier 
64*01a344a2SDavid du Colombier 		case Devro:
65*01a344a2SDavid du Colombier 			d1 = d1->ro.parent;
66*01a344a2SDavid du Colombier 			d2 = d2->ro.parent;
67*01a344a2SDavid du Colombier 			break;
68*01a344a2SDavid du Colombier 
69*01a344a2SDavid du Colombier 		case Devjuke:
70*01a344a2SDavid du Colombier 		case Devcw:
71*01a344a2SDavid du Colombier 			if(devcmpr(d1->cw.c, d2->cw.c))
72*01a344a2SDavid du Colombier 				return 1;
73*01a344a2SDavid du Colombier 			d1 = d1->cw.w;
74*01a344a2SDavid du Colombier 			d2 = d2->cw.w;
75*01a344a2SDavid du Colombier 			break;
76*01a344a2SDavid du Colombier 
77*01a344a2SDavid du Colombier 		case Devfworm:
78*01a344a2SDavid du Colombier 			d1 = d1->fw.fw;
79*01a344a2SDavid du Colombier 			d2 = d2->fw.fw;
80*01a344a2SDavid du Colombier 			break;
81*01a344a2SDavid du Colombier 
82*01a344a2SDavid du Colombier 		case Devwren:
83*01a344a2SDavid du Colombier 		case Devworm:
84*01a344a2SDavid du Colombier 		case Devlworm:
85*01a344a2SDavid du Colombier 			if(d1->wren.ctrl == d2->wren.ctrl)
86*01a344a2SDavid du Colombier 			if(d1->wren.targ == d2->wren.targ)
87*01a344a2SDavid du Colombier 			if(d1->wren.lun == d2->wren.lun)
88*01a344a2SDavid du Colombier 				return 0;
89*01a344a2SDavid du Colombier 			return 1;
90*01a344a2SDavid du Colombier 
91*01a344a2SDavid du Colombier 		case Devpart:
92*01a344a2SDavid du Colombier 			if(d1->part.base == d2->part.base)
93*01a344a2SDavid du Colombier 			if(d1->part.size == d2->part.size) {
94*01a344a2SDavid du Colombier 				d1 = d1->part.d;
95*01a344a2SDavid du Colombier 				d2 = d2->part.d;
96*01a344a2SDavid du Colombier 				break;
97*01a344a2SDavid du Colombier 			}
98*01a344a2SDavid du Colombier 			return 1;
99*01a344a2SDavid du Colombier 		}
100*01a344a2SDavid du Colombier 	}
101*01a344a2SDavid du Colombier 	return 0;
102*01a344a2SDavid du Colombier }
103*01a344a2SDavid du Colombier 
104*01a344a2SDavid du Colombier void
cdiag(char * s,int c1)105*01a344a2SDavid du Colombier cdiag(char *s, int c1)
106*01a344a2SDavid du Colombier {
107*01a344a2SDavid du Colombier 
108*01a344a2SDavid du Colombier 	f.charp--;
109*01a344a2SDavid du Colombier 	if(f.error == 0) {
110*01a344a2SDavid du Colombier 		print("config diag: %s -- <%c>\n", s, c1);
111*01a344a2SDavid du Colombier 		f.error = 1;
112*01a344a2SDavid du Colombier 	}
113*01a344a2SDavid du Colombier }
114*01a344a2SDavid du Colombier 
115*01a344a2SDavid du Colombier int
cnumb(void)116*01a344a2SDavid du Colombier cnumb(void)
117*01a344a2SDavid du Colombier {
118*01a344a2SDavid du Colombier 	int c, n;
119*01a344a2SDavid du Colombier 
120*01a344a2SDavid du Colombier 	c = *f.charp++;
121*01a344a2SDavid du Colombier 	if(c == '<') {
122*01a344a2SDavid du Colombier 		n = f.nextiter;
123*01a344a2SDavid du Colombier 		if(n >= 0) {
124*01a344a2SDavid du Colombier 			f.nextiter = n+f.diriter;
125*01a344a2SDavid du Colombier 			if(n == f.lastiter) {
126*01a344a2SDavid du Colombier 				f.nextiter = -1;
127*01a344a2SDavid du Colombier 				f.lastiter = -1;
128*01a344a2SDavid du Colombier 			}
129*01a344a2SDavid du Colombier 			do {
130*01a344a2SDavid du Colombier 				c = *f.charp++;
131*01a344a2SDavid du Colombier 			} while (c != '>');
132*01a344a2SDavid du Colombier 			return n;
133*01a344a2SDavid du Colombier 		}
134*01a344a2SDavid du Colombier 		n = cnumb();
135*01a344a2SDavid du Colombier 		if(*f.charp++ != '-') {
136*01a344a2SDavid du Colombier 			cdiag("- expected", f.charp[-1]);
137*01a344a2SDavid du Colombier 			return 0;
138*01a344a2SDavid du Colombier 		}
139*01a344a2SDavid du Colombier 		c = cnumb();
140*01a344a2SDavid du Colombier 		if(*f.charp++ != '>') {
141*01a344a2SDavid du Colombier 			cdiag("> expected", f.charp[-1]);
142*01a344a2SDavid du Colombier 			return 0;
143*01a344a2SDavid du Colombier 		}
144*01a344a2SDavid du Colombier 		f.lastiter = c;
145*01a344a2SDavid du Colombier 		f.diriter = 1;
146*01a344a2SDavid du Colombier 		if(n > c)
147*01a344a2SDavid du Colombier 			f.diriter = -1;
148*01a344a2SDavid du Colombier 		f.nextiter = n+f.diriter;
149*01a344a2SDavid du Colombier 		return n;
150*01a344a2SDavid du Colombier 	}
151*01a344a2SDavid du Colombier 	if(!isascii(c) || !isdigit(c)) {
152*01a344a2SDavid du Colombier 		cdiag("number expected", c);
153*01a344a2SDavid du Colombier 		return 0;
154*01a344a2SDavid du Colombier 	}
155*01a344a2SDavid du Colombier 	n = 0;
156*01a344a2SDavid du Colombier 	while(isascii(c) && isdigit(c)) {
157*01a344a2SDavid du Colombier 		n = n*10 + (c-'0');
158*01a344a2SDavid du Colombier 		c = *f.charp++;
159*01a344a2SDavid du Colombier 	}
160*01a344a2SDavid du Colombier 	f.charp--;
161*01a344a2SDavid du Colombier 	return n;
162*01a344a2SDavid du Colombier }
163*01a344a2SDavid du Colombier 
164*01a344a2SDavid du Colombier Device*
config1(int c)165*01a344a2SDavid du Colombier config1(int c)
166*01a344a2SDavid du Colombier {
167*01a344a2SDavid du Colombier 	Device *d, *t;
168*01a344a2SDavid du Colombier 	int m;
169*01a344a2SDavid du Colombier 
170*01a344a2SDavid du Colombier 	d = malloc(sizeof(Device));
171*01a344a2SDavid du Colombier 	do {
172*01a344a2SDavid du Colombier 		t = config();
173*01a344a2SDavid du Colombier 		if(d->cat.first == 0)
174*01a344a2SDavid du Colombier 			d->cat.first = t;
175*01a344a2SDavid du Colombier 		else
176*01a344a2SDavid du Colombier 			d->cat.last->link = t;
177*01a344a2SDavid du Colombier 		d->cat.last = t;
178*01a344a2SDavid du Colombier 		if(f.error)
179*01a344a2SDavid du Colombier 			return devnone;
180*01a344a2SDavid du Colombier 		m = *f.charp;
181*01a344a2SDavid du Colombier 		if(c == '(' && m == ')')
182*01a344a2SDavid du Colombier 			d->type = Devmcat;
183*01a344a2SDavid du Colombier 		else if(c == '[' && m == ']')
184*01a344a2SDavid du Colombier 			d->type = Devmlev;
185*01a344a2SDavid du Colombier 		else if(c == '{' && m == '}')
186*01a344a2SDavid du Colombier 			d->type = Devmirr;
187*01a344a2SDavid du Colombier 	} while (d->type == 0);
188*01a344a2SDavid du Colombier 	f.charp++;
189*01a344a2SDavid du Colombier 	if(d->cat.first == d->cat.last)
190*01a344a2SDavid du Colombier 		d = d->cat.first;
191*01a344a2SDavid du Colombier 	return d;
192*01a344a2SDavid du Colombier }
193*01a344a2SDavid du Colombier 
194*01a344a2SDavid du Colombier static void
map(Device * d)195*01a344a2SDavid du Colombier map(Device *d)
196*01a344a2SDavid du Colombier {
197*01a344a2SDavid du Colombier 	Map *map;
198*01a344a2SDavid du Colombier 
199*01a344a2SDavid du Colombier 	if (d->type != Devwren || d->wren.mapped)
200*01a344a2SDavid du Colombier 		return;
201*01a344a2SDavid du Colombier 	for (map = devmap; map != nil; map = map->next)
202*01a344a2SDavid du Colombier 		if (devcmpr(d, map->fdev) == 0)
203*01a344a2SDavid du Colombier 			break;
204*01a344a2SDavid du Colombier 	if (map == nil)
205*01a344a2SDavid du Colombier 		return;
206*01a344a2SDavid du Colombier 	if (access(map->to, AEXIST) >= 0)
207*01a344a2SDavid du Colombier { print("map: mapped wren %Z to existing file %s\n", d, map->to); // DEBUG
208*01a344a2SDavid du Colombier 		d->wren.file = map->to;		/* wren -> file mapping */
209*01a344a2SDavid du Colombier }
210*01a344a2SDavid du Colombier 	else if (map->tdev != nil)
211*01a344a2SDavid du Colombier { print("map: mapped wren %Z to dev %Z\n", d, map->tdev); // DEBUG
212*01a344a2SDavid du Colombier 		*d = *map->tdev;		/* wren -> wren mapping */
213*01a344a2SDavid du Colombier }
214*01a344a2SDavid du Colombier 	else
215*01a344a2SDavid du Colombier 		print("bad mapping %Z to %s; no such file or device",
216*01a344a2SDavid du Colombier 			d, map->to);
217*01a344a2SDavid du Colombier 	d->wren.mapped = 1;
218*01a344a2SDavid du Colombier }
219*01a344a2SDavid du Colombier 
220*01a344a2SDavid du Colombier Device*
config(void)221*01a344a2SDavid du Colombier config(void)
222*01a344a2SDavid du Colombier {
223*01a344a2SDavid du Colombier 	int c, m;
224*01a344a2SDavid du Colombier 	Device *d;
225*01a344a2SDavid du Colombier 	char *icp;
226*01a344a2SDavid du Colombier 
227*01a344a2SDavid du Colombier 	if(f.error)
228*01a344a2SDavid du Colombier 		return devnone;
229*01a344a2SDavid du Colombier 	d = malloc(sizeof(Device));
230*01a344a2SDavid du Colombier 
231*01a344a2SDavid du Colombier 	c = *f.charp++;
232*01a344a2SDavid du Colombier 	switch(c) {
233*01a344a2SDavid du Colombier 	default:
234*01a344a2SDavid du Colombier 		cdiag("unknown type", c);
235*01a344a2SDavid du Colombier 		return devnone;
236*01a344a2SDavid du Colombier 
237*01a344a2SDavid du Colombier 	case '(':	/* (d+) one or multiple cat */
238*01a344a2SDavid du Colombier 	case '[':	/* [d+] one or multiple interleave */
239*01a344a2SDavid du Colombier 	case '{':	/* {d+} a mirrored device and optional mirrors */
240*01a344a2SDavid du Colombier 		return config1(c);
241*01a344a2SDavid du Colombier 
242*01a344a2SDavid du Colombier 	case 'f':	/* fd fake worm */
243*01a344a2SDavid du Colombier 		d->type = Devfworm;
244*01a344a2SDavid du Colombier 		d->fw.fw = config();
245*01a344a2SDavid du Colombier 		break;
246*01a344a2SDavid du Colombier 
247*01a344a2SDavid du Colombier 	case 'n':
248*01a344a2SDavid du Colombier 		d->type = Devnone;
249*01a344a2SDavid du Colombier 		break;
250*01a344a2SDavid du Colombier 
251*01a344a2SDavid du Colombier 	case 'w':	/* w[#.]#[.#] wren	[ctrl] unit [lun] */
252*01a344a2SDavid du Colombier 	case 'r':	/* r# worm side */
253*01a344a2SDavid du Colombier 	case 'l':	/* l# labelled-worm side */
254*01a344a2SDavid du Colombier 		icp = f.charp;
255*01a344a2SDavid du Colombier 		d->type = Devwren;
256*01a344a2SDavid du Colombier 		d->wren.ctrl = 0;
257*01a344a2SDavid du Colombier 		d->wren.targ = cnumb();
258*01a344a2SDavid du Colombier 		d->wren.lun = 0;
259*01a344a2SDavid du Colombier 		m = *f.charp;
260*01a344a2SDavid du Colombier 		if(m == '.') {
261*01a344a2SDavid du Colombier 			f.charp++;
262*01a344a2SDavid du Colombier 			d->wren.lun = cnumb();
263*01a344a2SDavid du Colombier 			m = *f.charp;
264*01a344a2SDavid du Colombier 			if(m == '.') {
265*01a344a2SDavid du Colombier 				f.charp++;
266*01a344a2SDavid du Colombier 				d->wren.ctrl = d->wren.targ;
267*01a344a2SDavid du Colombier 				d->wren.targ = d->wren.lun;
268*01a344a2SDavid du Colombier 				d->wren.lun = cnumb();
269*01a344a2SDavid du Colombier 			}
270*01a344a2SDavid du Colombier 		}
271*01a344a2SDavid du Colombier 		if(f.nextiter >= 0)
272*01a344a2SDavid du Colombier 			f.charp = icp-1;
273*01a344a2SDavid du Colombier 		if(c == 'r')		/* worms are virtual and not uniqued */
274*01a344a2SDavid du Colombier 			d->type = Devworm;
275*01a344a2SDavid du Colombier 		else if(c == 'l')
276*01a344a2SDavid du Colombier 			d->type = Devlworm;
277*01a344a2SDavid du Colombier 		else
278*01a344a2SDavid du Colombier 			map(d);		/* subject wrens to optional mapping */
279*01a344a2SDavid du Colombier 		break;
280*01a344a2SDavid du Colombier 
281*01a344a2SDavid du Colombier 	case 'o':	/* o ro part of last cw */
282*01a344a2SDavid du Colombier 		if(f.lastcw == 0) {
283*01a344a2SDavid du Colombier 			cdiag("no cw to match", c);
284*01a344a2SDavid du Colombier 			return devnone;
285*01a344a2SDavid du Colombier 		}
286*01a344a2SDavid du Colombier 		return f.lastcw->cw.ro;
287*01a344a2SDavid du Colombier 
288*01a344a2SDavid du Colombier 	case 'j':	/* DD jukebox */
289*01a344a2SDavid du Colombier 		d->type = Devjuke;
290*01a344a2SDavid du Colombier 		d->j.j = config();
291*01a344a2SDavid du Colombier 		d->j.m = config();
292*01a344a2SDavid du Colombier 		break;
293*01a344a2SDavid du Colombier 
294*01a344a2SDavid du Colombier 	case 'c':	/* cache/worm */
295*01a344a2SDavid du Colombier 		d->type = Devcw;
296*01a344a2SDavid du Colombier 		d->cw.c = config();
297*01a344a2SDavid du Colombier 		d->cw.w = config();
298*01a344a2SDavid du Colombier 		d->cw.ro = malloc(sizeof(Device));
299*01a344a2SDavid du Colombier 		d->cw.ro->type = Devro;
300*01a344a2SDavid du Colombier 		d->cw.ro->ro.parent = d;
301*01a344a2SDavid du Colombier 		f.lastcw = d;
302*01a344a2SDavid du Colombier 		break;
303*01a344a2SDavid du Colombier 
304*01a344a2SDavid du Colombier 	case 'p':	/* pd#.# partition base% size% */
305*01a344a2SDavid du Colombier 		d->type = Devpart;
306*01a344a2SDavid du Colombier 		d->part.d = config();
307*01a344a2SDavid du Colombier 		d->part.base = cnumb();
308*01a344a2SDavid du Colombier 		c = *f.charp++;
309*01a344a2SDavid du Colombier 		if(c != '.')
310*01a344a2SDavid du Colombier 			cdiag("dot expected", c);
311*01a344a2SDavid du Colombier 		d->part.size = cnumb();
312*01a344a2SDavid du Colombier 		break;
313*01a344a2SDavid du Colombier 
314*01a344a2SDavid du Colombier 	case 'x':	/* xD swab a device's metadata */
315*01a344a2SDavid du Colombier 		d->type = Devswab;
316*01a344a2SDavid du Colombier 		d->swab.d = config();
317*01a344a2SDavid du Colombier 		break;
318*01a344a2SDavid du Colombier 	}
319*01a344a2SDavid du Colombier 	d->dlink = f.devlist;
320*01a344a2SDavid du Colombier 	f.devlist = d;
321*01a344a2SDavid du Colombier 	return d;
322*01a344a2SDavid du Colombier }
323*01a344a2SDavid du Colombier 
324*01a344a2SDavid du Colombier Device*
iconfig(char * s)325*01a344a2SDavid du Colombier iconfig(char *s)
326*01a344a2SDavid du Colombier {
327*01a344a2SDavid du Colombier 	Device *d;
328*01a344a2SDavid du Colombier 
329*01a344a2SDavid du Colombier 	f.nextiter = -1;
330*01a344a2SDavid du Colombier 	f.lastiter = -1;
331*01a344a2SDavid du Colombier 	f.error = 0;
332*01a344a2SDavid du Colombier 	f.icharp = s;
333*01a344a2SDavid du Colombier 	f.charp = f.icharp;
334*01a344a2SDavid du Colombier 	d = config();
335*01a344a2SDavid du Colombier 	if(*f.charp) {
336*01a344a2SDavid du Colombier 		cdiag("junk on end", *f.charp);
337*01a344a2SDavid du Colombier 		f.error = 1;
338*01a344a2SDavid du Colombier 	}
339*01a344a2SDavid du Colombier 	return d;
340*01a344a2SDavid du Colombier }
341*01a344a2SDavid du Colombier 
342*01a344a2SDavid du Colombier int
testconfig(char * s)343*01a344a2SDavid du Colombier testconfig(char *s)
344*01a344a2SDavid du Colombier {
345*01a344a2SDavid du Colombier 	iconfig(s);
346*01a344a2SDavid du Colombier 	return f.error;
347*01a344a2SDavid du Colombier }
348*01a344a2SDavid du Colombier 
349*01a344a2SDavid du Colombier /*
350*01a344a2SDavid du Colombier  * if b is a prefix of a, return 0.
351*01a344a2SDavid du Colombier  */
352*01a344a2SDavid du Colombier int
astrcmp(char * a,char * b)353*01a344a2SDavid du Colombier astrcmp(char *a, char *b)
354*01a344a2SDavid du Colombier {
355*01a344a2SDavid du Colombier 	int n, c;
356*01a344a2SDavid du Colombier 
357*01a344a2SDavid du Colombier 	n = strlen(b);
358*01a344a2SDavid du Colombier 	if(memcmp(a, b, n) != 0)
359*01a344a2SDavid du Colombier 		return 1;
360*01a344a2SDavid du Colombier 	c = a[n];
361*01a344a2SDavid du Colombier 	if(c == '\0')
362*01a344a2SDavid du Colombier 		return 0;
363*01a344a2SDavid du Colombier 	if(a[n+1])
364*01a344a2SDavid du Colombier 		return 1;
365*01a344a2SDavid du Colombier 	if(isascii(c) && isdigit(c))
366*01a344a2SDavid du Colombier 		return 0;
367*01a344a2SDavid du Colombier 	return 1;
368*01a344a2SDavid du Colombier }
369*01a344a2SDavid du Colombier 
370*01a344a2SDavid du Colombier static Fspar *
getpar(char * name)371*01a344a2SDavid du Colombier getpar(char *name)
372*01a344a2SDavid du Colombier {
373*01a344a2SDavid du Colombier 	Fspar *fsp;
374*01a344a2SDavid du Colombier 
375*01a344a2SDavid du Colombier 	for (fsp = fspar; fsp->name != nil; fsp++)
376*01a344a2SDavid du Colombier 		if (strcmp(name, fsp->name) == 0)
377*01a344a2SDavid du Colombier 			return fsp;
378*01a344a2SDavid du Colombier 	return nil;
379*01a344a2SDavid du Colombier }
380*01a344a2SDavid du Colombier 
381*01a344a2SDavid du Colombier /*
382*01a344a2SDavid du Colombier  * continue to parse obsolete keywords so that old configurations can
383*01a344a2SDavid du Colombier  * still work.
384*01a344a2SDavid du Colombier  */
385*01a344a2SDavid du Colombier void
mergeconf(Iobuf * p)386*01a344a2SDavid du Colombier mergeconf(Iobuf *p)
387*01a344a2SDavid du Colombier {
388*01a344a2SDavid du Colombier 	char word[Maxword+1];
389*01a344a2SDavid du Colombier 	char *cp;
390*01a344a2SDavid du Colombier 	Filsys *fs;
391*01a344a2SDavid du Colombier 	Fspar *fsp;
392*01a344a2SDavid du Colombier 
393*01a344a2SDavid du Colombier 	for (cp = p->iobuf; *cp != '\0'; cp++) {
394*01a344a2SDavid du Colombier 		cp = getwrd(word, cp);
395*01a344a2SDavid du Colombier 		if(word[0] == '\0')
396*01a344a2SDavid du Colombier 			break;
397*01a344a2SDavid du Colombier 		else if (word[0] == '#')
398*01a344a2SDavid du Colombier 			while (*cp != '\n' && *cp != '\0')
399*01a344a2SDavid du Colombier 				cp++;
400*01a344a2SDavid du Colombier 		else if(strcmp(word, "service") == 0) {
401*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
402*01a344a2SDavid du Colombier 			if(service[0] == 0)
403*01a344a2SDavid du Colombier 				strncpy(service, word, sizeof service);
404*01a344a2SDavid du Colombier 		} else if(strcmp(word, "ipauth") == 0)	/* obsolete */
405*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
406*01a344a2SDavid du Colombier 		else if(astrcmp(word, "ip") == 0)	/* obsolete */
407*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
408*01a344a2SDavid du Colombier 		else if(astrcmp(word, "ipgw") == 0)	/* obsolete */
409*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
410*01a344a2SDavid du Colombier 		else if(astrcmp(word, "ipsntp") == 0)	/* obsolete */
411*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
412*01a344a2SDavid du Colombier 		else if(astrcmp(word, "ipmask") == 0)	/* obsolete */
413*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
414*01a344a2SDavid du Colombier 		else if(strcmp(word, "filsys") == 0) {
415*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
416*01a344a2SDavid du Colombier 			for(fs = filsys; fs < filsys + nelem(filsys) - 1 &&
417*01a344a2SDavid du Colombier 			    fs->name; fs++)
418*01a344a2SDavid du Colombier 				if(strcmp(fs->name, word) == 0)
419*01a344a2SDavid du Colombier 					break;
420*01a344a2SDavid du Colombier 			if (fs >= filsys + nelem(filsys) - 1)
421*01a344a2SDavid du Colombier 				panic("out of filsys structures");
422*01a344a2SDavid du Colombier 			if (fs->name && strcmp(fs->name, word) == 0 &&
423*01a344a2SDavid du Colombier 			    fs->flags & FEDIT)
424*01a344a2SDavid du Colombier 				cp = getwrd(word, cp);	/* swallow conf */
425*01a344a2SDavid du Colombier 			else {
426*01a344a2SDavid du Colombier 				fs->name = strdup(word);
427*01a344a2SDavid du Colombier 				cp = getwrd(word, cp);
428*01a344a2SDavid du Colombier 				if (word[0] == '\0')
429*01a344a2SDavid du Colombier 					fs->conf = nil;
430*01a344a2SDavid du Colombier 				else
431*01a344a2SDavid du Colombier 					fs->conf = strdup(word);
432*01a344a2SDavid du Colombier 			}
433*01a344a2SDavid du Colombier 		} else if ((fsp = getpar(word)) != nil) {
434*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
435*01a344a2SDavid du Colombier 			if (!isascii(word[0]) || !isdigit(word[0]))
436*01a344a2SDavid du Colombier 				print("bad %s value: %s", fsp->name, word);
437*01a344a2SDavid du Colombier 			else
438*01a344a2SDavid du Colombier 				fsp->declared = atol(word);
439*01a344a2SDavid du Colombier 		} else {
440*01a344a2SDavid du Colombier 			putbuf(p);
441*01a344a2SDavid du Colombier 			panic("unknown keyword in config block: %s", word);
442*01a344a2SDavid du Colombier 		}
443*01a344a2SDavid du Colombier 
444*01a344a2SDavid du Colombier 		if(*cp != '\n') {
445*01a344a2SDavid du Colombier 			putbuf(p);
446*01a344a2SDavid du Colombier 			panic("syntax error in config block at `%s'", word);
447*01a344a2SDavid du Colombier 		}
448*01a344a2SDavid du Colombier 	}
449*01a344a2SDavid du Colombier }
450*01a344a2SDavid du Colombier 
451*01a344a2SDavid du Colombier void
cmd_printconf(int,char * [])452*01a344a2SDavid du Colombier cmd_printconf(int, char *[])
453*01a344a2SDavid du Colombier {
454*01a344a2SDavid du Colombier 	char *p, *s;
455*01a344a2SDavid du Colombier 	Iobuf *iob;
456*01a344a2SDavid du Colombier 
457*01a344a2SDavid du Colombier 	iob = getbuf(confdev, 0, Brd);
458*01a344a2SDavid du Colombier 	if(iob == nil)
459*01a344a2SDavid du Colombier 		return;
460*01a344a2SDavid du Colombier 	if(checktag(iob, Tconfig, 0)){
461*01a344a2SDavid du Colombier 		putbuf(iob);
462*01a344a2SDavid du Colombier 		return;
463*01a344a2SDavid du Colombier 	}
464*01a344a2SDavid du Colombier 
465*01a344a2SDavid du Colombier 	print("config %s\n", nvrgetconfig());
466*01a344a2SDavid du Colombier 	for(s = p = iob->iobuf; *p != 0 && p < iob->iobuf+BUFSIZE; ){
467*01a344a2SDavid du Colombier 		if(*p++ != '\n')
468*01a344a2SDavid du Colombier 			continue;
469*01a344a2SDavid du Colombier 		if (strncmp(s, "ip", 2) != 0)	/* don't print obsolete cmds */
470*01a344a2SDavid du Colombier 			print("%.*s", (int)(p-s), s);
471*01a344a2SDavid du Colombier 		s = p;
472*01a344a2SDavid du Colombier 	}
473*01a344a2SDavid du Colombier 	if(p != s)
474*01a344a2SDavid du Colombier 		print("%.*s", (int)(p-s), s);
475*01a344a2SDavid du Colombier 	print("end\n");
476*01a344a2SDavid du Colombier 
477*01a344a2SDavid du Colombier 	putbuf(iob);
478*01a344a2SDavid du Colombier }
479*01a344a2SDavid du Colombier 
480*01a344a2SDavid du Colombier void
sysinit(void)481*01a344a2SDavid du Colombier sysinit(void)
482*01a344a2SDavid du Colombier {
483*01a344a2SDavid du Colombier 	int error;
484*01a344a2SDavid du Colombier 	char *cp, *ep;
485*01a344a2SDavid du Colombier 	Device *d;
486*01a344a2SDavid du Colombier 	Filsys *fs;
487*01a344a2SDavid du Colombier 	Fspar *fsp;
488*01a344a2SDavid du Colombier 	Iobuf *p;
489*01a344a2SDavid du Colombier 
490*01a344a2SDavid du Colombier 	cons.chan = fs_chaninit(Devcon, 1, 0);
491*01a344a2SDavid du Colombier 
492*01a344a2SDavid du Colombier start:
493*01a344a2SDavid du Colombier 	/*
494*01a344a2SDavid du Colombier 	 * part 1 -- read the config file
495*01a344a2SDavid du Colombier 	 */
496*01a344a2SDavid du Colombier 	devnone = iconfig("n");
497*01a344a2SDavid du Colombier 
498*01a344a2SDavid du Colombier 	cp = nvrgetconfig();
499*01a344a2SDavid du Colombier 	print("config %s\n", cp);
500*01a344a2SDavid du Colombier 
501*01a344a2SDavid du Colombier 	confdev = d = iconfig(cp);
502*01a344a2SDavid du Colombier 	devinit(d);
503*01a344a2SDavid du Colombier 	if(f.newconf) {
504*01a344a2SDavid du Colombier 		p = getbuf(d, 0, Bmod);
505*01a344a2SDavid du Colombier 		memset(p->iobuf, 0, RBUFSIZE);
506*01a344a2SDavid du Colombier 		settag(p, Tconfig, 0);
507*01a344a2SDavid du Colombier 	} else
508*01a344a2SDavid du Colombier 		p = getbuf(d, 0, Brd|Bmod);
509*01a344a2SDavid du Colombier 	if(!p || checktag(p, Tconfig, 0))
510*01a344a2SDavid du Colombier 		panic("config io");
511*01a344a2SDavid du Colombier 
512*01a344a2SDavid du Colombier 	mergeconf(p);
513*01a344a2SDavid du Colombier 
514*01a344a2SDavid du Colombier 	if (resetparams) {
515*01a344a2SDavid du Colombier 		for (fsp = fspar; fsp->name != nil; fsp++)
516*01a344a2SDavid du Colombier 			fsp->declared = 0;
517*01a344a2SDavid du Colombier 		resetparams = 0;
518*01a344a2SDavid du Colombier 	}
519*01a344a2SDavid du Colombier 
520*01a344a2SDavid du Colombier 	for (fsp = fspar; fsp->name != nil; fsp++) {
521*01a344a2SDavid du Colombier 		/* supply defaults from this cwfs instance */
522*01a344a2SDavid du Colombier 		if (fsp->declared == 0) {
523*01a344a2SDavid du Colombier 			fsp->declared = fsp->actual;
524*01a344a2SDavid du Colombier 			f.modconf = 1;
525*01a344a2SDavid du Colombier 		}
526*01a344a2SDavid du Colombier 		/* warn if declared value is not our compiled-in value */
527*01a344a2SDavid du Colombier 		if (fsp->declared != fsp->actual)
528*01a344a2SDavid du Colombier 			print("warning: config %s %ld != compiled-in %ld\n",
529*01a344a2SDavid du Colombier 				fsp->name, fsp->declared, fsp->actual);
530*01a344a2SDavid du Colombier 	}
531*01a344a2SDavid du Colombier 
532*01a344a2SDavid du Colombier 	if(f.modconf) {
533*01a344a2SDavid du Colombier 		memset(p->iobuf, 0, BUFSIZE);
534*01a344a2SDavid du Colombier 		p->flags |= Bmod|Bimm;
535*01a344a2SDavid du Colombier 		cp = p->iobuf;
536*01a344a2SDavid du Colombier 		ep = p->iobuf + RBUFSIZE - 1;
537*01a344a2SDavid du Colombier 		if(service[0])
538*01a344a2SDavid du Colombier 			cp = seprint(cp, ep, "service %s\n", service);
539*01a344a2SDavid du Colombier 		for(fs=filsys; fs->name; fs++)
540*01a344a2SDavid du Colombier 			if(fs->conf && fs->conf[0] != '\0')
541*01a344a2SDavid du Colombier 				cp = seprint(cp, ep, "filsys %s %s\n", fs->name,
542*01a344a2SDavid du Colombier 					fs->conf);
543*01a344a2SDavid du Colombier 
544*01a344a2SDavid du Colombier 		for (fsp = fspar; fsp->name != nil; fsp++)
545*01a344a2SDavid du Colombier 			cp = seprint(cp, ep, "%s %ld\n",
546*01a344a2SDavid du Colombier 				fsp->name, fsp->declared);
547*01a344a2SDavid du Colombier 
548*01a344a2SDavid du Colombier 		putbuf(p);
549*01a344a2SDavid du Colombier 		f.modconf = f.newconf = 0;
550*01a344a2SDavid du Colombier 		print("config block written\n");
551*01a344a2SDavid du Colombier 		goto start;
552*01a344a2SDavid du Colombier 	}
553*01a344a2SDavid du Colombier 	putbuf(p);
554*01a344a2SDavid du Colombier 
555*01a344a2SDavid du Colombier 	print("service    %s\n", service);
556*01a344a2SDavid du Colombier 
557*01a344a2SDavid du Colombier loop:
558*01a344a2SDavid du Colombier 	/*
559*01a344a2SDavid du Colombier 	 * part 2 -- squeeze out the deleted filesystems
560*01a344a2SDavid du Colombier 	 */
561*01a344a2SDavid du Colombier 	for(fs=filsys; fs->name; fs++)
562*01a344a2SDavid du Colombier 		if(fs->conf == nil || fs->conf[0] == '\0') {
563*01a344a2SDavid du Colombier 			for(; fs->name; fs++)
564*01a344a2SDavid du Colombier 				*fs = *(fs+1);
565*01a344a2SDavid du Colombier 			goto loop;
566*01a344a2SDavid du Colombier 		}
567*01a344a2SDavid du Colombier 	if(filsys[0].name == nil)
568*01a344a2SDavid du Colombier 		panic("no filsys");
569*01a344a2SDavid du Colombier 
570*01a344a2SDavid du Colombier 	/*
571*01a344a2SDavid du Colombier 	 * part 3 -- compile the device expression
572*01a344a2SDavid du Colombier 	 */
573*01a344a2SDavid du Colombier 	error = 0;
574*01a344a2SDavid du Colombier 	for(fs=filsys; fs->name; fs++) {
575*01a344a2SDavid du Colombier 		print("filsys %s %s\n", fs->name, fs->conf);
576*01a344a2SDavid du Colombier 		fs->dev = iconfig(fs->conf);
577*01a344a2SDavid du Colombier 		if(f.error) {
578*01a344a2SDavid du Colombier 			error = 1;
579*01a344a2SDavid du Colombier 			continue;
580*01a344a2SDavid du Colombier 		}
581*01a344a2SDavid du Colombier 	}
582*01a344a2SDavid du Colombier 	if(error)
583*01a344a2SDavid du Colombier 		panic("fs config");
584*01a344a2SDavid du Colombier 
585*01a344a2SDavid du Colombier 	/*
586*01a344a2SDavid du Colombier 	 * part 4 -- initialize the devices
587*01a344a2SDavid du Colombier 	 */
588*01a344a2SDavid du Colombier 	for(fs=filsys; fs->name; fs++) {
589*01a344a2SDavid du Colombier 		delay(3000);
590*01a344a2SDavid du Colombier 		print("sysinit: %s\n", fs->name);
591*01a344a2SDavid du Colombier 		if(fs->flags & FREAM)
592*01a344a2SDavid du Colombier 			devream(fs->dev, 1);
593*01a344a2SDavid du Colombier 		if(fs->flags & FRECOVER)
594*01a344a2SDavid du Colombier 			devrecover(fs->dev);
595*01a344a2SDavid du Colombier 		devinit(fs->dev);
596*01a344a2SDavid du Colombier 	}
597*01a344a2SDavid du Colombier 
598*01a344a2SDavid du Colombier 	/*
599*01a344a2SDavid du Colombier 	 * part 5 -- optionally copy devices or worms
600*01a344a2SDavid du Colombier 	 */
601*01a344a2SDavid du Colombier 	if (copyworm) {
602*01a344a2SDavid du Colombier 		dowormcopy();		/* can return if user quits early */
603*01a344a2SDavid du Colombier 		panic("copyworm bailed out!");
604*01a344a2SDavid du Colombier 	}
605*01a344a2SDavid du Colombier 	if (copydev)
606*01a344a2SDavid du Colombier 		if (dodevcopy() < 0)
607*01a344a2SDavid du Colombier 			panic("copydev failed!");
608*01a344a2SDavid du Colombier 		else
609*01a344a2SDavid du Colombier 			panic("copydev done.");
610*01a344a2SDavid du Colombier }
611*01a344a2SDavid du Colombier 
612*01a344a2SDavid du Colombier /* an unfinished idea.  a non-blocking rawchar() would help. */
613*01a344a2SDavid du Colombier static int
userabort(char * msg)614*01a344a2SDavid du Colombier userabort(char *msg)
615*01a344a2SDavid du Colombier {
616*01a344a2SDavid du Colombier 	USED(msg);
617*01a344a2SDavid du Colombier 	return 0;
618*01a344a2SDavid du Colombier }
619*01a344a2SDavid du Colombier 
620*01a344a2SDavid du Colombier static int
blockok(Device * d,Off a)621*01a344a2SDavid du Colombier blockok(Device *d, Off a)
622*01a344a2SDavid du Colombier {
623*01a344a2SDavid du Colombier 	Iobuf *p = getbuf(d, a, Brd);
624*01a344a2SDavid du Colombier 
625*01a344a2SDavid du Colombier 	if (p == 0) {
626*01a344a2SDavid du Colombier 		print("i/o error reading %Z block %lld\n", d, (Wideoff)a);
627*01a344a2SDavid du Colombier 		return 0;
628*01a344a2SDavid du Colombier 	}
629*01a344a2SDavid du Colombier 	putbuf(p);
630*01a344a2SDavid du Colombier 	return 1;
631*01a344a2SDavid du Colombier }
632*01a344a2SDavid du Colombier 
633*01a344a2SDavid du Colombier /*
634*01a344a2SDavid du Colombier  * special case for fake worms only:
635*01a344a2SDavid du Colombier  * we need to size the inner cw's worm device.
636*01a344a2SDavid du Colombier  * in particular, we want to avoid copying the fake-worm bitmap
637*01a344a2SDavid du Colombier  * at the end of the device.
638*01a344a2SDavid du Colombier  *
639*01a344a2SDavid du Colombier  * N.B.: for real worms (e.g. cw jukes), we need to compute devsize(cw(juke)),
640*01a344a2SDavid du Colombier  * *NOT* devsize(juke).
641*01a344a2SDavid du Colombier  */
642*01a344a2SDavid du Colombier static Device *
wormof(Device * dev)643*01a344a2SDavid du Colombier wormof(Device *dev)
644*01a344a2SDavid du Colombier {
645*01a344a2SDavid du Colombier 	Device *worm = dev, *cw;
646*01a344a2SDavid du Colombier 
647*01a344a2SDavid du Colombier 	if (dev->type == Devfworm) {
648*01a344a2SDavid du Colombier 		cw = dev->fw.fw;
649*01a344a2SDavid du Colombier 		if (cw != nil && cw->type == Devcw)
650*01a344a2SDavid du Colombier 			worm = cw->cw.w;
651*01a344a2SDavid du Colombier 	}
652*01a344a2SDavid du Colombier 	// print("wormof(%Z)=%Z\n", dev, worm);
653*01a344a2SDavid du Colombier 	return worm;
654*01a344a2SDavid du Colombier }
655*01a344a2SDavid du Colombier 
656*01a344a2SDavid du Colombier /*
657*01a344a2SDavid du Colombier  * return the number of the highest-numbered block actually written, plus 1.
658*01a344a2SDavid du Colombier  * 0 indicates an error.
659*01a344a2SDavid du Colombier  */
660*01a344a2SDavid du Colombier static Devsize
writtensize(Device * worm)661*01a344a2SDavid du Colombier writtensize(Device *worm)
662*01a344a2SDavid du Colombier {
663*01a344a2SDavid du Colombier 	Devsize lim = devsize(worm);
664*01a344a2SDavid du Colombier 	Iobuf *p;
665*01a344a2SDavid du Colombier 
666*01a344a2SDavid du Colombier 	print("devsize(%Z) = %lld\n", worm, (Wideoff)lim);
667*01a344a2SDavid du Colombier 	if (!blockok(worm, 0) || !blockok(worm, lim-1))
668*01a344a2SDavid du Colombier 		return 0;
669*01a344a2SDavid du Colombier 	delay(5*1000);
670*01a344a2SDavid du Colombier 	if (userabort("sanity checks"))
671*01a344a2SDavid du Colombier 		return 0;
672*01a344a2SDavid du Colombier 
673*01a344a2SDavid du Colombier 	/* find worm's last valid block in case "worm" is an (f)worm */
674*01a344a2SDavid du Colombier 	while (lim > 0) {
675*01a344a2SDavid du Colombier 		if (userabort("sizing")) {
676*01a344a2SDavid du Colombier 			lim = 0;		/* you lose */
677*01a344a2SDavid du Colombier 			break;
678*01a344a2SDavid du Colombier 		}
679*01a344a2SDavid du Colombier 		--lim;
680*01a344a2SDavid du Colombier 		p = getbuf(worm, lim, Brd);
681*01a344a2SDavid du Colombier 		if (p != 0) {			/* actually read one okay? */
682*01a344a2SDavid du Colombier 			putbuf(p);
683*01a344a2SDavid du Colombier 			break;
684*01a344a2SDavid du Colombier 		}
685*01a344a2SDavid du Colombier 	}
686*01a344a2SDavid du Colombier 	print("limit(%Z) = %lld\n", worm, (Wideoff)lim);
687*01a344a2SDavid du Colombier 	if (lim <= 0)
688*01a344a2SDavid du Colombier 		return 0;
689*01a344a2SDavid du Colombier 	return lim + 1;
690*01a344a2SDavid du Colombier }
691*01a344a2SDavid du Colombier 
692*01a344a2SDavid du Colombier /* copy worm fs from "main"'s inner worm to "output" */
693*01a344a2SDavid du Colombier static void
dowormcopy(void)694*01a344a2SDavid du Colombier dowormcopy(void)
695*01a344a2SDavid du Colombier {
696*01a344a2SDavid du Colombier 	Filsys *f1, *f2;
697*01a344a2SDavid du Colombier 	Device *fdev, *from, *to = nil;
698*01a344a2SDavid du Colombier 	Iobuf *p;
699*01a344a2SDavid du Colombier 	Off a;
700*01a344a2SDavid du Colombier 	Devsize lim;
701*01a344a2SDavid du Colombier 
702*01a344a2SDavid du Colombier 	/*
703*01a344a2SDavid du Colombier 	 * convert file system names into Filsyss and Devices.
704*01a344a2SDavid du Colombier 	 */
705*01a344a2SDavid du Colombier 
706*01a344a2SDavid du Colombier 	f1 = fsstr("main");
707*01a344a2SDavid du Colombier 	if(f1 == nil)
708*01a344a2SDavid du Colombier 		panic("main file system missing");
709*01a344a2SDavid du Colombier 	fdev = f1->dev;
710*01a344a2SDavid du Colombier 	from = wormof(fdev);			/* fake worm special */
711*01a344a2SDavid du Colombier 	if (from->type != Devfworm && from->type != Devcw) {
712*01a344a2SDavid du Colombier 		print("main file system is not a worm; copyworm may not do what you want!\n");
713*01a344a2SDavid du Colombier 		print("waiting for 20 seconds...\n");
714*01a344a2SDavid du Colombier 		delay(20000);
715*01a344a2SDavid du Colombier 	}
716*01a344a2SDavid du Colombier 
717*01a344a2SDavid du Colombier 	f2 = fsstr("output");
718*01a344a2SDavid du Colombier 	if(f2 == nil) {
719*01a344a2SDavid du Colombier 		print("no output file system - check only\n\n");
720*01a344a2SDavid du Colombier 		print("reading worm from %Z (worm %Z)\n", fdev, from);
721*01a344a2SDavid du Colombier 	} else {
722*01a344a2SDavid du Colombier 		to = f2->dev;
723*01a344a2SDavid du Colombier 		print("\ncopying worm from %Z (worm %Z) to %Z, starting in 8 seconds\n",
724*01a344a2SDavid du Colombier 			fdev, from, to);
725*01a344a2SDavid du Colombier 		delay(8000);
726*01a344a2SDavid du Colombier 	}
727*01a344a2SDavid du Colombier 	if (userabort("preparing to copy"))
728*01a344a2SDavid du Colombier 		return;
729*01a344a2SDavid du Colombier 
730*01a344a2SDavid du Colombier 	/*
731*01a344a2SDavid du Colombier 	 * initialise devices, size them, more sanity checking.
732*01a344a2SDavid du Colombier 	 */
733*01a344a2SDavid du Colombier 
734*01a344a2SDavid du Colombier 	devinit(from);
735*01a344a2SDavid du Colombier 	if (0 && fdev != from) {
736*01a344a2SDavid du Colombier 		devinit(fdev);
737*01a344a2SDavid du Colombier 		print("debugging, sizing %Z first\n", fdev);
738*01a344a2SDavid du Colombier 		writtensize(fdev);
739*01a344a2SDavid du Colombier 	}
740*01a344a2SDavid du Colombier 	lim = writtensize(from);
741*01a344a2SDavid du Colombier 	if(lim == 0)
742*01a344a2SDavid du Colombier 		panic("no blocks to copy on %Z", from);
743*01a344a2SDavid du Colombier 	if (to) {
744*01a344a2SDavid du Colombier 		print("reaming %Z in 8 seconds\n", to);
745*01a344a2SDavid du Colombier 		delay(8000);
746*01a344a2SDavid du Colombier 		if (userabort("preparing to ream & copy"))
747*01a344a2SDavid du Colombier 			return;
748*01a344a2SDavid du Colombier 		devream(to, 0);
749*01a344a2SDavid du Colombier 		devinit(to);
750*01a344a2SDavid du Colombier 		print("copying worm: %lld blocks from %Z to %Z\n",
751*01a344a2SDavid du Colombier 			(Wideoff)lim, from, to);
752*01a344a2SDavid du Colombier 	}
753*01a344a2SDavid du Colombier 	/* can't read to's blocks in case to is a real WORM device */
754*01a344a2SDavid du Colombier 
755*01a344a2SDavid du Colombier 	/*
756*01a344a2SDavid du Colombier 	 * Copy written fs blocks, a block at a time (or just read
757*01a344a2SDavid du Colombier 	 * if no "output" fs).
758*01a344a2SDavid du Colombier 	 */
759*01a344a2SDavid du Colombier 
760*01a344a2SDavid du Colombier 	for (a = 0; a < lim; a++) {
761*01a344a2SDavid du Colombier 		if (userabort("copy"))
762*01a344a2SDavid du Colombier 			break;
763*01a344a2SDavid du Colombier 		p = getbuf(from, a, Brd);
764*01a344a2SDavid du Colombier 		/*
765*01a344a2SDavid du Colombier 		 * if from is a real WORM device, we'll get errors trying to
766*01a344a2SDavid du Colombier 		 * read unwritten blocks, but the unwritten blocks need not
767*01a344a2SDavid du Colombier 		 * be contiguous.
768*01a344a2SDavid du Colombier 		 */
769*01a344a2SDavid du Colombier 		if (p == 0) {
770*01a344a2SDavid du Colombier 			print("%lld not written yet; can't read\n", (Wideoff)a);
771*01a344a2SDavid du Colombier 			continue;
772*01a344a2SDavid du Colombier 		}
773*01a344a2SDavid du Colombier 		if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) {
774*01a344a2SDavid du Colombier 			print("out block %lld: write error; bailing",
775*01a344a2SDavid du Colombier 				(Wideoff)a);
776*01a344a2SDavid du Colombier 			break;
777*01a344a2SDavid du Colombier 		}
778*01a344a2SDavid du Colombier 		putbuf(p);
779*01a344a2SDavid du Colombier 		if(a % 20000 == 0)
780*01a344a2SDavid du Colombier 			print("block %lld %T\n", (Wideoff)a, time(nil));
781*01a344a2SDavid du Colombier 	}
782*01a344a2SDavid du Colombier 
783*01a344a2SDavid du Colombier 	/*
784*01a344a2SDavid du Colombier 	 * wrap up: sync target, loop
785*01a344a2SDavid du Colombier 	 */
786*01a344a2SDavid du Colombier 	print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to);
787*01a344a2SDavid du Colombier 	sync("wormcopy");
788*01a344a2SDavid du Colombier 	delay(2000);
789*01a344a2SDavid du Colombier 	print("looping; reset the machine at any time.\n");
790*01a344a2SDavid du Colombier 	for (; ; )
791*01a344a2SDavid du Colombier 		continue;		/* await reset */
792*01a344a2SDavid du Colombier }
793*01a344a2SDavid du Colombier 
794*01a344a2SDavid du Colombier /* copy device from src to dest */
795*01a344a2SDavid du Colombier static int
dodevcopy(void)796*01a344a2SDavid du Colombier dodevcopy(void)
797*01a344a2SDavid du Colombier {
798*01a344a2SDavid du Colombier 	Device *from, *to;
799*01a344a2SDavid du Colombier 	Iobuf *p;
800*01a344a2SDavid du Colombier 	Off a;
801*01a344a2SDavid du Colombier 	Devsize lim, tosize;
802*01a344a2SDavid du Colombier 
803*01a344a2SDavid du Colombier 	/*
804*01a344a2SDavid du Colombier 	 * convert config strings into Devices.
805*01a344a2SDavid du Colombier 	 */
806*01a344a2SDavid du Colombier 	from = iconfig(src);
807*01a344a2SDavid du Colombier 	if(f.error || from == nil) {
808*01a344a2SDavid du Colombier 		print("bad src device %s\n", src);
809*01a344a2SDavid du Colombier 		return -1;
810*01a344a2SDavid du Colombier 	}
811*01a344a2SDavid du Colombier 	to = iconfig(dest);
812*01a344a2SDavid du Colombier 	if(f.error || to == nil) {
813*01a344a2SDavid du Colombier 		print("bad dest device %s\n", dest);
814*01a344a2SDavid du Colombier 		return -1;
815*01a344a2SDavid du Colombier 	}
816*01a344a2SDavid du Colombier 
817*01a344a2SDavid du Colombier 	/*
818*01a344a2SDavid du Colombier 	 * initialise devices, size them, more sanity checking.
819*01a344a2SDavid du Colombier 	 */
820*01a344a2SDavid du Colombier 
821*01a344a2SDavid du Colombier 	devinit(from);
822*01a344a2SDavid du Colombier 	lim = devsize(from);
823*01a344a2SDavid du Colombier 	if(lim == 0)
824*01a344a2SDavid du Colombier 		panic("no blocks to copy on %Z", from);
825*01a344a2SDavid du Colombier 	devinit(to);
826*01a344a2SDavid du Colombier 	tosize = devsize(to);
827*01a344a2SDavid du Colombier 	if(tosize == 0)
828*01a344a2SDavid du Colombier 		panic("no blocks to copy on %Z", to);
829*01a344a2SDavid du Colombier 
830*01a344a2SDavid du Colombier 	/* use smaller of the device sizes */
831*01a344a2SDavid du Colombier 	if (tosize < lim)
832*01a344a2SDavid du Colombier 		lim = tosize;
833*01a344a2SDavid du Colombier 
834*01a344a2SDavid du Colombier 	print("copy %Z to %Z in 8 seconds\n", from, to);
835*01a344a2SDavid du Colombier 	delay(8000);
836*01a344a2SDavid du Colombier 	if (userabort("preparing to copy"))
837*01a344a2SDavid du Colombier 		return -1;
838*01a344a2SDavid du Colombier 	print("copying dev: %lld blocks from %Z to %Z\n", (Wideoff)lim,
839*01a344a2SDavid du Colombier 		from, to);
840*01a344a2SDavid du Colombier 
841*01a344a2SDavid du Colombier 	/*
842*01a344a2SDavid du Colombier 	 * Copy all blocks, a block at a time.
843*01a344a2SDavid du Colombier 	 */
844*01a344a2SDavid du Colombier 
845*01a344a2SDavid du Colombier 	for (a = 0; a < lim; a++) {
846*01a344a2SDavid du Colombier 		if (userabort("copy"))
847*01a344a2SDavid du Colombier 			break;
848*01a344a2SDavid du Colombier 		p = getbuf(from, a, Brd);
849*01a344a2SDavid du Colombier 		/*
850*01a344a2SDavid du Colombier 		 * if from is a real WORM device, we'll get errors trying to
851*01a344a2SDavid du Colombier 		 * read unwritten blocks, but the unwritten blocks need not
852*01a344a2SDavid du Colombier 		 * be contiguous.
853*01a344a2SDavid du Colombier 		 */
854*01a344a2SDavid du Colombier 		if (p == 0) {
855*01a344a2SDavid du Colombier 			print("%lld not written yet; can't read\n", (Wideoff)a);
856*01a344a2SDavid du Colombier 			continue;
857*01a344a2SDavid du Colombier 		}
858*01a344a2SDavid du Colombier 		if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) {
859*01a344a2SDavid du Colombier 			print("out block %lld: write error; bailing",
860*01a344a2SDavid du Colombier 				(Wideoff)a);
861*01a344a2SDavid du Colombier 			break;
862*01a344a2SDavid du Colombier 		}
863*01a344a2SDavid du Colombier 		putbuf(p);
864*01a344a2SDavid du Colombier 		if(a % 20000 == 0)
865*01a344a2SDavid du Colombier 			print("block %lld %T\n", (Wideoff)a, time(nil));
866*01a344a2SDavid du Colombier 	}
867*01a344a2SDavid du Colombier 
868*01a344a2SDavid du Colombier 	/*
869*01a344a2SDavid du Colombier 	 * wrap up: sync target
870*01a344a2SDavid du Colombier 	 */
871*01a344a2SDavid du Colombier 	print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to);
872*01a344a2SDavid du Colombier 	sync("devcopy");
873*01a344a2SDavid du Colombier 	return 0;
874*01a344a2SDavid du Colombier }
875*01a344a2SDavid du Colombier 
876*01a344a2SDavid du Colombier static void
setconfig(char * dev)877*01a344a2SDavid du Colombier setconfig(char *dev)
878*01a344a2SDavid du Colombier {
879*01a344a2SDavid du Colombier 	if (dev != nil && !testconfig(dev))
880*01a344a2SDavid du Colombier 		nvrsetconfig(dev);	/* if it fails, it will complain */
881*01a344a2SDavid du Colombier }
882*01a344a2SDavid du Colombier 
883*01a344a2SDavid du Colombier void
arginit(void)884*01a344a2SDavid du Colombier arginit(void)
885*01a344a2SDavid du Colombier {
886*01a344a2SDavid du Colombier 	int verb;
887*01a344a2SDavid du Colombier 	char *line;
888*01a344a2SDavid du Colombier 	char word[Maxword+1], *cp;
889*01a344a2SDavid du Colombier 	Filsys *fs;
890*01a344a2SDavid du Colombier 
891*01a344a2SDavid du Colombier 	if(nvrcheck() == 0) {
892*01a344a2SDavid du Colombier 		setconfig(conf.confdev);
893*01a344a2SDavid du Colombier 		if (!conf.configfirst)
894*01a344a2SDavid du Colombier 			return;
895*01a344a2SDavid du Colombier 	}
896*01a344a2SDavid du Colombier 
897*01a344a2SDavid du Colombier 	/* nvr was bad or invoker requested configuration step */
898*01a344a2SDavid du Colombier 	setconfig(conf.confdev);
899*01a344a2SDavid du Colombier 	for (;;) {
900*01a344a2SDavid du Colombier 		print("config: ");
901*01a344a2SDavid du Colombier 		if ((line = Brdline(&bin, '\n')) == nil)
902*01a344a2SDavid du Colombier 			return;
903*01a344a2SDavid du Colombier 		line[Blinelen(&bin)-1] = '\0';
904*01a344a2SDavid du Colombier 
905*01a344a2SDavid du Colombier 		cp = getwrd(word, line);
906*01a344a2SDavid du Colombier 		if (word[0] == '\0' || word[0] == '#')
907*01a344a2SDavid du Colombier 			continue;
908*01a344a2SDavid du Colombier 		if(strcmp(word, "end") == 0)
909*01a344a2SDavid du Colombier 			return;
910*01a344a2SDavid du Colombier 		if(strcmp(word, "halt") == 0)
911*01a344a2SDavid du Colombier 			exit();
912*01a344a2SDavid du Colombier 		if(strcmp(word, "queryjuke") == 0) {
913*01a344a2SDavid du Colombier 			getwrd(word, cp);
914*01a344a2SDavid du Colombier 			if(testconfig(word) == 0)
915*01a344a2SDavid du Colombier 				querychanger(iconfig(word));
916*01a344a2SDavid du Colombier 			continue;
917*01a344a2SDavid du Colombier 		}
918*01a344a2SDavid du Colombier 
919*01a344a2SDavid du Colombier 		if(strcmp(word, "allow") == 0) {
920*01a344a2SDavid du Colombier 			wstatallow = 1;
921*01a344a2SDavid du Colombier 			writeallow = 1;
922*01a344a2SDavid du Colombier 			continue;
923*01a344a2SDavid du Colombier 		}
924*01a344a2SDavid du Colombier 		if(strcmp(word, "copyworm") == 0) {
925*01a344a2SDavid du Colombier 			copyworm = 1;
926*01a344a2SDavid du Colombier 			continue;
927*01a344a2SDavid du Colombier 		}
928*01a344a2SDavid du Colombier 		if(strcmp(word, "copydev") == 0) {
929*01a344a2SDavid du Colombier 			cp = getwrd(word, cp);
930*01a344a2SDavid du Colombier 			if(testconfig(word))
931*01a344a2SDavid du Colombier 				continue;
932*01a344a2SDavid du Colombier 			src = strdup(word);
933*01a344a2SDavid du Colombier 			getwrd(word, cp);
934*01a344a2SDavid du Colombier 			if(testconfig(word))
935*01a344a2SDavid du Colombier 				continue;
936*01a344a2SDavid du Colombier 			dest = strdup(word);
937*01a344a2SDavid du Colombier 			copydev = 1;
938*01a344a2SDavid du Colombier 			continue;
939*01a344a2SDavid du Colombier 		}
940*01a344a2SDavid du Colombier 		if(strcmp(word, "noauth") == 0) {
941*01a344a2SDavid du Colombier 			noauth = !noauth;
942*01a344a2SDavid du Colombier 			continue;
943*01a344a2SDavid du Colombier 		}
944*01a344a2SDavid du Colombier 		if(strcmp(word, "noattach") == 0) {
945*01a344a2SDavid du Colombier 			noattach = !noattach;
946*01a344a2SDavid du Colombier 			continue;
947*01a344a2SDavid du Colombier 		}
948*01a344a2SDavid du Colombier 		if(strcmp(word, "readonly") == 0) {
949*01a344a2SDavid du Colombier 			readonly = 1;
950*01a344a2SDavid du Colombier 			continue;
951*01a344a2SDavid du Colombier 		}
952*01a344a2SDavid du Colombier 
953*01a344a2SDavid du Colombier 		if(strcmp(word, "ream") == 0) {
954*01a344a2SDavid du Colombier 			verb = FREAM;
955*01a344a2SDavid du Colombier 			goto gfsname;
956*01a344a2SDavid du Colombier 		}
957*01a344a2SDavid du Colombier 		if(strcmp(word, "recover") == 0) {
958*01a344a2SDavid du Colombier 			verb = FRECOVER;
959*01a344a2SDavid du Colombier 			goto gfsname;
960*01a344a2SDavid du Colombier 		}
961*01a344a2SDavid du Colombier 		if(strcmp(word, "filsys") == 0) {
962*01a344a2SDavid du Colombier 			verb = FEDIT;
963*01a344a2SDavid du Colombier 			goto gfsname;
964*01a344a2SDavid du Colombier 		}
965*01a344a2SDavid du Colombier 
966*01a344a2SDavid du Colombier 		if(strcmp(word, "nvram") == 0) {
967*01a344a2SDavid du Colombier 			getwrd(word, cp);
968*01a344a2SDavid du Colombier 			if(testconfig(word))
969*01a344a2SDavid du Colombier 				continue;
970*01a344a2SDavid du Colombier 			/* if it fails, it will complain */
971*01a344a2SDavid du Colombier 			nvrsetconfig(word);
972*01a344a2SDavid du Colombier 			continue;
973*01a344a2SDavid du Colombier 		}
974*01a344a2SDavid du Colombier 		if(strcmp(word, "config") == 0) {
975*01a344a2SDavid du Colombier 			getwrd(word, cp);
976*01a344a2SDavid du Colombier 			if(!testconfig(word) && nvrsetconfig(word) == 0)
977*01a344a2SDavid du Colombier 				f.newconf = 1;
978*01a344a2SDavid du Colombier 			continue;
979*01a344a2SDavid du Colombier 		}
980*01a344a2SDavid du Colombier 		if(strcmp(word, "service") == 0) {
981*01a344a2SDavid du Colombier 			getwrd(word, cp);
982*01a344a2SDavid du Colombier 			strncpy(service, word, sizeof service);
983*01a344a2SDavid du Colombier 			f.modconf = 1;
984*01a344a2SDavid du Colombier 			continue;
985*01a344a2SDavid du Colombier 		}
986*01a344a2SDavid du Colombier 		if (strcmp(word, "resetparams") == 0) {
987*01a344a2SDavid du Colombier 			resetparams++;
988*01a344a2SDavid du Colombier 			continue;
989*01a344a2SDavid du Colombier 		}
990*01a344a2SDavid du Colombier 
991*01a344a2SDavid du Colombier 		/*
992*01a344a2SDavid du Colombier 		 * continue to parse obsolete keywords so that old
993*01a344a2SDavid du Colombier 		 * configurations can still work.
994*01a344a2SDavid du Colombier 		 */
995*01a344a2SDavid du Colombier 		if (strcmp(word, "ipauth") != 0 &&
996*01a344a2SDavid du Colombier 		    astrcmp(word, "ip") != 0 &&
997*01a344a2SDavid du Colombier 		    astrcmp(word, "ipgw") != 0 &&
998*01a344a2SDavid du Colombier 		    astrcmp(word, "ipmask") != 0 &&
999*01a344a2SDavid du Colombier 		    astrcmp(word, "ipsntp") != 0) {
1000*01a344a2SDavid du Colombier 			print("unknown config command\n");
1001*01a344a2SDavid du Colombier 			print("\ttype end to get out\n");
1002*01a344a2SDavid du Colombier 			continue;
1003*01a344a2SDavid du Colombier 		}
1004*01a344a2SDavid du Colombier 
1005*01a344a2SDavid du Colombier 		getwrd(word, cp);
1006*01a344a2SDavid du Colombier 		f.modconf = 1;
1007*01a344a2SDavid du Colombier 		continue;
1008*01a344a2SDavid du Colombier 
1009*01a344a2SDavid du Colombier 	gfsname:
1010*01a344a2SDavid du Colombier 		cp = getwrd(word, cp);
1011*01a344a2SDavid du Colombier 		for(fs=filsys; fs->name; fs++)
1012*01a344a2SDavid du Colombier 			if(strcmp(word, fs->name) == 0)
1013*01a344a2SDavid du Colombier 				break;
1014*01a344a2SDavid du Colombier 		if (fs->name == nil) {
1015*01a344a2SDavid du Colombier 			memset(fs, 0, sizeof *fs);
1016*01a344a2SDavid du Colombier 			fs->name = strdup(word);
1017*01a344a2SDavid du Colombier 		}
1018*01a344a2SDavid du Colombier 		switch(verb) {
1019*01a344a2SDavid du Colombier 		case FREAM:
1020*01a344a2SDavid du Colombier 			if(strcmp(fs->name, "main") == 0)
1021*01a344a2SDavid du Colombier 				wstatallow = 1;	/* only set, never reset */
1022*01a344a2SDavid du Colombier 			/* fallthrough */
1023*01a344a2SDavid du Colombier 		case FRECOVER:
1024*01a344a2SDavid du Colombier 			fs->flags |= verb;
1025*01a344a2SDavid du Colombier 			break;
1026*01a344a2SDavid du Colombier 		case FEDIT:
1027*01a344a2SDavid du Colombier 			f.modconf = 1;
1028*01a344a2SDavid du Colombier 			getwrd(word, cp);
1029*01a344a2SDavid du Colombier 			fs->flags |= verb;
1030*01a344a2SDavid du Colombier 			if(word[0] == 0)
1031*01a344a2SDavid du Colombier 				fs->conf = nil;
1032*01a344a2SDavid du Colombier 			else if(!testconfig(word))
1033*01a344a2SDavid du Colombier 				fs->conf = strdup(word);
1034*01a344a2SDavid du Colombier 			break;
1035*01a344a2SDavid du Colombier 		}
1036*01a344a2SDavid du Colombier 	}
1037*01a344a2SDavid du Colombier }
1038