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