xref: /plan9/sys/src/cmd/fossil/Ccons.c (revision b8a11165c6411897fdf740a1fb2f87ac0998b113)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier 
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier 
55e96a66cSDavid du Colombier enum {
65e96a66cSDavid du Colombier 	Nl	= 256,			/* max. command line length */
75e96a66cSDavid du Colombier 	Nq	= 8*1024,		/* amount of I/O buffered */
85e96a66cSDavid du Colombier };
95e96a66cSDavid du Colombier 
105e96a66cSDavid du Colombier typedef struct Q {
115e96a66cSDavid du Colombier 	VtLock*	lock;
125e96a66cSDavid du Colombier 	VtRendez* full;
135e96a66cSDavid du Colombier 	VtRendez* empty;
145e96a66cSDavid du Colombier 
155e96a66cSDavid du Colombier 	char	q[Nq];
165e96a66cSDavid du Colombier 	int	n;
175e96a66cSDavid du Colombier 	int	r;
185e96a66cSDavid du Colombier 	int	w;
195e96a66cSDavid du Colombier } Q;
205e96a66cSDavid du Colombier 
215e96a66cSDavid du Colombier typedef struct Cons {
225e96a66cSDavid du Colombier 	VtLock*	lock;
235e96a66cSDavid du Colombier 	int	ref;
245e96a66cSDavid du Colombier 	int	closed;
255e96a66cSDavid du Colombier 	int	fd;
265e96a66cSDavid du Colombier 	int	srvfd;
275e96a66cSDavid du Colombier 	int	ctlfd;
285e96a66cSDavid du Colombier 	Q*	iq;		/* points to console.iq */
295e96a66cSDavid du Colombier 	Q*	oq;		/* points to console.oq */
305e96a66cSDavid du Colombier } Cons;
315e96a66cSDavid du Colombier 
32*b8a11165SDavid du Colombier char *currfsysname;
33*b8a11165SDavid du Colombier 
345e96a66cSDavid du Colombier static struct {
355e96a66cSDavid du Colombier 	Q*	iq;		/* input */
365e96a66cSDavid du Colombier 	Q*	oq;		/* output */
375e96a66cSDavid du Colombier 	char	l[Nl];		/* command line assembly */
385e96a66cSDavid du Colombier 	int	nl;		/* current line length */
39dc5a79c1SDavid du Colombier 	int	nopens;
405e96a66cSDavid du Colombier 
415e96a66cSDavid du Colombier 	char*	prompt;
425e96a66cSDavid du Colombier 	int	np;
435e96a66cSDavid du Colombier } console;
445e96a66cSDavid du Colombier 
455e96a66cSDavid du Colombier static void
consClose(Cons * cons)465e96a66cSDavid du Colombier consClose(Cons* cons)
475e96a66cSDavid du Colombier {
485e96a66cSDavid du Colombier 	vtLock(cons->lock);
495e96a66cSDavid du Colombier 	cons->closed = 1;
505e96a66cSDavid du Colombier 
515e96a66cSDavid du Colombier 	cons->ref--;
525e96a66cSDavid du Colombier 	if(cons->ref > 0){
535e96a66cSDavid du Colombier 		vtLock(cons->iq->lock);
545e96a66cSDavid du Colombier 		vtWakeup(cons->iq->full);
555e96a66cSDavid du Colombier 		vtUnlock(cons->iq->lock);
565e96a66cSDavid du Colombier 		vtLock(cons->oq->lock);
575e96a66cSDavid du Colombier 		vtWakeup(cons->oq->empty);
585e96a66cSDavid du Colombier 		vtUnlock(cons->oq->lock);
595e96a66cSDavid du Colombier 		vtUnlock(cons->lock);
605e96a66cSDavid du Colombier 		return;
615e96a66cSDavid du Colombier 	}
625e96a66cSDavid du Colombier 
635e96a66cSDavid du Colombier 	if(cons->ctlfd != -1){
645e96a66cSDavid du Colombier 		close(cons->ctlfd);
655e96a66cSDavid du Colombier 		cons->srvfd = -1;
665e96a66cSDavid du Colombier 	}
675e96a66cSDavid du Colombier 	if(cons->srvfd != -1){
685e96a66cSDavid du Colombier 		close(cons->srvfd);
695e96a66cSDavid du Colombier 		cons->srvfd = -1;
705e96a66cSDavid du Colombier 	}
715e96a66cSDavid du Colombier 	if(cons->fd != -1){
725e96a66cSDavid du Colombier 		close(cons->fd);
735e96a66cSDavid du Colombier 		cons->fd = -1;
745e96a66cSDavid du Colombier 	}
755e96a66cSDavid du Colombier 	vtUnlock(cons->lock);
765e96a66cSDavid du Colombier 	vtLockFree(cons->lock);
775e96a66cSDavid du Colombier 	vtMemFree(cons);
78dc5a79c1SDavid du Colombier 	console.nopens--;
795e96a66cSDavid du Colombier }
805e96a66cSDavid du Colombier 
815e96a66cSDavid du Colombier static void
consIProc(void * v)825e96a66cSDavid du Colombier consIProc(void* v)
835e96a66cSDavid du Colombier {
845e96a66cSDavid du Colombier 	Q *q;
855e96a66cSDavid du Colombier 	Cons *cons;
865e96a66cSDavid du Colombier 	int n, w;
875e96a66cSDavid du Colombier 	char buf[Nq/4];
885e96a66cSDavid du Colombier 
895e96a66cSDavid du Colombier 	vtThreadSetName("consI");
905e96a66cSDavid du Colombier 
915e96a66cSDavid du Colombier 	cons = v;
925e96a66cSDavid du Colombier 	q = cons->iq;
935e96a66cSDavid du Colombier 	for(;;){
945e96a66cSDavid du Colombier 		/*
955e96a66cSDavid du Colombier 		 * Can't tell the difference between zero-length read
965e96a66cSDavid du Colombier 		 * and eof, so keep calling read until we get an error.
975e96a66cSDavid du Colombier 		 */
985e96a66cSDavid du Colombier 		if(cons->closed || (n = read(cons->fd, buf, Nq/4)) < 0)
995e96a66cSDavid du Colombier 			break;
1005e96a66cSDavid du Colombier 		vtLock(q->lock);
1015e96a66cSDavid du Colombier 		while(Nq - q->n < n && !cons->closed)
1025e96a66cSDavid du Colombier 			vtSleep(q->full);
1035e96a66cSDavid du Colombier 		w = Nq - q->w;
1045e96a66cSDavid du Colombier 		if(w < n){
1055e96a66cSDavid du Colombier 			memmove(&q->q[q->w], buf, w);
1065e96a66cSDavid du Colombier 			memmove(&q->q[0], buf + w, n - w);
1075e96a66cSDavid du Colombier 		}
1085e96a66cSDavid du Colombier 		else
1095e96a66cSDavid du Colombier 			memmove(&q->q[q->w], buf, n);
1105e96a66cSDavid du Colombier 		q->w = (q->w + n) % Nq;
1115e96a66cSDavid du Colombier 		q->n += n;
1125e96a66cSDavid du Colombier 		vtWakeup(q->empty);
1135e96a66cSDavid du Colombier 		vtUnlock(q->lock);
1145e96a66cSDavid du Colombier 	}
1155e96a66cSDavid du Colombier 	consClose(cons);
1165e96a66cSDavid du Colombier }
1175e96a66cSDavid du Colombier 
1185e96a66cSDavid du Colombier static void
consOProc(void * v)1195e96a66cSDavid du Colombier consOProc(void* v)
1205e96a66cSDavid du Colombier {
1215e96a66cSDavid du Colombier 	Q *q;
1225e96a66cSDavid du Colombier 	Cons *cons;
1235e96a66cSDavid du Colombier 	char buf[Nq];
1245e96a66cSDavid du Colombier 	int lastn, n, r;
1255e96a66cSDavid du Colombier 
1265e96a66cSDavid du Colombier 	vtThreadSetName("consO");
1275e96a66cSDavid du Colombier 
1285e96a66cSDavid du Colombier 	cons = v;
1295e96a66cSDavid du Colombier 	q = cons->oq;
1305e96a66cSDavid du Colombier 	vtLock(q->lock);
1315e96a66cSDavid du Colombier 	lastn = 0;
1325e96a66cSDavid du Colombier 	for(;;){
1335e96a66cSDavid du Colombier 		while(lastn == q->n && !cons->closed)
1345e96a66cSDavid du Colombier 			vtSleep(q->empty);
1355e96a66cSDavid du Colombier 		if((n = q->n - lastn) > Nq)
1365e96a66cSDavid du Colombier 			n = Nq;
1375e96a66cSDavid du Colombier 		if(n > q->w){
1385e96a66cSDavid du Colombier 			r = n - q->w;
1395e96a66cSDavid du Colombier 			memmove(buf, &q->q[Nq - r], r);
1405e96a66cSDavid du Colombier 			memmove(buf+r, &q->q[0], n - r);
1415e96a66cSDavid du Colombier 		}
1425e96a66cSDavid du Colombier 		else
1435e96a66cSDavid du Colombier 			memmove(buf, &q->q[q->w - n], n);
1445e96a66cSDavid du Colombier 		lastn = q->n;
1455e96a66cSDavid du Colombier 		vtUnlock(q->lock);
1465e96a66cSDavid du Colombier 		if(cons->closed || write(cons->fd, buf, n) < 0)
1475e96a66cSDavid du Colombier 			break;
1485e96a66cSDavid du Colombier 		vtLock(q->lock);
1495e96a66cSDavid du Colombier 		vtWakeup(q->empty);
1505e96a66cSDavid du Colombier 	}
1515e96a66cSDavid du Colombier 	consClose(cons);
1525e96a66cSDavid du Colombier }
1535e96a66cSDavid du Colombier 
1545e96a66cSDavid du Colombier int
consOpen(int fd,int srvfd,int ctlfd)1555e96a66cSDavid du Colombier consOpen(int fd, int srvfd, int ctlfd)
1565e96a66cSDavid du Colombier {
1575e96a66cSDavid du Colombier 	Cons *cons;
1585e96a66cSDavid du Colombier 
1595e96a66cSDavid du Colombier 	cons = vtMemAllocZ(sizeof(Cons));
1605e96a66cSDavid du Colombier 	cons->lock = vtLockAlloc();
1615e96a66cSDavid du Colombier 	cons->fd = fd;
1625e96a66cSDavid du Colombier 	cons->srvfd = srvfd;
1635e96a66cSDavid du Colombier 	cons->ctlfd = ctlfd;
1645e96a66cSDavid du Colombier 	cons->iq = console.iq;
1655e96a66cSDavid du Colombier 	cons->oq = console.oq;
166dc5a79c1SDavid du Colombier 	console.nopens++;
1675e96a66cSDavid du Colombier 
1685e96a66cSDavid du Colombier 	vtLock(cons->lock);
1695e96a66cSDavid du Colombier 	cons->ref = 2;
1705e96a66cSDavid du Colombier 	cons->closed = 0;
1715e96a66cSDavid du Colombier 	if(vtThread(consOProc, cons) < 0){
1725e96a66cSDavid du Colombier 		cons->ref--;
1735e96a66cSDavid du Colombier 		vtUnlock(cons->lock);
1745e96a66cSDavid du Colombier 		consClose(cons);
1755e96a66cSDavid du Colombier 		return 0;
1765e96a66cSDavid du Colombier 	}
1775e96a66cSDavid du Colombier 	vtUnlock(cons->lock);
1785e96a66cSDavid du Colombier 
1795e96a66cSDavid du Colombier 	if(ctlfd >= 0)
1805e96a66cSDavid du Colombier 		consIProc(cons);
1815e96a66cSDavid du Colombier 	else if(vtThread(consIProc, cons) < 0){
1825e96a66cSDavid du Colombier 		consClose(cons);
1835e96a66cSDavid du Colombier 		return 0;
1845e96a66cSDavid du Colombier 	}
1855e96a66cSDavid du Colombier 
1865e96a66cSDavid du Colombier 	return 1;
1875e96a66cSDavid du Colombier }
1885e96a66cSDavid du Colombier 
1895e96a66cSDavid du Colombier static int
qWrite(Q * q,char * p,int n)1905e96a66cSDavid du Colombier qWrite(Q* q, char* p, int n)
1915e96a66cSDavid du Colombier {
1925e96a66cSDavid du Colombier 	int w;
1935e96a66cSDavid du Colombier 
1945e96a66cSDavid du Colombier 	vtLock(q->lock);
1955e96a66cSDavid du Colombier 	if(n > Nq - q->w){
1965e96a66cSDavid du Colombier 		w = Nq - q->w;
1975e96a66cSDavid du Colombier 		memmove(&q->q[q->w], p, w);
1985e96a66cSDavid du Colombier 		memmove(&q->q[0], p + w, n - w);
1995e96a66cSDavid du Colombier 		q->w = n - w;
2005e96a66cSDavid du Colombier 	}
2015e96a66cSDavid du Colombier 	else{
2025e96a66cSDavid du Colombier 		memmove(&q->q[q->w], p, n);
2035e96a66cSDavid du Colombier 		q->w += n;
2045e96a66cSDavid du Colombier 	}
2055e96a66cSDavid du Colombier 	q->n += n;
2065e96a66cSDavid du Colombier 	vtWakeup(q->empty);
2075e96a66cSDavid du Colombier 	vtUnlock(q->lock);
2085e96a66cSDavid du Colombier 
2095e96a66cSDavid du Colombier 	return n;
2105e96a66cSDavid du Colombier }
2115e96a66cSDavid du Colombier 
2125e96a66cSDavid du Colombier static Q*
qAlloc(void)2135e96a66cSDavid du Colombier qAlloc(void)
2145e96a66cSDavid du Colombier {
2155e96a66cSDavid du Colombier 	Q *q;
2165e96a66cSDavid du Colombier 
2175e96a66cSDavid du Colombier 	q = vtMemAllocZ(sizeof(Q));
2185e96a66cSDavid du Colombier 	q->lock = vtLockAlloc();
2195e96a66cSDavid du Colombier 	q->full = vtRendezAlloc(q->lock);
2205e96a66cSDavid du Colombier 	q->empty = vtRendezAlloc(q->lock);
2215e96a66cSDavid du Colombier 	q->n = q->r = q->w = 0;
2225e96a66cSDavid du Colombier 
2235e96a66cSDavid du Colombier 	return q;
2245e96a66cSDavid du Colombier }
2255e96a66cSDavid du Colombier 
2265e96a66cSDavid du Colombier static void
consProc(void *)2275e96a66cSDavid du Colombier consProc(void*)
2285e96a66cSDavid du Colombier {
2295e96a66cSDavid du Colombier 	Q *q;
2305e96a66cSDavid du Colombier 	int argc, i, n, r;
2315e96a66cSDavid du Colombier 	char *argv[20], buf[Nq], *lp, *wbuf;
232*b8a11165SDavid du Colombier 	char procname[64];
2335e96a66cSDavid du Colombier 
234*b8a11165SDavid du Colombier 	snprint(procname, sizeof procname, "cons %s", currfsysname);
235*b8a11165SDavid du Colombier 	vtThreadSetName(procname);
2365e96a66cSDavid du Colombier 
2375e96a66cSDavid du Colombier 	q = console.iq;
2385e96a66cSDavid du Colombier 	qWrite(console.oq, console.prompt, console.np);
2395e96a66cSDavid du Colombier 	vtLock(q->lock);
2405e96a66cSDavid du Colombier 	for(;;){
2415e96a66cSDavid du Colombier 		while((n = q->n) == 0)
2425e96a66cSDavid du Colombier 			vtSleep(q->empty);
2435e96a66cSDavid du Colombier 		r = Nq - q->r;
2445e96a66cSDavid du Colombier 		if(r < n){
2455e96a66cSDavid du Colombier 			memmove(buf, &q->q[q->r], r);
2465e96a66cSDavid du Colombier 			memmove(buf + r, &q->q[0], n - r);
2475e96a66cSDavid du Colombier 		}
2485e96a66cSDavid du Colombier 		else
2495e96a66cSDavid du Colombier 			memmove(buf, &q->q[q->r], n);
2505e96a66cSDavid du Colombier 		q->r = (q->r + n) % Nq;
2515e96a66cSDavid du Colombier 		q->n -= n;
2525e96a66cSDavid du Colombier 		vtWakeup(q->full);
2535e96a66cSDavid du Colombier 		vtUnlock(q->lock);
2545e96a66cSDavid du Colombier 
2555e96a66cSDavid du Colombier 		for(i = 0; i < n; i++){
2565e96a66cSDavid du Colombier 			switch(buf[i]){
2575e96a66cSDavid du Colombier 			case '\004':				/* ^D */
2585e96a66cSDavid du Colombier 				if(console.nl == 0){
2595e96a66cSDavid du Colombier 					qWrite(console.oq, "\n", 1);
2605e96a66cSDavid du Colombier 					break;
2615e96a66cSDavid du Colombier 				}
2625e96a66cSDavid du Colombier 				/*FALLTHROUGH*/
2635e96a66cSDavid du Colombier 			default:
2645e96a66cSDavid du Colombier 				if(console.nl < Nl-1){
2655e96a66cSDavid du Colombier 					qWrite(console.oq, &buf[i], 1);
2665e96a66cSDavid du Colombier 					console.l[console.nl++] = buf[i];
2675e96a66cSDavid du Colombier 				}
2685e96a66cSDavid du Colombier 				continue;
2695e96a66cSDavid du Colombier 			case '\b':
2705e96a66cSDavid du Colombier 				if(console.nl != 0){
2715e96a66cSDavid du Colombier 					qWrite(console.oq, &buf[i], 1);
2725e96a66cSDavid du Colombier 					console.nl--;
2735e96a66cSDavid du Colombier 				}
2745e96a66cSDavid du Colombier 				continue;
2755e96a66cSDavid du Colombier 			case '\n':
2765e96a66cSDavid du Colombier 				qWrite(console.oq, &buf[i], 1);
2775e96a66cSDavid du Colombier 				break;
2785e96a66cSDavid du Colombier 			case '\025':				/* ^U */
2795e96a66cSDavid du Colombier 				qWrite(console.oq, "^U\n", 3);
2805e96a66cSDavid du Colombier 				console.nl = 0;
2815e96a66cSDavid du Colombier 				break;
2825e96a66cSDavid du Colombier 			case '\027':				/* ^W */
2835e96a66cSDavid du Colombier 				console.l[console.nl] = '\0';
2845e96a66cSDavid du Colombier 				wbuf = vtMemAlloc(console.nl+1);
2855e96a66cSDavid du Colombier 				memmove(wbuf, console.l, console.nl+1);
2865e96a66cSDavid du Colombier 				argc = tokenize(wbuf, argv, nelem(argv));
2875e96a66cSDavid du Colombier 				if(argc > 0)
2885e96a66cSDavid du Colombier 					argc--;
2895e96a66cSDavid du Colombier 				console.nl = 0;
2905e96a66cSDavid du Colombier 				lp = console.l;
2915e96a66cSDavid du Colombier 				for(i = 0; i < argc; i++)
2925e96a66cSDavid du Colombier 					lp += sprint(lp, "%q ", argv[i]);
2935e96a66cSDavid du Colombier 				console.nl = lp - console.l;
2945e96a66cSDavid du Colombier 				vtMemFree(wbuf);
2955e96a66cSDavid du Colombier 				qWrite(console.oq, "^W\n", 3);
2965e96a66cSDavid du Colombier 				if(console.nl == 0)
2975e96a66cSDavid du Colombier 					break;
2985e96a66cSDavid du Colombier 				qWrite(console.oq, console.l, console.nl);
2995e96a66cSDavid du Colombier 				continue;
3005e96a66cSDavid du Colombier 			case '\177':
3015e96a66cSDavid du Colombier 				qWrite(console.oq, "\n", 1);
3025e96a66cSDavid du Colombier 				console.nl = 0;
3035e96a66cSDavid du Colombier 				break;
3045e96a66cSDavid du Colombier 			}
3055e96a66cSDavid du Colombier 
3065e96a66cSDavid du Colombier 			console.l[console.nl] = '\0';
3075e96a66cSDavid du Colombier 			if(console.nl != 0)
3085e96a66cSDavid du Colombier 				cliExec(console.l);
3095e96a66cSDavid du Colombier 
3105e96a66cSDavid du Colombier 			console.nl = 0;
3115e96a66cSDavid du Colombier 			qWrite(console.oq, console.prompt, console.np);
3125e96a66cSDavid du Colombier 		}
3135e96a66cSDavid du Colombier 
3145e96a66cSDavid du Colombier 		vtLock(q->lock);
3155e96a66cSDavid du Colombier 	}
3165e96a66cSDavid du Colombier }
3175e96a66cSDavid du Colombier 
3185e96a66cSDavid du Colombier int
consWrite(char * buf,int len)3195e96a66cSDavid du Colombier consWrite(char* buf, int len)
3205e96a66cSDavid du Colombier {
3215e96a66cSDavid du Colombier 	if(console.oq == nil)
322dc5a79c1SDavid du Colombier 		return write(2, buf, len);
323dc5a79c1SDavid du Colombier 	if(console.nopens == 0)
324dc5a79c1SDavid du Colombier 		write(2, buf, len);
3255e96a66cSDavid du Colombier 	return qWrite(console.oq, buf, len);
3265e96a66cSDavid du Colombier }
3275e96a66cSDavid du Colombier 
3285e96a66cSDavid du Colombier int
consPrompt(char * prompt)3295e96a66cSDavid du Colombier consPrompt(char* prompt)
3305e96a66cSDavid du Colombier {
3315e96a66cSDavid du Colombier 	char buf[ERRMAX];
3325e96a66cSDavid du Colombier 
3335e96a66cSDavid du Colombier 	if(prompt == nil)
3345e96a66cSDavid du Colombier 		prompt = "prompt";
3355e96a66cSDavid du Colombier 
3365e96a66cSDavid du Colombier 	vtMemFree(console.prompt);
3375e96a66cSDavid du Colombier 	console.np = snprint(buf, sizeof(buf), "%s: ", prompt);
3385e96a66cSDavid du Colombier 	console.prompt = vtStrDup(buf);
3395e96a66cSDavid du Colombier 
3405e96a66cSDavid du Colombier 	return console.np;
3415e96a66cSDavid du Colombier }
3425e96a66cSDavid du Colombier 
3435e96a66cSDavid du Colombier int
consTTY(void)3445e96a66cSDavid du Colombier consTTY(void)
3455e96a66cSDavid du Colombier {
3465e96a66cSDavid du Colombier 	int ctl, fd;
3475e96a66cSDavid du Colombier 	char *name, *p;
3485e96a66cSDavid du Colombier 
3495e96a66cSDavid du Colombier 	name = "/dev/cons";
3505e96a66cSDavid du Colombier 	if((fd = open(name, ORDWR)) < 0){
3515e96a66cSDavid du Colombier 		name = "#c/cons";
3525e96a66cSDavid du Colombier 		if((fd = open(name, ORDWR)) < 0){
3535e96a66cSDavid du Colombier 			vtSetError("consTTY: open %s: %r", name);
3545e96a66cSDavid du Colombier 			return 0;
3555e96a66cSDavid du Colombier 		}
3565e96a66cSDavid du Colombier 	}
3575e96a66cSDavid du Colombier 
3585e96a66cSDavid du Colombier 	p = smprint("%sctl", name);
3595e96a66cSDavid du Colombier 	if((ctl = open(p, OWRITE)) < 0){
3605e96a66cSDavid du Colombier 		close(fd);
3615e96a66cSDavid du Colombier 		vtSetError("consTTY: open %s: %r", p);
3625e96a66cSDavid du Colombier 		free(p);
3635e96a66cSDavid du Colombier 		return 0;
3645e96a66cSDavid du Colombier 	}
3655e96a66cSDavid du Colombier 	if(write(ctl, "rawon", 5) < 0){
3665e96a66cSDavid du Colombier 		close(ctl);
3675e96a66cSDavid du Colombier 		close(fd);
3685e96a66cSDavid du Colombier 		vtSetError("consTTY: write %s: %r", p);
3695e96a66cSDavid du Colombier 		free(p);
3705e96a66cSDavid du Colombier 		return 0;
3715e96a66cSDavid du Colombier 	}
3725e96a66cSDavid du Colombier 	free(p);
3735e96a66cSDavid du Colombier 
3745e96a66cSDavid du Colombier 	if(consOpen(fd, fd, ctl) == 0){
3755e96a66cSDavid du Colombier 		close(ctl);
3765e96a66cSDavid du Colombier 		close(fd);
3775e96a66cSDavid du Colombier 		return 0;
3785e96a66cSDavid du Colombier 	}
3795e96a66cSDavid du Colombier 
3805e96a66cSDavid du Colombier 	return 1;
3815e96a66cSDavid du Colombier }
3825e96a66cSDavid du Colombier 
3835e96a66cSDavid du Colombier int
consInit(void)3845e96a66cSDavid du Colombier consInit(void)
3855e96a66cSDavid du Colombier {
3865e96a66cSDavid du Colombier 	console.iq = qAlloc();
3875e96a66cSDavid du Colombier 	console.oq = qAlloc();
3885e96a66cSDavid du Colombier 	console.nl = 0;
3895e96a66cSDavid du Colombier 
3905e96a66cSDavid du Colombier 	consPrompt(nil);
3915e96a66cSDavid du Colombier 
3925e96a66cSDavid du Colombier 	if(vtThread(consProc, nil) < 0){
3935e96a66cSDavid du Colombier 		vtFatal("can't start console proc");
3945e96a66cSDavid du Colombier 		return 0;
3955e96a66cSDavid du Colombier 	}
3965e96a66cSDavid du Colombier 
3975e96a66cSDavid du Colombier 	return 1;
3985e96a66cSDavid du Colombier }
399