xref: /plan9-contrib/sys/src/cmd/unix/drawterm/kern/devcons.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include	"u.h"
2*8ccd4a63SDavid du Colombier #include	"lib.h"
3*8ccd4a63SDavid du Colombier #include	"dat.h"
4*8ccd4a63SDavid du Colombier #include	"fns.h"
5*8ccd4a63SDavid du Colombier #include	"error.h"
6*8ccd4a63SDavid du Colombier 
7*8ccd4a63SDavid du Colombier #include 	"keyboard.h"
8*8ccd4a63SDavid du Colombier 
9*8ccd4a63SDavid du Colombier void	(*consdebug)(void) = nil;
10*8ccd4a63SDavid du Colombier void	(*screenputs)(char*, int) = nil;
11*8ccd4a63SDavid du Colombier 
12*8ccd4a63SDavid du Colombier Queue*	kbdq;			/* unprocessed console input */
13*8ccd4a63SDavid du Colombier Queue*	lineq;			/* processed console input */
14*8ccd4a63SDavid du Colombier Queue*	serialoq;		/* serial console output */
15*8ccd4a63SDavid du Colombier Queue*	kprintoq;		/* console output, for /dev/kprint */
16*8ccd4a63SDavid du Colombier long	kprintinuse;		/* test and set whether /dev/kprint is open */
17*8ccd4a63SDavid du Colombier int	iprintscreenputs = 0;
18*8ccd4a63SDavid du Colombier 
19*8ccd4a63SDavid du Colombier int	panicking;
20*8ccd4a63SDavid du Colombier 
21*8ccd4a63SDavid du Colombier struct
22*8ccd4a63SDavid du Colombier {
23*8ccd4a63SDavid du Colombier 	int exiting;
24*8ccd4a63SDavid du Colombier 	int machs;
25*8ccd4a63SDavid du Colombier } active;
26*8ccd4a63SDavid du Colombier 
27*8ccd4a63SDavid du Colombier static struct
28*8ccd4a63SDavid du Colombier {
29*8ccd4a63SDavid du Colombier 	QLock lk;
30*8ccd4a63SDavid du Colombier 
31*8ccd4a63SDavid du Colombier 	int	raw;		/* true if we shouldn't process input */
32*8ccd4a63SDavid du Colombier 	int	ctl;		/* number of opens to the control file */
33*8ccd4a63SDavid du Colombier 	int	x;		/* index into line */
34*8ccd4a63SDavid du Colombier 	char	line[1024];	/* current input line */
35*8ccd4a63SDavid du Colombier 
36*8ccd4a63SDavid du Colombier 	int	count;
37*8ccd4a63SDavid du Colombier 	int	ctlpoff;
38*8ccd4a63SDavid du Colombier 
39*8ccd4a63SDavid du Colombier 	/* a place to save up characters at interrupt time before dumping them in the queue */
40*8ccd4a63SDavid du Colombier 	Lock	lockputc;
41*8ccd4a63SDavid du Colombier 	char	istage[1024];
42*8ccd4a63SDavid du Colombier 	char	*iw;
43*8ccd4a63SDavid du Colombier 	char	*ir;
44*8ccd4a63SDavid du Colombier 	char	*ie;
45*8ccd4a63SDavid du Colombier } kbd = {
46*8ccd4a63SDavid du Colombier 	{ 0 },
47*8ccd4a63SDavid du Colombier 	0,
48*8ccd4a63SDavid du Colombier 	0,
49*8ccd4a63SDavid du Colombier 	0,
50*8ccd4a63SDavid du Colombier 	{ 0 },
51*8ccd4a63SDavid du Colombier 	0,
52*8ccd4a63SDavid du Colombier 	0,
53*8ccd4a63SDavid du Colombier 	{ 0 },
54*8ccd4a63SDavid du Colombier 	{ 0 },
55*8ccd4a63SDavid du Colombier 	kbd.istage,
56*8ccd4a63SDavid du Colombier 	kbd.istage,
57*8ccd4a63SDavid du Colombier 	kbd.istage + sizeof(kbd.istage),
58*8ccd4a63SDavid du Colombier };
59*8ccd4a63SDavid du Colombier 
60*8ccd4a63SDavid du Colombier char	*sysname;
61*8ccd4a63SDavid du Colombier vlong	fasthz;
62*8ccd4a63SDavid du Colombier 
63*8ccd4a63SDavid du Colombier static int	readtime(ulong, char*, int);
64*8ccd4a63SDavid du Colombier static int	readbintime(char*, int);
65*8ccd4a63SDavid du Colombier static int	writetime(char*, int);
66*8ccd4a63SDavid du Colombier static int	writebintime(char*, int);
67*8ccd4a63SDavid du Colombier 
68*8ccd4a63SDavid du Colombier enum
69*8ccd4a63SDavid du Colombier {
70*8ccd4a63SDavid du Colombier 	CMreboot,
71*8ccd4a63SDavid du Colombier 	CMpanic,
72*8ccd4a63SDavid du Colombier };
73*8ccd4a63SDavid du Colombier 
74*8ccd4a63SDavid du Colombier Cmdtab rebootmsg[] =
75*8ccd4a63SDavid du Colombier {
76*8ccd4a63SDavid du Colombier 	CMreboot,	"reboot",	0,
77*8ccd4a63SDavid du Colombier 	CMpanic,	"panic",	0,
78*8ccd4a63SDavid du Colombier };
79*8ccd4a63SDavid du Colombier 
80*8ccd4a63SDavid du Colombier int
81*8ccd4a63SDavid du Colombier return0(void *v)
82*8ccd4a63SDavid du Colombier {
83*8ccd4a63SDavid du Colombier 	return 0;
84*8ccd4a63SDavid du Colombier }
85*8ccd4a63SDavid du Colombier 
86*8ccd4a63SDavid du Colombier void
87*8ccd4a63SDavid du Colombier printinit(void)
88*8ccd4a63SDavid du Colombier {
89*8ccd4a63SDavid du Colombier 	lineq = qopen(2*1024, 0, nil, nil);
90*8ccd4a63SDavid du Colombier 	if(lineq == nil)
91*8ccd4a63SDavid du Colombier 		panic("printinit");
92*8ccd4a63SDavid du Colombier 	qnoblock(lineq, 1);
93*8ccd4a63SDavid du Colombier 
94*8ccd4a63SDavid du Colombier 	kbdq = qopen(4*1024, 0, 0, 0);
95*8ccd4a63SDavid du Colombier 	if(kbdq == nil)
96*8ccd4a63SDavid du Colombier 		panic("kbdinit");
97*8ccd4a63SDavid du Colombier 	qnoblock(kbdq, 1);
98*8ccd4a63SDavid du Colombier }
99*8ccd4a63SDavid du Colombier 
100*8ccd4a63SDavid du Colombier int
101*8ccd4a63SDavid du Colombier consactive(void)
102*8ccd4a63SDavid du Colombier {
103*8ccd4a63SDavid du Colombier 	if(serialoq)
104*8ccd4a63SDavid du Colombier 		return qlen(serialoq) > 0;
105*8ccd4a63SDavid du Colombier 	return 0;
106*8ccd4a63SDavid du Colombier }
107*8ccd4a63SDavid du Colombier 
108*8ccd4a63SDavid du Colombier void
109*8ccd4a63SDavid du Colombier prflush(void)
110*8ccd4a63SDavid du Colombier {
111*8ccd4a63SDavid du Colombier /*
112*8ccd4a63SDavid du Colombier 	ulong now;
113*8ccd4a63SDavid du Colombier 
114*8ccd4a63SDavid du Colombier 	now = m->ticks;
115*8ccd4a63SDavid du Colombier 	while(consactive())
116*8ccd4a63SDavid du Colombier 		if(m->ticks - now >= HZ)
117*8ccd4a63SDavid du Colombier 			break;
118*8ccd4a63SDavid du Colombier */
119*8ccd4a63SDavid du Colombier }
120*8ccd4a63SDavid du Colombier 
121*8ccd4a63SDavid du Colombier /*
122*8ccd4a63SDavid du Colombier  *   Print a string on the console.  Convert \n to \r\n for serial
123*8ccd4a63SDavid du Colombier  *   line consoles.  Locking of the queues is left up to the screen
124*8ccd4a63SDavid du Colombier  *   or uart code.  Multi-line messages to serial consoles may get
125*8ccd4a63SDavid du Colombier  *   interspersed with other messages.
126*8ccd4a63SDavid du Colombier  */
127*8ccd4a63SDavid du Colombier static void
128*8ccd4a63SDavid du Colombier putstrn0(char *str, int n, int usewrite)
129*8ccd4a63SDavid du Colombier {
130*8ccd4a63SDavid du Colombier 	/*
131*8ccd4a63SDavid du Colombier 	 *  if someone is reading /dev/kprint,
132*8ccd4a63SDavid du Colombier 	 *  put the message there.
133*8ccd4a63SDavid du Colombier 	 *  if not and there's an attached bit mapped display,
134*8ccd4a63SDavid du Colombier 	 *  put the message there.
135*8ccd4a63SDavid du Colombier 	 *
136*8ccd4a63SDavid du Colombier 	 *  if there's a serial line being used as a console,
137*8ccd4a63SDavid du Colombier 	 *  put the message there.
138*8ccd4a63SDavid du Colombier 	 */
139*8ccd4a63SDavid du Colombier 	if(kprintoq != nil && !qisclosed(kprintoq)){
140*8ccd4a63SDavid du Colombier 		if(usewrite)
141*8ccd4a63SDavid du Colombier 			qwrite(kprintoq, str, n);
142*8ccd4a63SDavid du Colombier 		else
143*8ccd4a63SDavid du Colombier 			qiwrite(kprintoq, str, n);
144*8ccd4a63SDavid du Colombier 	}else if(screenputs != nil)
145*8ccd4a63SDavid du Colombier 		screenputs(str, n);
146*8ccd4a63SDavid du Colombier }
147*8ccd4a63SDavid du Colombier 
148*8ccd4a63SDavid du Colombier void
149*8ccd4a63SDavid du Colombier putstrn(char *str, int n)
150*8ccd4a63SDavid du Colombier {
151*8ccd4a63SDavid du Colombier 	putstrn0(str, n, 0);
152*8ccd4a63SDavid du Colombier }
153*8ccd4a63SDavid du Colombier 
154*8ccd4a63SDavid du Colombier int noprint;
155*8ccd4a63SDavid du Colombier 
156*8ccd4a63SDavid du Colombier int
157*8ccd4a63SDavid du Colombier print(char *fmt, ...)
158*8ccd4a63SDavid du Colombier {
159*8ccd4a63SDavid du Colombier 	int n;
160*8ccd4a63SDavid du Colombier 	va_list arg;
161*8ccd4a63SDavid du Colombier 	char buf[PRINTSIZE];
162*8ccd4a63SDavid du Colombier 
163*8ccd4a63SDavid du Colombier 	if(noprint)
164*8ccd4a63SDavid du Colombier 		return -1;
165*8ccd4a63SDavid du Colombier 
166*8ccd4a63SDavid du Colombier 	va_start(arg, fmt);
167*8ccd4a63SDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
168*8ccd4a63SDavid du Colombier 	va_end(arg);
169*8ccd4a63SDavid du Colombier 	putstrn(buf, n);
170*8ccd4a63SDavid du Colombier 
171*8ccd4a63SDavid du Colombier 	return n;
172*8ccd4a63SDavid du Colombier }
173*8ccd4a63SDavid du Colombier 
174*8ccd4a63SDavid du Colombier void
175*8ccd4a63SDavid du Colombier panic(char *fmt, ...)
176*8ccd4a63SDavid du Colombier {
177*8ccd4a63SDavid du Colombier 	int n;
178*8ccd4a63SDavid du Colombier 	va_list arg;
179*8ccd4a63SDavid du Colombier 	char buf[PRINTSIZE];
180*8ccd4a63SDavid du Colombier 
181*8ccd4a63SDavid du Colombier 	kprintoq = nil;	/* don't try to write to /dev/kprint */
182*8ccd4a63SDavid du Colombier 
183*8ccd4a63SDavid du Colombier 	if(panicking)
184*8ccd4a63SDavid du Colombier 		for(;;);
185*8ccd4a63SDavid du Colombier 	panicking = 1;
186*8ccd4a63SDavid du Colombier 
187*8ccd4a63SDavid du Colombier 	splhi();
188*8ccd4a63SDavid du Colombier 	strcpy(buf, "panic: ");
189*8ccd4a63SDavid du Colombier 	va_start(arg, fmt);
190*8ccd4a63SDavid du Colombier 	n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
191*8ccd4a63SDavid du Colombier 	va_end(arg);
192*8ccd4a63SDavid du Colombier 	buf[n] = '\n';
193*8ccd4a63SDavid du Colombier 	uartputs(buf, n+1);
194*8ccd4a63SDavid du Colombier 	if(consdebug)
195*8ccd4a63SDavid du Colombier 		(*consdebug)();
196*8ccd4a63SDavid du Colombier 	spllo();
197*8ccd4a63SDavid du Colombier 	prflush();
198*8ccd4a63SDavid du Colombier 	putstrn(buf, n+1);
199*8ccd4a63SDavid du Colombier 	dumpstack();
200*8ccd4a63SDavid du Colombier 
201*8ccd4a63SDavid du Colombier 	exit(1);
202*8ccd4a63SDavid du Colombier }
203*8ccd4a63SDavid du Colombier 
204*8ccd4a63SDavid du Colombier int
205*8ccd4a63SDavid du Colombier pprint(char *fmt, ...)
206*8ccd4a63SDavid du Colombier {
207*8ccd4a63SDavid du Colombier 	int n;
208*8ccd4a63SDavid du Colombier 	Chan *c;
209*8ccd4a63SDavid du Colombier 	va_list arg;
210*8ccd4a63SDavid du Colombier 	char buf[2*PRINTSIZE];
211*8ccd4a63SDavid du Colombier 
212*8ccd4a63SDavid du Colombier 	if(up == nil || up->fgrp == nil)
213*8ccd4a63SDavid du Colombier 		return 0;
214*8ccd4a63SDavid du Colombier 
215*8ccd4a63SDavid du Colombier 	c = up->fgrp->fd[2];
216*8ccd4a63SDavid du Colombier 	if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
217*8ccd4a63SDavid du Colombier 		return 0;
218*8ccd4a63SDavid du Colombier 	n = sprint(buf, "%s %lud: ", up->text, up->pid);
219*8ccd4a63SDavid du Colombier 	va_start(arg, fmt);
220*8ccd4a63SDavid du Colombier 	n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
221*8ccd4a63SDavid du Colombier 	va_end(arg);
222*8ccd4a63SDavid du Colombier 
223*8ccd4a63SDavid du Colombier 	if(waserror())
224*8ccd4a63SDavid du Colombier 		return 0;
225*8ccd4a63SDavid du Colombier 	devtab[c->type]->write(c, buf, n, c->offset);
226*8ccd4a63SDavid du Colombier 	poperror();
227*8ccd4a63SDavid du Colombier 
228*8ccd4a63SDavid du Colombier 	lock(&c->ref.lk);
229*8ccd4a63SDavid du Colombier 	c->offset += n;
230*8ccd4a63SDavid du Colombier 	unlock(&c->ref.lk);
231*8ccd4a63SDavid du Colombier 
232*8ccd4a63SDavid du Colombier 	return n;
233*8ccd4a63SDavid du Colombier }
234*8ccd4a63SDavid du Colombier 
235*8ccd4a63SDavid du Colombier static void
236*8ccd4a63SDavid du Colombier echoscreen(char *buf, int n)
237*8ccd4a63SDavid du Colombier {
238*8ccd4a63SDavid du Colombier 	char *e, *p;
239*8ccd4a63SDavid du Colombier 	char ebuf[128];
240*8ccd4a63SDavid du Colombier 	int x;
241*8ccd4a63SDavid du Colombier 
242*8ccd4a63SDavid du Colombier 	p = ebuf;
243*8ccd4a63SDavid du Colombier 	e = ebuf + sizeof(ebuf) - 4;
244*8ccd4a63SDavid du Colombier 	while(n-- > 0){
245*8ccd4a63SDavid du Colombier 		if(p >= e){
246*8ccd4a63SDavid du Colombier 			screenputs(ebuf, p - ebuf);
247*8ccd4a63SDavid du Colombier 			p = ebuf;
248*8ccd4a63SDavid du Colombier 		}
249*8ccd4a63SDavid du Colombier 		x = *buf++;
250*8ccd4a63SDavid du Colombier 		if(x == 0x15){
251*8ccd4a63SDavid du Colombier 			*p++ = '^';
252*8ccd4a63SDavid du Colombier 			*p++ = 'U';
253*8ccd4a63SDavid du Colombier 			*p++ = '\n';
254*8ccd4a63SDavid du Colombier 		} else
255*8ccd4a63SDavid du Colombier 			*p++ = x;
256*8ccd4a63SDavid du Colombier 	}
257*8ccd4a63SDavid du Colombier 	if(p != ebuf)
258*8ccd4a63SDavid du Colombier 		screenputs(ebuf, p - ebuf);
259*8ccd4a63SDavid du Colombier }
260*8ccd4a63SDavid du Colombier 
261*8ccd4a63SDavid du Colombier static void
262*8ccd4a63SDavid du Colombier echoserialoq(char *buf, int n)
263*8ccd4a63SDavid du Colombier {
264*8ccd4a63SDavid du Colombier 	char *e, *p;
265*8ccd4a63SDavid du Colombier 	char ebuf[128];
266*8ccd4a63SDavid du Colombier 	int x;
267*8ccd4a63SDavid du Colombier 
268*8ccd4a63SDavid du Colombier 	p = ebuf;
269*8ccd4a63SDavid du Colombier 	e = ebuf + sizeof(ebuf) - 4;
270*8ccd4a63SDavid du Colombier 	while(n-- > 0){
271*8ccd4a63SDavid du Colombier 		if(p >= e){
272*8ccd4a63SDavid du Colombier 			qiwrite(serialoq, ebuf, p - ebuf);
273*8ccd4a63SDavid du Colombier 			p = ebuf;
274*8ccd4a63SDavid du Colombier 		}
275*8ccd4a63SDavid du Colombier 		x = *buf++;
276*8ccd4a63SDavid du Colombier 		if(x == '\n'){
277*8ccd4a63SDavid du Colombier 			*p++ = '\r';
278*8ccd4a63SDavid du Colombier 			*p++ = '\n';
279*8ccd4a63SDavid du Colombier 		} else if(x == 0x15){
280*8ccd4a63SDavid du Colombier 			*p++ = '^';
281*8ccd4a63SDavid du Colombier 			*p++ = 'U';
282*8ccd4a63SDavid du Colombier 			*p++ = '\n';
283*8ccd4a63SDavid du Colombier 		} else
284*8ccd4a63SDavid du Colombier 			*p++ = x;
285*8ccd4a63SDavid du Colombier 	}
286*8ccd4a63SDavid du Colombier 	if(p != ebuf)
287*8ccd4a63SDavid du Colombier 		qiwrite(serialoq, ebuf, p - ebuf);
288*8ccd4a63SDavid du Colombier }
289*8ccd4a63SDavid du Colombier 
290*8ccd4a63SDavid du Colombier static void
291*8ccd4a63SDavid du Colombier echo(char *buf, int n)
292*8ccd4a63SDavid du Colombier {
293*8ccd4a63SDavid du Colombier 	static int ctrlt;
294*8ccd4a63SDavid du Colombier 	int x;
295*8ccd4a63SDavid du Colombier 	char *e, *p;
296*8ccd4a63SDavid du Colombier 
297*8ccd4a63SDavid du Colombier 	e = buf+n;
298*8ccd4a63SDavid du Colombier 	for(p = buf; p < e; p++){
299*8ccd4a63SDavid du Colombier 		switch(*p){
300*8ccd4a63SDavid du Colombier 		case 0x10:	/* ^P */
301*8ccd4a63SDavid du Colombier 			if(cpuserver && !kbd.ctlpoff){
302*8ccd4a63SDavid du Colombier 				active.exiting = 1;
303*8ccd4a63SDavid du Colombier 				return;
304*8ccd4a63SDavid du Colombier 			}
305*8ccd4a63SDavid du Colombier 			break;
306*8ccd4a63SDavid du Colombier 		case 0x14:	/* ^T */
307*8ccd4a63SDavid du Colombier 			ctrlt++;
308*8ccd4a63SDavid du Colombier 			if(ctrlt > 2)
309*8ccd4a63SDavid du Colombier 				ctrlt = 2;
310*8ccd4a63SDavid du Colombier 			continue;
311*8ccd4a63SDavid du Colombier 		}
312*8ccd4a63SDavid du Colombier 
313*8ccd4a63SDavid du Colombier 		if(ctrlt != 2)
314*8ccd4a63SDavid du Colombier 			continue;
315*8ccd4a63SDavid du Colombier 
316*8ccd4a63SDavid du Colombier 		/* ^T escapes */
317*8ccd4a63SDavid du Colombier 		ctrlt = 0;
318*8ccd4a63SDavid du Colombier 		switch(*p){
319*8ccd4a63SDavid du Colombier 		case 'S':
320*8ccd4a63SDavid du Colombier 			x = splhi();
321*8ccd4a63SDavid du Colombier 			dumpstack();
322*8ccd4a63SDavid du Colombier 			procdump();
323*8ccd4a63SDavid du Colombier 			splx(x);
324*8ccd4a63SDavid du Colombier 			return;
325*8ccd4a63SDavid du Colombier 		case 's':
326*8ccd4a63SDavid du Colombier 			dumpstack();
327*8ccd4a63SDavid du Colombier 			return;
328*8ccd4a63SDavid du Colombier 		case 'x':
329*8ccd4a63SDavid du Colombier 			xsummary();
330*8ccd4a63SDavid du Colombier 			ixsummary();
331*8ccd4a63SDavid du Colombier 			mallocsummary();
332*8ccd4a63SDavid du Colombier 			pagersummary();
333*8ccd4a63SDavid du Colombier 			return;
334*8ccd4a63SDavid du Colombier 		case 'd':
335*8ccd4a63SDavid du Colombier 			if(consdebug == nil)
336*8ccd4a63SDavid du Colombier 				consdebug = rdb;
337*8ccd4a63SDavid du Colombier 			else
338*8ccd4a63SDavid du Colombier 				consdebug = nil;
339*8ccd4a63SDavid du Colombier 			print("consdebug now 0x%p\n", consdebug);
340*8ccd4a63SDavid du Colombier 			return;
341*8ccd4a63SDavid du Colombier 		case 'D':
342*8ccd4a63SDavid du Colombier 			if(consdebug == nil)
343*8ccd4a63SDavid du Colombier 				consdebug = rdb;
344*8ccd4a63SDavid du Colombier 			consdebug();
345*8ccd4a63SDavid du Colombier 			return;
346*8ccd4a63SDavid du Colombier 		case 'p':
347*8ccd4a63SDavid du Colombier 			x = spllo();
348*8ccd4a63SDavid du Colombier 			procdump();
349*8ccd4a63SDavid du Colombier 			splx(x);
350*8ccd4a63SDavid du Colombier 			return;
351*8ccd4a63SDavid du Colombier 		case 'q':
352*8ccd4a63SDavid du Colombier 			scheddump();
353*8ccd4a63SDavid du Colombier 			return;
354*8ccd4a63SDavid du Colombier 		case 'k':
355*8ccd4a63SDavid du Colombier 			killbig();
356*8ccd4a63SDavid du Colombier 			return;
357*8ccd4a63SDavid du Colombier 		case 'r':
358*8ccd4a63SDavid du Colombier 			exit(0);
359*8ccd4a63SDavid du Colombier 			return;
360*8ccd4a63SDavid du Colombier 		}
361*8ccd4a63SDavid du Colombier 	}
362*8ccd4a63SDavid du Colombier 
363*8ccd4a63SDavid du Colombier 	qproduce(kbdq, buf, n);
364*8ccd4a63SDavid du Colombier 	if(kbd.raw)
365*8ccd4a63SDavid du Colombier 		return;
366*8ccd4a63SDavid du Colombier 	if(screenputs != nil)
367*8ccd4a63SDavid du Colombier 		echoscreen(buf, n);
368*8ccd4a63SDavid du Colombier 	if(serialoq)
369*8ccd4a63SDavid du Colombier 		echoserialoq(buf, n);
370*8ccd4a63SDavid du Colombier }
371*8ccd4a63SDavid du Colombier 
372*8ccd4a63SDavid du Colombier /*
373*8ccd4a63SDavid du Colombier  *  Called by a uart interrupt for console input.
374*8ccd4a63SDavid du Colombier  *
375*8ccd4a63SDavid du Colombier  *  turn '\r' into '\n' before putting it into the queue.
376*8ccd4a63SDavid du Colombier  */
377*8ccd4a63SDavid du Colombier int
378*8ccd4a63SDavid du Colombier kbdcr2nl(Queue *q, int ch)
379*8ccd4a63SDavid du Colombier {
380*8ccd4a63SDavid du Colombier 	char *next;
381*8ccd4a63SDavid du Colombier 
382*8ccd4a63SDavid du Colombier 	USED(q);
383*8ccd4a63SDavid du Colombier 	ilock(&kbd.lockputc);		/* just a mutex */
384*8ccd4a63SDavid du Colombier 	if(ch == '\r' && !kbd.raw)
385*8ccd4a63SDavid du Colombier 		ch = '\n';
386*8ccd4a63SDavid du Colombier 	next = kbd.iw+1;
387*8ccd4a63SDavid du Colombier 	if(next >= kbd.ie)
388*8ccd4a63SDavid du Colombier 		next = kbd.istage;
389*8ccd4a63SDavid du Colombier 	if(next != kbd.ir){
390*8ccd4a63SDavid du Colombier 		*kbd.iw = ch;
391*8ccd4a63SDavid du Colombier 		kbd.iw = next;
392*8ccd4a63SDavid du Colombier 	}
393*8ccd4a63SDavid du Colombier 	iunlock(&kbd.lockputc);
394*8ccd4a63SDavid du Colombier 	return 0;
395*8ccd4a63SDavid du Colombier }
396*8ccd4a63SDavid du Colombier static
397*8ccd4a63SDavid du Colombier void
398*8ccd4a63SDavid du Colombier _kbdputc(int c)
399*8ccd4a63SDavid du Colombier {
400*8ccd4a63SDavid du Colombier 	Rune r;
401*8ccd4a63SDavid du Colombier 	char buf[UTFmax];
402*8ccd4a63SDavid du Colombier 	int n;
403*8ccd4a63SDavid du Colombier 
404*8ccd4a63SDavid du Colombier 	r = c;
405*8ccd4a63SDavid du Colombier 	n = runetochar(buf, &r);
406*8ccd4a63SDavid du Colombier 	if(n == 0)
407*8ccd4a63SDavid du Colombier 		return;
408*8ccd4a63SDavid du Colombier 	echo(buf, n);
409*8ccd4a63SDavid du Colombier //	kbd.c = r;
410*8ccd4a63SDavid du Colombier //	qproduce(kbdq, buf, n);
411*8ccd4a63SDavid du Colombier }
412*8ccd4a63SDavid du Colombier 
413*8ccd4a63SDavid du Colombier /* _kbdputc, but with compose translation */
414*8ccd4a63SDavid du Colombier int
415*8ccd4a63SDavid du Colombier kbdputc(Queue *q, int c)
416*8ccd4a63SDavid du Colombier {
417*8ccd4a63SDavid du Colombier 	int	i;
418*8ccd4a63SDavid du Colombier 	static int collecting, nk;
419*8ccd4a63SDavid du Colombier 	static Rune kc[5];
420*8ccd4a63SDavid du Colombier 
421*8ccd4a63SDavid du Colombier 	 if(c == Kalt){
422*8ccd4a63SDavid du Colombier 		 collecting = 1;
423*8ccd4a63SDavid du Colombier 		 nk = 0;
424*8ccd4a63SDavid du Colombier 		 return 0;
425*8ccd4a63SDavid du Colombier 	 }
426*8ccd4a63SDavid du Colombier 
427*8ccd4a63SDavid du Colombier 	 if(!collecting){
428*8ccd4a63SDavid du Colombier 		 _kbdputc(c);
429*8ccd4a63SDavid du Colombier 		 return 0;
430*8ccd4a63SDavid du Colombier 	 }
431*8ccd4a63SDavid du Colombier 
432*8ccd4a63SDavid du Colombier 	kc[nk++] = c;
433*8ccd4a63SDavid du Colombier 	c = latin1(kc, nk);
434*8ccd4a63SDavid du Colombier 	if(c < -1)  /* need more keystrokes */
435*8ccd4a63SDavid du Colombier 		return 0;
436*8ccd4a63SDavid du Colombier 	if(c != -1) /* valid sequence */
437*8ccd4a63SDavid du Colombier 		_kbdputc(c);
438*8ccd4a63SDavid du Colombier 	else
439*8ccd4a63SDavid du Colombier 		for(i=0; i<nk; i++)
440*8ccd4a63SDavid du Colombier 		 	_kbdputc(kc[i]);
441*8ccd4a63SDavid du Colombier 	nk = 0;
442*8ccd4a63SDavid du Colombier 	collecting = 0;
443*8ccd4a63SDavid du Colombier 
444*8ccd4a63SDavid du Colombier 	return 0;
445*8ccd4a63SDavid du Colombier }
446*8ccd4a63SDavid du Colombier 
447*8ccd4a63SDavid du Colombier 
448*8ccd4a63SDavid du Colombier enum{
449*8ccd4a63SDavid du Colombier 	Qdir,
450*8ccd4a63SDavid du Colombier 	Qbintime,
451*8ccd4a63SDavid du Colombier 	Qcons,
452*8ccd4a63SDavid du Colombier 	Qconsctl,
453*8ccd4a63SDavid du Colombier 	Qcpunote,
454*8ccd4a63SDavid du Colombier 	Qcputime,
455*8ccd4a63SDavid du Colombier 	Qdrivers,
456*8ccd4a63SDavid du Colombier 	Qkprint,
457*8ccd4a63SDavid du Colombier 	Qhostdomain,
458*8ccd4a63SDavid du Colombier 	Qhostowner,
459*8ccd4a63SDavid du Colombier 	Qnull,
460*8ccd4a63SDavid du Colombier 	Qosversion,
461*8ccd4a63SDavid du Colombier 	Qpgrpid,
462*8ccd4a63SDavid du Colombier 	Qpid,
463*8ccd4a63SDavid du Colombier 	Qppid,
464*8ccd4a63SDavid du Colombier 	Qrandom,
465*8ccd4a63SDavid du Colombier 	Qreboot,
466*8ccd4a63SDavid du Colombier 	Qsecstore,
467*8ccd4a63SDavid du Colombier 	Qsnarf,
468*8ccd4a63SDavid du Colombier 	Qswap,
469*8ccd4a63SDavid du Colombier 	Qsysname,
470*8ccd4a63SDavid du Colombier 	Qsysstat,
471*8ccd4a63SDavid du Colombier 	Qtime,
472*8ccd4a63SDavid du Colombier 	Quser,
473*8ccd4a63SDavid du Colombier 	Qzero,
474*8ccd4a63SDavid du Colombier };
475*8ccd4a63SDavid du Colombier 
476*8ccd4a63SDavid du Colombier enum
477*8ccd4a63SDavid du Colombier {
478*8ccd4a63SDavid du Colombier 	VLNUMSIZE=	22,
479*8ccd4a63SDavid du Colombier };
480*8ccd4a63SDavid du Colombier 
481*8ccd4a63SDavid du Colombier static Dirtab consdir[]={
482*8ccd4a63SDavid du Colombier 	".",	{Qdir, 0, QTDIR},	0,		DMDIR|0555,
483*8ccd4a63SDavid du Colombier 	"bintime",	{Qbintime},	24,		0664,
484*8ccd4a63SDavid du Colombier 	"cons",		{Qcons},	0,		0660,
485*8ccd4a63SDavid du Colombier 	"consctl",	{Qconsctl},	0,		0220,
486*8ccd4a63SDavid du Colombier 	"cpunote",	{Qcpunote},	0,		0444,
487*8ccd4a63SDavid du Colombier 	"cputime",	{Qcputime},	6*NUMSIZE,	0444,
488*8ccd4a63SDavid du Colombier 	"drivers",	{Qdrivers},	0,		0444,
489*8ccd4a63SDavid du Colombier 	"hostdomain",	{Qhostdomain},	DOMLEN,		0664,
490*8ccd4a63SDavid du Colombier 	"hostowner",	{Qhostowner},	0,	0664,
491*8ccd4a63SDavid du Colombier 	"kprint",		{Qkprint, 0, QTEXCL},	0,	DMEXCL|0440,
492*8ccd4a63SDavid du Colombier 	"null",		{Qnull},	0,		0666,
493*8ccd4a63SDavid du Colombier 	"osversion",	{Qosversion},	0,		0444,
494*8ccd4a63SDavid du Colombier 	"pgrpid",	{Qpgrpid},	NUMSIZE,	0444,
495*8ccd4a63SDavid du Colombier 	"pid",		{Qpid},		NUMSIZE,	0444,
496*8ccd4a63SDavid du Colombier 	"ppid",		{Qppid},	NUMSIZE,	0444,
497*8ccd4a63SDavid du Colombier 	"random",	{Qrandom},	0,		0444,
498*8ccd4a63SDavid du Colombier 	"reboot",	{Qreboot},	0,		0664,
499*8ccd4a63SDavid du Colombier 	"secstore",	{Qsecstore},	0,		0666,
500*8ccd4a63SDavid du Colombier 	"snarf",	{Qsnarf},		0,		0666,
501*8ccd4a63SDavid du Colombier 	"swap",		{Qswap},	0,		0664,
502*8ccd4a63SDavid du Colombier 	"sysname",	{Qsysname},	0,		0664,
503*8ccd4a63SDavid du Colombier 	"sysstat",	{Qsysstat},	0,		0666,
504*8ccd4a63SDavid du Colombier 	"time",		{Qtime},	NUMSIZE+3*VLNUMSIZE,	0664,
505*8ccd4a63SDavid du Colombier 	"user",		{Quser},	0,	0666,
506*8ccd4a63SDavid du Colombier 	"zero",		{Qzero},	0,		0444,
507*8ccd4a63SDavid du Colombier };
508*8ccd4a63SDavid du Colombier 
509*8ccd4a63SDavid du Colombier char secstorebuf[65536];
510*8ccd4a63SDavid du Colombier Dirtab *secstoretab = &consdir[Qsecstore];
511*8ccd4a63SDavid du Colombier Dirtab *snarftab = &consdir[Qsnarf];
512*8ccd4a63SDavid du Colombier 
513*8ccd4a63SDavid du Colombier int
514*8ccd4a63SDavid du Colombier readnum(ulong off, char *buf, ulong n, ulong val, int size)
515*8ccd4a63SDavid du Colombier {
516*8ccd4a63SDavid du Colombier 	char tmp[64];
517*8ccd4a63SDavid du Colombier 
518*8ccd4a63SDavid du Colombier 	snprint(tmp, sizeof(tmp), "%*.0lud", size-1, val);
519*8ccd4a63SDavid du Colombier 	tmp[size-1] = ' ';
520*8ccd4a63SDavid du Colombier 	if(off >= size)
521*8ccd4a63SDavid du Colombier 		return 0;
522*8ccd4a63SDavid du Colombier 	if(off+n > size)
523*8ccd4a63SDavid du Colombier 		n = size-off;
524*8ccd4a63SDavid du Colombier 	memmove(buf, tmp+off, n);
525*8ccd4a63SDavid du Colombier 	return n;
526*8ccd4a63SDavid du Colombier }
527*8ccd4a63SDavid du Colombier 
528*8ccd4a63SDavid du Colombier int
529*8ccd4a63SDavid du Colombier readstr(ulong off, char *buf, ulong n, char *str)
530*8ccd4a63SDavid du Colombier {
531*8ccd4a63SDavid du Colombier 	int size;
532*8ccd4a63SDavid du Colombier 
533*8ccd4a63SDavid du Colombier 	size = strlen(str);
534*8ccd4a63SDavid du Colombier 	if(off >= size)
535*8ccd4a63SDavid du Colombier 		return 0;
536*8ccd4a63SDavid du Colombier 	if(off+n > size)
537*8ccd4a63SDavid du Colombier 		n = size-off;
538*8ccd4a63SDavid du Colombier 	memmove(buf, str+off, n);
539*8ccd4a63SDavid du Colombier 	return n;
540*8ccd4a63SDavid du Colombier }
541*8ccd4a63SDavid du Colombier 
542*8ccd4a63SDavid du Colombier static void
543*8ccd4a63SDavid du Colombier consinit(void)
544*8ccd4a63SDavid du Colombier {
545*8ccd4a63SDavid du Colombier 	todinit();
546*8ccd4a63SDavid du Colombier 	randominit();
547*8ccd4a63SDavid du Colombier 	/*
548*8ccd4a63SDavid du Colombier 	 * at 115200 baud, the 1024 char buffer takes 56 ms to process,
549*8ccd4a63SDavid du Colombier 	 * processing it every 22 ms should be fine
550*8ccd4a63SDavid du Colombier 	 */
551*8ccd4a63SDavid du Colombier /*	addclock0link(kbdputcclock, 22); */
552*8ccd4a63SDavid du Colombier }
553*8ccd4a63SDavid du Colombier 
554*8ccd4a63SDavid du Colombier static Chan*
555*8ccd4a63SDavid du Colombier consattach(char *spec)
556*8ccd4a63SDavid du Colombier {
557*8ccd4a63SDavid du Colombier 	return devattach('c', spec);
558*8ccd4a63SDavid du Colombier }
559*8ccd4a63SDavid du Colombier 
560*8ccd4a63SDavid du Colombier static Walkqid*
561*8ccd4a63SDavid du Colombier conswalk(Chan *c, Chan *nc, char **name, int nname)
562*8ccd4a63SDavid du Colombier {
563*8ccd4a63SDavid du Colombier 	return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
564*8ccd4a63SDavid du Colombier }
565*8ccd4a63SDavid du Colombier 
566*8ccd4a63SDavid du Colombier static int
567*8ccd4a63SDavid du Colombier consstat(Chan *c, uchar *dp, int n)
568*8ccd4a63SDavid du Colombier {
569*8ccd4a63SDavid du Colombier 	return devstat(c, dp, n, consdir, nelem(consdir), devgen);
570*8ccd4a63SDavid du Colombier }
571*8ccd4a63SDavid du Colombier 
572*8ccd4a63SDavid du Colombier static Chan*
573*8ccd4a63SDavid du Colombier consopen(Chan *c, int omode)
574*8ccd4a63SDavid du Colombier {
575*8ccd4a63SDavid du Colombier 	c->aux = nil;
576*8ccd4a63SDavid du Colombier 	c = devopen(c, omode, consdir, nelem(consdir), devgen);
577*8ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
578*8ccd4a63SDavid du Colombier 	case Qconsctl:
579*8ccd4a63SDavid du Colombier 		qlock(&kbd.lk);
580*8ccd4a63SDavid du Colombier 		kbd.ctl++;
581*8ccd4a63SDavid du Colombier 		qunlock(&kbd.lk);
582*8ccd4a63SDavid du Colombier 		break;
583*8ccd4a63SDavid du Colombier 
584*8ccd4a63SDavid du Colombier 	case Qkprint:
585*8ccd4a63SDavid du Colombier 		if(tas(&kprintinuse) != 0){
586*8ccd4a63SDavid du Colombier 			c->flag &= ~COPEN;
587*8ccd4a63SDavid du Colombier 			error(Einuse);
588*8ccd4a63SDavid du Colombier 		}
589*8ccd4a63SDavid du Colombier 		if(kprintoq == nil){
590*8ccd4a63SDavid du Colombier 			kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
591*8ccd4a63SDavid du Colombier 			if(kprintoq == nil){
592*8ccd4a63SDavid du Colombier 				c->flag &= ~COPEN;
593*8ccd4a63SDavid du Colombier 				error(Enomem);
594*8ccd4a63SDavid du Colombier 			}
595*8ccd4a63SDavid du Colombier 			qnoblock(kprintoq, 1);
596*8ccd4a63SDavid du Colombier 		}else
597*8ccd4a63SDavid du Colombier 			qreopen(kprintoq);
598*8ccd4a63SDavid du Colombier 		c->iounit = qiomaxatomic;
599*8ccd4a63SDavid du Colombier 		break;
600*8ccd4a63SDavid du Colombier 
601*8ccd4a63SDavid du Colombier 	case Qsecstore:
602*8ccd4a63SDavid du Colombier 		if(omode == ORDWR)
603*8ccd4a63SDavid du Colombier 			error(Eperm);
604*8ccd4a63SDavid du Colombier 		if(omode != OREAD)
605*8ccd4a63SDavid du Colombier 			memset(secstorebuf, 0, sizeof secstorebuf);
606*8ccd4a63SDavid du Colombier 		break;
607*8ccd4a63SDavid du Colombier 
608*8ccd4a63SDavid du Colombier 	case Qsnarf:
609*8ccd4a63SDavid du Colombier 		if(omode == ORDWR)
610*8ccd4a63SDavid du Colombier 			error(Eperm);
611*8ccd4a63SDavid du Colombier 		if(omode == OREAD)
612*8ccd4a63SDavid du Colombier 			c->aux = strdup("");
613*8ccd4a63SDavid du Colombier 		else
614*8ccd4a63SDavid du Colombier 			c->aux = mallocz(SnarfSize, 1);
615*8ccd4a63SDavid du Colombier 		break;
616*8ccd4a63SDavid du Colombier 	}
617*8ccd4a63SDavid du Colombier 	return c;
618*8ccd4a63SDavid du Colombier }
619*8ccd4a63SDavid du Colombier 
620*8ccd4a63SDavid du Colombier static void
621*8ccd4a63SDavid du Colombier consclose(Chan *c)
622*8ccd4a63SDavid du Colombier {
623*8ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
624*8ccd4a63SDavid du Colombier 	/* last close of control file turns off raw */
625*8ccd4a63SDavid du Colombier 	case Qconsctl:
626*8ccd4a63SDavid du Colombier 		if(c->flag&COPEN){
627*8ccd4a63SDavid du Colombier 			qlock(&kbd.lk);
628*8ccd4a63SDavid du Colombier 			if(--kbd.ctl == 0)
629*8ccd4a63SDavid du Colombier 				kbd.raw = 0;
630*8ccd4a63SDavid du Colombier 			qunlock(&kbd.lk);
631*8ccd4a63SDavid du Colombier 		}
632*8ccd4a63SDavid du Colombier 		break;
633*8ccd4a63SDavid du Colombier 
634*8ccd4a63SDavid du Colombier 	/* close of kprint allows other opens */
635*8ccd4a63SDavid du Colombier 	case Qkprint:
636*8ccd4a63SDavid du Colombier 		if(c->flag & COPEN){
637*8ccd4a63SDavid du Colombier 			kprintinuse = 0;
638*8ccd4a63SDavid du Colombier 			qhangup(kprintoq, nil);
639*8ccd4a63SDavid du Colombier 		}
640*8ccd4a63SDavid du Colombier 		break;
641*8ccd4a63SDavid du Colombier 
642*8ccd4a63SDavid du Colombier 	case Qsnarf:
643*8ccd4a63SDavid du Colombier 		if(c->mode == OWRITE)
644*8ccd4a63SDavid du Colombier 			clipwrite(c->aux);
645*8ccd4a63SDavid du Colombier 		free(c->aux);
646*8ccd4a63SDavid du Colombier 		break;
647*8ccd4a63SDavid du Colombier 	}
648*8ccd4a63SDavid du Colombier }
649*8ccd4a63SDavid du Colombier 
650*8ccd4a63SDavid du Colombier static long
651*8ccd4a63SDavid du Colombier consread(Chan *c, void *buf, long n, vlong off)
652*8ccd4a63SDavid du Colombier {
653*8ccd4a63SDavid du Colombier 	char *b;
654*8ccd4a63SDavid du Colombier 	char tmp[128];		/* must be >= 6*NUMSIZE */
655*8ccd4a63SDavid du Colombier 	char *cbuf = buf;
656*8ccd4a63SDavid du Colombier 	int ch, i, eol;
657*8ccd4a63SDavid du Colombier 	vlong offset = off;
658*8ccd4a63SDavid du Colombier 
659*8ccd4a63SDavid du Colombier 	if(n <= 0)
660*8ccd4a63SDavid du Colombier 		return n;
661*8ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
662*8ccd4a63SDavid du Colombier 	case Qdir:
663*8ccd4a63SDavid du Colombier 		return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
664*8ccd4a63SDavid du Colombier 
665*8ccd4a63SDavid du Colombier 	case Qcons:
666*8ccd4a63SDavid du Colombier 		qlock(&kbd.lk);
667*8ccd4a63SDavid du Colombier 		if(waserror()) {
668*8ccd4a63SDavid du Colombier 			qunlock(&kbd.lk);
669*8ccd4a63SDavid du Colombier 			nexterror();
670*8ccd4a63SDavid du Colombier 		}
671*8ccd4a63SDavid du Colombier 		if(kbd.raw) {
672*8ccd4a63SDavid du Colombier 			if(qcanread(lineq))
673*8ccd4a63SDavid du Colombier 				n = qread(lineq, buf, n);
674*8ccd4a63SDavid du Colombier 			else {
675*8ccd4a63SDavid du Colombier 				/* read as much as possible */
676*8ccd4a63SDavid du Colombier 				do {
677*8ccd4a63SDavid du Colombier 					i = qread(kbdq, cbuf, n);
678*8ccd4a63SDavid du Colombier 					cbuf += i;
679*8ccd4a63SDavid du Colombier 					n -= i;
680*8ccd4a63SDavid du Colombier 				} while (n>0 && qcanread(kbdq));
681*8ccd4a63SDavid du Colombier 				n = cbuf - (char*)buf;
682*8ccd4a63SDavid du Colombier 			}
683*8ccd4a63SDavid du Colombier 		} else {
684*8ccd4a63SDavid du Colombier 			while(!qcanread(lineq)) {
685*8ccd4a63SDavid du Colombier 				qread(kbdq, &kbd.line[kbd.x], 1);
686*8ccd4a63SDavid du Colombier 				ch = kbd.line[kbd.x];
687*8ccd4a63SDavid du Colombier 				eol = 0;
688*8ccd4a63SDavid du Colombier 				switch(ch){
689*8ccd4a63SDavid du Colombier 				case '\b':
690*8ccd4a63SDavid du Colombier 					if(kbd.x)
691*8ccd4a63SDavid du Colombier 						kbd.x--;
692*8ccd4a63SDavid du Colombier 					break;
693*8ccd4a63SDavid du Colombier 				case 0x15:
694*8ccd4a63SDavid du Colombier 					kbd.x = 0;
695*8ccd4a63SDavid du Colombier 					break;
696*8ccd4a63SDavid du Colombier 				case '\n':
697*8ccd4a63SDavid du Colombier 				case 0x04:
698*8ccd4a63SDavid du Colombier 					eol = 1;
699*8ccd4a63SDavid du Colombier 				default:
700*8ccd4a63SDavid du Colombier 					kbd.line[kbd.x++] = ch;
701*8ccd4a63SDavid du Colombier 					break;
702*8ccd4a63SDavid du Colombier 				}
703*8ccd4a63SDavid du Colombier 				if(kbd.x == sizeof(kbd.line) || eol){
704*8ccd4a63SDavid du Colombier 					if(ch == 0x04)
705*8ccd4a63SDavid du Colombier 						kbd.x--;
706*8ccd4a63SDavid du Colombier 					qwrite(lineq, kbd.line, kbd.x);
707*8ccd4a63SDavid du Colombier 					kbd.x = 0;
708*8ccd4a63SDavid du Colombier 				}
709*8ccd4a63SDavid du Colombier 			}
710*8ccd4a63SDavid du Colombier 			n = qread(lineq, buf, n);
711*8ccd4a63SDavid du Colombier 		}
712*8ccd4a63SDavid du Colombier 		qunlock(&kbd.lk);
713*8ccd4a63SDavid du Colombier 		poperror();
714*8ccd4a63SDavid du Colombier 		return n;
715*8ccd4a63SDavid du Colombier 
716*8ccd4a63SDavid du Colombier 	case Qcpunote:
717*8ccd4a63SDavid du Colombier 		sleep(&up->sleep, return0, nil);
718*8ccd4a63SDavid du Colombier 
719*8ccd4a63SDavid du Colombier 	case Qcputime:
720*8ccd4a63SDavid du Colombier 		return 0;
721*8ccd4a63SDavid du Colombier 
722*8ccd4a63SDavid du Colombier 	case Qkprint:
723*8ccd4a63SDavid du Colombier 		return qread(kprintoq, buf, n);
724*8ccd4a63SDavid du Colombier 
725*8ccd4a63SDavid du Colombier 	case Qpgrpid:
726*8ccd4a63SDavid du Colombier 		return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
727*8ccd4a63SDavid du Colombier 
728*8ccd4a63SDavid du Colombier 	case Qpid:
729*8ccd4a63SDavid du Colombier 		return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
730*8ccd4a63SDavid du Colombier 
731*8ccd4a63SDavid du Colombier 	case Qppid:
732*8ccd4a63SDavid du Colombier 		return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
733*8ccd4a63SDavid du Colombier 
734*8ccd4a63SDavid du Colombier 	case Qtime:
735*8ccd4a63SDavid du Colombier 		return readtime((ulong)offset, buf, n);
736*8ccd4a63SDavid du Colombier 
737*8ccd4a63SDavid du Colombier 	case Qbintime:
738*8ccd4a63SDavid du Colombier 		return readbintime(buf, n);
739*8ccd4a63SDavid du Colombier 
740*8ccd4a63SDavid du Colombier 	case Qhostowner:
741*8ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, eve);
742*8ccd4a63SDavid du Colombier 
743*8ccd4a63SDavid du Colombier 	case Qhostdomain:
744*8ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, hostdomain);
745*8ccd4a63SDavid du Colombier 
746*8ccd4a63SDavid du Colombier 	case Quser:
747*8ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, up->user);
748*8ccd4a63SDavid du Colombier 
749*8ccd4a63SDavid du Colombier 	case Qnull:
750*8ccd4a63SDavid du Colombier 		return 0;
751*8ccd4a63SDavid du Colombier 
752*8ccd4a63SDavid du Colombier 	case Qsnarf:
753*8ccd4a63SDavid du Colombier 		if(offset == 0){
754*8ccd4a63SDavid du Colombier 			free(c->aux);
755*8ccd4a63SDavid du Colombier 			c->aux = clipread();
756*8ccd4a63SDavid du Colombier 		}
757*8ccd4a63SDavid du Colombier 		if(c->aux == nil)
758*8ccd4a63SDavid du Colombier 			return 0;
759*8ccd4a63SDavid du Colombier 		return readstr(offset, buf, n, c->aux);
760*8ccd4a63SDavid du Colombier 
761*8ccd4a63SDavid du Colombier 	case Qsecstore:
762*8ccd4a63SDavid du Colombier 		return readstr(offset, buf, n, secstorebuf);
763*8ccd4a63SDavid du Colombier 
764*8ccd4a63SDavid du Colombier 	case Qsysstat:
765*8ccd4a63SDavid du Colombier 		return 0;
766*8ccd4a63SDavid du Colombier 
767*8ccd4a63SDavid du Colombier 	case Qswap:
768*8ccd4a63SDavid du Colombier 		return 0;
769*8ccd4a63SDavid du Colombier 
770*8ccd4a63SDavid du Colombier 	case Qsysname:
771*8ccd4a63SDavid du Colombier 		if(sysname == nil)
772*8ccd4a63SDavid du Colombier 			return 0;
773*8ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, sysname);
774*8ccd4a63SDavid du Colombier 
775*8ccd4a63SDavid du Colombier 	case Qrandom:
776*8ccd4a63SDavid du Colombier 		return randomread(buf, n);
777*8ccd4a63SDavid du Colombier 
778*8ccd4a63SDavid du Colombier 	case Qdrivers:
779*8ccd4a63SDavid du Colombier 		b = malloc(READSTR);
780*8ccd4a63SDavid du Colombier 		if(b == nil)
781*8ccd4a63SDavid du Colombier 			error(Enomem);
782*8ccd4a63SDavid du Colombier 		n = 0;
783*8ccd4a63SDavid du Colombier 		for(i = 0; devtab[i] != nil; i++)
784*8ccd4a63SDavid du Colombier 			n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc,  devtab[i]->name);
785*8ccd4a63SDavid du Colombier 		if(waserror()){
786*8ccd4a63SDavid du Colombier 			free(b);
787*8ccd4a63SDavid du Colombier 			nexterror();
788*8ccd4a63SDavid du Colombier 		}
789*8ccd4a63SDavid du Colombier 		n = readstr((ulong)offset, buf, n, b);
790*8ccd4a63SDavid du Colombier 		free(b);
791*8ccd4a63SDavid du Colombier 		poperror();
792*8ccd4a63SDavid du Colombier 		return n;
793*8ccd4a63SDavid du Colombier 
794*8ccd4a63SDavid du Colombier 	case Qzero:
795*8ccd4a63SDavid du Colombier 		memset(buf, 0, n);
796*8ccd4a63SDavid du Colombier 		return n;
797*8ccd4a63SDavid du Colombier 
798*8ccd4a63SDavid du Colombier 	case Qosversion:
799*8ccd4a63SDavid du Colombier 		snprint(tmp, sizeof tmp, "2000");
800*8ccd4a63SDavid du Colombier 		n = readstr((ulong)offset, buf, n, tmp);
801*8ccd4a63SDavid du Colombier 		return n;
802*8ccd4a63SDavid du Colombier 
803*8ccd4a63SDavid du Colombier 	default:
804*8ccd4a63SDavid du Colombier 		print("consread 0x%llux\n", c->qid.path);
805*8ccd4a63SDavid du Colombier 		error(Egreg);
806*8ccd4a63SDavid du Colombier 	}
807*8ccd4a63SDavid du Colombier 	return -1;		/* never reached */
808*8ccd4a63SDavid du Colombier }
809*8ccd4a63SDavid du Colombier 
810*8ccd4a63SDavid du Colombier static long
811*8ccd4a63SDavid du Colombier conswrite(Chan *c, void *va, long n, vlong off)
812*8ccd4a63SDavid du Colombier {
813*8ccd4a63SDavid du Colombier 	char buf[256];
814*8ccd4a63SDavid du Colombier 	long l, bp;
815*8ccd4a63SDavid du Colombier 	char *a = va;
816*8ccd4a63SDavid du Colombier 	int fd;
817*8ccd4a63SDavid du Colombier 	Chan *swc;
818*8ccd4a63SDavid du Colombier 	ulong offset = off;
819*8ccd4a63SDavid du Colombier 	Cmdbuf *cb;
820*8ccd4a63SDavid du Colombier 	Cmdtab *ct;
821*8ccd4a63SDavid du Colombier 
822*8ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
823*8ccd4a63SDavid du Colombier 	case Qcons:
824*8ccd4a63SDavid du Colombier 		/*
825*8ccd4a63SDavid du Colombier 		 * Can't page fault in putstrn, so copy the data locally.
826*8ccd4a63SDavid du Colombier 		 */
827*8ccd4a63SDavid du Colombier 		l = n;
828*8ccd4a63SDavid du Colombier 		while(l > 0){
829*8ccd4a63SDavid du Colombier 			bp = l;
830*8ccd4a63SDavid du Colombier 			if(bp > sizeof buf)
831*8ccd4a63SDavid du Colombier 				bp = sizeof buf;
832*8ccd4a63SDavid du Colombier 			memmove(buf, a, bp);
833*8ccd4a63SDavid du Colombier 			putstrn0(buf, bp, 1);
834*8ccd4a63SDavid du Colombier 			a += bp;
835*8ccd4a63SDavid du Colombier 			l -= bp;
836*8ccd4a63SDavid du Colombier 		}
837*8ccd4a63SDavid du Colombier 		break;
838*8ccd4a63SDavid du Colombier 
839*8ccd4a63SDavid du Colombier 	case Qconsctl:
840*8ccd4a63SDavid du Colombier 		if(n >= sizeof(buf))
841*8ccd4a63SDavid du Colombier 			n = sizeof(buf)-1;
842*8ccd4a63SDavid du Colombier 		strncpy(buf, a, n);
843*8ccd4a63SDavid du Colombier 		buf[n] = 0;
844*8ccd4a63SDavid du Colombier 		for(a = buf; a;){
845*8ccd4a63SDavid du Colombier 			if(strncmp(a, "rawon", 5) == 0){
846*8ccd4a63SDavid du Colombier 				qlock(&kbd.lk);
847*8ccd4a63SDavid du Colombier 				if(kbd.x){
848*8ccd4a63SDavid du Colombier 					qwrite(kbdq, kbd.line, kbd.x);
849*8ccd4a63SDavid du Colombier 					kbd.x = 0;
850*8ccd4a63SDavid du Colombier 				}
851*8ccd4a63SDavid du Colombier 				kbd.raw = 1;
852*8ccd4a63SDavid du Colombier 				qunlock(&kbd.lk);
853*8ccd4a63SDavid du Colombier 			} else if(strncmp(a, "rawoff", 6) == 0){
854*8ccd4a63SDavid du Colombier 				qlock(&kbd.lk);
855*8ccd4a63SDavid du Colombier 				kbd.raw = 0;
856*8ccd4a63SDavid du Colombier 				kbd.x = 0;
857*8ccd4a63SDavid du Colombier 				qunlock(&kbd.lk);
858*8ccd4a63SDavid du Colombier 			} else if(strncmp(a, "ctlpon", 6) == 0){
859*8ccd4a63SDavid du Colombier 				kbd.ctlpoff = 0;
860*8ccd4a63SDavid du Colombier 			} else if(strncmp(a, "ctlpoff", 7) == 0){
861*8ccd4a63SDavid du Colombier 				kbd.ctlpoff = 1;
862*8ccd4a63SDavid du Colombier 			}
863*8ccd4a63SDavid du Colombier 			if((a = strchr(a, ' ')))
864*8ccd4a63SDavid du Colombier 				a++;
865*8ccd4a63SDavid du Colombier 		}
866*8ccd4a63SDavid du Colombier 		break;
867*8ccd4a63SDavid du Colombier 
868*8ccd4a63SDavid du Colombier 	case Qtime:
869*8ccd4a63SDavid du Colombier 		if(!iseve())
870*8ccd4a63SDavid du Colombier 			error(Eperm);
871*8ccd4a63SDavid du Colombier 		return writetime(a, n);
872*8ccd4a63SDavid du Colombier 
873*8ccd4a63SDavid du Colombier 	case Qbintime:
874*8ccd4a63SDavid du Colombier 		if(!iseve())
875*8ccd4a63SDavid du Colombier 			error(Eperm);
876*8ccd4a63SDavid du Colombier 		return writebintime(a, n);
877*8ccd4a63SDavid du Colombier 
878*8ccd4a63SDavid du Colombier 	case Qhostowner:
879*8ccd4a63SDavid du Colombier 		return hostownerwrite(a, n);
880*8ccd4a63SDavid du Colombier 
881*8ccd4a63SDavid du Colombier 	case Qhostdomain:
882*8ccd4a63SDavid du Colombier 		return hostdomainwrite(a, n);
883*8ccd4a63SDavid du Colombier 
884*8ccd4a63SDavid du Colombier 	case Quser:
885*8ccd4a63SDavid du Colombier 		return userwrite(a, n);
886*8ccd4a63SDavid du Colombier 
887*8ccd4a63SDavid du Colombier 	case Qnull:
888*8ccd4a63SDavid du Colombier 		break;
889*8ccd4a63SDavid du Colombier 
890*8ccd4a63SDavid du Colombier 	case Qreboot:
891*8ccd4a63SDavid du Colombier 		if(!iseve())
892*8ccd4a63SDavid du Colombier 			error(Eperm);
893*8ccd4a63SDavid du Colombier 		cb = parsecmd(a, n);
894*8ccd4a63SDavid du Colombier 
895*8ccd4a63SDavid du Colombier 		if(waserror()) {
896*8ccd4a63SDavid du Colombier 			free(cb);
897*8ccd4a63SDavid du Colombier 			nexterror();
898*8ccd4a63SDavid du Colombier 		}
899*8ccd4a63SDavid du Colombier 		ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
900*8ccd4a63SDavid du Colombier 		switch(ct->index) {
901*8ccd4a63SDavid du Colombier 		case CMreboot:
902*8ccd4a63SDavid du Colombier 			rebootcmd(cb->nf-1, cb->f+1);
903*8ccd4a63SDavid du Colombier 			break;
904*8ccd4a63SDavid du Colombier 		case CMpanic:
905*8ccd4a63SDavid du Colombier 			panic("/dev/reboot");
906*8ccd4a63SDavid du Colombier 		}
907*8ccd4a63SDavid du Colombier 		poperror();
908*8ccd4a63SDavid du Colombier 		free(cb);
909*8ccd4a63SDavid du Colombier 		break;
910*8ccd4a63SDavid du Colombier 
911*8ccd4a63SDavid du Colombier 	case Qsecstore:
912*8ccd4a63SDavid du Colombier 		if(offset >= sizeof secstorebuf || offset+n+1 >= sizeof secstorebuf)
913*8ccd4a63SDavid du Colombier 			error(Etoobig);
914*8ccd4a63SDavid du Colombier 		secstoretab->qid.vers++;
915*8ccd4a63SDavid du Colombier 		memmove(secstorebuf+offset, va, n);
916*8ccd4a63SDavid du Colombier 		return n;
917*8ccd4a63SDavid du Colombier 
918*8ccd4a63SDavid du Colombier 	case Qsnarf:
919*8ccd4a63SDavid du Colombier 		if(offset >= SnarfSize || offset+n >= SnarfSize)
920*8ccd4a63SDavid du Colombier 			error(Etoobig);
921*8ccd4a63SDavid du Colombier 		snarftab->qid.vers++;
922*8ccd4a63SDavid du Colombier 		memmove((uchar*)c->aux+offset, va, n);
923*8ccd4a63SDavid du Colombier 		return n;
924*8ccd4a63SDavid du Colombier 
925*8ccd4a63SDavid du Colombier 	case Qsysstat:
926*8ccd4a63SDavid du Colombier 		n = 0;
927*8ccd4a63SDavid du Colombier 		break;
928*8ccd4a63SDavid du Colombier 
929*8ccd4a63SDavid du Colombier 	case Qswap:
930*8ccd4a63SDavid du Colombier 		if(n >= sizeof buf)
931*8ccd4a63SDavid du Colombier 			error(Egreg);
932*8ccd4a63SDavid du Colombier 		memmove(buf, va, n);	/* so we can NUL-terminate */
933*8ccd4a63SDavid du Colombier 		buf[n] = 0;
934*8ccd4a63SDavid du Colombier 		/* start a pager if not already started */
935*8ccd4a63SDavid du Colombier 		if(strncmp(buf, "start", 5) == 0){
936*8ccd4a63SDavid du Colombier 			kickpager();
937*8ccd4a63SDavid du Colombier 			break;
938*8ccd4a63SDavid du Colombier 		}
939*8ccd4a63SDavid du Colombier 		if(cpuserver && !iseve())
940*8ccd4a63SDavid du Colombier 			error(Eperm);
941*8ccd4a63SDavid du Colombier 		if(buf[0]<'0' || '9'<buf[0])
942*8ccd4a63SDavid du Colombier 			error(Ebadarg);
943*8ccd4a63SDavid du Colombier 		fd = strtoul(buf, 0, 0);
944*8ccd4a63SDavid du Colombier 		swc = fdtochan(fd, -1, 1, 1);
945*8ccd4a63SDavid du Colombier 		setswapchan(swc);
946*8ccd4a63SDavid du Colombier 		break;
947*8ccd4a63SDavid du Colombier 
948*8ccd4a63SDavid du Colombier 	case Qsysname:
949*8ccd4a63SDavid du Colombier 		if(offset != 0)
950*8ccd4a63SDavid du Colombier 			error(Ebadarg);
951*8ccd4a63SDavid du Colombier 		if(n <= 0 || n >= sizeof buf)
952*8ccd4a63SDavid du Colombier 			error(Ebadarg);
953*8ccd4a63SDavid du Colombier 		strncpy(buf, a, n);
954*8ccd4a63SDavid du Colombier 		buf[n] = 0;
955*8ccd4a63SDavid du Colombier 		if(buf[n-1] == '\n')
956*8ccd4a63SDavid du Colombier 			buf[n-1] = 0;
957*8ccd4a63SDavid du Colombier 		kstrdup(&sysname, buf);
958*8ccd4a63SDavid du Colombier 		break;
959*8ccd4a63SDavid du Colombier 
960*8ccd4a63SDavid du Colombier 	default:
961*8ccd4a63SDavid du Colombier 		print("conswrite: 0x%llux\n", c->qid.path);
962*8ccd4a63SDavid du Colombier 		error(Egreg);
963*8ccd4a63SDavid du Colombier 	}
964*8ccd4a63SDavid du Colombier 	return n;
965*8ccd4a63SDavid du Colombier }
966*8ccd4a63SDavid du Colombier 
967*8ccd4a63SDavid du Colombier Dev consdevtab = {
968*8ccd4a63SDavid du Colombier 	'c',
969*8ccd4a63SDavid du Colombier 	"cons",
970*8ccd4a63SDavid du Colombier 
971*8ccd4a63SDavid du Colombier 	devreset,
972*8ccd4a63SDavid du Colombier 	consinit,
973*8ccd4a63SDavid du Colombier 	devshutdown,
974*8ccd4a63SDavid du Colombier 	consattach,
975*8ccd4a63SDavid du Colombier 	conswalk,
976*8ccd4a63SDavid du Colombier 	consstat,
977*8ccd4a63SDavid du Colombier 	consopen,
978*8ccd4a63SDavid du Colombier 	devcreate,
979*8ccd4a63SDavid du Colombier 	consclose,
980*8ccd4a63SDavid du Colombier 	consread,
981*8ccd4a63SDavid du Colombier 	devbread,
982*8ccd4a63SDavid du Colombier 	conswrite,
983*8ccd4a63SDavid du Colombier 	devbwrite,
984*8ccd4a63SDavid du Colombier 	devremove,
985*8ccd4a63SDavid du Colombier 	devwstat,
986*8ccd4a63SDavid du Colombier };
987*8ccd4a63SDavid du Colombier 
988*8ccd4a63SDavid du Colombier static uvlong uvorder = (uvlong) 0x0001020304050607ULL;
989*8ccd4a63SDavid du Colombier 
990*8ccd4a63SDavid du Colombier static uchar*
991*8ccd4a63SDavid du Colombier le2vlong(vlong *to, uchar *f)
992*8ccd4a63SDavid du Colombier {
993*8ccd4a63SDavid du Colombier 	uchar *t, *o;
994*8ccd4a63SDavid du Colombier 	int i;
995*8ccd4a63SDavid du Colombier 
996*8ccd4a63SDavid du Colombier 	t = (uchar*)to;
997*8ccd4a63SDavid du Colombier 	o = (uchar*)&uvorder;
998*8ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(vlong); i++)
999*8ccd4a63SDavid du Colombier 		t[o[i]] = f[i];
1000*8ccd4a63SDavid du Colombier 	return f+sizeof(vlong);
1001*8ccd4a63SDavid du Colombier }
1002*8ccd4a63SDavid du Colombier 
1003*8ccd4a63SDavid du Colombier static uchar*
1004*8ccd4a63SDavid du Colombier vlong2le(uchar *t, vlong from)
1005*8ccd4a63SDavid du Colombier {
1006*8ccd4a63SDavid du Colombier 	uchar *f, *o;
1007*8ccd4a63SDavid du Colombier 	int i;
1008*8ccd4a63SDavid du Colombier 
1009*8ccd4a63SDavid du Colombier 	f = (uchar*)&from;
1010*8ccd4a63SDavid du Colombier 	o = (uchar*)&uvorder;
1011*8ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(vlong); i++)
1012*8ccd4a63SDavid du Colombier 		t[i] = f[o[i]];
1013*8ccd4a63SDavid du Colombier 	return t+sizeof(vlong);
1014*8ccd4a63SDavid du Colombier }
1015*8ccd4a63SDavid du Colombier 
1016*8ccd4a63SDavid du Colombier static long order = 0x00010203;
1017*8ccd4a63SDavid du Colombier 
1018*8ccd4a63SDavid du Colombier static uchar*
1019*8ccd4a63SDavid du Colombier le2long(long *to, uchar *f)
1020*8ccd4a63SDavid du Colombier {
1021*8ccd4a63SDavid du Colombier 	uchar *t, *o;
1022*8ccd4a63SDavid du Colombier 	int i;
1023*8ccd4a63SDavid du Colombier 
1024*8ccd4a63SDavid du Colombier 	t = (uchar*)to;
1025*8ccd4a63SDavid du Colombier 	o = (uchar*)&order;
1026*8ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(long); i++)
1027*8ccd4a63SDavid du Colombier 		t[o[i]] = f[i];
1028*8ccd4a63SDavid du Colombier 	return f+sizeof(long);
1029*8ccd4a63SDavid du Colombier }
1030*8ccd4a63SDavid du Colombier 
1031*8ccd4a63SDavid du Colombier /*
1032*8ccd4a63SDavid du Colombier static uchar*
1033*8ccd4a63SDavid du Colombier long2le(uchar *t, long from)
1034*8ccd4a63SDavid du Colombier {
1035*8ccd4a63SDavid du Colombier 	uchar *f, *o;
1036*8ccd4a63SDavid du Colombier 	int i;
1037*8ccd4a63SDavid du Colombier 
1038*8ccd4a63SDavid du Colombier 	f = (uchar*)&from;
1039*8ccd4a63SDavid du Colombier 	o = (uchar*)&order;
1040*8ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(long); i++)
1041*8ccd4a63SDavid du Colombier 		t[i] = f[o[i]];
1042*8ccd4a63SDavid du Colombier 	return t+sizeof(long);
1043*8ccd4a63SDavid du Colombier }
1044*8ccd4a63SDavid du Colombier */
1045*8ccd4a63SDavid du Colombier 
1046*8ccd4a63SDavid du Colombier char *Ebadtimectl = "bad time control";
1047*8ccd4a63SDavid du Colombier 
1048*8ccd4a63SDavid du Colombier /*
1049*8ccd4a63SDavid du Colombier  *  like the old #c/time but with added info.  Return
1050*8ccd4a63SDavid du Colombier  *
1051*8ccd4a63SDavid du Colombier  *	secs	nanosecs	fastticks	fasthz
1052*8ccd4a63SDavid du Colombier  */
1053*8ccd4a63SDavid du Colombier static int
1054*8ccd4a63SDavid du Colombier readtime(ulong off, char *buf, int n)
1055*8ccd4a63SDavid du Colombier {
1056*8ccd4a63SDavid du Colombier 	vlong	nsec, ticks;
1057*8ccd4a63SDavid du Colombier 	long sec;
1058*8ccd4a63SDavid du Colombier 	char str[7*NUMSIZE];
1059*8ccd4a63SDavid du Colombier 
1060*8ccd4a63SDavid du Colombier 	nsec = todget(&ticks);
1061*8ccd4a63SDavid du Colombier 	if(fasthz == (vlong)0)
1062*8ccd4a63SDavid du Colombier 		fastticks((uvlong*)&fasthz);
1063*8ccd4a63SDavid du Colombier 	sec = nsec/((uvlong) 1000000000);
1064*8ccd4a63SDavid du Colombier 	snprint(str, sizeof(str), "%*.0lud %*.0llud %*.0llud %*.0llud ",
1065*8ccd4a63SDavid du Colombier 		NUMSIZE-1, sec,
1066*8ccd4a63SDavid du Colombier 		VLNUMSIZE-1, nsec,
1067*8ccd4a63SDavid du Colombier 		VLNUMSIZE-1, ticks,
1068*8ccd4a63SDavid du Colombier 		VLNUMSIZE-1, fasthz);
1069*8ccd4a63SDavid du Colombier 	return readstr(off, buf, n, str);
1070*8ccd4a63SDavid du Colombier }
1071*8ccd4a63SDavid du Colombier 
1072*8ccd4a63SDavid du Colombier /*
1073*8ccd4a63SDavid du Colombier  *  set the time in seconds
1074*8ccd4a63SDavid du Colombier  */
1075*8ccd4a63SDavid du Colombier static int
1076*8ccd4a63SDavid du Colombier writetime(char *buf, int n)
1077*8ccd4a63SDavid du Colombier {
1078*8ccd4a63SDavid du Colombier 	char b[13];
1079*8ccd4a63SDavid du Colombier 	long i;
1080*8ccd4a63SDavid du Colombier 	vlong now;
1081*8ccd4a63SDavid du Colombier 
1082*8ccd4a63SDavid du Colombier 	if(n >= sizeof(b))
1083*8ccd4a63SDavid du Colombier 		error(Ebadtimectl);
1084*8ccd4a63SDavid du Colombier 	strncpy(b, buf, n);
1085*8ccd4a63SDavid du Colombier 	b[n] = 0;
1086*8ccd4a63SDavid du Colombier 	i = strtol(b, 0, 0);
1087*8ccd4a63SDavid du Colombier 	if(i <= 0)
1088*8ccd4a63SDavid du Colombier 		error(Ebadtimectl);
1089*8ccd4a63SDavid du Colombier 	now = i*((vlong) 1000000000);
1090*8ccd4a63SDavid du Colombier 	todset(now, 0, 0);
1091*8ccd4a63SDavid du Colombier 	return n;
1092*8ccd4a63SDavid du Colombier }
1093*8ccd4a63SDavid du Colombier 
1094*8ccd4a63SDavid du Colombier /*
1095*8ccd4a63SDavid du Colombier  *  read binary time info.  all numbers are little endian.
1096*8ccd4a63SDavid du Colombier  *  ticks and nsec are syncronized.
1097*8ccd4a63SDavid du Colombier  */
1098*8ccd4a63SDavid du Colombier static int
1099*8ccd4a63SDavid du Colombier readbintime(char *buf, int n)
1100*8ccd4a63SDavid du Colombier {
1101*8ccd4a63SDavid du Colombier 	int i;
1102*8ccd4a63SDavid du Colombier 	vlong nsec, ticks;
1103*8ccd4a63SDavid du Colombier 	uchar *b = (uchar*)buf;
1104*8ccd4a63SDavid du Colombier 
1105*8ccd4a63SDavid du Colombier 	i = 0;
1106*8ccd4a63SDavid du Colombier 	if(fasthz == (vlong)0)
1107*8ccd4a63SDavid du Colombier 		fastticks((uvlong*)&fasthz);
1108*8ccd4a63SDavid du Colombier 	nsec = todget(&ticks);
1109*8ccd4a63SDavid du Colombier 	if(n >= 3*sizeof(uvlong)){
1110*8ccd4a63SDavid du Colombier 		vlong2le(b+2*sizeof(uvlong), fasthz);
1111*8ccd4a63SDavid du Colombier 		i += sizeof(uvlong);
1112*8ccd4a63SDavid du Colombier 	}
1113*8ccd4a63SDavid du Colombier 	if(n >= 2*sizeof(uvlong)){
1114*8ccd4a63SDavid du Colombier 		vlong2le(b+sizeof(uvlong), ticks);
1115*8ccd4a63SDavid du Colombier 		i += sizeof(uvlong);
1116*8ccd4a63SDavid du Colombier 	}
1117*8ccd4a63SDavid du Colombier 	if(n >= 8){
1118*8ccd4a63SDavid du Colombier 		vlong2le(b, nsec);
1119*8ccd4a63SDavid du Colombier 		i += sizeof(vlong);
1120*8ccd4a63SDavid du Colombier 	}
1121*8ccd4a63SDavid du Colombier 	return i;
1122*8ccd4a63SDavid du Colombier }
1123*8ccd4a63SDavid du Colombier 
1124*8ccd4a63SDavid du Colombier /*
1125*8ccd4a63SDavid du Colombier  *  set any of the following
1126*8ccd4a63SDavid du Colombier  *	- time in nsec
1127*8ccd4a63SDavid du Colombier  *	- nsec trim applied over some seconds
1128*8ccd4a63SDavid du Colombier  *	- clock frequency
1129*8ccd4a63SDavid du Colombier  */
1130*8ccd4a63SDavid du Colombier static int
1131*8ccd4a63SDavid du Colombier writebintime(char *buf, int n)
1132*8ccd4a63SDavid du Colombier {
1133*8ccd4a63SDavid du Colombier 	uchar *p;
1134*8ccd4a63SDavid du Colombier 	vlong delta;
1135*8ccd4a63SDavid du Colombier 	long period;
1136*8ccd4a63SDavid du Colombier 
1137*8ccd4a63SDavid du Colombier 	n--;
1138*8ccd4a63SDavid du Colombier 	p = (uchar*)buf + 1;
1139*8ccd4a63SDavid du Colombier 	switch(*buf){
1140*8ccd4a63SDavid du Colombier 	case 'n':
1141*8ccd4a63SDavid du Colombier 		if(n < sizeof(vlong))
1142*8ccd4a63SDavid du Colombier 			error(Ebadtimectl);
1143*8ccd4a63SDavid du Colombier 		le2vlong(&delta, p);
1144*8ccd4a63SDavid du Colombier 		todset(delta, 0, 0);
1145*8ccd4a63SDavid du Colombier 		break;
1146*8ccd4a63SDavid du Colombier 	case 'd':
1147*8ccd4a63SDavid du Colombier 		if(n < sizeof(vlong)+sizeof(long))
1148*8ccd4a63SDavid du Colombier 			error(Ebadtimectl);
1149*8ccd4a63SDavid du Colombier 		p = le2vlong(&delta, p);
1150*8ccd4a63SDavid du Colombier 		le2long(&period, p);
1151*8ccd4a63SDavid du Colombier 		todset(-1, delta, period);
1152*8ccd4a63SDavid du Colombier 		break;
1153*8ccd4a63SDavid du Colombier 	case 'f':
1154*8ccd4a63SDavid du Colombier 		if(n < sizeof(uvlong))
1155*8ccd4a63SDavid du Colombier 			error(Ebadtimectl);
1156*8ccd4a63SDavid du Colombier 		le2vlong(&fasthz, p);
1157*8ccd4a63SDavid du Colombier 		todsetfreq(fasthz);
1158*8ccd4a63SDavid du Colombier 		break;
1159*8ccd4a63SDavid du Colombier 	}
1160*8ccd4a63SDavid du Colombier 	return n;
1161*8ccd4a63SDavid du Colombier }
1162*8ccd4a63SDavid du Colombier 
1163*8ccd4a63SDavid du Colombier 
1164*8ccd4a63SDavid du Colombier int
1165*8ccd4a63SDavid du Colombier iprint(char *fmt, ...)
1166*8ccd4a63SDavid du Colombier {
1167*8ccd4a63SDavid du Colombier 	int n, s;
1168*8ccd4a63SDavid du Colombier 	va_list arg;
1169*8ccd4a63SDavid du Colombier 	char buf[PRINTSIZE];
1170*8ccd4a63SDavid du Colombier 
1171*8ccd4a63SDavid du Colombier 	s = splhi();
1172*8ccd4a63SDavid du Colombier 	va_start(arg, fmt);
1173*8ccd4a63SDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
1174*8ccd4a63SDavid du Colombier 	va_end(arg);
1175*8ccd4a63SDavid du Colombier 	if(screenputs != nil && iprintscreenputs)
1176*8ccd4a63SDavid du Colombier 		screenputs(buf, n);
1177*8ccd4a63SDavid du Colombier #undef write
1178*8ccd4a63SDavid du Colombier 	write(2, buf, n);
1179*8ccd4a63SDavid du Colombier 	splx(s);
1180*8ccd4a63SDavid du Colombier 
1181*8ccd4a63SDavid du Colombier 	return n;
1182*8ccd4a63SDavid du Colombier }
1183*8ccd4a63SDavid du Colombier 
1184