xref: /plan9-contrib/sys/src/cmd/rc/io.c (revision fbd2c77cf86542e8f8bf27bfe7d1dfc5f8f29c74)
13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "fns.h"
5276e7d6dSDavid du Colombier 
6276e7d6dSDavid du Colombier enum { Stralloc = 100, };
7276e7d6dSDavid du Colombier 
83e12c5d1SDavid du Colombier int pfmtnest = 0;
9dc5a79c1SDavid du Colombier 
10dc5a79c1SDavid du Colombier void
11dc5a79c1SDavid du Colombier pfmt(io *f, char *fmt, ...)
12dc5a79c1SDavid du Colombier {
133e12c5d1SDavid du Colombier 	va_list ap;
149a747e4fSDavid du Colombier 	char err[ERRMAX];
15*fbd2c77cSDavid du Colombier 
163e12c5d1SDavid du Colombier 	va_start(ap, fmt);
173e12c5d1SDavid du Colombier 	pfmtnest++;
18*fbd2c77cSDavid du Colombier 	for(;*fmt;fmt++) {
19*fbd2c77cSDavid du Colombier 		if(*fmt!='%') {
20dc5a79c1SDavid du Colombier 			pchr(f, *fmt);
21*fbd2c77cSDavid du Colombier 			continue;
22*fbd2c77cSDavid du Colombier 		}
23*fbd2c77cSDavid du Colombier 		if(*++fmt == '\0')		/* "blah%"? */
24*fbd2c77cSDavid du Colombier 			break;
25*fbd2c77cSDavid du Colombier 		switch(*fmt){
26dc5a79c1SDavid du Colombier 		case 'c':
27dc5a79c1SDavid du Colombier 			pchr(f, va_arg(ap, int));
28dc5a79c1SDavid du Colombier 			break;
29dc5a79c1SDavid du Colombier 		case 'd':
30dc5a79c1SDavid du Colombier 			pdec(f, va_arg(ap, int));
31dc5a79c1SDavid du Colombier 			break;
32dc5a79c1SDavid du Colombier 		case 'o':
33dc5a79c1SDavid du Colombier 			poct(f, va_arg(ap, unsigned));
34dc5a79c1SDavid du Colombier 			break;
35dc5a79c1SDavid du Colombier 		case 'p':
3673e742d7SDavid du Colombier 			pptr(f, va_arg(ap, void*));
3773e742d7SDavid du Colombier 			break;
38dc5a79c1SDavid du Colombier 		case 'Q':
39dc5a79c1SDavid du Colombier 			pquo(f, va_arg(ap, char *));
40dc5a79c1SDavid du Colombier 			break;
41dc5a79c1SDavid du Colombier 		case 'q':
42dc5a79c1SDavid du Colombier 			pwrd(f, va_arg(ap, char *));
43dc5a79c1SDavid du Colombier 			break;
44dc5a79c1SDavid du Colombier 		case 'r':
45dc5a79c1SDavid du Colombier 			errstr(err, sizeof err); pstr(f, err);
46dc5a79c1SDavid du Colombier 			break;
47dc5a79c1SDavid du Colombier 		case 's':
48dc5a79c1SDavid du Colombier 			pstr(f, va_arg(ap, char *));
49dc5a79c1SDavid du Colombier 			break;
50dc5a79c1SDavid du Colombier 		case 't':
51dc5a79c1SDavid du Colombier 			pcmd(f, va_arg(ap, struct tree *));
52dc5a79c1SDavid du Colombier 			break;
53dc5a79c1SDavid du Colombier 		case 'v':
54dc5a79c1SDavid du Colombier 			pval(f, va_arg(ap, struct word *));
55dc5a79c1SDavid du Colombier 			break;
56dc5a79c1SDavid du Colombier 		default:
57dc5a79c1SDavid du Colombier 			pchr(f, *fmt);
58dc5a79c1SDavid du Colombier 			break;
593e12c5d1SDavid du Colombier 		}
60*fbd2c77cSDavid du Colombier 	}
613e12c5d1SDavid du Colombier 	va_end(ap);
62dc5a79c1SDavid du Colombier 	if(--pfmtnest==0)
63dc5a79c1SDavid du Colombier 		flush(f);
643e12c5d1SDavid du Colombier }
65dc5a79c1SDavid du Colombier 
66dc5a79c1SDavid du Colombier void
67dc5a79c1SDavid du Colombier pchr(io *b, int c)
687dd7cddfSDavid du Colombier {
69dc5a79c1SDavid du Colombier 	if(b->bufp==b->ebuf)
70dc5a79c1SDavid du Colombier 		fullbuf(b, c);
7199eb86a7SDavid du Colombier 	else *b->bufp++=c;
727dd7cddfSDavid du Colombier }
73dc5a79c1SDavid du Colombier 
74dc5a79c1SDavid du Colombier int
75dc5a79c1SDavid du Colombier rchr(io *b)
767dd7cddfSDavid du Colombier {
77dc5a79c1SDavid du Colombier 	if(b->bufp==b->ebuf)
78dc5a79c1SDavid du Colombier 		return emptybuf(b);
79276e7d6dSDavid du Colombier 	return *b->bufp++;
807dd7cddfSDavid du Colombier }
81dc5a79c1SDavid du Colombier 
82dc5a79c1SDavid du Colombier void
83dc5a79c1SDavid du Colombier pquo(io *f, char *s)
843e12c5d1SDavid du Colombier {
853e12c5d1SDavid du Colombier 	pchr(f, '\'');
863e12c5d1SDavid du Colombier 	for(;*s;s++)
87dc5a79c1SDavid du Colombier 		if(*s=='\'')
88dc5a79c1SDavid du Colombier 			pfmt(f, "''");
8999eb86a7SDavid du Colombier 		else pchr(f, *s);
903e12c5d1SDavid du Colombier 	pchr(f, '\'');
913e12c5d1SDavid du Colombier }
92dc5a79c1SDavid du Colombier 
93dc5a79c1SDavid du Colombier void
94dc5a79c1SDavid du Colombier pwrd(io *f, char *s)
953e12c5d1SDavid du Colombier {
963e12c5d1SDavid du Colombier 	char *t;
97fed0fa9eSDavid du Colombier 	for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break;
98dc5a79c1SDavid du Colombier 	if(t==s || *t)
99dc5a79c1SDavid du Colombier 		pquo(f, s);
10099eb86a7SDavid du Colombier 	else pstr(f, s);
1013e12c5d1SDavid du Colombier }
102dc5a79c1SDavid du Colombier 
103dc5a79c1SDavid du Colombier void
10473e742d7SDavid du Colombier pptr(io *f, void *v)
1053e12c5d1SDavid du Colombier {
1063e12c5d1SDavid du Colombier 	int n;
10773e742d7SDavid du Colombier 	uintptr p;
10873e742d7SDavid du Colombier 
10973e742d7SDavid du Colombier 	p = (uintptr)v;
11073e742d7SDavid du Colombier 	if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
11199eb86a7SDavid du Colombier 		for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
11273e742d7SDavid du Colombier 
11399eb86a7SDavid du Colombier 	for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
1143e12c5d1SDavid du Colombier }
115dc5a79c1SDavid du Colombier 
116dc5a79c1SDavid du Colombier void
117dc5a79c1SDavid du Colombier pstr(io *f, char *s)
1183e12c5d1SDavid du Colombier {
119dc5a79c1SDavid du Colombier 	if(s==0)
120dc5a79c1SDavid du Colombier 		s="(null)";
12199eb86a7SDavid du Colombier 	while(*s) pchr(f, *s++);
1223e12c5d1SDavid du Colombier }
123dc5a79c1SDavid du Colombier 
124dc5a79c1SDavid du Colombier void
12573e742d7SDavid du Colombier pdec(io *f, int n)
1263e12c5d1SDavid du Colombier {
1273e12c5d1SDavid du Colombier 	if(n<0){
1283e12c5d1SDavid du Colombier 		n=-n;
1293e12c5d1SDavid du Colombier 		if(n>=0){
1303e12c5d1SDavid du Colombier 			pchr(f, '-');
1313e12c5d1SDavid du Colombier 			pdec(f, n);
1323e12c5d1SDavid du Colombier 			return;
1333e12c5d1SDavid du Colombier 		}
1343e12c5d1SDavid du Colombier 		/* n is two's complement minimum integer */
1353e12c5d1SDavid du Colombier 		n = 1-n;
1363e12c5d1SDavid du Colombier 		pchr(f, '-');
1373e12c5d1SDavid du Colombier 		pdec(f, n/10);
1383e12c5d1SDavid du Colombier 		pchr(f, n%10+'1');
1393e12c5d1SDavid du Colombier 		return;
1403e12c5d1SDavid du Colombier 	}
141dc5a79c1SDavid du Colombier 	if(n>9)
142dc5a79c1SDavid du Colombier 		pdec(f, n/10);
1433e12c5d1SDavid du Colombier 	pchr(f, n%10+'0');
1443e12c5d1SDavid du Colombier }
145dc5a79c1SDavid du Colombier 
146dc5a79c1SDavid du Colombier void
14773e742d7SDavid du Colombier poct(io *f, unsigned n)
1483e12c5d1SDavid du Colombier {
149dc5a79c1SDavid du Colombier 	if(n>7)
150dc5a79c1SDavid du Colombier 		poct(f, n>>3);
1513e12c5d1SDavid du Colombier 	pchr(f, (n&7)+'0');
1523e12c5d1SDavid du Colombier }
153dc5a79c1SDavid du Colombier 
154dc5a79c1SDavid du Colombier void
155dc5a79c1SDavid du Colombier pval(io *f, word *a)
1563e12c5d1SDavid du Colombier {
1573e12c5d1SDavid du Colombier 	if(a){
1583e12c5d1SDavid du Colombier 		while(a->next && a->next->word){
159276e7d6dSDavid du Colombier 			pwrd(f, (char *)a->word);
1603e12c5d1SDavid du Colombier 			pchr(f, ' ');
1613e12c5d1SDavid du Colombier 			a = a->next;
1623e12c5d1SDavid du Colombier 		}
163276e7d6dSDavid du Colombier 		pwrd(f, (char *)a->word);
1643e12c5d1SDavid du Colombier 	}
1653e12c5d1SDavid du Colombier }
166dc5a79c1SDavid du Colombier 
167dc5a79c1SDavid du Colombier int
168dc5a79c1SDavid du Colombier fullbuf(io *f, int c)
1693e12c5d1SDavid du Colombier {
1703e12c5d1SDavid du Colombier 	flush(f);
1713e12c5d1SDavid du Colombier 	return *f->bufp++=c;
1723e12c5d1SDavid du Colombier }
173dc5a79c1SDavid du Colombier 
174dc5a79c1SDavid du Colombier void
175dc5a79c1SDavid du Colombier flush(io *f)
1763e12c5d1SDavid du Colombier {
1773e12c5d1SDavid du Colombier 	int n;
178276e7d6dSDavid du Colombier 
1793e12c5d1SDavid du Colombier 	if(f->strp){
1803e12c5d1SDavid du Colombier 		n = f->ebuf - f->strp;
181276e7d6dSDavid du Colombier 		f->strp = realloc(f->strp, n+Stralloc+1);
182dc5a79c1SDavid du Colombier 		if(f->strp==0)
183276e7d6dSDavid du Colombier 			panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
1843e12c5d1SDavid du Colombier 		f->bufp = f->strp + n;
185276e7d6dSDavid du Colombier 		f->ebuf = f->bufp + Stralloc;
186276e7d6dSDavid du Colombier 		memset(f->bufp, '\0', Stralloc+1);
1873e12c5d1SDavid du Colombier 	}
1883e12c5d1SDavid du Colombier 	else{
1893e12c5d1SDavid du Colombier 		n = f->bufp-f->buf;
190276e7d6dSDavid du Colombier 		if(n && Write(f->fd, f->buf, n) != n){
191276e7d6dSDavid du Colombier 			Write(2, "Write error\n", 12);
192dc5a79c1SDavid du Colombier 			if(ntrap)
193dc5a79c1SDavid du Colombier 				dotrap();
1943e12c5d1SDavid du Colombier 		}
1953e12c5d1SDavid du Colombier 		f->bufp = f->buf;
1963e12c5d1SDavid du Colombier 		f->ebuf = f->buf+NBUF;
1973e12c5d1SDavid du Colombier 	}
1983e12c5d1SDavid du Colombier }
199dc5a79c1SDavid du Colombier 
200dc5a79c1SDavid du Colombier io*
201dc5a79c1SDavid du Colombier openfd(int fd)
202dc5a79c1SDavid du Colombier {
2033e12c5d1SDavid du Colombier 	io *f = new(struct io);
2043e12c5d1SDavid du Colombier 	f->fd = fd;
2053e12c5d1SDavid du Colombier 	f->bufp = f->ebuf = f->buf;
2063e12c5d1SDavid du Colombier 	f->strp = 0;
2073e12c5d1SDavid du Colombier 	return f;
2083e12c5d1SDavid du Colombier }
209dc5a79c1SDavid du Colombier 
210dc5a79c1SDavid du Colombier io*
211dc5a79c1SDavid du Colombier openstr(void)
212dc5a79c1SDavid du Colombier {
2133e12c5d1SDavid du Colombier 	io *f = new(struct io);
214276e7d6dSDavid du Colombier 
2153e12c5d1SDavid du Colombier 	f->fd = -1;
216276e7d6dSDavid du Colombier 	f->bufp = f->strp = emalloc(Stralloc+1);
217276e7d6dSDavid du Colombier 	f->ebuf = f->bufp + Stralloc;
218276e7d6dSDavid du Colombier 	memset(f->bufp, '\0', Stralloc+1);
2193e12c5d1SDavid du Colombier 	return f;
2203e12c5d1SDavid du Colombier }
2213e12c5d1SDavid du Colombier /*
2223e12c5d1SDavid du Colombier  * Open a corebuffer to read.  EOF occurs after reading len
2233e12c5d1SDavid du Colombier  * characters from buf.
2243e12c5d1SDavid du Colombier  */
225dc5a79c1SDavid du Colombier 
226dc5a79c1SDavid du Colombier io*
227dc5a79c1SDavid du Colombier opencore(char *s, int len)
2283e12c5d1SDavid du Colombier {
2293e12c5d1SDavid du Colombier 	io *f = new(struct io);
230276e7d6dSDavid du Colombier 	uchar *buf = emalloc(len);
231276e7d6dSDavid du Colombier 
2323e12c5d1SDavid du Colombier 	f->fd = -1 /*open("/dev/null", 0)*/;
2333e12c5d1SDavid du Colombier 	f->bufp = f->strp = buf;
2343e12c5d1SDavid du Colombier 	f->ebuf = buf+len;
2353e12c5d1SDavid du Colombier 	Memcpy(buf, s, len);
2363e12c5d1SDavid du Colombier 	return f;
2373e12c5d1SDavid du Colombier }
238dc5a79c1SDavid du Colombier 
239dc5a79c1SDavid du Colombier void
240dc5a79c1SDavid du Colombier rewind(io *io)
2413e12c5d1SDavid du Colombier {
242dc5a79c1SDavid du Colombier 	if(io->fd==-1)
243dc5a79c1SDavid du Colombier 		io->bufp = io->strp;
2443e12c5d1SDavid du Colombier 	else{
2453e12c5d1SDavid du Colombier 		io->bufp = io->ebuf = io->buf;
24699eb86a7SDavid du Colombier 		Seek(io->fd, 0L, 0);
2473e12c5d1SDavid du Colombier 	}
2483e12c5d1SDavid du Colombier }
249dc5a79c1SDavid du Colombier 
250dc5a79c1SDavid du Colombier void
251dc5a79c1SDavid du Colombier closeio(io *io)
2523e12c5d1SDavid du Colombier {
253dc5a79c1SDavid du Colombier 	if(io->fd>=0)
254dc5a79c1SDavid du Colombier 		close(io->fd);
255dc5a79c1SDavid du Colombier 	if(io->strp)
256dc5a79c1SDavid du Colombier 		efree(io->strp);
257276e7d6dSDavid du Colombier 	efree(io);
2583e12c5d1SDavid du Colombier }
259dc5a79c1SDavid du Colombier 
260dc5a79c1SDavid du Colombier int
261dc5a79c1SDavid du Colombier emptybuf(io *f)
2623e12c5d1SDavid du Colombier {
2633e12c5d1SDavid du Colombier 	int n;
26499eb86a7SDavid du Colombier 	if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
2653e12c5d1SDavid du Colombier 	f->bufp = f->buf;
2663e12c5d1SDavid du Colombier 	f->ebuf = f->buf + n;
267276e7d6dSDavid du Colombier 	return *f->bufp++;
2683e12c5d1SDavid du Colombier }
269