xref: /plan9/sys/src/cmd/fossil/Ccons.c (revision 5e96a66c77eb9140492ca53f857cbbf108e128ed)
1*5e96a66cSDavid du Colombier #include "stdinc.h"
2*5e96a66cSDavid du Colombier 
3*5e96a66cSDavid du Colombier #include "9.h"
4*5e96a66cSDavid du Colombier 
5*5e96a66cSDavid du Colombier enum {
6*5e96a66cSDavid du Colombier 	Nl	= 256,			/* max. command line length */
7*5e96a66cSDavid du Colombier 	Nq	= 8*1024,		/* amount of I/O buffered */
8*5e96a66cSDavid du Colombier };
9*5e96a66cSDavid du Colombier 
10*5e96a66cSDavid du Colombier typedef struct Q {
11*5e96a66cSDavid du Colombier 	VtLock*	lock;
12*5e96a66cSDavid du Colombier 	VtRendez* full;
13*5e96a66cSDavid du Colombier 	VtRendez* empty;
14*5e96a66cSDavid du Colombier 
15*5e96a66cSDavid du Colombier 	char	q[Nq];
16*5e96a66cSDavid du Colombier 	int	n;
17*5e96a66cSDavid du Colombier 	int	r;
18*5e96a66cSDavid du Colombier 	int	w;
19*5e96a66cSDavid du Colombier } Q;
20*5e96a66cSDavid du Colombier 
21*5e96a66cSDavid du Colombier typedef struct Cons {
22*5e96a66cSDavid du Colombier 	VtLock*	lock;
23*5e96a66cSDavid du Colombier 	int	ref;
24*5e96a66cSDavid du Colombier 	int	closed;
25*5e96a66cSDavid du Colombier 	int	fd;
26*5e96a66cSDavid du Colombier 	int	srvfd;
27*5e96a66cSDavid du Colombier 	int	ctlfd;
28*5e96a66cSDavid du Colombier 	Q*	iq;		/* points to console.iq */
29*5e96a66cSDavid du Colombier 	Q*	oq;		/* points to console.oq */
30*5e96a66cSDavid du Colombier } Cons;
31*5e96a66cSDavid du Colombier 
32*5e96a66cSDavid du Colombier static struct {
33*5e96a66cSDavid du Colombier 	Q*	iq;		/* input */
34*5e96a66cSDavid du Colombier 	Q*	oq;		/* output */
35*5e96a66cSDavid du Colombier 	char	l[Nl];		/* command line assembly */
36*5e96a66cSDavid du Colombier 	int	nl;		/* current line length */
37*5e96a66cSDavid du Colombier 
38*5e96a66cSDavid du Colombier 	char*	prompt;
39*5e96a66cSDavid du Colombier 	int	np;
40*5e96a66cSDavid du Colombier } console;
41*5e96a66cSDavid du Colombier 
42*5e96a66cSDavid du Colombier static void
43*5e96a66cSDavid du Colombier consClose(Cons* cons)
44*5e96a66cSDavid du Colombier {
45*5e96a66cSDavid du Colombier 	vtLock(cons->lock);
46*5e96a66cSDavid du Colombier 	cons->closed = 1;
47*5e96a66cSDavid du Colombier 
48*5e96a66cSDavid du Colombier 	cons->ref--;
49*5e96a66cSDavid du Colombier 	if(cons->ref > 0){
50*5e96a66cSDavid du Colombier 		vtLock(cons->iq->lock);
51*5e96a66cSDavid du Colombier 		vtWakeup(cons->iq->full);
52*5e96a66cSDavid du Colombier 		vtUnlock(cons->iq->lock);
53*5e96a66cSDavid du Colombier 		vtLock(cons->oq->lock);
54*5e96a66cSDavid du Colombier 		vtWakeup(cons->oq->empty);
55*5e96a66cSDavid du Colombier 		vtUnlock(cons->oq->lock);
56*5e96a66cSDavid du Colombier 		vtUnlock(cons->lock);
57*5e96a66cSDavid du Colombier 		return;
58*5e96a66cSDavid du Colombier 	}
59*5e96a66cSDavid du Colombier 
60*5e96a66cSDavid du Colombier 	if(cons->ctlfd != -1){
61*5e96a66cSDavid du Colombier 		close(cons->ctlfd);
62*5e96a66cSDavid du Colombier 		cons->srvfd = -1;
63*5e96a66cSDavid du Colombier 	}
64*5e96a66cSDavid du Colombier 	if(cons->srvfd != -1){
65*5e96a66cSDavid du Colombier 		close(cons->srvfd);
66*5e96a66cSDavid du Colombier 		cons->srvfd = -1;
67*5e96a66cSDavid du Colombier 	}
68*5e96a66cSDavid du Colombier 	if(cons->fd != -1){
69*5e96a66cSDavid du Colombier 		close(cons->fd);
70*5e96a66cSDavid du Colombier 		cons->fd = -1;
71*5e96a66cSDavid du Colombier 	}
72*5e96a66cSDavid du Colombier 
73*5e96a66cSDavid du Colombier 	vtUnlock(cons->lock);
74*5e96a66cSDavid du Colombier 	vtLockFree(cons->lock);
75*5e96a66cSDavid du Colombier 	vtMemFree(cons);
76*5e96a66cSDavid du Colombier }
77*5e96a66cSDavid du Colombier 
78*5e96a66cSDavid du Colombier static void
79*5e96a66cSDavid du Colombier consIProc(void* v)
80*5e96a66cSDavid du Colombier {
81*5e96a66cSDavid du Colombier 	Q *q;
82*5e96a66cSDavid du Colombier 	Cons *cons;
83*5e96a66cSDavid du Colombier 	int n, w;
84*5e96a66cSDavid du Colombier 	char buf[Nq/4];
85*5e96a66cSDavid du Colombier 
86*5e96a66cSDavid du Colombier 	vtThreadSetName("consI");
87*5e96a66cSDavid du Colombier 
88*5e96a66cSDavid du Colombier 	cons = v;
89*5e96a66cSDavid du Colombier 	q = cons->iq;
90*5e96a66cSDavid du Colombier 	for(;;){
91*5e96a66cSDavid du Colombier 		/*
92*5e96a66cSDavid du Colombier 		 * Can't tell the difference between zero-length read
93*5e96a66cSDavid du Colombier 		 * and eof, so keep calling read until we get an error.
94*5e96a66cSDavid du Colombier 		 */
95*5e96a66cSDavid du Colombier 		if(cons->closed || (n = read(cons->fd, buf, Nq/4)) < 0)
96*5e96a66cSDavid du Colombier 			break;
97*5e96a66cSDavid du Colombier 		vtLock(q->lock);
98*5e96a66cSDavid du Colombier 		while(Nq - q->n < n && !cons->closed)
99*5e96a66cSDavid du Colombier 			vtSleep(q->full);
100*5e96a66cSDavid du Colombier 		w = Nq - q->w;
101*5e96a66cSDavid du Colombier 		if(w < n){
102*5e96a66cSDavid du Colombier 			memmove(&q->q[q->w], buf, w);
103*5e96a66cSDavid du Colombier 			memmove(&q->q[0], buf + w, n - w);
104*5e96a66cSDavid du Colombier 		}
105*5e96a66cSDavid du Colombier 		else
106*5e96a66cSDavid du Colombier 			memmove(&q->q[q->w], buf, n);
107*5e96a66cSDavid du Colombier 		q->w = (q->w + n) % Nq;
108*5e96a66cSDavid du Colombier 		q->n += n;
109*5e96a66cSDavid du Colombier 		vtWakeup(q->empty);
110*5e96a66cSDavid du Colombier 		vtUnlock(q->lock);
111*5e96a66cSDavid du Colombier 	}
112*5e96a66cSDavid du Colombier 	consClose(cons);
113*5e96a66cSDavid du Colombier }
114*5e96a66cSDavid du Colombier 
115*5e96a66cSDavid du Colombier static void
116*5e96a66cSDavid du Colombier consOProc(void* v)
117*5e96a66cSDavid du Colombier {
118*5e96a66cSDavid du Colombier 	Q *q;
119*5e96a66cSDavid du Colombier 	Cons *cons;
120*5e96a66cSDavid du Colombier 	char buf[Nq];
121*5e96a66cSDavid du Colombier 	int lastn, n, r;
122*5e96a66cSDavid du Colombier 
123*5e96a66cSDavid du Colombier 	vtThreadSetName("consO");
124*5e96a66cSDavid du Colombier 
125*5e96a66cSDavid du Colombier 	cons = v;
126*5e96a66cSDavid du Colombier 	q = cons->oq;
127*5e96a66cSDavid du Colombier 	vtLock(q->lock);
128*5e96a66cSDavid du Colombier 	lastn = 0;
129*5e96a66cSDavid du Colombier 	for(;;){
130*5e96a66cSDavid du Colombier 		while(lastn == q->n && !cons->closed)
131*5e96a66cSDavid du Colombier 			vtSleep(q->empty);
132*5e96a66cSDavid du Colombier 		if((n = q->n - lastn) > Nq)
133*5e96a66cSDavid du Colombier 			n = Nq;
134*5e96a66cSDavid du Colombier 		if(n > q->w){
135*5e96a66cSDavid du Colombier 			r = n - q->w;
136*5e96a66cSDavid du Colombier 			memmove(buf, &q->q[Nq - r], r);
137*5e96a66cSDavid du Colombier 			memmove(buf+r, &q->q[0], n - r);
138*5e96a66cSDavid du Colombier 		}
139*5e96a66cSDavid du Colombier 		else
140*5e96a66cSDavid du Colombier 			memmove(buf, &q->q[q->w - n], n);
141*5e96a66cSDavid du Colombier 		lastn = q->n;
142*5e96a66cSDavid du Colombier 		vtUnlock(q->lock);
143*5e96a66cSDavid du Colombier 		if(cons->closed || write(cons->fd, buf, n) < 0)
144*5e96a66cSDavid du Colombier 			break;
145*5e96a66cSDavid du Colombier 		vtLock(q->lock);
146*5e96a66cSDavid du Colombier 		vtWakeup(q->empty);
147*5e96a66cSDavid du Colombier 	}
148*5e96a66cSDavid du Colombier 	consClose(cons);
149*5e96a66cSDavid du Colombier }
150*5e96a66cSDavid du Colombier 
151*5e96a66cSDavid du Colombier int
152*5e96a66cSDavid du Colombier consOpen(int fd, int srvfd, int ctlfd)
153*5e96a66cSDavid du Colombier {
154*5e96a66cSDavid du Colombier 	Cons *cons;
155*5e96a66cSDavid du Colombier 
156*5e96a66cSDavid du Colombier 	cons = vtMemAllocZ(sizeof(Cons));
157*5e96a66cSDavid du Colombier 	cons->lock = vtLockAlloc();
158*5e96a66cSDavid du Colombier 	cons->fd = fd;
159*5e96a66cSDavid du Colombier 	cons->srvfd = srvfd;
160*5e96a66cSDavid du Colombier 	cons->ctlfd = ctlfd;
161*5e96a66cSDavid du Colombier 	cons->iq = console.iq;
162*5e96a66cSDavid du Colombier 	cons->oq = console.oq;
163*5e96a66cSDavid du Colombier 
164*5e96a66cSDavid du Colombier 	vtLock(cons->lock);
165*5e96a66cSDavid du Colombier 	cons->ref = 2;
166*5e96a66cSDavid du Colombier 	cons->closed = 0;
167*5e96a66cSDavid du Colombier 	if(vtThread(consOProc, cons) < 0){
168*5e96a66cSDavid du Colombier 		cons->ref--;
169*5e96a66cSDavid du Colombier 		vtUnlock(cons->lock);
170*5e96a66cSDavid du Colombier 		consClose(cons);
171*5e96a66cSDavid du Colombier 		return 0;
172*5e96a66cSDavid du Colombier 	}
173*5e96a66cSDavid du Colombier 	vtUnlock(cons->lock);
174*5e96a66cSDavid du Colombier 
175*5e96a66cSDavid du Colombier 	if(ctlfd >= 0)
176*5e96a66cSDavid du Colombier 		consIProc(cons);
177*5e96a66cSDavid du Colombier 	else if(vtThread(consIProc, cons) < 0){
178*5e96a66cSDavid du Colombier 		consClose(cons);
179*5e96a66cSDavid du Colombier 		return 0;
180*5e96a66cSDavid du Colombier 	}
181*5e96a66cSDavid du Colombier 
182*5e96a66cSDavid du Colombier 	return 1;
183*5e96a66cSDavid du Colombier }
184*5e96a66cSDavid du Colombier 
185*5e96a66cSDavid du Colombier static int
186*5e96a66cSDavid du Colombier qWrite(Q* q, char* p, int n)
187*5e96a66cSDavid du Colombier {
188*5e96a66cSDavid du Colombier 	int w;
189*5e96a66cSDavid du Colombier 
190*5e96a66cSDavid du Colombier 	vtLock(q->lock);
191*5e96a66cSDavid du Colombier 	if(n > Nq - q->w){
192*5e96a66cSDavid du Colombier 		w = Nq - q->w;
193*5e96a66cSDavid du Colombier 		memmove(&q->q[q->w], p, w);
194*5e96a66cSDavid du Colombier 		memmove(&q->q[0], p + w, n - w);
195*5e96a66cSDavid du Colombier 		q->w = n - w;
196*5e96a66cSDavid du Colombier 	}
197*5e96a66cSDavid du Colombier 	else{
198*5e96a66cSDavid du Colombier 		memmove(&q->q[q->w], p, n);
199*5e96a66cSDavid du Colombier 		q->w += n;
200*5e96a66cSDavid du Colombier 	}
201*5e96a66cSDavid du Colombier 	q->n += n;
202*5e96a66cSDavid du Colombier 	vtWakeup(q->empty);
203*5e96a66cSDavid du Colombier 	vtUnlock(q->lock);
204*5e96a66cSDavid du Colombier 
205*5e96a66cSDavid du Colombier 	return n;
206*5e96a66cSDavid du Colombier }
207*5e96a66cSDavid du Colombier 
208*5e96a66cSDavid du Colombier static Q*
209*5e96a66cSDavid du Colombier qAlloc(void)
210*5e96a66cSDavid du Colombier {
211*5e96a66cSDavid du Colombier 	Q *q;
212*5e96a66cSDavid du Colombier 
213*5e96a66cSDavid du Colombier 	q = vtMemAllocZ(sizeof(Q));
214*5e96a66cSDavid du Colombier 	q->lock = vtLockAlloc();
215*5e96a66cSDavid du Colombier 	q->full = vtRendezAlloc(q->lock);
216*5e96a66cSDavid du Colombier 	q->empty = vtRendezAlloc(q->lock);
217*5e96a66cSDavid du Colombier 	q->n = q->r = q->w = 0;
218*5e96a66cSDavid du Colombier 
219*5e96a66cSDavid du Colombier 	return q;
220*5e96a66cSDavid du Colombier }
221*5e96a66cSDavid du Colombier 
222*5e96a66cSDavid du Colombier static void
223*5e96a66cSDavid du Colombier consProc(void*)
224*5e96a66cSDavid du Colombier {
225*5e96a66cSDavid du Colombier 	Q *q;
226*5e96a66cSDavid du Colombier 	int argc, i, n, r;
227*5e96a66cSDavid du Colombier 	char *argv[20], buf[Nq], *lp, *wbuf;
228*5e96a66cSDavid du Colombier 
229*5e96a66cSDavid du Colombier 	vtThreadSetName("cons");
230*5e96a66cSDavid du Colombier 
231*5e96a66cSDavid du Colombier 	q = console.iq;
232*5e96a66cSDavid du Colombier 	qWrite(console.oq, console.prompt, console.np);
233*5e96a66cSDavid du Colombier 	vtLock(q->lock);
234*5e96a66cSDavid du Colombier 	for(;;){
235*5e96a66cSDavid du Colombier 		while((n = q->n) == 0)
236*5e96a66cSDavid du Colombier 			vtSleep(q->empty);
237*5e96a66cSDavid du Colombier 		r = Nq - q->r;
238*5e96a66cSDavid du Colombier 		if(r < n){
239*5e96a66cSDavid du Colombier 			memmove(buf, &q->q[q->r], r);
240*5e96a66cSDavid du Colombier 			memmove(buf + r, &q->q[0], n - r);
241*5e96a66cSDavid du Colombier 		}
242*5e96a66cSDavid du Colombier 		else
243*5e96a66cSDavid du Colombier 			memmove(buf, &q->q[q->r], n);
244*5e96a66cSDavid du Colombier 		q->r = (q->r + n) % Nq;
245*5e96a66cSDavid du Colombier 		q->n -= n;
246*5e96a66cSDavid du Colombier 		vtWakeup(q->full);
247*5e96a66cSDavid du Colombier 		vtUnlock(q->lock);
248*5e96a66cSDavid du Colombier 
249*5e96a66cSDavid du Colombier 		for(i = 0; i < n; i++){
250*5e96a66cSDavid du Colombier 			switch(buf[i]){
251*5e96a66cSDavid du Colombier 			case '\004':				/* ^D */
252*5e96a66cSDavid du Colombier 				if(console.nl == 0){
253*5e96a66cSDavid du Colombier 					qWrite(console.oq, "\n", 1);
254*5e96a66cSDavid du Colombier 					break;
255*5e96a66cSDavid du Colombier 				}
256*5e96a66cSDavid du Colombier 				/*FALLTHROUGH*/
257*5e96a66cSDavid du Colombier 			default:
258*5e96a66cSDavid du Colombier 				if(console.nl < Nl-1){
259*5e96a66cSDavid du Colombier 					qWrite(console.oq, &buf[i], 1);
260*5e96a66cSDavid du Colombier 					console.l[console.nl++] = buf[i];
261*5e96a66cSDavid du Colombier 				}
262*5e96a66cSDavid du Colombier 				continue;
263*5e96a66cSDavid du Colombier 			case '\b':
264*5e96a66cSDavid du Colombier 				if(console.nl != 0){
265*5e96a66cSDavid du Colombier 					qWrite(console.oq, &buf[i], 1);
266*5e96a66cSDavid du Colombier 					console.nl--;
267*5e96a66cSDavid du Colombier 				}
268*5e96a66cSDavid du Colombier 				continue;
269*5e96a66cSDavid du Colombier 			case '\n':
270*5e96a66cSDavid du Colombier 				qWrite(console.oq, &buf[i], 1);
271*5e96a66cSDavid du Colombier 				break;
272*5e96a66cSDavid du Colombier 			case '\025':				/* ^U */
273*5e96a66cSDavid du Colombier 				qWrite(console.oq, "^U\n", 3);
274*5e96a66cSDavid du Colombier 				console.nl = 0;
275*5e96a66cSDavid du Colombier 				break;
276*5e96a66cSDavid du Colombier 			case '\027':				/* ^W */
277*5e96a66cSDavid du Colombier 				console.l[console.nl] = '\0';
278*5e96a66cSDavid du Colombier 				wbuf = vtMemAlloc(console.nl+1);
279*5e96a66cSDavid du Colombier 				memmove(wbuf, console.l, console.nl+1);
280*5e96a66cSDavid du Colombier 				argc = tokenize(wbuf, argv, nelem(argv));
281*5e96a66cSDavid du Colombier 				if(argc > 0)
282*5e96a66cSDavid du Colombier 					argc--;
283*5e96a66cSDavid du Colombier 				console.nl = 0;
284*5e96a66cSDavid du Colombier 				lp = console.l;
285*5e96a66cSDavid du Colombier 				for(i = 0; i < argc; i++)
286*5e96a66cSDavid du Colombier 					lp += sprint(lp, "%q ", argv[i]);
287*5e96a66cSDavid du Colombier 				console.nl = lp - console.l;
288*5e96a66cSDavid du Colombier 				vtMemFree(wbuf);
289*5e96a66cSDavid du Colombier 				qWrite(console.oq, "^W\n", 3);
290*5e96a66cSDavid du Colombier 				if(console.nl == 0)
291*5e96a66cSDavid du Colombier 					break;
292*5e96a66cSDavid du Colombier 				qWrite(console.oq, console.l, console.nl);
293*5e96a66cSDavid du Colombier 				continue;
294*5e96a66cSDavid du Colombier 			case '\177':
295*5e96a66cSDavid du Colombier 				qWrite(console.oq, "\n", 1);
296*5e96a66cSDavid du Colombier 				console.nl = 0;
297*5e96a66cSDavid du Colombier 				break;
298*5e96a66cSDavid du Colombier 			}
299*5e96a66cSDavid du Colombier 
300*5e96a66cSDavid du Colombier 			console.l[console.nl] = '\0';
301*5e96a66cSDavid du Colombier 			if(console.nl != 0)
302*5e96a66cSDavid du Colombier 				cliExec(console.l);
303*5e96a66cSDavid du Colombier 
304*5e96a66cSDavid du Colombier 			console.nl = 0;
305*5e96a66cSDavid du Colombier 			qWrite(console.oq, console.prompt, console.np);
306*5e96a66cSDavid du Colombier 		}
307*5e96a66cSDavid du Colombier 
308*5e96a66cSDavid du Colombier 		vtLock(q->lock);
309*5e96a66cSDavid du Colombier 	}
310*5e96a66cSDavid du Colombier }
311*5e96a66cSDavid du Colombier 
312*5e96a66cSDavid du Colombier int
313*5e96a66cSDavid du Colombier consWrite(char* buf, int len)
314*5e96a66cSDavid du Colombier {
315*5e96a66cSDavid du Colombier 	if(console.oq == nil)
316*5e96a66cSDavid du Colombier 		return fprint(2, buf, len);
317*5e96a66cSDavid du Colombier 	return qWrite(console.oq, buf, len);
318*5e96a66cSDavid du Colombier }
319*5e96a66cSDavid du Colombier 
320*5e96a66cSDavid du Colombier int
321*5e96a66cSDavid du Colombier consPrompt(char* prompt)
322*5e96a66cSDavid du Colombier {
323*5e96a66cSDavid du Colombier 	char buf[ERRMAX];
324*5e96a66cSDavid du Colombier 
325*5e96a66cSDavid du Colombier 	if(prompt == nil)
326*5e96a66cSDavid du Colombier 		prompt = "prompt";
327*5e96a66cSDavid du Colombier 
328*5e96a66cSDavid du Colombier 	vtMemFree(console.prompt);
329*5e96a66cSDavid du Colombier 	console.np = snprint(buf, sizeof(buf), "%s: ", prompt);
330*5e96a66cSDavid du Colombier 	console.prompt = vtStrDup(buf);
331*5e96a66cSDavid du Colombier 
332*5e96a66cSDavid du Colombier 	return console.np;
333*5e96a66cSDavid du Colombier }
334*5e96a66cSDavid du Colombier 
335*5e96a66cSDavid du Colombier int
336*5e96a66cSDavid du Colombier consTTY(void)
337*5e96a66cSDavid du Colombier {
338*5e96a66cSDavid du Colombier 	int ctl, fd;
339*5e96a66cSDavid du Colombier 	char *name, *p;
340*5e96a66cSDavid du Colombier 
341*5e96a66cSDavid du Colombier 	name = "/dev/cons";
342*5e96a66cSDavid du Colombier 	if((fd = open(name, ORDWR)) < 0){
343*5e96a66cSDavid du Colombier 		name = "#c/cons";
344*5e96a66cSDavid du Colombier 		if((fd = open(name, ORDWR)) < 0){
345*5e96a66cSDavid du Colombier 			vtSetError("consTTY: open %s: %r", name);
346*5e96a66cSDavid du Colombier 			return 0;
347*5e96a66cSDavid du Colombier 		}
348*5e96a66cSDavid du Colombier 	}
349*5e96a66cSDavid du Colombier 
350*5e96a66cSDavid du Colombier 	p = smprint("%sctl", name);
351*5e96a66cSDavid du Colombier 	if((ctl = open(p, OWRITE)) < 0){
352*5e96a66cSDavid du Colombier 		close(fd);
353*5e96a66cSDavid du Colombier 		vtSetError("consTTY: open %s: %r", p);
354*5e96a66cSDavid du Colombier 		free(p);
355*5e96a66cSDavid du Colombier 		return 0;
356*5e96a66cSDavid du Colombier 	}
357*5e96a66cSDavid du Colombier 	if(write(ctl, "rawon", 5) < 0){
358*5e96a66cSDavid du Colombier 		close(ctl);
359*5e96a66cSDavid du Colombier 		close(fd);
360*5e96a66cSDavid du Colombier 		vtSetError("consTTY: write %s: %r", p);
361*5e96a66cSDavid du Colombier 		free(p);
362*5e96a66cSDavid du Colombier 		return 0;
363*5e96a66cSDavid du Colombier 	}
364*5e96a66cSDavid du Colombier 	free(p);
365*5e96a66cSDavid du Colombier 
366*5e96a66cSDavid du Colombier 	if(consOpen(fd, fd, ctl) == 0){
367*5e96a66cSDavid du Colombier 		close(ctl);
368*5e96a66cSDavid du Colombier 		close(fd);
369*5e96a66cSDavid du Colombier 		return 0;
370*5e96a66cSDavid du Colombier 	}
371*5e96a66cSDavid du Colombier 
372*5e96a66cSDavid du Colombier 	return 1;
373*5e96a66cSDavid du Colombier }
374*5e96a66cSDavid du Colombier 
375*5e96a66cSDavid du Colombier int
376*5e96a66cSDavid du Colombier consInit(void)
377*5e96a66cSDavid du Colombier {
378*5e96a66cSDavid du Colombier 	console.iq = qAlloc();
379*5e96a66cSDavid du Colombier 	console.oq = qAlloc();
380*5e96a66cSDavid du Colombier 	console.nl = 0;
381*5e96a66cSDavid du Colombier 
382*5e96a66cSDavid du Colombier 	consPrompt(nil);
383*5e96a66cSDavid du Colombier 
384*5e96a66cSDavid du Colombier 	if(vtThread(consProc, nil) < 0){
385*5e96a66cSDavid du Colombier 		vtFatal("can't start console proc");
386*5e96a66cSDavid du Colombier 		return 0;
387*5e96a66cSDavid du Colombier 	}
388*5e96a66cSDavid du Colombier 
389*5e96a66cSDavid du Colombier 	return 1;
390*5e96a66cSDavid du Colombier }
391