Move stdin/stdout/stderr to #cons
[akaros.git] / kern / drivers / dev / cons.c
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 #include <arch/arch.h>
11 #include <ros/fs.h>
12 #include <ns.h>
13 #include <kmalloc.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <time.h>
17 #include <atomic.h>
18 #include <smp.h>
19 #include <error.h>
20 #include <sys/queue.h>
21 #include <event.h>
22 #include <ros/procinfo.h>
23
24 #if 0
25 void (*consdebug) (void) = NULL;
26 #endif
27 void (*screenputs) (const char *, int) = cputbuf;
28
29 struct queue *kbdq;                             /* unprocessed console input */
30 struct queue *lineq;                    /* processed console input */
31 struct queue *serialoq;                 /* serial console output */
32 struct queue *kprintoq;                 /* console output, for /dev/kprint */
33 atomic_t kprintinuse = 0;               /* test and set whether /dev/kprint is open */
34 int iprintscreenputs = 1;
35 int keepbroken = 1;
36
37 struct queue *cons_q;                   /* Akaros cons input: keyboard, serial, etc */
38
39 static uint8_t logbuffer[1 << 20];
40 static int index = 0;
41 static struct queue *logqueue = NULL;
42 static int reading_kmesg = 0;
43
44 typedef unsigned char uint8_t;
45
46 void logbuf(int c)
47 {
48         if (reading_kmesg)
49                 return;
50         if (index > 1 << 20)
51                 return;
52         logbuffer[index++] = c;
53 }
54
55 /*
56  *  return true if current user is eve
57  */
58 int iseve(void)
59 {
60 #if 0
61         return strcmp(eve, o->user) == 0;
62 #endif
63         return 1;
64 }
65
66 char *eve = "eve";
67 char hostdomain[256] = "akaros.org";
68
69 static struct {
70         qlock_t qlock;
71
72         int raw;                                        /* true if we shouldn't process input */
73         struct kref ctl;                        /* number of opens to the control file */
74         int x;                                          /* index into line */
75         char line[1024];                        /* current input line */
76
77         int count;
78         int ctlpoff;
79
80         /* a place to save up characters at interrupt time before dumping them in the queue */
81         spinlock_t lockputc;
82         char istage[1024];
83         char *iw;
84         char *ir;
85         char *ie;
86 } kbd = {
87 .iw = kbd.istage,.ir = kbd.istage,.ie = kbd.istage + sizeof(kbd.istage),};
88
89 char *sysname;
90 int64_t fasthz;
91
92 static int readtime(uint32_t, char *, int);
93 static int readbintime(char *, int);
94 static int writetime(char *, int);
95 static int writebintime(char *, int);
96 static void killkid(void);
97
98 enum {
99         CMbroken,
100         CMconsole,
101         CMhalt,
102         CMnobroken,
103         CMpanic,
104         CMreboot,
105 };
106
107
108 struct cmdtab rebootmsg[] = {
109         {CMbroken, "broken", 0},
110         {CMconsole, "console", 1},
111         {CMhalt, "halt", 1},
112         {CMnobroken, "nobroken", 0},
113         {CMpanic, "panic", 0},
114         {CMreboot, "reboot", 0},
115 };
116
117 void printinit(void)
118 {
119         lineq = qopen(2 * 1024, 0, NULL, NULL);
120         if (lineq == NULL)
121                 panic("printinit");
122         qdropoverflow(lineq, 1);
123 }
124
125 int consactive(void)
126 {
127         if (serialoq)
128                 return qlen(serialoq) > 0;
129         return 0;
130 }
131
132 void prflush(void)
133 {
134         long times = 0;
135
136         while (consactive())
137                 if (times++ > 1000)
138                         break;
139 }
140
141 /*
142  * Log console output so it can be retrieved via /dev/kmesg.
143  * This is good for catching boot-time messages after the fact.
144  */
145 struct {
146         spinlock_t lk;
147         char buf[1 << 20];
148         unsigned int n;
149 } kmesg;
150
151 static void kmesgputs(char *str, int n)
152 {
153         unsigned int nn, d;
154
155         spin_lock_irqsave(&kmesg.lk);
156         /* take the tail of huge writes */
157         if (n > sizeof kmesg.buf) {
158                 d = n - sizeof kmesg.buf;
159                 str += d;
160                 n -= d;
161         }
162
163         /* slide the buffer down to make room */
164         nn = kmesg.n;
165         if (nn + n >= sizeof kmesg.buf) {
166                 d = nn + n - sizeof kmesg.buf;
167                 if (d)
168                         memmove(kmesg.buf, kmesg.buf + d, sizeof kmesg.buf - d);
169                 nn -= d;
170         }
171
172         /* copy the data in */
173         memmove(kmesg.buf + nn, str, n);
174         nn += n;
175         kmesg.n = nn;
176         spin_unlock_irqsave(&kmesg.lk);
177 }
178
179 /*
180  *   Print a string on the console.  Convert \n to \r\n for serial
181  *   line consoles.  Locking of the queues is left up to the screen
182  *   or uart code.  Multi-line messages to serial consoles may get
183  *   interspersed with other messages.
184  */
185 static void putstrn0(char *str, int n, int usewrite)
186 {
187         int m;
188         char *t;
189
190 #if 0
191         if (!islo())
192                 usewrite = 0;
193 #endif
194
195         /*
196          *  how many different output devices do we need?
197          */
198         kmesgputs(str, n);
199
200         /*
201          *  if someone is reading /dev/kprint
202          *  put the message there.
203          *  if not and there's an attached bit mapped display,
204          *  put the message there.
205          *
206          *  if there's a serial line being used as a console,
207          *  put the message there.
208          */
209         if (kprintoq != NULL && !qisclosed(kprintoq)) {
210                 if (usewrite)
211                         qwrite(kprintoq, str, n);
212                 else
213                         qiwrite(kprintoq, str, n);
214         } else if (screenputs != NULL)
215                 screenputs(str, n);
216
217         if (serialoq == NULL) {
218 #if 0
219                 uartputs(str, n);
220 #endif
221                 return;
222         }
223
224         while (n > 0) {
225                 t = memchr(str, '\n', n);
226                 if (t && !kbd.raw) {
227                         m = t - str;
228                         if (usewrite) {
229                                 qwrite(serialoq, str, m);
230                                 qwrite(serialoq, "\r\n", 2);
231                         } else {
232                                 qiwrite(serialoq, str, m);
233                                 qiwrite(serialoq, "\r\n", 2);
234                         }
235                         n -= m + 1;
236                         str = t + 1;
237                 } else {
238                         if (usewrite)
239                                 qwrite(serialoq, str, n);
240                         else
241                                 qiwrite(serialoq, str, n);
242                         break;
243                 }
244         }
245 }
246
247 void putstrn(char *str, int n)
248 {
249         putstrn0(str, n, 0);
250 }
251
252 int noprint;
253
254 int print(char *fmt, ...)
255 {
256         int n;
257         va_list arg;
258         char buf[PRINTSIZE];
259
260         if (noprint)
261                 return -1;
262
263         va_start(arg, fmt);
264         n = vsnprintf(buf, sizeof(buf), fmt, arg);
265         va_end(arg);
266         putstrn(buf, n);
267
268         return n;
269 }
270
271 /*
272  * Want to interlock iprints to avoid interlaced output on
273  * multiprocessor, but don't want to deadlock if one processor
274  * dies during print and another has something important to say.
275  * Make a good faith effort.
276  */
277 static spinlock_t iprintlock;
278 static int iprintcanlock(spinlock_t * l)
279 {
280         int i;
281
282         for (i = 0; i < 1000; i++) {
283                 if (spin_trylock(l))
284                         return 1;
285         }
286         return 0;
287 }
288
289 int iprint(char *fmt, ...)
290 {
291         int8_t s = 0;
292         int n, locked;
293         va_list arg;
294         char buf[PRINTSIZE];
295
296         disable_irqsave(&s);
297         va_start(arg, fmt);
298         n = vsnprintf(buf, sizeof(buf), fmt, arg);
299         va_end(arg);
300         locked = iprintcanlock(&iprintlock);
301         if (screenputs != NULL && iprintscreenputs)
302                 screenputs(buf, n);
303 #if 0
304         uartputs(buf, n);
305 #endif
306         if (locked)
307                 spin_unlock(&iprintlock);
308         enable_irqsave(&s);
309
310         return n;
311 }
312
313 /* libmp at least contains a few calls to sysfatal; simulate with panic */
314 void sysfatal(char *fmt, ...)
315 {
316         char err[256];
317         va_list arg;
318
319         va_start(arg, fmt);
320         vsnprintf(err, sizeof err, fmt, arg);
321         va_end(arg);
322         panic("sysfatal: %s", err);
323 }
324
325 void _assert(char *fmt)
326 {
327         panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
328 }
329
330 #if 0
331 int pprint(char *fmt, ...)
332 {
333         ERRSTACK(2);
334         int n;
335         struct chan *c;
336         va_list arg;
337         char buf[2 * PRINTSIZE];
338
339         if (up == NULL || current->fgrp == NULL)
340                 return 0;
341
342         c = current->fgrp->fd[2];
343         if (c == 0 || (c->mode != O_WRITE && c->mode != O_RDWR))
344                 return 0;
345         n = snprintf(buf, sizeof buf, "%s %lud: ", current->text, current->pid);
346         va_start(arg, fmt);
347         n = vsnprintf(buf + n, sizeof(buf), fmt, arg);
348         va_end(arg);
349
350         if (waserror())
351                 return 0;
352         devtab[c->type]->write(c, buf, n, c->offset);
353         poperror();
354
355         spin_lock(&c->lock);
356         c->offset += n;
357         spin_unlock(&c->lock);
358
359         return n;
360 }
361 #endif
362
363 static void echoscreen(char *buf, int n)
364 {
365         char *e, *p;
366         char ebuf[128];
367         int x;
368
369         p = ebuf;
370         e = ebuf + sizeof(ebuf) - 4;
371         while (n-- > 0) {
372                 if (p >= e) {
373                         screenputs(ebuf, p - ebuf);
374                         p = ebuf;
375                 }
376                 x = *buf++;
377                 if (x == 0x15) {
378                         *p++ = '^';
379                         *p++ = 'U';
380                         *p++ = '\n';
381                 } else
382                         *p++ = x;
383         }
384         if (p != ebuf)
385                 screenputs(ebuf, p - ebuf);
386 }
387
388 static void echoserialoq(char *buf, int n)
389 {
390         char *e, *p;
391         char ebuf[128];
392         int x;
393
394         p = ebuf;
395         e = ebuf + sizeof(ebuf) - 4;
396         while (n-- > 0) {
397                 if (p >= e) {
398                         qiwrite(serialoq, ebuf, p - ebuf);
399                         p = ebuf;
400                 }
401                 x = *buf++;
402                 if (x == '\n') {
403                         *p++ = '\r';
404                         *p++ = '\n';
405                 } else if (x == 0x15) {
406                         *p++ = '^';
407                         *p++ = 'U';
408                         *p++ = '\n';
409                 } else
410                         *p++ = x;
411         }
412         if (p != ebuf)
413                 qiwrite(serialoq, ebuf, p - ebuf);
414 }
415
416 static void echo(char *buf, int n)
417 {
418         static int ctrlt, pid;
419         char *e, *p;
420
421         if (n == 0)
422                 return;
423
424         e = buf + n;
425         for (p = buf; p < e; p++) {
426                 switch (*p) {
427 #if 0
428                         case 0x10:      /* ^P */
429                                 if (cpuserver && !kbd.ctlpoff) {
430                                         active.exiting = 1;
431                                         return;
432                                 }
433                                 break;
434 #endif
435                         case 0x14:      /* ^T */
436                                 ctrlt++;
437                                 if (ctrlt > 2)
438                                         ctrlt = 2;
439                                 continue;
440                 }
441
442                 if (ctrlt != 2)
443                         continue;
444
445                 /* ^T escapes */
446                 ctrlt = 0;
447                 switch (*p) {
448 #if 0
449                         case 'S':{
450                                         int8_t x = 0;
451                                         disable_irqsave(&x);
452                                         dumpstack();
453                                         procdump();
454                                         enable_irqsave(&x);
455                                         return;
456                                 }
457 #endif
458                         case 's':
459                                 dumpstack();
460                                 return;
461 #if 0
462                         case 'x':
463                                 xsummary();
464                                 ixsummary();
465                                 mallocsummary();
466                                 memorysummary();
467                                 pagersummary();
468                                 return;
469                         case 'd':
470                                 if (consdebug == NULL)
471                                         consdebug = rdb;
472                                 else
473                                         consdebug = NULL;
474                                 printd("consdebug now %#p\n", consdebug);
475                                 return;
476                         case 'D':
477                                 if (consdebug == NULL)
478                                         consdebug = rdb;
479                                 consdebug();
480                                 return;
481                         case 'p':
482                                 x = spllo();
483                                 procdump();
484                                 splx(x);
485                                 return;
486                         case 'q':
487                                 scheddump();
488                                 return;
489                         case 'k':
490                                 killbig("^t ^t k");
491                                 return;
492 #endif
493                         case 'r':
494                                 exit(0);
495                                 return;
496                 }
497         }
498
499         qwrite(kbdq, buf, n);   /* was once qproduce, YMMV */
500         if (kbd.raw)
501                 return;
502         kmesgputs(buf, n);
503         if (screenputs != NULL)
504                 echoscreen(buf, n);
505         if (serialoq)
506                 echoserialoq(buf, n);
507 }
508
509 /*
510  *  Called by a uart interrupt for console input.
511  *
512  *  turn '\r' into '\n' before putting it into the queue.
513  */
514 int kbdcr2nl(struct queue *ignored_queue, int ch)
515 {
516         char *next;
517
518         spin_lock_irqsave(&kbd.lockputc);       /* just a mutex */
519         if (ch == '\r' && !kbd.raw)
520                 ch = '\n';
521         next = kbd.iw + 1;
522         if (next >= kbd.ie)
523                 next = kbd.istage;
524         if (next != kbd.ir) {
525                 *kbd.iw = ch;
526                 kbd.iw = next;
527         }
528         spin_unlock_irqsave(&kbd.lockputc);
529         return 0;
530 }
531
532 /*
533  *  Put character, possibly a rune, into read queue at interrupt time.
534  *  Called at interrupt time to process a character.
535  */
536 int kbdputc(struct queue *unused_queue, int ch)
537 {
538         int i, n;
539         char buf[3];
540         // Akaros does not use Rune et al.
541         //Rune r;
542         int r;
543         char *next;
544
545         if (kbd.ir == NULL)
546                 return 0;       /* in case we're not inited yet */
547
548         spin_lock_irqsave(&kbd.lockputc);       /* just a mutex */
549         r = ch;
550         //n = runetochar(buf, &r);
551         // Fake Rune support.
552         n = 1;
553         buf[0] = r;
554         for (i = 0; i < n; i++) {
555                 next = kbd.iw + 1;
556                 if (next >= kbd.ie)
557                         next = kbd.istage;
558                 if (next == kbd.ir)
559                         break;
560                 *kbd.iw = buf[i];
561                 kbd.iw = next;
562         }
563         spin_unlock_irqsave(&kbd.lockputc);
564         return 0;
565 }
566
567 /*
568  *  we save up input characters till clock time to reduce
569  *  per character interrupt overhead.
570  */
571 static void kbdputcclock(void)
572 {
573         char *iw;
574
575         /* this amortizes cost of qproduce */
576         if (kbd.iw != kbd.ir) {
577                 iw = kbd.iw;
578                 if (iw < kbd.ir) {
579                         echo(kbd.ir, kbd.ie - kbd.ir);
580                         kbd.ir = kbd.istage;
581                 }
582                 if (kbd.ir != iw) {
583                         echo(kbd.ir, iw - kbd.ir);
584                         kbd.ir = iw;
585                 }
586         }
587 }
588
589 enum {
590         Qdir,
591         Qbintime,
592         Qconfig,
593         Qcons,
594         Qconsctl,
595         Qcputime,
596         Qdrivers,
597         Qhostdomain,
598         Qhostowner,
599         Qklog,
600         Qkmesg,
601         Qkprint,
602         Qnull,
603         Qosversion,
604         Qpgrpid,
605         Qpid,
606         Qppid,
607         Qreboot,
608         Qstdin,
609         Qstdout,
610         Qstderr,
611         Qswap,
612         Qsysctl,
613         Qsysname,
614         Qsysstat,
615         Qtime,
616         Quser,
617         Qzero,
618         Qkillkid,
619 };
620
621 enum {
622         VLNUMSIZE = 22,
623         DOMLEN = 256,
624 };
625
626 static struct dirtab consdir[] = {
627         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
628         {"bintime", {Qbintime}, 24, 0664},
629         {"config", {Qconfig}, 0, 0444},
630         {"cons", {Qcons}, 0, 0660},
631         {"consctl", {Qconsctl}, 0, 0220},
632         // FIXME -- we don't have real permissions yet so we set it to 222, not 220
633         {"killkid", {Qkillkid}, 0, 0220 | /* BOGUS */ 2},
634         {"cputime", {Qcputime}, 6 * NUMSIZE, 0444},
635         {"drivers", {Qdrivers}, 0, 0444},
636         {"hostdomain", {Qhostdomain}, DOMLEN, 0664},
637         {"hostowner", {Qhostowner}, 0, 0664},
638         {"klog", {Qklog}, 0, 0440},
639         {"kmesg", {Qkmesg}, 0, 0440},
640         {"kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL | 0440},
641         {"null", {Qnull}, 0, 0666},
642         {"osversion", {Qosversion}, 0, 0444},
643         {"pgrpid", {Qpgrpid}, NUMSIZE, 0444},
644         {"pid", {Qpid}, NUMSIZE, 0444},
645         {"ppid", {Qppid}, NUMSIZE, 0444},
646         {"reboot", {Qreboot}, 0, 0660},
647         {"stdin", {Qstdin}, 0, 0666},
648         {"stdout", {Qstdout}, 0, 0666},
649         {"stderr", {Qstderr}, 0, 0666},
650         {"swap", {Qswap}, 0, 0664},
651         {"sysctl", {Qsysctl}, 0, 0666},
652         {"sysname", {Qsysname}, 0, 0664},
653         {"sysstat", {Qsysstat}, 0, 0666},
654         {"time", {Qtime}, NUMSIZE + 3 * VLNUMSIZE, 0664},
655         {"user", {Quser}, 0, 0666},
656         {"zero", {Qzero}, 0, 0444},
657 };
658
659 int consreadnum(uint32_t off, char *buf, uint32_t n, uint32_t val, int size)
660 {
661         char tmp[64];
662
663         snprintf(tmp, sizeof(tmp), "%*lud", size - 1, val);
664         tmp[size - 1] = ' ';
665         if (off >= size)
666                 return 0;
667         if (off + n > size)
668                 n = size - off;
669         memmove(buf, tmp + off, n);
670         return n;
671 }
672
673 int consreadstr(uint32_t off, char *buf, uint32_t n, char *str)
674 {
675         int size;
676
677         size = strlen(str);
678         if (off >= size)
679                 return 0;
680         if (off + n > size)
681                 n = size - off;
682         memmove(buf, str + off, n);
683         return n;
684 }
685
686 static void consinit(void)
687 {
688         kstrdup(&sysname, "nanwan");
689         cons_q = qopen(256, 0, 0, 0);
690 #if 0
691         todinit();
692 #endif
693         /*
694          * at 115200 baud, the 1024 char buffer takes 56 ms to process,
695          * processing it every 22 ms should be fine
696          */
697 #if 0
698         addclock0link(kbdputcclock, 22);
699 #endif
700 }
701
702 static char *devname(void);
703
704 static struct chan *consattach(char *spec)
705 {
706         return devattach(devname(), spec);
707 }
708
709 static struct walkqid *conswalk(struct chan *c, struct chan *nc, char **name,
710                                                                 int nname)
711 {
712         return devwalk(c, nc, name, nname, consdir, ARRAY_SIZE(consdir), devgen);
713 }
714
715 static int consstat(struct chan *c, uint8_t * dp, int n)
716 {
717         return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen);
718 }
719
720 static struct chan *consopen(struct chan *c, int omode)
721 {
722         c->aux = NULL;
723         c = devopen(c, omode, consdir, ARRAY_SIZE(consdir), devgen);
724         switch ((uint32_t) c->qid.path) {
725                 case Qconsctl:
726                         kref_get(&kbd.ctl, 1);
727                         break;
728
729                 case Qkprint:
730                         if (atomic_swap(&kprintinuse, 1) != 0) {
731                                 c->flag &= ~COPEN;
732                                 error(EADDRINUSE, "kprintinuse lock failed");
733                         }
734                         if (kprintoq == NULL) {
735                                 kprintoq = qopen(8 * 1024, Qcoalesce, 0, 0);
736                                 if (kprintoq == NULL) {
737                                         c->flag &= ~COPEN;
738                                         error(ENOMEM, "Can't allocate kprintoq");
739                                 }
740                                 qdropoverflow(kprintoq, 1);
741                         } else
742                                 qreopen(kprintoq);
743                         c->iounit = qiomaxatomic;
744                         break;
745         }
746         return c;
747 }
748
749 static void consclose(struct chan *c)
750 {
751         switch ((uint32_t) c->qid.path) {
752                         /* last close of control file turns off raw */
753                 case Qconsctl:
754                         if (c->flag & COPEN) {
755                                 if (kref_put(&kbd.ctl) == 0)
756                                         kbd.raw = 0;
757                         }
758                         break;
759
760                         /* close of kprint allows other opens */
761                 case Qkprint:
762                         if (c->flag & COPEN) {
763                                 kprintinuse = 0;
764                                 qhangup(kprintoq, NULL);
765                         }
766                         break;
767         }
768 }
769
770 static long consread(struct chan *c, void *buf, long n, int64_t off)
771 {
772         ERRSTACK(1);
773         uint32_t l;
774 #if 0
775         Mach *mp;
776 #endif
777         char *b, *bp, ch;
778         char tmp[256];                          /* must be >= 18*NUMSIZE (Qswap) */
779         int i, k, id, send;
780         int64_t offset = off;
781 #if 0
782         extern char configfile[];
783 #endif
784
785         if (n <= 0)
786                 return n;
787
788         switch ((uint32_t) c->qid.path) {
789                 case Qdir:
790                         return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen);
791
792                 case Qcons:
793                         qlock(&(&kbd)->qlock);
794                         if (waserror()) {
795                                 qunlock(&(&kbd)->qlock);
796                                 nexterror();
797                         }
798                         while (!qcanread(lineq)) {
799                                 if (qread(kbdq, &ch, 1) == 0)
800                                         continue;
801                                 send = 0;
802                                 if (ch == 0) {
803                                         /* flush output on rawoff -> rawon */
804                                         if (kbd.x > 0)
805                                                 send = !qcanread(kbdq);
806                                 } else if (kbd.raw) {
807                                         kbd.line[kbd.x++] = ch;
808                                         send = !qcanread(kbdq);
809                                 } else {
810                                         switch (ch) {
811                                                 case '\b':
812                                                         if (kbd.x > 0)
813                                                                 kbd.x--;
814                                                         break;
815                                                 case 0x15:      /* ^U */
816                                                         kbd.x = 0;
817                                                         break;
818                                                 case '\n':
819                                                 case 0x04:      /* ^D */
820                                                         send = 1;
821                                                 default:
822                                                         if (ch != 0x04)
823                                                                 kbd.line[kbd.x++] = ch;
824                                                         break;
825                                         }
826                                 }
827                                 if (send || kbd.x == sizeof kbd.line) {
828                                         qwrite(lineq, kbd.line, kbd.x);
829                                         kbd.x = 0;
830                                 }
831                         }
832                         n = qread(lineq, buf, n);
833                         qunlock(&(&kbd)->qlock);
834                         poperror();
835                         return n;
836
837 #if 0
838                 case Qcputime:
839                         k = offset;
840                         if (k >= 6 * NUMSIZE)
841                                 return 0;
842                         if (k + n > 6 * NUMSIZE)
843                                 n = 6 * NUMSIZE - k;
844                         /* easiest to format in a separate buffer and copy out */
845                         for (i = 0; i < 6 && NUMSIZE * i < k + n; i++) {
846                                 l = current->time[i];
847                                 if (i == TReal)
848                                         l = MACHP(0)->ticks - l;
849                                 l = TK2MS(l);
850                                 consreadnum(0, tmp + NUMSIZE * i, NUMSIZE, l, NUMSIZE);
851                         }
852                         memmove(buf, tmp + k, n);
853                         return n;
854 #endif
855
856                 case Qkmesg:
857                         /*
858                          * This is unlocked to avoid tying up a process
859                          * that's writing to the buffer.  kmesg.n never
860                          * gets smaller, so worst case the reader will
861                          * see a slurred buffer.
862                          */
863                         if (off >= kmesg.n)
864                                 n = 0;
865                         else {
866                                 if (off + n > kmesg.n)
867                                         n = kmesg.n - off;
868                                 memmove(buf, kmesg.buf + off, n);
869                         }
870                         return n;
871
872                 case Qkprint:
873                         return qread(kprintoq, buf, n);
874
875                 case Qpgrpid:
876                         return consreadnum((uint32_t) offset, buf, n, current->pgrp->pgrpid,
877                                                            NUMSIZE);
878
879                 case Qpid:
880                         return consreadnum((uint32_t) offset, buf, n, current->pid,
881                                                            NUMSIZE);
882
883                 case Qppid:
884                         return consreadnum((uint32_t) offset, buf, n, current->ppid,
885                                                            NUMSIZE);
886
887                 case Qtime:
888                         return readtime((uint32_t) offset, buf, n);
889
890                 case Qbintime:
891                         return readbintime(buf, n);
892
893                 case Qhostowner:
894                         return consreadstr((uint32_t) offset, buf, n, eve);
895
896                 case Qhostdomain:
897                         return consreadstr((uint32_t) offset, buf, n, hostdomain);
898
899                 case Quser:
900                         return consreadstr((uint32_t) offset, buf, n, current->user);
901
902                 case Qnull:
903                         return 0;
904
905 #if 0
906                 case Qconfig:
907                         return consreadstr((uint32_t) offset, buf, n, configfile);
908
909                 case Qsysstat:
910                         b = kzmalloc(conf.nmach * (NUMSIZE * 11 + 1) + 1, 0);   /* +1 for NUL */
911                         bp = b;
912                         for (id = 0; id < 32; id++) {
913                                 if (active.machs & (1 << id)) {
914                                         mp = MACHP(id);
915                                         consreadnum(0, bp, NUMSIZE, id, NUMSIZE);
916                                         bp += NUMSIZE;
917                                         consreadnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
918                                         bp += NUMSIZE;
919                                         consreadnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
920                                         bp += NUMSIZE;
921                                         consreadnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
922                                         bp += NUMSIZE;
923                                         consreadnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
924                                         bp += NUMSIZE;
925                                         consreadnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
926                                         bp += NUMSIZE;
927                                         consreadnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
928                                         bp += NUMSIZE;
929                                         consreadnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
930                                         bp += NUMSIZE;
931                                         consreadnum(0, bp, NUMSIZE,
932                                                                 (mp->perf.avg_inidle * 100) / mp->perf.period,
933                                                                 NUMSIZE);
934                                         bp += NUMSIZE;
935                                         consreadnum(0, bp, NUMSIZE,
936                                                                 (mp->perf.avg_inintr * 100) / mp->perf.period,
937                                                                 NUMSIZE);
938                                         bp += NUMSIZE;
939                                         *bp++ = '\n';
940                                 }
941                         }
942                         if (waserror()) {
943                                 kfree(b);
944                                 nexterror();
945                         }
946                         n = consreadstr((uint32_t) offset, buf, n, b);
947                         kfree(b);
948                         poperror();
949                         return n;
950
951                 case Qswap:
952                         snprintf(tmp, sizeof tmp,
953                                          "%lud memory\n"
954                                          "%d pagesize\n"
955                                          "%lud kernel\n"
956                                          "%lud/%lud user\n"
957                                          "%lud/%lud swap\n"
958                                          "%lud/%lud kernel malloc\n"
959                                          "%lud/%lud kernel draw\n",
960                                          conf.npage * BY2PG,
961                                          BY2PG,
962                                          conf.npage - conf.upages,
963                                          palloc.user - palloc.freecount, palloc.user,
964                                          conf.nswap - swapalloc.free, conf.nswap,
965                                          mainmem->cursize, mainmem->maxsize,
966                                          imagmem->cursize, imagmem->maxsize);
967
968                         return consreadstr((uint32_t) offset, buf, n, tmp);
969 #endif
970
971                 case Qstdin:
972                         return qread(cons_q, buf, n);
973                 case Qsysname:
974                         /* TODO: this is racy */
975                         if (sysname == NULL)
976                                 return 0;
977                         return consreadstr((uint32_t) offset, buf, n, sysname);
978
979                 case Qdrivers:
980                         b = kzmalloc(READSTR, 0);
981                         if (b == NULL)
982                                 error(ENOMEM, "allocation for /dev/drivers read failed");
983                         k = 0;
984                         for (int i = 0; &devtab[i] < __devtabend; i++)
985                                 k += snprintf(b + k, READSTR - k, "#%s\n", devtab[i].name);
986                         if (waserror()) {
987                                 kfree(b);
988                                 nexterror();
989                         }
990                         n = consreadstr((uint32_t) offset, buf, n, b);
991                         kfree(b);
992                         poperror();
993                         return n;
994
995                 case Qklog:
996                         //return qread(klogq, buf, n);
997                         /* the queue gives us some elasticity for log reading. */
998                         if (!logqueue)
999                                 logqueue = qopen(1 << 20, 0, 0, 0);
1000                         if (logqueue) {
1001                                 int ret;
1002                                 /* atomic sets/gets are not that important in this case. */
1003                                 reading_kmesg = 1;
1004                                 qwrite(logqueue, logbuffer, index);
1005                                 index = 0;
1006                                 ret = qread(logqueue, buf, n);
1007                                 reading_kmesg = 0;
1008                                 return ret;
1009                         }
1010                         break;
1011
1012                 case Qzero:
1013                         memset(buf, 0, n);
1014                         return n;
1015
1016                 case Qosversion:
1017                         snprintf(tmp, sizeof tmp, "2000");
1018                         n = consreadstr((uint32_t) offset, buf, n, tmp);
1019                         return n;
1020
1021                 default:
1022                         printd("consread %#llux\n", c->qid.path);
1023                         error(EINVAL, "bad QID in consread");
1024         }
1025         return -1;      /* never reached */
1026 }
1027
1028 static long conswrite(struct chan *c, void *va, long n, int64_t off)
1029 {
1030         ERRSTACK(1);
1031         char buf[256], ch;
1032         long l, bp;
1033         char *a;
1034         //Mach *mp;
1035         int id, fd;
1036         struct chan *swc;
1037         uint32_t offset;
1038         struct cmdbuf *cb;
1039         struct cmdtab *ct;
1040         int x;
1041         uint64_t rip, rsp, cr3, flags, vcpu;
1042         int ret;
1043
1044         a = va;
1045         offset = off;
1046
1047         switch ((uint32_t) c->qid.path) {
1048                 case Qcons:
1049                         /*
1050                          * Can't page fault in putstrn, so copy the data locally.
1051                          */
1052                         l = n;
1053                         while (l > 0) {
1054                                 bp = l;
1055                                 if (bp > sizeof buf)
1056                                         bp = sizeof buf;
1057                                 memmove(buf, a, bp);
1058                                 putstrn0(buf, bp, 1);
1059                                 a += bp;
1060                                 l -= bp;
1061                         }
1062                         break;
1063
1064                 /* TODO: have it take a command about just *how* to kill the kid? */
1065                 case Qkillkid:
1066                         killkid();
1067                         break;
1068
1069                 case Qconsctl:
1070                         if (n >= sizeof(buf))
1071                                 n = sizeof(buf) - 1;
1072                         strncpy(buf, a, n);
1073                         buf[n] = 0;
1074                         for (a = buf; a;) {
1075                                 if (strncmp(a, "rawon", 5) == 0) {
1076                                         kbd.raw = 1;
1077                                         /* clumsy hack - wake up reader */
1078                                         ch = 0;
1079                                         qwrite(kbdq, &ch, 1);
1080                                 } else if (strncmp(a, "rawoff", 6) == 0) {
1081                                         kbd.raw = 0;
1082                                 } else if (strncmp(a, "ctlpon", 6) == 0) {
1083                                         kbd.ctlpoff = 0;
1084                                 } else if (strncmp(a, "ctlpoff", 7) == 0) {
1085                                         kbd.ctlpoff = 1;
1086                                 }
1087                                 if ((a = strchr(a, ' ')) != NULL)
1088                                         a++;
1089                         }
1090                         break;
1091
1092                 case Qtime:
1093                         if (!iseve())
1094                                 error(EPERM, "Hodie Natus Est Radici Frater");
1095                         return writetime(a, n);
1096
1097                 case Qbintime:
1098                         if (!iseve())
1099                                 error(EPERM, ERROR_FIXME);
1100                         return writebintime(a, n);
1101
1102 #if 0
1103                 case Qhostowner:
1104                         return hostownerwrite(a, n);
1105
1106                 case Qhostdomain:
1107                         return hostdomainwrite(a, n);
1108
1109                 case Quser:
1110                         return userwrite(a, n);
1111 #endif
1112
1113                 case Qnull:
1114                         break;
1115
1116                 case Qconfig:
1117                         error(EPERM, "Cannot write to config QID");
1118                         break;
1119
1120                 case Qsysctl:
1121                         //if (!iseve()) error(EPERM, ERROR_FIXME);
1122                         cb = parsecmd(a, n);
1123                         if (cb->nf > 1)
1124                         printd("cons sysctl cmd %s\n", cb->f[0]);
1125
1126                 case Qreboot:
1127                         if (!iseve())
1128                                 error(EPERM, ERROR_FIXME);
1129                         cb = parsecmd(a, n);
1130
1131                         if (waserror()) {
1132                                 kfree(cb);
1133                                 nexterror();
1134                         }
1135                         ct = lookupcmd(cb, rebootmsg, ARRAY_SIZE(rebootmsg));
1136                         switch (ct->index) {
1137                                 case CMhalt:
1138                                         cpu_halt();
1139                                         break;
1140                                 case CMbroken:
1141                                         keepbroken = 1;
1142                                         break;
1143                                 case CMnobroken:
1144                                         keepbroken = 0;
1145                                         break;
1146                                 case CMreboot:
1147                                         reboot();
1148                                         break;
1149                                 case CMpanic:
1150                                         *(uint32_t *) 0 = 0;
1151                                         panic("/dev/reboot");
1152                                         break;
1153                         }
1154                         poperror();
1155                         kfree(cb);
1156                         break;
1157
1158 #if 0
1159                 case Qsysstat:
1160                         for (id = 0; id < 32; id++) {
1161                                 if (active.machs & (1 << id)) {
1162                                         mp = MACHP(id);
1163                                         mp->cs = 0;
1164                                         mp->intr = 0;
1165                                         mp->syscall = 0;
1166                                         mp->pfault = 0;
1167                                         mp->tlbfault = 0;
1168                                         mp->tlbpurge = 0;
1169                                 }
1170                         }
1171                         break;
1172
1173                 case Qswap:
1174                         if (n >= sizeof buf)
1175                                 error(EINVAL, "n is bigger than sizeof buf for Qswap");
1176                         memmove(buf, va, n);    /* so we can NUL-terminate */
1177                         buf[n] = 0;
1178                         /* start a pager if not already started */
1179                         if (strncmp(buf, "start", 5) == 0) {
1180                                 kickpager();
1181                                 break;
1182                         }
1183                         if (!iseve())
1184                                 error(EPERM, ERROR_FIXME);
1185                         if (buf[0] < '0' || '9' < buf[0])
1186                                 error(EINVAL, ERROR_FIXME);
1187                         fd = strtoul(buf, 0, 0);
1188                         swc = fdtochan(fd, -1, 1, 1);
1189                         setswapchan(swc);
1190                         break;
1191 #endif
1192
1193                 case Qstdout:
1194                 case Qstderr:
1195                         px_lock();
1196                         if (waserror()) {
1197                                 px_unlock();
1198                                 nexterror();
1199                         }
1200                         /* TODO: tty hack.  they are sending us an escape sequence, and the
1201                          * keyboard would try to print it (which it can't do yet).  The hack
1202                          * is even dirtier in that we only detect it if it is the first
1203                          * char, and we ignore everything else.  \033 is 0x1b. */
1204                         if (((char*)va)[0] != '\033')
1205                                 cputbuf(va, n);
1206                         poperror();
1207                         px_unlock();
1208                         return n;
1209                 case Qsysname:
1210                         /* TODO: this is racy */
1211                         if (offset != 0)
1212                                 error(EINVAL, ERROR_FIXME);
1213                         if (n <= 0 || n >= sizeof buf)
1214                                 error(EINVAL, ERROR_FIXME);
1215                         strncpy(buf, a, n);
1216                         buf[n] = 0;
1217                         if (buf[n - 1] == '\n')
1218                                 buf[n - 1] = 0;
1219                         kstrdup(&sysname, buf);
1220                         break;
1221
1222                 default:
1223                         printd("conswrite: %#llux\n", c->qid.path);
1224                         error(EINVAL, "bad QID in conswrite");
1225         }
1226         return n;
1227 }
1228
1229 static char *cons_chaninfo(struct chan *ch, char *ret, size_t ret_l)
1230 {
1231         switch ((uint32_t)ch->qid.path) {
1232         case Qstdin:
1233                 snprintf(ret, ret_l, "qio len: %d", qlen(cons_q));
1234                 break;
1235         default:
1236                 return devchaninfo(ch, ret, ret_l);
1237         }
1238         return ret;
1239 }
1240
1241 struct dev consdevtab __devtab = {
1242         .name = "cons",
1243
1244         .reset = devreset,
1245         .init = consinit,
1246         .shutdown = devshutdown,
1247         .attach = consattach,
1248         .walk = conswalk,
1249         .stat = consstat,
1250         .open = consopen,
1251         .create = devcreate,
1252         .close = consclose,
1253         .read = consread,
1254         .bread = devbread,
1255         .write = conswrite,
1256         .bwrite = devbwrite,
1257         .remove = devremove,
1258         .wstat = devwstat,
1259         .power = devpower,
1260         .chaninfo = cons_chaninfo,
1261 };
1262
1263 static char *devname(void)
1264 {
1265         return consdevtab.name;
1266 }
1267
1268 static uint64_t uvorder = 0x0001020304050607ULL;
1269
1270 static uint8_t *le2int64_t(int64_t * to, uint8_t * f)
1271 {
1272         uint8_t *t, *o;
1273         int i;
1274
1275         t = (uint8_t *) to;
1276         o = (uint8_t *) & uvorder;
1277         for (i = 0; i < sizeof(int64_t); i++)
1278                 t[o[i]] = f[i];
1279         return f + sizeof(int64_t);
1280 }
1281
1282 static uint8_t *int64_t2le(uint8_t * t, int64_t from)
1283 {
1284         uint8_t *f, *o;
1285         int i;
1286
1287         f = (uint8_t *) & from;
1288         o = (uint8_t *) & uvorder;
1289         for (i = 0; i < sizeof(int64_t); i++)
1290                 t[i] = f[o[i]];
1291         return t + sizeof(int64_t);
1292 }
1293
1294 static long order = 0x00010203;
1295
1296 static uint8_t *le2long(long *to, uint8_t * f)
1297 {
1298         uint8_t *t, *o;
1299         int i;
1300
1301         t = (uint8_t *) & to;
1302         o = (uint8_t *) & order;
1303         for (i = 0; i < sizeof(long); i++)
1304                 t[o[i]] = f[i];
1305         return f + sizeof(long);
1306 }
1307
1308 static uint8_t *long2le(uint8_t * t, long from)
1309 {
1310         uint8_t *f, *o;
1311         int i;
1312
1313         f = (uint8_t *) & from;
1314         o = (uint8_t *) & order;
1315         for (i = 0; i < sizeof(long); i++)
1316                 t[i] = f[o[i]];
1317         return t + sizeof(long);
1318 }
1319
1320 char *Ebadtimectl = "bad time control";
1321
1322 /*
1323  *  like the old #c/time but with added info.  Return
1324  *
1325  *      secs    nanosecs        fastticks       fasthz
1326  */
1327 static int readtime(uint32_t off, char *buf, int n)
1328 {
1329         int64_t nsec, ticks;
1330         long sec;
1331         char str[7 * NUMSIZE];
1332
1333         if (fasthz == 0LL)
1334                 fasthz = __proc_global_info.tsc_freq;
1335 #if 0
1336         fastticks((uint64_t *) & fasthz);
1337         nsec = todget(&ticks);
1338 #endif
1339         ticks = read_tsc();
1340         nsec = tsc2nsec(ticks);
1341         sec = nsec / 1000000000ULL;
1342         snprintf(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
1343                          NUMSIZE - 1, sec,
1344                          VLNUMSIZE - 1, nsec, VLNUMSIZE - 1, ticks, VLNUMSIZE - 1, fasthz);
1345         return consreadstr(off, buf, n, str);
1346 }
1347
1348 /*
1349  *  set the time in seconds
1350  */
1351 static int writetime(char *buf, int n)
1352 {
1353         char b[13];
1354         long i;
1355         int64_t now;
1356
1357         if (n >= sizeof(b))
1358                 error(EINVAL, "bad size in writetime");
1359         strncpy(b, buf, n);
1360         b[n] = 0;
1361         i = strtol(b, 0, 0);
1362         if (i <= 0)
1363                 error(EINVAL, "Bad time in write");
1364         now = i * 1000000000LL;
1365 #if 0
1366         todset(now, 0, 0);
1367 #endif
1368         return n;
1369 }
1370
1371 /*
1372  *  read binary time info.  all numbers are little endian.
1373  *  ticks and nsec are syncronized.
1374  */
1375 static int readbintime(char *buf, int n)
1376 {
1377         int i;
1378         int64_t nsec, ticks;
1379         uint8_t *b = (uint8_t *) buf;
1380
1381         i = 0;
1382         if (fasthz == 0LL)
1383                 fasthz = __proc_global_info.tsc_freq;
1384 #if 0
1385         fastticks((uint64_t *) & fasthz);
1386         nsec = todget(&ticks);
1387 #endif
1388         ticks = read_tsc();
1389         nsec = tsc2nsec(ticks);
1390         if (n >= 3 * sizeof(uint64_t)) {
1391                 int64_t2le(b + 2 * sizeof(uint64_t), fasthz);
1392                 i += sizeof(uint64_t);
1393         }
1394         if (n >= 2 * sizeof(uint64_t)) {
1395                 int64_t2le(b + sizeof(uint64_t), ticks);
1396                 i += sizeof(uint64_t);
1397         }
1398         if (n >= 8) {
1399                 int64_t2le(b, nsec);
1400                 i += sizeof(int64_t);
1401         }
1402         return i;
1403 }
1404
1405 /*
1406  *  set any of the following
1407  *      - time in nsec
1408  *      - nsec trim applied over some seconds
1409  *      - clock frequency
1410  */
1411 static int writebintime(char *buf, int n)
1412 {
1413         uint8_t *p;
1414         int64_t delta = 0;
1415         long period = 0;
1416
1417         n--;
1418         p = (uint8_t *) buf + 1;
1419         switch (*buf) {
1420                 case 'n':
1421                         if (n < sizeof(int64_t))
1422                                 error(EINVAL, ERROR_FIXME);
1423                         le2int64_t(&delta, p);
1424 #if 0
1425                         todset(delta, 0, 0);
1426 #endif
1427                         break;
1428                 case 'd':
1429                         if (n < sizeof(int64_t) + sizeof(long))
1430                                 error(EINVAL, ERROR_FIXME);
1431                         p = le2int64_t(&delta, p);
1432                         le2long(&period, p);
1433 #if 0
1434                         todset(-1, delta, period);
1435 #endif
1436                         break;
1437                 case 'f':
1438                         if (n < sizeof(uint64_t))
1439                                 error(EINVAL, ERROR_FIXME);
1440                         le2int64_t(&fasthz, p);
1441                         if (fasthz <= 0)
1442                                 error(EINVAL, ERROR_FIXME);
1443 #if 0
1444                         todsetfreq(fasthz);
1445 #endif
1446                         break;
1447         }
1448         return n;
1449 }
1450
1451 /*
1452  * find_first_kid finds your immediate descendant. Not because we're
1453  * trying to give it a check from the estate, mind you. We're here on
1454  * much more unpleasant business. To make it easy to call this
1455  * multiple times without lots of fussy checking, we allow it to be
1456  * called with NULL pointers; hence find_first_kid(find_first_kid(x))
1457  * works even if x is chaste and will return NULL.
1458  */
1459 static struct proc *find_first_kid(struct proc *p)
1460 {
1461         struct proc *kid;
1462
1463         cv_lock(&p->child_wait);
1464         kid = TAILQ_FIRST(&p->children);
1465         if (kid) {
1466                 proc_incref(kid, 1);
1467                 proc_decref(p);
1468         }
1469         cv_unlock(&p->child_wait);
1470         return kid;
1471 }
1472
1473 /*
1474  * killkid manages population issues by killing your kids.  This is a
1475  * particular temporary (we think) function for ssh. As such, we are
1476  * going to make a Command Decision to never kill the top level
1477  * kid. We start on grandkids, in other words.  Hey, the parent/child
1478  * terminology was Ken's idea; go yell at him.  If you want, we can
1479  * rename this to DrownCuteKittens.
1480  *
1481  * This was hard to get right so it's way more verbose than you might think we need.
1482  * Sorry.
1483  */
1484 void killkid(void)
1485 {
1486         struct proc *check, *kid, *grandkid, *victim;
1487
1488         /* find first grandkid */
1489         proc_incref(current, 1);
1490         kid = find_first_kid(current);
1491         if (!kid) {
1492                 proc_decref(current);
1493                 return;
1494         }
1495         grandkid = find_first_kid(kid);
1496         if (!grandkid) {
1497                 proc_decref(kid);
1498                 return;
1499         }
1500         victim = grandkid;
1501         while (1) {
1502                 check = find_first_kid(victim);
1503                 if (!check)
1504                         break;
1505                 victim = check;
1506         }
1507         send_posix_signal(victim, SIGINT);
1508         proc_decref(victim);
1509 }
1510
1511 void cons_add_char(char c)
1512 {
1513         qiwrite(cons_q, &c, sizeof(char));
1514 }