xref: /plan9/sys/src/cmd/unix/drawterm/kern/devcons.c (revision 96cbc34f1b36a29efdcfd47b10e70703a690febc)
18ccd4a63SDavid du Colombier #include	"u.h"
28ccd4a63SDavid du Colombier #include	"lib.h"
38ccd4a63SDavid du Colombier #include	"dat.h"
48ccd4a63SDavid du Colombier #include	"fns.h"
58ccd4a63SDavid du Colombier #include	"error.h"
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier #include 	"keyboard.h"
88ccd4a63SDavid du Colombier 
9ec59a3ddSDavid du Colombier void	(*consdebug)(void) = 0;
10ec59a3ddSDavid du Colombier void	(*screenputs)(char*, int) = 0;
118ccd4a63SDavid du Colombier 
128ccd4a63SDavid du Colombier Queue*	kbdq;			/* unprocessed console input */
138ccd4a63SDavid du Colombier Queue*	lineq;			/* processed console input */
148ccd4a63SDavid du Colombier Queue*	serialoq;		/* serial console output */
158ccd4a63SDavid du Colombier Queue*	kprintoq;		/* console output, for /dev/kprint */
168ccd4a63SDavid du Colombier long	kprintinuse;		/* test and set whether /dev/kprint is open */
17*96cbc34fSDavid du Colombier Lock	kprintlock;
188ccd4a63SDavid du Colombier int	iprintscreenputs = 0;
198ccd4a63SDavid du Colombier 
208ccd4a63SDavid du Colombier int	panicking;
218ccd4a63SDavid du Colombier 
228ccd4a63SDavid du Colombier struct
238ccd4a63SDavid du Colombier {
248ccd4a63SDavid du Colombier 	int exiting;
258ccd4a63SDavid du Colombier 	int machs;
268ccd4a63SDavid du Colombier } active;
278ccd4a63SDavid du Colombier 
288ccd4a63SDavid du Colombier static struct
298ccd4a63SDavid du Colombier {
308ccd4a63SDavid du Colombier 	QLock lk;
318ccd4a63SDavid du Colombier 
328ccd4a63SDavid du Colombier 	int	raw;		/* true if we shouldn't process input */
338ccd4a63SDavid du Colombier 	int	ctl;		/* number of opens to the control file */
348ccd4a63SDavid du Colombier 	int	x;		/* index into line */
358ccd4a63SDavid du Colombier 	char	line[1024];	/* current input line */
368ccd4a63SDavid du Colombier 
378ccd4a63SDavid du Colombier 	int	count;
388ccd4a63SDavid du Colombier 	int	ctlpoff;
398ccd4a63SDavid du Colombier 
408ccd4a63SDavid du Colombier 	/* a place to save up characters at interrupt time before dumping them in the queue */
418ccd4a63SDavid du Colombier 	Lock	lockputc;
428ccd4a63SDavid du Colombier 	char	istage[1024];
438ccd4a63SDavid du Colombier 	char	*iw;
448ccd4a63SDavid du Colombier 	char	*ir;
458ccd4a63SDavid du Colombier 	char	*ie;
468ccd4a63SDavid du Colombier } kbd = {
478ccd4a63SDavid du Colombier 	{ 0 },
488ccd4a63SDavid du Colombier 	0,
498ccd4a63SDavid du Colombier 	0,
508ccd4a63SDavid du Colombier 	0,
518ccd4a63SDavid du Colombier 	{ 0 },
528ccd4a63SDavid du Colombier 	0,
538ccd4a63SDavid du Colombier 	0,
548ccd4a63SDavid du Colombier 	{ 0 },
558ccd4a63SDavid du Colombier 	{ 0 },
568ccd4a63SDavid du Colombier 	kbd.istage,
578ccd4a63SDavid du Colombier 	kbd.istage,
588ccd4a63SDavid du Colombier 	kbd.istage + sizeof(kbd.istage),
598ccd4a63SDavid du Colombier };
608ccd4a63SDavid du Colombier 
618ccd4a63SDavid du Colombier char	*sysname;
628ccd4a63SDavid du Colombier vlong	fasthz;
638ccd4a63SDavid du Colombier 
648ccd4a63SDavid du Colombier static int	readtime(ulong, char*, int);
658ccd4a63SDavid du Colombier static int	readbintime(char*, int);
668ccd4a63SDavid du Colombier static int	writetime(char*, int);
678ccd4a63SDavid du Colombier static int	writebintime(char*, int);
688ccd4a63SDavid du Colombier 
698ccd4a63SDavid du Colombier enum
708ccd4a63SDavid du Colombier {
718ccd4a63SDavid du Colombier 	CMreboot,
728ccd4a63SDavid du Colombier 	CMpanic,
738ccd4a63SDavid du Colombier };
748ccd4a63SDavid du Colombier 
758ccd4a63SDavid du Colombier Cmdtab rebootmsg[] =
768ccd4a63SDavid du Colombier {
778ccd4a63SDavid du Colombier 	CMreboot,	"reboot",	0,
788ccd4a63SDavid du Colombier 	CMpanic,	"panic",	0,
798ccd4a63SDavid du Colombier };
808ccd4a63SDavid du Colombier 
818ccd4a63SDavid du Colombier int
return0(void * v)828ccd4a63SDavid du Colombier return0(void *v)
838ccd4a63SDavid du Colombier {
848ccd4a63SDavid du Colombier 	return 0;
858ccd4a63SDavid du Colombier }
868ccd4a63SDavid du Colombier 
878ccd4a63SDavid du Colombier void
printinit(void)888ccd4a63SDavid du Colombier printinit(void)
898ccd4a63SDavid du Colombier {
90ec59a3ddSDavid du Colombier 	lineq = qopen(2*1024, 0, 0, nil);
918ccd4a63SDavid du Colombier 	if(lineq == nil)
928ccd4a63SDavid du Colombier 		panic("printinit");
938ccd4a63SDavid du Colombier 	qnoblock(lineq, 1);
948ccd4a63SDavid du Colombier 
958ccd4a63SDavid du Colombier 	kbdq = qopen(4*1024, 0, 0, 0);
968ccd4a63SDavid du Colombier 	if(kbdq == nil)
978ccd4a63SDavid du Colombier 		panic("kbdinit");
988ccd4a63SDavid du Colombier 	qnoblock(kbdq, 1);
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier 
1018ccd4a63SDavid du Colombier int
consactive(void)1028ccd4a63SDavid du Colombier consactive(void)
1038ccd4a63SDavid du Colombier {
1048ccd4a63SDavid du Colombier 	if(serialoq)
1058ccd4a63SDavid du Colombier 		return qlen(serialoq) > 0;
1068ccd4a63SDavid du Colombier 	return 0;
1078ccd4a63SDavid du Colombier }
1088ccd4a63SDavid du Colombier 
1098ccd4a63SDavid du Colombier void
prflush(void)1108ccd4a63SDavid du Colombier prflush(void)
1118ccd4a63SDavid du Colombier {
1128ccd4a63SDavid du Colombier /*
1138ccd4a63SDavid du Colombier 	ulong now;
1148ccd4a63SDavid du Colombier 
1158ccd4a63SDavid du Colombier 	now = m->ticks;
1168ccd4a63SDavid du Colombier 	while(consactive())
1178ccd4a63SDavid du Colombier 		if(m->ticks - now >= HZ)
1188ccd4a63SDavid du Colombier 			break;
1198ccd4a63SDavid du Colombier */
1208ccd4a63SDavid du Colombier }
1218ccd4a63SDavid du Colombier 
1228ccd4a63SDavid du Colombier /*
1238ccd4a63SDavid du Colombier  *   Print a string on the console.  Convert \n to \r\n for serial
1248ccd4a63SDavid du Colombier  *   line consoles.  Locking of the queues is left up to the screen
1258ccd4a63SDavid du Colombier  *   or uart code.  Multi-line messages to serial consoles may get
1268ccd4a63SDavid du Colombier  *   interspersed with other messages.
1278ccd4a63SDavid du Colombier  */
1288ccd4a63SDavid du Colombier static void
putstrn0(char * str,int n,int usewrite)1298ccd4a63SDavid du Colombier putstrn0(char *str, int n, int usewrite)
1308ccd4a63SDavid du Colombier {
1318ccd4a63SDavid du Colombier 	/*
1328ccd4a63SDavid du Colombier 	 *  if someone is reading /dev/kprint,
1338ccd4a63SDavid du Colombier 	 *  put the message there.
1348ccd4a63SDavid du Colombier 	 *  if not and there's an attached bit mapped display,
1358ccd4a63SDavid du Colombier 	 *  put the message there.
1368ccd4a63SDavid du Colombier 	 *
1378ccd4a63SDavid du Colombier 	 *  if there's a serial line being used as a console,
1388ccd4a63SDavid du Colombier 	 *  put the message there.
1398ccd4a63SDavid du Colombier 	 */
1408ccd4a63SDavid du Colombier 	if(kprintoq != nil && !qisclosed(kprintoq)){
1418ccd4a63SDavid du Colombier 		if(usewrite)
1428ccd4a63SDavid du Colombier 			qwrite(kprintoq, str, n);
1438ccd4a63SDavid du Colombier 		else
1448ccd4a63SDavid du Colombier 			qiwrite(kprintoq, str, n);
145*96cbc34fSDavid du Colombier 	}else if(screenputs != 0)
1468ccd4a63SDavid du Colombier 		screenputs(str, n);
1478ccd4a63SDavid du Colombier }
1488ccd4a63SDavid du Colombier 
1498ccd4a63SDavid du Colombier void
putstrn(char * str,int n)1508ccd4a63SDavid du Colombier putstrn(char *str, int n)
1518ccd4a63SDavid du Colombier {
1528ccd4a63SDavid du Colombier 	putstrn0(str, n, 0);
1538ccd4a63SDavid du Colombier }
1548ccd4a63SDavid du Colombier 
1558ccd4a63SDavid du Colombier int noprint;
1568ccd4a63SDavid du Colombier 
1578ccd4a63SDavid du Colombier int
print(char * fmt,...)1588ccd4a63SDavid du Colombier print(char *fmt, ...)
1598ccd4a63SDavid du Colombier {
1608ccd4a63SDavid du Colombier 	int n;
1618ccd4a63SDavid du Colombier 	va_list arg;
1628ccd4a63SDavid du Colombier 	char buf[PRINTSIZE];
1638ccd4a63SDavid du Colombier 
1648ccd4a63SDavid du Colombier 	if(noprint)
1658ccd4a63SDavid du Colombier 		return -1;
1668ccd4a63SDavid du Colombier 
1678ccd4a63SDavid du Colombier 	va_start(arg, fmt);
1688ccd4a63SDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
1698ccd4a63SDavid du Colombier 	va_end(arg);
1708ccd4a63SDavid du Colombier 	putstrn(buf, n);
1718ccd4a63SDavid du Colombier 
1728ccd4a63SDavid du Colombier 	return n;
1738ccd4a63SDavid du Colombier }
1748ccd4a63SDavid du Colombier 
1758ccd4a63SDavid du Colombier void
panic(char * fmt,...)1768ccd4a63SDavid du Colombier panic(char *fmt, ...)
1778ccd4a63SDavid du Colombier {
1788ccd4a63SDavid du Colombier 	int n;
1798ccd4a63SDavid du Colombier 	va_list arg;
1808ccd4a63SDavid du Colombier 	char buf[PRINTSIZE];
1818ccd4a63SDavid du Colombier 
1828ccd4a63SDavid du Colombier 	kprintoq = nil;	/* don't try to write to /dev/kprint */
1838ccd4a63SDavid du Colombier 
1848ccd4a63SDavid du Colombier 	if(panicking)
1858ccd4a63SDavid du Colombier 		for(;;);
1868ccd4a63SDavid du Colombier 	panicking = 1;
1878ccd4a63SDavid du Colombier 
1888ccd4a63SDavid du Colombier 	splhi();
1898ccd4a63SDavid du Colombier 	strcpy(buf, "panic: ");
1908ccd4a63SDavid du Colombier 	va_start(arg, fmt);
1918ccd4a63SDavid du Colombier 	n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
1928ccd4a63SDavid du Colombier 	va_end(arg);
1938ccd4a63SDavid du Colombier 	buf[n] = '\n';
1948ccd4a63SDavid du Colombier 	uartputs(buf, n+1);
1958ccd4a63SDavid du Colombier 	if(consdebug)
1968ccd4a63SDavid du Colombier 		(*consdebug)();
1978ccd4a63SDavid du Colombier 	spllo();
1988ccd4a63SDavid du Colombier 	prflush();
1998ccd4a63SDavid du Colombier 	putstrn(buf, n+1);
2008ccd4a63SDavid du Colombier 	dumpstack();
2018ccd4a63SDavid du Colombier 
2028ccd4a63SDavid du Colombier 	exit(1);
2038ccd4a63SDavid du Colombier }
2048ccd4a63SDavid du Colombier 
2058ccd4a63SDavid du Colombier int
pprint(char * fmt,...)2068ccd4a63SDavid du Colombier pprint(char *fmt, ...)
2078ccd4a63SDavid du Colombier {
2088ccd4a63SDavid du Colombier 	int n;
2098ccd4a63SDavid du Colombier 	Chan *c;
2108ccd4a63SDavid du Colombier 	va_list arg;
2118ccd4a63SDavid du Colombier 	char buf[2*PRINTSIZE];
2128ccd4a63SDavid du Colombier 
2138ccd4a63SDavid du Colombier 	if(up == nil || up->fgrp == nil)
2148ccd4a63SDavid du Colombier 		return 0;
2158ccd4a63SDavid du Colombier 
2168ccd4a63SDavid du Colombier 	c = up->fgrp->fd[2];
2178ccd4a63SDavid du Colombier 	if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
2188ccd4a63SDavid du Colombier 		return 0;
2198ccd4a63SDavid du Colombier 	n = sprint(buf, "%s %lud: ", up->text, up->pid);
2208ccd4a63SDavid du Colombier 	va_start(arg, fmt);
2218ccd4a63SDavid du Colombier 	n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
2228ccd4a63SDavid du Colombier 	va_end(arg);
2238ccd4a63SDavid du Colombier 
2248ccd4a63SDavid du Colombier 	if(waserror())
2258ccd4a63SDavid du Colombier 		return 0;
2268ccd4a63SDavid du Colombier 	devtab[c->type]->write(c, buf, n, c->offset);
2278ccd4a63SDavid du Colombier 	poperror();
2288ccd4a63SDavid du Colombier 
2298ccd4a63SDavid du Colombier 	lock(&c->ref.lk);
2308ccd4a63SDavid du Colombier 	c->offset += n;
2318ccd4a63SDavid du Colombier 	unlock(&c->ref.lk);
2328ccd4a63SDavid du Colombier 
2338ccd4a63SDavid du Colombier 	return n;
2348ccd4a63SDavid du Colombier }
2358ccd4a63SDavid du Colombier 
2368ccd4a63SDavid du Colombier static void
echoscreen(char * buf,int n)2378ccd4a63SDavid du Colombier echoscreen(char *buf, int n)
2388ccd4a63SDavid du Colombier {
2398ccd4a63SDavid du Colombier 	char *e, *p;
2408ccd4a63SDavid du Colombier 	char ebuf[128];
2418ccd4a63SDavid du Colombier 	int x;
2428ccd4a63SDavid du Colombier 
2438ccd4a63SDavid du Colombier 	p = ebuf;
2448ccd4a63SDavid du Colombier 	e = ebuf + sizeof(ebuf) - 4;
2458ccd4a63SDavid du Colombier 	while(n-- > 0){
2468ccd4a63SDavid du Colombier 		if(p >= e){
2478ccd4a63SDavid du Colombier 			screenputs(ebuf, p - ebuf);
2488ccd4a63SDavid du Colombier 			p = ebuf;
2498ccd4a63SDavid du Colombier 		}
2508ccd4a63SDavid du Colombier 		x = *buf++;
2518ccd4a63SDavid du Colombier 		if(x == 0x15){
2528ccd4a63SDavid du Colombier 			*p++ = '^';
2538ccd4a63SDavid du Colombier 			*p++ = 'U';
2548ccd4a63SDavid du Colombier 			*p++ = '\n';
2558ccd4a63SDavid du Colombier 		} else
2568ccd4a63SDavid du Colombier 			*p++ = x;
2578ccd4a63SDavid du Colombier 	}
2588ccd4a63SDavid du Colombier 	if(p != ebuf)
2598ccd4a63SDavid du Colombier 		screenputs(ebuf, p - ebuf);
2608ccd4a63SDavid du Colombier }
2618ccd4a63SDavid du Colombier 
2628ccd4a63SDavid du Colombier static void
echoserialoq(char * buf,int n)2638ccd4a63SDavid du Colombier echoserialoq(char *buf, int n)
2648ccd4a63SDavid du Colombier {
2658ccd4a63SDavid du Colombier 	char *e, *p;
2668ccd4a63SDavid du Colombier 	char ebuf[128];
2678ccd4a63SDavid du Colombier 	int x;
2688ccd4a63SDavid du Colombier 
2698ccd4a63SDavid du Colombier 	p = ebuf;
2708ccd4a63SDavid du Colombier 	e = ebuf + sizeof(ebuf) - 4;
2718ccd4a63SDavid du Colombier 	while(n-- > 0){
2728ccd4a63SDavid du Colombier 		if(p >= e){
2738ccd4a63SDavid du Colombier 			qiwrite(serialoq, ebuf, p - ebuf);
2748ccd4a63SDavid du Colombier 			p = ebuf;
2758ccd4a63SDavid du Colombier 		}
2768ccd4a63SDavid du Colombier 		x = *buf++;
2778ccd4a63SDavid du Colombier 		if(x == '\n'){
2788ccd4a63SDavid du Colombier 			*p++ = '\r';
2798ccd4a63SDavid du Colombier 			*p++ = '\n';
2808ccd4a63SDavid du Colombier 		} else if(x == 0x15){
2818ccd4a63SDavid du Colombier 			*p++ = '^';
2828ccd4a63SDavid du Colombier 			*p++ = 'U';
2838ccd4a63SDavid du Colombier 			*p++ = '\n';
2848ccd4a63SDavid du Colombier 		} else
2858ccd4a63SDavid du Colombier 			*p++ = x;
2868ccd4a63SDavid du Colombier 	}
2878ccd4a63SDavid du Colombier 	if(p != ebuf)
2888ccd4a63SDavid du Colombier 		qiwrite(serialoq, ebuf, p - ebuf);
2898ccd4a63SDavid du Colombier }
2908ccd4a63SDavid du Colombier 
2918ccd4a63SDavid du Colombier static void
echo(char * buf,int n)2928ccd4a63SDavid du Colombier echo(char *buf, int n)
2938ccd4a63SDavid du Colombier {
2948ccd4a63SDavid du Colombier 	static int ctrlt;
2958ccd4a63SDavid du Colombier 	int x;
2968ccd4a63SDavid du Colombier 	char *e, *p;
2978ccd4a63SDavid du Colombier 
2988ccd4a63SDavid du Colombier 	e = buf+n;
2998ccd4a63SDavid du Colombier 	for(p = buf; p < e; p++){
3008ccd4a63SDavid du Colombier 		switch(*p){
3018ccd4a63SDavid du Colombier 		case 0x10:	/* ^P */
3028ccd4a63SDavid du Colombier 			if(cpuserver && !kbd.ctlpoff){
3038ccd4a63SDavid du Colombier 				active.exiting = 1;
3048ccd4a63SDavid du Colombier 				return;
3058ccd4a63SDavid du Colombier 			}
3068ccd4a63SDavid du Colombier 			break;
3078ccd4a63SDavid du Colombier 		case 0x14:	/* ^T */
3088ccd4a63SDavid du Colombier 			ctrlt++;
3098ccd4a63SDavid du Colombier 			if(ctrlt > 2)
3108ccd4a63SDavid du Colombier 				ctrlt = 2;
3118ccd4a63SDavid du Colombier 			continue;
3128ccd4a63SDavid du Colombier 		}
3138ccd4a63SDavid du Colombier 
3148ccd4a63SDavid du Colombier 		if(ctrlt != 2)
3158ccd4a63SDavid du Colombier 			continue;
3168ccd4a63SDavid du Colombier 
3178ccd4a63SDavid du Colombier 		/* ^T escapes */
3188ccd4a63SDavid du Colombier 		ctrlt = 0;
3198ccd4a63SDavid du Colombier 		switch(*p){
3208ccd4a63SDavid du Colombier 		case 'S':
3218ccd4a63SDavid du Colombier 			x = splhi();
3228ccd4a63SDavid du Colombier 			dumpstack();
3238ccd4a63SDavid du Colombier 			procdump();
3248ccd4a63SDavid du Colombier 			splx(x);
3258ccd4a63SDavid du Colombier 			return;
3268ccd4a63SDavid du Colombier 		case 's':
3278ccd4a63SDavid du Colombier 			dumpstack();
3288ccd4a63SDavid du Colombier 			return;
3298ccd4a63SDavid du Colombier 		case 'x':
3308ccd4a63SDavid du Colombier 			xsummary();
3318ccd4a63SDavid du Colombier 			ixsummary();
3328ccd4a63SDavid du Colombier 			mallocsummary();
3338ccd4a63SDavid du Colombier 			pagersummary();
3348ccd4a63SDavid du Colombier 			return;
3358ccd4a63SDavid du Colombier 		case 'd':
336ec59a3ddSDavid du Colombier 			if(consdebug == 0)
3378ccd4a63SDavid du Colombier 				consdebug = rdb;
3388ccd4a63SDavid du Colombier 			else
339ec59a3ddSDavid du Colombier 				consdebug = 0;
3408ccd4a63SDavid du Colombier 			print("consdebug now 0x%p\n", consdebug);
3418ccd4a63SDavid du Colombier 			return;
3428ccd4a63SDavid du Colombier 		case 'D':
343ec59a3ddSDavid du Colombier 			if(consdebug == 0)
3448ccd4a63SDavid du Colombier 				consdebug = rdb;
3458ccd4a63SDavid du Colombier 			consdebug();
3468ccd4a63SDavid du Colombier 			return;
3478ccd4a63SDavid du Colombier 		case 'p':
3488ccd4a63SDavid du Colombier 			x = spllo();
3498ccd4a63SDavid du Colombier 			procdump();
3508ccd4a63SDavid du Colombier 			splx(x);
3518ccd4a63SDavid du Colombier 			return;
3528ccd4a63SDavid du Colombier 		case 'q':
3538ccd4a63SDavid du Colombier 			scheddump();
3548ccd4a63SDavid du Colombier 			return;
3558ccd4a63SDavid du Colombier 		case 'k':
3568ccd4a63SDavid du Colombier 			killbig();
3578ccd4a63SDavid du Colombier 			return;
3588ccd4a63SDavid du Colombier 		case 'r':
3598ccd4a63SDavid du Colombier 			exit(0);
3608ccd4a63SDavid du Colombier 			return;
3618ccd4a63SDavid du Colombier 		}
3628ccd4a63SDavid du Colombier 	}
3638ccd4a63SDavid du Colombier 
3648ccd4a63SDavid du Colombier 	qproduce(kbdq, buf, n);
3658ccd4a63SDavid du Colombier 	if(kbd.raw)
3668ccd4a63SDavid du Colombier 		return;
367ec59a3ddSDavid du Colombier 	if(screenputs != 0)
3688ccd4a63SDavid du Colombier 		echoscreen(buf, n);
3698ccd4a63SDavid du Colombier 	if(serialoq)
3708ccd4a63SDavid du Colombier 		echoserialoq(buf, n);
3718ccd4a63SDavid du Colombier }
3728ccd4a63SDavid du Colombier 
3738ccd4a63SDavid du Colombier /*
3748ccd4a63SDavid du Colombier  *  Called by a uart interrupt for console input.
3758ccd4a63SDavid du Colombier  *
3768ccd4a63SDavid du Colombier  *  turn '\r' into '\n' before putting it into the queue.
3778ccd4a63SDavid du Colombier  */
3788ccd4a63SDavid du Colombier int
kbdcr2nl(Queue * q,int ch)3798ccd4a63SDavid du Colombier kbdcr2nl(Queue *q, int ch)
3808ccd4a63SDavid du Colombier {
3818ccd4a63SDavid du Colombier 	char *next;
3828ccd4a63SDavid du Colombier 
3838ccd4a63SDavid du Colombier 	USED(q);
3848ccd4a63SDavid du Colombier 	ilock(&kbd.lockputc);		/* just a mutex */
3858ccd4a63SDavid du Colombier 	if(ch == '\r' && !kbd.raw)
3868ccd4a63SDavid du Colombier 		ch = '\n';
3878ccd4a63SDavid du Colombier 	next = kbd.iw+1;
3888ccd4a63SDavid du Colombier 	if(next >= kbd.ie)
3898ccd4a63SDavid du Colombier 		next = kbd.istage;
3908ccd4a63SDavid du Colombier 	if(next != kbd.ir){
3918ccd4a63SDavid du Colombier 		*kbd.iw = ch;
3928ccd4a63SDavid du Colombier 		kbd.iw = next;
3938ccd4a63SDavid du Colombier 	}
3948ccd4a63SDavid du Colombier 	iunlock(&kbd.lockputc);
3958ccd4a63SDavid du Colombier 	return 0;
3968ccd4a63SDavid du Colombier }
3978ccd4a63SDavid du Colombier static
3988ccd4a63SDavid du Colombier void
_kbdputc(int c)3998ccd4a63SDavid du Colombier _kbdputc(int c)
4008ccd4a63SDavid du Colombier {
4018ccd4a63SDavid du Colombier 	Rune r;
4028ccd4a63SDavid du Colombier 	char buf[UTFmax];
4038ccd4a63SDavid du Colombier 	int n;
4048ccd4a63SDavid du Colombier 
4058ccd4a63SDavid du Colombier 	r = c;
4068ccd4a63SDavid du Colombier 	n = runetochar(buf, &r);
4078ccd4a63SDavid du Colombier 	if(n == 0)
4088ccd4a63SDavid du Colombier 		return;
4098ccd4a63SDavid du Colombier 	echo(buf, n);
4108ccd4a63SDavid du Colombier //	kbd.c = r;
4118ccd4a63SDavid du Colombier //	qproduce(kbdq, buf, n);
4128ccd4a63SDavid du Colombier }
4138ccd4a63SDavid du Colombier 
4148ccd4a63SDavid du Colombier /* _kbdputc, but with compose translation */
4158ccd4a63SDavid du Colombier int
kbdputc(Queue * q,int c)4168ccd4a63SDavid du Colombier kbdputc(Queue *q, int c)
4178ccd4a63SDavid du Colombier {
4188ccd4a63SDavid du Colombier 	int	i;
4198ccd4a63SDavid du Colombier 	static int collecting, nk;
4208ccd4a63SDavid du Colombier 	static Rune kc[5];
4218ccd4a63SDavid du Colombier 
4228ccd4a63SDavid du Colombier 	 if(c == Kalt){
4238ccd4a63SDavid du Colombier 		 collecting = 1;
4248ccd4a63SDavid du Colombier 		 nk = 0;
4258ccd4a63SDavid du Colombier 		 return 0;
4268ccd4a63SDavid du Colombier 	 }
4278ccd4a63SDavid du Colombier 
4288ccd4a63SDavid du Colombier 	 if(!collecting){
4298ccd4a63SDavid du Colombier 		 _kbdputc(c);
4308ccd4a63SDavid du Colombier 		 return 0;
4318ccd4a63SDavid du Colombier 	 }
4328ccd4a63SDavid du Colombier 
4338ccd4a63SDavid du Colombier 	kc[nk++] = c;
4348ccd4a63SDavid du Colombier 	c = latin1(kc, nk);
4358ccd4a63SDavid du Colombier 	if(c < -1)  /* need more keystrokes */
4368ccd4a63SDavid du Colombier 		return 0;
4378ccd4a63SDavid du Colombier 	if(c != -1) /* valid sequence */
4388ccd4a63SDavid du Colombier 		_kbdputc(c);
4398ccd4a63SDavid du Colombier 	else
4408ccd4a63SDavid du Colombier 		for(i=0; i<nk; i++)
4418ccd4a63SDavid du Colombier 		 	_kbdputc(kc[i]);
4428ccd4a63SDavid du Colombier 	nk = 0;
4438ccd4a63SDavid du Colombier 	collecting = 0;
4448ccd4a63SDavid du Colombier 
4458ccd4a63SDavid du Colombier 	return 0;
4468ccd4a63SDavid du Colombier }
4478ccd4a63SDavid du Colombier 
4488ccd4a63SDavid du Colombier 
4498ccd4a63SDavid du Colombier enum{
4508ccd4a63SDavid du Colombier 	Qdir,
4518ccd4a63SDavid du Colombier 	Qbintime,
4528ccd4a63SDavid du Colombier 	Qcons,
4538ccd4a63SDavid du Colombier 	Qconsctl,
4548ccd4a63SDavid du Colombier 	Qcpunote,
4558ccd4a63SDavid du Colombier 	Qcputime,
4568ccd4a63SDavid du Colombier 	Qdrivers,
4578ccd4a63SDavid du Colombier 	Qkprint,
4588ccd4a63SDavid du Colombier 	Qhostdomain,
4598ccd4a63SDavid du Colombier 	Qhostowner,
4608ccd4a63SDavid du Colombier 	Qnull,
4618ccd4a63SDavid du Colombier 	Qosversion,
4628ccd4a63SDavid du Colombier 	Qpgrpid,
4638ccd4a63SDavid du Colombier 	Qpid,
4648ccd4a63SDavid du Colombier 	Qppid,
4658ccd4a63SDavid du Colombier 	Qrandom,
4668ccd4a63SDavid du Colombier 	Qreboot,
4678ccd4a63SDavid du Colombier 	Qsecstore,
468ec59a3ddSDavid du Colombier 	Qshowfile,
4698ccd4a63SDavid du Colombier 	Qsnarf,
4708ccd4a63SDavid du Colombier 	Qswap,
4718ccd4a63SDavid du Colombier 	Qsysname,
4728ccd4a63SDavid du Colombier 	Qsysstat,
4738ccd4a63SDavid du Colombier 	Qtime,
4748ccd4a63SDavid du Colombier 	Quser,
4758ccd4a63SDavid du Colombier 	Qzero,
4768ccd4a63SDavid du Colombier };
4778ccd4a63SDavid du Colombier 
4788ccd4a63SDavid du Colombier enum
4798ccd4a63SDavid du Colombier {
4808ccd4a63SDavid du Colombier 	VLNUMSIZE=	22,
4818ccd4a63SDavid du Colombier };
4828ccd4a63SDavid du Colombier 
4838ccd4a63SDavid du Colombier static Dirtab consdir[]={
4848ccd4a63SDavid du Colombier 	".",	{Qdir, 0, QTDIR},	0,		DMDIR|0555,
4858ccd4a63SDavid du Colombier 	"bintime",	{Qbintime},	24,		0664,
4868ccd4a63SDavid du Colombier 	"cons",		{Qcons},	0,		0660,
4878ccd4a63SDavid du Colombier 	"consctl",	{Qconsctl},	0,		0220,
4888ccd4a63SDavid du Colombier 	"cpunote",	{Qcpunote},	0,		0444,
4898ccd4a63SDavid du Colombier 	"cputime",	{Qcputime},	6*NUMSIZE,	0444,
4908ccd4a63SDavid du Colombier 	"drivers",	{Qdrivers},	0,		0444,
4918ccd4a63SDavid du Colombier 	"hostdomain",	{Qhostdomain},	DOMLEN,		0664,
4928ccd4a63SDavid du Colombier 	"hostowner",	{Qhostowner},	0,	0664,
4938ccd4a63SDavid du Colombier 	"kprint",		{Qkprint, 0, QTEXCL},	0,	DMEXCL|0440,
4948ccd4a63SDavid du Colombier 	"null",		{Qnull},	0,		0666,
4958ccd4a63SDavid du Colombier 	"osversion",	{Qosversion},	0,		0444,
4968ccd4a63SDavid du Colombier 	"pgrpid",	{Qpgrpid},	NUMSIZE,	0444,
4978ccd4a63SDavid du Colombier 	"pid",		{Qpid},		NUMSIZE,	0444,
4988ccd4a63SDavid du Colombier 	"ppid",		{Qppid},	NUMSIZE,	0444,
4998ccd4a63SDavid du Colombier 	"random",	{Qrandom},	0,		0444,
5008ccd4a63SDavid du Colombier 	"reboot",	{Qreboot},	0,		0664,
5018ccd4a63SDavid du Colombier 	"secstore",	{Qsecstore},	0,		0666,
502ec59a3ddSDavid du Colombier 	"showfile",	{Qshowfile},	0,	0220,
5038ccd4a63SDavid du Colombier 	"snarf",	{Qsnarf},		0,		0666,
5048ccd4a63SDavid du Colombier 	"swap",		{Qswap},	0,		0664,
5058ccd4a63SDavid du Colombier 	"sysname",	{Qsysname},	0,		0664,
5068ccd4a63SDavid du Colombier 	"sysstat",	{Qsysstat},	0,		0666,
5078ccd4a63SDavid du Colombier 	"time",		{Qtime},	NUMSIZE+3*VLNUMSIZE,	0664,
5088ccd4a63SDavid du Colombier 	"user",		{Quser},	0,	0666,
5098ccd4a63SDavid du Colombier 	"zero",		{Qzero},	0,		0444,
5108ccd4a63SDavid du Colombier };
5118ccd4a63SDavid du Colombier 
5128ccd4a63SDavid du Colombier char secstorebuf[65536];
5138ccd4a63SDavid du Colombier Dirtab *secstoretab = &consdir[Qsecstore];
5148ccd4a63SDavid du Colombier Dirtab *snarftab = &consdir[Qsnarf];
5158ccd4a63SDavid du Colombier 
5168ccd4a63SDavid du Colombier int
readnum(ulong off,char * buf,ulong n,ulong val,int size)5178ccd4a63SDavid du Colombier readnum(ulong off, char *buf, ulong n, ulong val, int size)
5188ccd4a63SDavid du Colombier {
5198ccd4a63SDavid du Colombier 	char tmp[64];
5208ccd4a63SDavid du Colombier 
5218ccd4a63SDavid du Colombier 	snprint(tmp, sizeof(tmp), "%*.0lud", size-1, val);
5228ccd4a63SDavid du Colombier 	tmp[size-1] = ' ';
5238ccd4a63SDavid du Colombier 	if(off >= size)
5248ccd4a63SDavid du Colombier 		return 0;
5258ccd4a63SDavid du Colombier 	if(off+n > size)
5268ccd4a63SDavid du Colombier 		n = size-off;
5278ccd4a63SDavid du Colombier 	memmove(buf, tmp+off, n);
5288ccd4a63SDavid du Colombier 	return n;
5298ccd4a63SDavid du Colombier }
5308ccd4a63SDavid du Colombier 
5318ccd4a63SDavid du Colombier int
readstr(ulong off,char * buf,ulong n,char * str)5328ccd4a63SDavid du Colombier readstr(ulong off, char *buf, ulong n, char *str)
5338ccd4a63SDavid du Colombier {
5348ccd4a63SDavid du Colombier 	int size;
5358ccd4a63SDavid du Colombier 
5368ccd4a63SDavid du Colombier 	size = strlen(str);
5378ccd4a63SDavid du Colombier 	if(off >= size)
5388ccd4a63SDavid du Colombier 		return 0;
5398ccd4a63SDavid du Colombier 	if(off+n > size)
5408ccd4a63SDavid du Colombier 		n = size-off;
5418ccd4a63SDavid du Colombier 	memmove(buf, str+off, n);
5428ccd4a63SDavid du Colombier 	return n;
5438ccd4a63SDavid du Colombier }
5448ccd4a63SDavid du Colombier 
5458ccd4a63SDavid du Colombier static void
consinit(void)5468ccd4a63SDavid du Colombier consinit(void)
5478ccd4a63SDavid du Colombier {
5488ccd4a63SDavid du Colombier 	todinit();
5498ccd4a63SDavid du Colombier 	randominit();
5508ccd4a63SDavid du Colombier 	/*
5518ccd4a63SDavid du Colombier 	 * at 115200 baud, the 1024 char buffer takes 56 ms to process,
5528ccd4a63SDavid du Colombier 	 * processing it every 22 ms should be fine
5538ccd4a63SDavid du Colombier 	 */
5548ccd4a63SDavid du Colombier /*	addclock0link(kbdputcclock, 22); */
5558ccd4a63SDavid du Colombier }
5568ccd4a63SDavid du Colombier 
5578ccd4a63SDavid du Colombier static Chan*
consattach(char * spec)5588ccd4a63SDavid du Colombier consattach(char *spec)
5598ccd4a63SDavid du Colombier {
5608ccd4a63SDavid du Colombier 	return devattach('c', spec);
5618ccd4a63SDavid du Colombier }
5628ccd4a63SDavid du Colombier 
5638ccd4a63SDavid du Colombier static Walkqid*
conswalk(Chan * c,Chan * nc,char ** name,int nname)5648ccd4a63SDavid du Colombier conswalk(Chan *c, Chan *nc, char **name, int nname)
5658ccd4a63SDavid du Colombier {
5668ccd4a63SDavid du Colombier 	return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
5678ccd4a63SDavid du Colombier }
5688ccd4a63SDavid du Colombier 
5698ccd4a63SDavid du Colombier static int
consstat(Chan * c,uchar * dp,int n)5708ccd4a63SDavid du Colombier consstat(Chan *c, uchar *dp, int n)
5718ccd4a63SDavid du Colombier {
5728ccd4a63SDavid du Colombier 	return devstat(c, dp, n, consdir, nelem(consdir), devgen);
5738ccd4a63SDavid du Colombier }
5748ccd4a63SDavid du Colombier 
5758ccd4a63SDavid du Colombier static Chan*
consopen(Chan * c,int omode)5768ccd4a63SDavid du Colombier consopen(Chan *c, int omode)
5778ccd4a63SDavid du Colombier {
5788ccd4a63SDavid du Colombier 	c->aux = nil;
5798ccd4a63SDavid du Colombier 	c = devopen(c, omode, consdir, nelem(consdir), devgen);
5808ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
5818ccd4a63SDavid du Colombier 	case Qconsctl:
5828ccd4a63SDavid du Colombier 		qlock(&kbd.lk);
5838ccd4a63SDavid du Colombier 		kbd.ctl++;
5848ccd4a63SDavid du Colombier 		qunlock(&kbd.lk);
5858ccd4a63SDavid du Colombier 		break;
5868ccd4a63SDavid du Colombier 
5878ccd4a63SDavid du Colombier 	case Qkprint:
588*96cbc34fSDavid du Colombier 		lock(&kprintlock);
589*96cbc34fSDavid du Colombier 		if(kprintinuse != 0){
5908ccd4a63SDavid du Colombier 			c->flag &= ~COPEN;
591*96cbc34fSDavid du Colombier 			unlock(&kprintlock);
5928ccd4a63SDavid du Colombier 			error(Einuse);
5938ccd4a63SDavid du Colombier 		}
594*96cbc34fSDavid du Colombier 		kprintinuse = 1;
595*96cbc34fSDavid du Colombier 		unlock(&kprintlock);
5968ccd4a63SDavid du Colombier 		if(kprintoq == nil){
5978ccd4a63SDavid du Colombier 			kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
5988ccd4a63SDavid du Colombier 			if(kprintoq == nil){
5998ccd4a63SDavid du Colombier 				c->flag &= ~COPEN;
6008ccd4a63SDavid du Colombier 				error(Enomem);
6018ccd4a63SDavid du Colombier 			}
6028ccd4a63SDavid du Colombier 			qnoblock(kprintoq, 1);
6038ccd4a63SDavid du Colombier 		}else
6048ccd4a63SDavid du Colombier 			qreopen(kprintoq);
6058ccd4a63SDavid du Colombier 		c->iounit = qiomaxatomic;
6068ccd4a63SDavid du Colombier 		break;
6078ccd4a63SDavid du Colombier 
6088ccd4a63SDavid du Colombier 	case Qsecstore:
6098ccd4a63SDavid du Colombier 		if(omode == ORDWR)
6108ccd4a63SDavid du Colombier 			error(Eperm);
6118ccd4a63SDavid du Colombier 		if(omode != OREAD)
6128ccd4a63SDavid du Colombier 			memset(secstorebuf, 0, sizeof secstorebuf);
6138ccd4a63SDavid du Colombier 		break;
6148ccd4a63SDavid du Colombier 
6158ccd4a63SDavid du Colombier 	case Qsnarf:
6168ccd4a63SDavid du Colombier 		if(omode == ORDWR)
6178ccd4a63SDavid du Colombier 			error(Eperm);
6188ccd4a63SDavid du Colombier 		if(omode == OREAD)
6198ccd4a63SDavid du Colombier 			c->aux = strdup("");
6208ccd4a63SDavid du Colombier 		else
6218ccd4a63SDavid du Colombier 			c->aux = mallocz(SnarfSize, 1);
6228ccd4a63SDavid du Colombier 		break;
6238ccd4a63SDavid du Colombier 	}
6248ccd4a63SDavid du Colombier 	return c;
6258ccd4a63SDavid du Colombier }
6268ccd4a63SDavid du Colombier 
6278ccd4a63SDavid du Colombier static void
consclose(Chan * c)6288ccd4a63SDavid du Colombier consclose(Chan *c)
6298ccd4a63SDavid du Colombier {
6308ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
6318ccd4a63SDavid du Colombier 	/* last close of control file turns off raw */
6328ccd4a63SDavid du Colombier 	case Qconsctl:
6338ccd4a63SDavid du Colombier 		if(c->flag&COPEN){
6348ccd4a63SDavid du Colombier 			qlock(&kbd.lk);
6358ccd4a63SDavid du Colombier 			if(--kbd.ctl == 0)
6368ccd4a63SDavid du Colombier 				kbd.raw = 0;
6378ccd4a63SDavid du Colombier 			qunlock(&kbd.lk);
6388ccd4a63SDavid du Colombier 		}
6398ccd4a63SDavid du Colombier 		break;
6408ccd4a63SDavid du Colombier 
6418ccd4a63SDavid du Colombier 	/* close of kprint allows other opens */
6428ccd4a63SDavid du Colombier 	case Qkprint:
6438ccd4a63SDavid du Colombier 		if(c->flag & COPEN){
6448ccd4a63SDavid du Colombier 			kprintinuse = 0;
6458ccd4a63SDavid du Colombier 			qhangup(kprintoq, nil);
6468ccd4a63SDavid du Colombier 		}
6478ccd4a63SDavid du Colombier 		break;
6488ccd4a63SDavid du Colombier 
6498ccd4a63SDavid du Colombier 	case Qsnarf:
6508ccd4a63SDavid du Colombier 		if(c->mode == OWRITE)
6518ccd4a63SDavid du Colombier 			clipwrite(c->aux);
6528ccd4a63SDavid du Colombier 		free(c->aux);
6538ccd4a63SDavid du Colombier 		break;
6548ccd4a63SDavid du Colombier 	}
6558ccd4a63SDavid du Colombier }
6568ccd4a63SDavid du Colombier 
6578ccd4a63SDavid du Colombier static long
consread(Chan * c,void * buf,long n,vlong off)6588ccd4a63SDavid du Colombier consread(Chan *c, void *buf, long n, vlong off)
6598ccd4a63SDavid du Colombier {
6608ccd4a63SDavid du Colombier 	char *b;
6618ccd4a63SDavid du Colombier 	char tmp[128];		/* must be >= 6*NUMSIZE */
6628ccd4a63SDavid du Colombier 	char *cbuf = buf;
6638ccd4a63SDavid du Colombier 	int ch, i, eol;
6648ccd4a63SDavid du Colombier 	vlong offset = off;
6658ccd4a63SDavid du Colombier 
6668ccd4a63SDavid du Colombier 	if(n <= 0)
6678ccd4a63SDavid du Colombier 		return n;
6688ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
6698ccd4a63SDavid du Colombier 	case Qdir:
6708ccd4a63SDavid du Colombier 		return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
6718ccd4a63SDavid du Colombier 
6728ccd4a63SDavid du Colombier 	case Qcons:
6738ccd4a63SDavid du Colombier 		qlock(&kbd.lk);
6748ccd4a63SDavid du Colombier 		if(waserror()) {
6758ccd4a63SDavid du Colombier 			qunlock(&kbd.lk);
6768ccd4a63SDavid du Colombier 			nexterror();
6778ccd4a63SDavid du Colombier 		}
6788ccd4a63SDavid du Colombier 		if(kbd.raw) {
6798ccd4a63SDavid du Colombier 			if(qcanread(lineq))
6808ccd4a63SDavid du Colombier 				n = qread(lineq, buf, n);
6818ccd4a63SDavid du Colombier 			else {
6828ccd4a63SDavid du Colombier 				/* read as much as possible */
6838ccd4a63SDavid du Colombier 				do {
6848ccd4a63SDavid du Colombier 					i = qread(kbdq, cbuf, n);
6858ccd4a63SDavid du Colombier 					cbuf += i;
6868ccd4a63SDavid du Colombier 					n -= i;
6878ccd4a63SDavid du Colombier 				} while (n>0 && qcanread(kbdq));
6888ccd4a63SDavid du Colombier 				n = cbuf - (char*)buf;
6898ccd4a63SDavid du Colombier 			}
6908ccd4a63SDavid du Colombier 		} else {
6918ccd4a63SDavid du Colombier 			while(!qcanread(lineq)) {
6928ccd4a63SDavid du Colombier 				qread(kbdq, &kbd.line[kbd.x], 1);
6938ccd4a63SDavid du Colombier 				ch = kbd.line[kbd.x];
6948ccd4a63SDavid du Colombier 				eol = 0;
6958ccd4a63SDavid du Colombier 				switch(ch){
6968ccd4a63SDavid du Colombier 				case '\b':
6978ccd4a63SDavid du Colombier 					if(kbd.x)
6988ccd4a63SDavid du Colombier 						kbd.x--;
6998ccd4a63SDavid du Colombier 					break;
7008ccd4a63SDavid du Colombier 				case 0x15:
7018ccd4a63SDavid du Colombier 					kbd.x = 0;
7028ccd4a63SDavid du Colombier 					break;
7038ccd4a63SDavid du Colombier 				case '\n':
7048ccd4a63SDavid du Colombier 				case 0x04:
7058ccd4a63SDavid du Colombier 					eol = 1;
7068ccd4a63SDavid du Colombier 				default:
7078ccd4a63SDavid du Colombier 					kbd.line[kbd.x++] = ch;
7088ccd4a63SDavid du Colombier 					break;
7098ccd4a63SDavid du Colombier 				}
7108ccd4a63SDavid du Colombier 				if(kbd.x == sizeof(kbd.line) || eol){
7118ccd4a63SDavid du Colombier 					if(ch == 0x04)
7128ccd4a63SDavid du Colombier 						kbd.x--;
7138ccd4a63SDavid du Colombier 					qwrite(lineq, kbd.line, kbd.x);
7148ccd4a63SDavid du Colombier 					kbd.x = 0;
7158ccd4a63SDavid du Colombier 				}
7168ccd4a63SDavid du Colombier 			}
7178ccd4a63SDavid du Colombier 			n = qread(lineq, buf, n);
7188ccd4a63SDavid du Colombier 		}
7198ccd4a63SDavid du Colombier 		qunlock(&kbd.lk);
7208ccd4a63SDavid du Colombier 		poperror();
7218ccd4a63SDavid du Colombier 		return n;
7228ccd4a63SDavid du Colombier 
7238ccd4a63SDavid du Colombier 	case Qcpunote:
7248ccd4a63SDavid du Colombier 		sleep(&up->sleep, return0, nil);
7258ccd4a63SDavid du Colombier 
7268ccd4a63SDavid du Colombier 	case Qcputime:
7278ccd4a63SDavid du Colombier 		return 0;
7288ccd4a63SDavid du Colombier 
7298ccd4a63SDavid du Colombier 	case Qkprint:
7308ccd4a63SDavid du Colombier 		return qread(kprintoq, buf, n);
7318ccd4a63SDavid du Colombier 
7328ccd4a63SDavid du Colombier 	case Qpgrpid:
7338ccd4a63SDavid du Colombier 		return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
7348ccd4a63SDavid du Colombier 
7358ccd4a63SDavid du Colombier 	case Qpid:
7368ccd4a63SDavid du Colombier 		return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
7378ccd4a63SDavid du Colombier 
7388ccd4a63SDavid du Colombier 	case Qppid:
7398ccd4a63SDavid du Colombier 		return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
7408ccd4a63SDavid du Colombier 
7418ccd4a63SDavid du Colombier 	case Qtime:
7428ccd4a63SDavid du Colombier 		return readtime((ulong)offset, buf, n);
7438ccd4a63SDavid du Colombier 
7448ccd4a63SDavid du Colombier 	case Qbintime:
7458ccd4a63SDavid du Colombier 		return readbintime(buf, n);
7468ccd4a63SDavid du Colombier 
7478ccd4a63SDavid du Colombier 	case Qhostowner:
7488ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, eve);
7498ccd4a63SDavid du Colombier 
7508ccd4a63SDavid du Colombier 	case Qhostdomain:
7518ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, hostdomain);
7528ccd4a63SDavid du Colombier 
7538ccd4a63SDavid du Colombier 	case Quser:
7548ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, up->user);
7558ccd4a63SDavid du Colombier 
7568ccd4a63SDavid du Colombier 	case Qnull:
7578ccd4a63SDavid du Colombier 		return 0;
7588ccd4a63SDavid du Colombier 
7598ccd4a63SDavid du Colombier 	case Qsnarf:
7608ccd4a63SDavid du Colombier 		if(offset == 0){
7618ccd4a63SDavid du Colombier 			free(c->aux);
7628ccd4a63SDavid du Colombier 			c->aux = clipread();
7638ccd4a63SDavid du Colombier 		}
7648ccd4a63SDavid du Colombier 		if(c->aux == nil)
7658ccd4a63SDavid du Colombier 			return 0;
7668ccd4a63SDavid du Colombier 		return readstr(offset, buf, n, c->aux);
7678ccd4a63SDavid du Colombier 
7688ccd4a63SDavid du Colombier 	case Qsecstore:
7698ccd4a63SDavid du Colombier 		return readstr(offset, buf, n, secstorebuf);
7708ccd4a63SDavid du Colombier 
7718ccd4a63SDavid du Colombier 	case Qsysstat:
7728ccd4a63SDavid du Colombier 		return 0;
7738ccd4a63SDavid du Colombier 
7748ccd4a63SDavid du Colombier 	case Qswap:
7758ccd4a63SDavid du Colombier 		return 0;
7768ccd4a63SDavid du Colombier 
7778ccd4a63SDavid du Colombier 	case Qsysname:
7788ccd4a63SDavid du Colombier 		if(sysname == nil)
7798ccd4a63SDavid du Colombier 			return 0;
7808ccd4a63SDavid du Colombier 		return readstr((ulong)offset, buf, n, sysname);
7818ccd4a63SDavid du Colombier 
7828ccd4a63SDavid du Colombier 	case Qrandom:
7838ccd4a63SDavid du Colombier 		return randomread(buf, n);
7848ccd4a63SDavid du Colombier 
7858ccd4a63SDavid du Colombier 	case Qdrivers:
7868ccd4a63SDavid du Colombier 		b = malloc(READSTR);
7878ccd4a63SDavid du Colombier 		if(b == nil)
7888ccd4a63SDavid du Colombier 			error(Enomem);
7898ccd4a63SDavid du Colombier 		n = 0;
7908ccd4a63SDavid du Colombier 		for(i = 0; devtab[i] != nil; i++)
7918ccd4a63SDavid du Colombier 			n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc,  devtab[i]->name);
7928ccd4a63SDavid du Colombier 		if(waserror()){
7938ccd4a63SDavid du Colombier 			free(b);
7948ccd4a63SDavid du Colombier 			nexterror();
7958ccd4a63SDavid du Colombier 		}
7968ccd4a63SDavid du Colombier 		n = readstr((ulong)offset, buf, n, b);
7978ccd4a63SDavid du Colombier 		free(b);
7988ccd4a63SDavid du Colombier 		poperror();
7998ccd4a63SDavid du Colombier 		return n;
8008ccd4a63SDavid du Colombier 
8018ccd4a63SDavid du Colombier 	case Qzero:
8028ccd4a63SDavid du Colombier 		memset(buf, 0, n);
8038ccd4a63SDavid du Colombier 		return n;
8048ccd4a63SDavid du Colombier 
8058ccd4a63SDavid du Colombier 	case Qosversion:
8068ccd4a63SDavid du Colombier 		snprint(tmp, sizeof tmp, "2000");
8078ccd4a63SDavid du Colombier 		n = readstr((ulong)offset, buf, n, tmp);
8088ccd4a63SDavid du Colombier 		return n;
8098ccd4a63SDavid du Colombier 
8108ccd4a63SDavid du Colombier 	default:
8118ccd4a63SDavid du Colombier 		print("consread 0x%llux\n", c->qid.path);
8128ccd4a63SDavid du Colombier 		error(Egreg);
8138ccd4a63SDavid du Colombier 	}
8148ccd4a63SDavid du Colombier 	return -1;		/* never reached */
8158ccd4a63SDavid du Colombier }
8168ccd4a63SDavid du Colombier 
8178ccd4a63SDavid du Colombier static long
conswrite(Chan * c,void * va,long n,vlong off)8188ccd4a63SDavid du Colombier conswrite(Chan *c, void *va, long n, vlong off)
8198ccd4a63SDavid du Colombier {
8208ccd4a63SDavid du Colombier 	char buf[256];
8218ccd4a63SDavid du Colombier 	long l, bp;
8228ccd4a63SDavid du Colombier 	char *a = va;
8238ccd4a63SDavid du Colombier 	int fd;
8248ccd4a63SDavid du Colombier 	Chan *swc;
8258ccd4a63SDavid du Colombier 	ulong offset = off;
8268ccd4a63SDavid du Colombier 	Cmdbuf *cb;
8278ccd4a63SDavid du Colombier 	Cmdtab *ct;
8288ccd4a63SDavid du Colombier 
8298ccd4a63SDavid du Colombier 	switch((ulong)c->qid.path){
8308ccd4a63SDavid du Colombier 	case Qcons:
8318ccd4a63SDavid du Colombier 		/*
8328ccd4a63SDavid du Colombier 		 * Can't page fault in putstrn, so copy the data locally.
8338ccd4a63SDavid du Colombier 		 */
8348ccd4a63SDavid du Colombier 		l = n;
8358ccd4a63SDavid du Colombier 		while(l > 0){
8368ccd4a63SDavid du Colombier 			bp = l;
8378ccd4a63SDavid du Colombier 			if(bp > sizeof buf)
8388ccd4a63SDavid du Colombier 				bp = sizeof buf;
8398ccd4a63SDavid du Colombier 			memmove(buf, a, bp);
8408ccd4a63SDavid du Colombier 			putstrn0(buf, bp, 1);
8418ccd4a63SDavid du Colombier 			a += bp;
8428ccd4a63SDavid du Colombier 			l -= bp;
8438ccd4a63SDavid du Colombier 		}
8448ccd4a63SDavid du Colombier 		break;
8458ccd4a63SDavid du Colombier 
8468ccd4a63SDavid du Colombier 	case Qconsctl:
8478ccd4a63SDavid du Colombier 		if(n >= sizeof(buf))
8488ccd4a63SDavid du Colombier 			n = sizeof(buf)-1;
8498ccd4a63SDavid du Colombier 		strncpy(buf, a, n);
8508ccd4a63SDavid du Colombier 		buf[n] = 0;
8518ccd4a63SDavid du Colombier 		for(a = buf; a;){
8528ccd4a63SDavid du Colombier 			if(strncmp(a, "rawon", 5) == 0){
8538ccd4a63SDavid du Colombier 				qlock(&kbd.lk);
8548ccd4a63SDavid du Colombier 				if(kbd.x){
8558ccd4a63SDavid du Colombier 					qwrite(kbdq, kbd.line, kbd.x);
8568ccd4a63SDavid du Colombier 					kbd.x = 0;
8578ccd4a63SDavid du Colombier 				}
8588ccd4a63SDavid du Colombier 				kbd.raw = 1;
8598ccd4a63SDavid du Colombier 				qunlock(&kbd.lk);
8608ccd4a63SDavid du Colombier 			} else if(strncmp(a, "rawoff", 6) == 0){
8618ccd4a63SDavid du Colombier 				qlock(&kbd.lk);
8628ccd4a63SDavid du Colombier 				kbd.raw = 0;
8638ccd4a63SDavid du Colombier 				kbd.x = 0;
8648ccd4a63SDavid du Colombier 				qunlock(&kbd.lk);
8658ccd4a63SDavid du Colombier 			} else if(strncmp(a, "ctlpon", 6) == 0){
8668ccd4a63SDavid du Colombier 				kbd.ctlpoff = 0;
8678ccd4a63SDavid du Colombier 			} else if(strncmp(a, "ctlpoff", 7) == 0){
8688ccd4a63SDavid du Colombier 				kbd.ctlpoff = 1;
8698ccd4a63SDavid du Colombier 			}
8708ccd4a63SDavid du Colombier 			if((a = strchr(a, ' ')))
8718ccd4a63SDavid du Colombier 				a++;
8728ccd4a63SDavid du Colombier 		}
8738ccd4a63SDavid du Colombier 		break;
8748ccd4a63SDavid du Colombier 
8758ccd4a63SDavid du Colombier 	case Qtime:
8768ccd4a63SDavid du Colombier 		if(!iseve())
8778ccd4a63SDavid du Colombier 			error(Eperm);
8788ccd4a63SDavid du Colombier 		return writetime(a, n);
8798ccd4a63SDavid du Colombier 
8808ccd4a63SDavid du Colombier 	case Qbintime:
8818ccd4a63SDavid du Colombier 		if(!iseve())
8828ccd4a63SDavid du Colombier 			error(Eperm);
8838ccd4a63SDavid du Colombier 		return writebintime(a, n);
8848ccd4a63SDavid du Colombier 
8858ccd4a63SDavid du Colombier 	case Qhostowner:
8868ccd4a63SDavid du Colombier 		return hostownerwrite(a, n);
8878ccd4a63SDavid du Colombier 
8888ccd4a63SDavid du Colombier 	case Qhostdomain:
8898ccd4a63SDavid du Colombier 		return hostdomainwrite(a, n);
8908ccd4a63SDavid du Colombier 
8918ccd4a63SDavid du Colombier 	case Quser:
8928ccd4a63SDavid du Colombier 		return userwrite(a, n);
8938ccd4a63SDavid du Colombier 
8948ccd4a63SDavid du Colombier 	case Qnull:
8958ccd4a63SDavid du Colombier 		break;
8968ccd4a63SDavid du Colombier 
8978ccd4a63SDavid du Colombier 	case Qreboot:
8988ccd4a63SDavid du Colombier 		if(!iseve())
8998ccd4a63SDavid du Colombier 			error(Eperm);
9008ccd4a63SDavid du Colombier 		cb = parsecmd(a, n);
9018ccd4a63SDavid du Colombier 
9028ccd4a63SDavid du Colombier 		if(waserror()) {
9038ccd4a63SDavid du Colombier 			free(cb);
9048ccd4a63SDavid du Colombier 			nexterror();
9058ccd4a63SDavid du Colombier 		}
9068ccd4a63SDavid du Colombier 		ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
9078ccd4a63SDavid du Colombier 		switch(ct->index) {
9088ccd4a63SDavid du Colombier 		case CMreboot:
9098ccd4a63SDavid du Colombier 			rebootcmd(cb->nf-1, cb->f+1);
9108ccd4a63SDavid du Colombier 			break;
9118ccd4a63SDavid du Colombier 		case CMpanic:
9128ccd4a63SDavid du Colombier 			panic("/dev/reboot");
9138ccd4a63SDavid du Colombier 		}
9148ccd4a63SDavid du Colombier 		poperror();
9158ccd4a63SDavid du Colombier 		free(cb);
9168ccd4a63SDavid du Colombier 		break;
9178ccd4a63SDavid du Colombier 
9188ccd4a63SDavid du Colombier 	case Qsecstore:
9198ccd4a63SDavid du Colombier 		if(offset >= sizeof secstorebuf || offset+n+1 >= sizeof secstorebuf)
9208ccd4a63SDavid du Colombier 			error(Etoobig);
9218ccd4a63SDavid du Colombier 		secstoretab->qid.vers++;
9228ccd4a63SDavid du Colombier 		memmove(secstorebuf+offset, va, n);
9238ccd4a63SDavid du Colombier 		return n;
9248ccd4a63SDavid du Colombier 
925ec59a3ddSDavid du Colombier 	case Qshowfile:
926ec59a3ddSDavid du Colombier 		return showfilewrite(a, n);
927ec59a3ddSDavid du Colombier 
9288ccd4a63SDavid du Colombier 	case Qsnarf:
9298ccd4a63SDavid du Colombier 		if(offset >= SnarfSize || offset+n >= SnarfSize)
9308ccd4a63SDavid du Colombier 			error(Etoobig);
9318ccd4a63SDavid du Colombier 		snarftab->qid.vers++;
9328ccd4a63SDavid du Colombier 		memmove((uchar*)c->aux+offset, va, n);
9338ccd4a63SDavid du Colombier 		return n;
9348ccd4a63SDavid du Colombier 
9358ccd4a63SDavid du Colombier 	case Qsysstat:
9368ccd4a63SDavid du Colombier 		n = 0;
9378ccd4a63SDavid du Colombier 		break;
9388ccd4a63SDavid du Colombier 
9398ccd4a63SDavid du Colombier 	case Qswap:
9408ccd4a63SDavid du Colombier 		if(n >= sizeof buf)
9418ccd4a63SDavid du Colombier 			error(Egreg);
9428ccd4a63SDavid du Colombier 		memmove(buf, va, n);	/* so we can NUL-terminate */
9438ccd4a63SDavid du Colombier 		buf[n] = 0;
9448ccd4a63SDavid du Colombier 		/* start a pager if not already started */
9458ccd4a63SDavid du Colombier 		if(strncmp(buf, "start", 5) == 0){
9468ccd4a63SDavid du Colombier 			kickpager();
9478ccd4a63SDavid du Colombier 			break;
9488ccd4a63SDavid du Colombier 		}
9498ccd4a63SDavid du Colombier 		if(cpuserver && !iseve())
9508ccd4a63SDavid du Colombier 			error(Eperm);
9518ccd4a63SDavid du Colombier 		if(buf[0]<'0' || '9'<buf[0])
9528ccd4a63SDavid du Colombier 			error(Ebadarg);
9538ccd4a63SDavid du Colombier 		fd = strtoul(buf, 0, 0);
9548ccd4a63SDavid du Colombier 		swc = fdtochan(fd, -1, 1, 1);
9558ccd4a63SDavid du Colombier 		setswapchan(swc);
9568ccd4a63SDavid du Colombier 		break;
9578ccd4a63SDavid du Colombier 
9588ccd4a63SDavid du Colombier 	case Qsysname:
9598ccd4a63SDavid du Colombier 		if(offset != 0)
9608ccd4a63SDavid du Colombier 			error(Ebadarg);
9618ccd4a63SDavid du Colombier 		if(n <= 0 || n >= sizeof buf)
9628ccd4a63SDavid du Colombier 			error(Ebadarg);
9638ccd4a63SDavid du Colombier 		strncpy(buf, a, n);
9648ccd4a63SDavid du Colombier 		buf[n] = 0;
9658ccd4a63SDavid du Colombier 		if(buf[n-1] == '\n')
9668ccd4a63SDavid du Colombier 			buf[n-1] = 0;
9678ccd4a63SDavid du Colombier 		kstrdup(&sysname, buf);
9688ccd4a63SDavid du Colombier 		break;
9698ccd4a63SDavid du Colombier 
9708ccd4a63SDavid du Colombier 	default:
9718ccd4a63SDavid du Colombier 		print("conswrite: 0x%llux\n", c->qid.path);
9728ccd4a63SDavid du Colombier 		error(Egreg);
9738ccd4a63SDavid du Colombier 	}
9748ccd4a63SDavid du Colombier 	return n;
9758ccd4a63SDavid du Colombier }
9768ccd4a63SDavid du Colombier 
9778ccd4a63SDavid du Colombier Dev consdevtab = {
9788ccd4a63SDavid du Colombier 	'c',
9798ccd4a63SDavid du Colombier 	"cons",
9808ccd4a63SDavid du Colombier 
9818ccd4a63SDavid du Colombier 	devreset,
9828ccd4a63SDavid du Colombier 	consinit,
9838ccd4a63SDavid du Colombier 	devshutdown,
9848ccd4a63SDavid du Colombier 	consattach,
9858ccd4a63SDavid du Colombier 	conswalk,
9868ccd4a63SDavid du Colombier 	consstat,
9878ccd4a63SDavid du Colombier 	consopen,
9888ccd4a63SDavid du Colombier 	devcreate,
9898ccd4a63SDavid du Colombier 	consclose,
9908ccd4a63SDavid du Colombier 	consread,
9918ccd4a63SDavid du Colombier 	devbread,
9928ccd4a63SDavid du Colombier 	conswrite,
9938ccd4a63SDavid du Colombier 	devbwrite,
9948ccd4a63SDavid du Colombier 	devremove,
9958ccd4a63SDavid du Colombier 	devwstat,
9968ccd4a63SDavid du Colombier };
9978ccd4a63SDavid du Colombier 
9988ccd4a63SDavid du Colombier static uvlong uvorder = (uvlong) 0x0001020304050607ULL;
9998ccd4a63SDavid du Colombier 
10008ccd4a63SDavid du Colombier static uchar*
le2vlong(vlong * to,uchar * f)10018ccd4a63SDavid du Colombier le2vlong(vlong *to, uchar *f)
10028ccd4a63SDavid du Colombier {
10038ccd4a63SDavid du Colombier 	uchar *t, *o;
10048ccd4a63SDavid du Colombier 	int i;
10058ccd4a63SDavid du Colombier 
10068ccd4a63SDavid du Colombier 	t = (uchar*)to;
10078ccd4a63SDavid du Colombier 	o = (uchar*)&uvorder;
10088ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(vlong); i++)
10098ccd4a63SDavid du Colombier 		t[o[i]] = f[i];
10108ccd4a63SDavid du Colombier 	return f+sizeof(vlong);
10118ccd4a63SDavid du Colombier }
10128ccd4a63SDavid du Colombier 
10138ccd4a63SDavid du Colombier static uchar*
vlong2le(uchar * t,vlong from)10148ccd4a63SDavid du Colombier vlong2le(uchar *t, vlong from)
10158ccd4a63SDavid du Colombier {
10168ccd4a63SDavid du Colombier 	uchar *f, *o;
10178ccd4a63SDavid du Colombier 	int i;
10188ccd4a63SDavid du Colombier 
10198ccd4a63SDavid du Colombier 	f = (uchar*)&from;
10208ccd4a63SDavid du Colombier 	o = (uchar*)&uvorder;
10218ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(vlong); i++)
10228ccd4a63SDavid du Colombier 		t[i] = f[o[i]];
10238ccd4a63SDavid du Colombier 	return t+sizeof(vlong);
10248ccd4a63SDavid du Colombier }
10258ccd4a63SDavid du Colombier 
10268ccd4a63SDavid du Colombier static long order = 0x00010203;
10278ccd4a63SDavid du Colombier 
10288ccd4a63SDavid du Colombier static uchar*
le2long(long * to,uchar * f)10298ccd4a63SDavid du Colombier le2long(long *to, uchar *f)
10308ccd4a63SDavid du Colombier {
10318ccd4a63SDavid du Colombier 	uchar *t, *o;
10328ccd4a63SDavid du Colombier 	int i;
10338ccd4a63SDavid du Colombier 
10348ccd4a63SDavid du Colombier 	t = (uchar*)to;
10358ccd4a63SDavid du Colombier 	o = (uchar*)&order;
10368ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(long); i++)
10378ccd4a63SDavid du Colombier 		t[o[i]] = f[i];
10388ccd4a63SDavid du Colombier 	return f+sizeof(long);
10398ccd4a63SDavid du Colombier }
10408ccd4a63SDavid du Colombier 
10418ccd4a63SDavid du Colombier /*
10428ccd4a63SDavid du Colombier static uchar*
10438ccd4a63SDavid du Colombier long2le(uchar *t, long from)
10448ccd4a63SDavid du Colombier {
10458ccd4a63SDavid du Colombier 	uchar *f, *o;
10468ccd4a63SDavid du Colombier 	int i;
10478ccd4a63SDavid du Colombier 
10488ccd4a63SDavid du Colombier 	f = (uchar*)&from;
10498ccd4a63SDavid du Colombier 	o = (uchar*)&order;
10508ccd4a63SDavid du Colombier 	for(i = 0; i < sizeof(long); i++)
10518ccd4a63SDavid du Colombier 		t[i] = f[o[i]];
10528ccd4a63SDavid du Colombier 	return t+sizeof(long);
10538ccd4a63SDavid du Colombier }
10548ccd4a63SDavid du Colombier */
10558ccd4a63SDavid du Colombier 
10568ccd4a63SDavid du Colombier char *Ebadtimectl = "bad time control";
10578ccd4a63SDavid du Colombier 
10588ccd4a63SDavid du Colombier /*
10598ccd4a63SDavid du Colombier  *  like the old #c/time but with added info.  Return
10608ccd4a63SDavid du Colombier  *
10618ccd4a63SDavid du Colombier  *	secs	nanosecs	fastticks	fasthz
10628ccd4a63SDavid du Colombier  */
10638ccd4a63SDavid du Colombier static int
readtime(ulong off,char * buf,int n)10648ccd4a63SDavid du Colombier readtime(ulong off, char *buf, int n)
10658ccd4a63SDavid du Colombier {
10668ccd4a63SDavid du Colombier 	vlong	nsec, ticks;
10678ccd4a63SDavid du Colombier 	long sec;
10688ccd4a63SDavid du Colombier 	char str[7*NUMSIZE];
10698ccd4a63SDavid du Colombier 
10708ccd4a63SDavid du Colombier 	nsec = todget(&ticks);
10718ccd4a63SDavid du Colombier 	if(fasthz == (vlong)0)
10728ccd4a63SDavid du Colombier 		fastticks((uvlong*)&fasthz);
10738ccd4a63SDavid du Colombier 	sec = nsec/((uvlong) 1000000000);
10748ccd4a63SDavid du Colombier 	snprint(str, sizeof(str), "%*.0lud %*.0llud %*.0llud %*.0llud ",
10758ccd4a63SDavid du Colombier 		NUMSIZE-1, sec,
10768ccd4a63SDavid du Colombier 		VLNUMSIZE-1, nsec,
10778ccd4a63SDavid du Colombier 		VLNUMSIZE-1, ticks,
10788ccd4a63SDavid du Colombier 		VLNUMSIZE-1, fasthz);
10798ccd4a63SDavid du Colombier 	return readstr(off, buf, n, str);
10808ccd4a63SDavid du Colombier }
10818ccd4a63SDavid du Colombier 
10828ccd4a63SDavid du Colombier /*
10838ccd4a63SDavid du Colombier  *  set the time in seconds
10848ccd4a63SDavid du Colombier  */
10858ccd4a63SDavid du Colombier static int
writetime(char * buf,int n)10868ccd4a63SDavid du Colombier writetime(char *buf, int n)
10878ccd4a63SDavid du Colombier {
10888ccd4a63SDavid du Colombier 	char b[13];
10898ccd4a63SDavid du Colombier 	long i;
10908ccd4a63SDavid du Colombier 	vlong now;
10918ccd4a63SDavid du Colombier 
10928ccd4a63SDavid du Colombier 	if(n >= sizeof(b))
10938ccd4a63SDavid du Colombier 		error(Ebadtimectl);
10948ccd4a63SDavid du Colombier 	strncpy(b, buf, n);
10958ccd4a63SDavid du Colombier 	b[n] = 0;
10968ccd4a63SDavid du Colombier 	i = strtol(b, 0, 0);
10978ccd4a63SDavid du Colombier 	if(i <= 0)
10988ccd4a63SDavid du Colombier 		error(Ebadtimectl);
10998ccd4a63SDavid du Colombier 	now = i*((vlong) 1000000000);
11008ccd4a63SDavid du Colombier 	todset(now, 0, 0);
11018ccd4a63SDavid du Colombier 	return n;
11028ccd4a63SDavid du Colombier }
11038ccd4a63SDavid du Colombier 
11048ccd4a63SDavid du Colombier /*
11058ccd4a63SDavid du Colombier  *  read binary time info.  all numbers are little endian.
11068ccd4a63SDavid du Colombier  *  ticks and nsec are syncronized.
11078ccd4a63SDavid du Colombier  */
11088ccd4a63SDavid du Colombier static int
readbintime(char * buf,int n)11098ccd4a63SDavid du Colombier readbintime(char *buf, int n)
11108ccd4a63SDavid du Colombier {
11118ccd4a63SDavid du Colombier 	int i;
11128ccd4a63SDavid du Colombier 	vlong nsec, ticks;
11138ccd4a63SDavid du Colombier 	uchar *b = (uchar*)buf;
11148ccd4a63SDavid du Colombier 
11158ccd4a63SDavid du Colombier 	i = 0;
11168ccd4a63SDavid du Colombier 	if(fasthz == (vlong)0)
11178ccd4a63SDavid du Colombier 		fastticks((uvlong*)&fasthz);
11188ccd4a63SDavid du Colombier 	nsec = todget(&ticks);
11198ccd4a63SDavid du Colombier 	if(n >= 3*sizeof(uvlong)){
11208ccd4a63SDavid du Colombier 		vlong2le(b+2*sizeof(uvlong), fasthz);
11218ccd4a63SDavid du Colombier 		i += sizeof(uvlong);
11228ccd4a63SDavid du Colombier 	}
11238ccd4a63SDavid du Colombier 	if(n >= 2*sizeof(uvlong)){
11248ccd4a63SDavid du Colombier 		vlong2le(b+sizeof(uvlong), ticks);
11258ccd4a63SDavid du Colombier 		i += sizeof(uvlong);
11268ccd4a63SDavid du Colombier 	}
11278ccd4a63SDavid du Colombier 	if(n >= 8){
11288ccd4a63SDavid du Colombier 		vlong2le(b, nsec);
11298ccd4a63SDavid du Colombier 		i += sizeof(vlong);
11308ccd4a63SDavid du Colombier 	}
11318ccd4a63SDavid du Colombier 	return i;
11328ccd4a63SDavid du Colombier }
11338ccd4a63SDavid du Colombier 
11348ccd4a63SDavid du Colombier /*
11358ccd4a63SDavid du Colombier  *  set any of the following
11368ccd4a63SDavid du Colombier  *	- time in nsec
11378ccd4a63SDavid du Colombier  *	- nsec trim applied over some seconds
11388ccd4a63SDavid du Colombier  *	- clock frequency
11398ccd4a63SDavid du Colombier  */
11408ccd4a63SDavid du Colombier static int
writebintime(char * buf,int n)11418ccd4a63SDavid du Colombier writebintime(char *buf, int n)
11428ccd4a63SDavid du Colombier {
11438ccd4a63SDavid du Colombier 	uchar *p;
11448ccd4a63SDavid du Colombier 	vlong delta;
11458ccd4a63SDavid du Colombier 	long period;
11468ccd4a63SDavid du Colombier 
11478ccd4a63SDavid du Colombier 	n--;
11488ccd4a63SDavid du Colombier 	p = (uchar*)buf + 1;
11498ccd4a63SDavid du Colombier 	switch(*buf){
11508ccd4a63SDavid du Colombier 	case 'n':
11518ccd4a63SDavid du Colombier 		if(n < sizeof(vlong))
11528ccd4a63SDavid du Colombier 			error(Ebadtimectl);
11538ccd4a63SDavid du Colombier 		le2vlong(&delta, p);
11548ccd4a63SDavid du Colombier 		todset(delta, 0, 0);
11558ccd4a63SDavid du Colombier 		break;
11568ccd4a63SDavid du Colombier 	case 'd':
11578ccd4a63SDavid du Colombier 		if(n < sizeof(vlong)+sizeof(long))
11588ccd4a63SDavid du Colombier 			error(Ebadtimectl);
11598ccd4a63SDavid du Colombier 		p = le2vlong(&delta, p);
11608ccd4a63SDavid du Colombier 		le2long(&period, p);
11618ccd4a63SDavid du Colombier 		todset(-1, delta, period);
11628ccd4a63SDavid du Colombier 		break;
11638ccd4a63SDavid du Colombier 	case 'f':
11648ccd4a63SDavid du Colombier 		if(n < sizeof(uvlong))
11658ccd4a63SDavid du Colombier 			error(Ebadtimectl);
11668ccd4a63SDavid du Colombier 		le2vlong(&fasthz, p);
11678ccd4a63SDavid du Colombier 		todsetfreq(fasthz);
11688ccd4a63SDavid du Colombier 		break;
11698ccd4a63SDavid du Colombier 	}
11708ccd4a63SDavid du Colombier 	return n;
11718ccd4a63SDavid du Colombier }
11728ccd4a63SDavid du Colombier 
11738ccd4a63SDavid du Colombier 
11748ccd4a63SDavid du Colombier int
iprint(char * fmt,...)11758ccd4a63SDavid du Colombier iprint(char *fmt, ...)
11768ccd4a63SDavid du Colombier {
11778ccd4a63SDavid du Colombier 	int n, s;
11788ccd4a63SDavid du Colombier 	va_list arg;
11798ccd4a63SDavid du Colombier 	char buf[PRINTSIZE];
11808ccd4a63SDavid du Colombier 
11818ccd4a63SDavid du Colombier 	s = splhi();
11828ccd4a63SDavid du Colombier 	va_start(arg, fmt);
11838ccd4a63SDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
11848ccd4a63SDavid du Colombier 	va_end(arg);
1185*96cbc34fSDavid du Colombier 	if(screenputs != 0 && iprintscreenputs)
11868ccd4a63SDavid du Colombier 		screenputs(buf, n);
11878ccd4a63SDavid du Colombier #undef write
11888ccd4a63SDavid du Colombier 	write(2, buf, n);
11898ccd4a63SDavid du Colombier 	splx(s);
11908ccd4a63SDavid du Colombier 
11918ccd4a63SDavid du Colombier 	return n;
11928ccd4a63SDavid du Colombier }
11938ccd4a63SDavid du Colombier 
1194