capdev: fix iseve check
[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 <env.h>
23 #include <ros/procinfo.h>
24
25 #if 0
26 void (*consdebug) (void) = NULL;
27 #endif
28 void (*screenputs) (const char *, int) = cputbuf;
29
30 struct queue *kbdq;                             /* unprocessed console input */
31 struct queue *lineq;                    /* processed console input */
32 struct queue *serialoq;                 /* serial console output */
33 struct queue *kprintoq;                 /* console output, for /dev/kprint */
34 atomic_t kprintinuse = 0;               /* test and set whether /dev/kprint is open */
35 int iprintscreenputs = 1;
36 int keepbroken = 1;
37
38 struct queue *cons_q;                   /* Akaros cons input: keyboard, serial, etc */
39 spinlock_t cons_q_lock = SPINLOCK_INITIALIZER;
40 struct fdtap_slist cons_q_fd_taps = SLIST_HEAD_INITIALIZER(cons_q_fd_taps);
41
42 static uint8_t logbuffer[1 << 20];
43 static int index = 0;
44 static struct queue *logqueue = NULL;
45 static int reading_kmesg = 0;
46
47 typedef unsigned char uint8_t;
48
49 void logbuf(int c)
50 {
51         if (reading_kmesg)
52                 return;
53         if (index > 1 << 20)
54                 return;
55         logbuffer[index++] = c;
56 }
57
58 /*
59  *  return true if current user is eve
60  */
61 int iseve(void)
62 {
63         return strcmp(eve.name, current->user.name) == 0;
64 }
65
66 struct username eve = {.name = "eve", .name_lock = SPINLOCK_INITIALIZER};
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         struct dir dir;
718         struct dirtab *tab;
719         int perm;
720
721         switch ((uint32_t)c->qid.path) {
722         case Qstdin:
723                 tab = &consdir[Qstdin];
724                 perm = tab->perm;
725                 perm |= qreadable(cons_q) ? DMREADABLE : 0;
726                 devdir(c, tab->qid, tab->name, qlen(cons_q), eve.name, perm, &dir);
727                 return dev_make_stat(c, &dir, dp, n);
728         default:
729                 return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen);
730         }
731 }
732
733 static struct chan *consopen(struct chan *c, int omode)
734 {
735         c->aux = NULL;
736         c = devopen(c, omode, consdir, ARRAY_SIZE(consdir), devgen);
737         switch ((uint32_t) c->qid.path) {
738                 case Qconsctl:
739                         kref_get(&kbd.ctl, 1);
740                         break;
741
742                 case Qkprint:
743                         if (atomic_swap(&kprintinuse, 1) != 0) {
744                                 c->flag &= ~COPEN;
745                                 error(EADDRINUSE, "kprintinuse lock failed");
746                         }
747                         if (kprintoq == NULL) {
748                                 kprintoq = qopen(8 * 1024, Qcoalesce, 0, 0);
749                                 if (kprintoq == NULL) {
750                                         c->flag &= ~COPEN;
751                                         error(ENOMEM, "Can't allocate kprintoq");
752                                 }
753                                 qdropoverflow(kprintoq, 1);
754                         } else
755                                 qreopen(kprintoq);
756                         c->iounit = qiomaxatomic;
757                         break;
758         }
759         return c;
760 }
761
762 static void consclose(struct chan *c)
763 {
764         switch ((uint32_t) c->qid.path) {
765                         /* last close of control file turns off raw */
766                 case Qconsctl:
767                         if (c->flag & COPEN) {
768                                 if (kref_put(&kbd.ctl) == 0)
769                                         kbd.raw = 0;
770                         }
771                         break;
772
773                         /* close of kprint allows other opens */
774                 case Qkprint:
775                         if (c->flag & COPEN) {
776                                 kprintinuse = 0;
777                                 qhangup(kprintoq, NULL);
778                         }
779                         break;
780         }
781 }
782
783 static long consread(struct chan *c, void *buf, long n, int64_t off)
784 {
785         ERRSTACK(1);
786         uint32_t l;
787 #if 0
788         Mach *mp;
789 #endif
790         char *b, *bp, ch;
791         char tmp[256];                          /* must be >= 18*NUMSIZE (Qswap) */
792         int i, k, id, send;
793         int64_t offset = off;
794 #if 0
795         extern char configfile[];
796 #endif
797
798         if (n <= 0)
799                 return n;
800
801         switch ((uint32_t) c->qid.path) {
802                 case Qdir:
803                         return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen);
804
805                 case Qcons:
806                         qlock(&(&kbd)->qlock);
807                         if (waserror()) {
808                                 qunlock(&(&kbd)->qlock);
809                                 nexterror();
810                         }
811                         while (!qcanread(lineq)) {
812                                 if (qread(kbdq, &ch, 1) == 0)
813                                         continue;
814                                 send = 0;
815                                 if (ch == 0) {
816                                         /* flush output on rawoff -> rawon */
817                                         if (kbd.x > 0)
818                                                 send = !qcanread(kbdq);
819                                 } else if (kbd.raw) {
820                                         kbd.line[kbd.x++] = ch;
821                                         send = !qcanread(kbdq);
822                                 } else {
823                                         switch (ch) {
824                                                 case '\b':
825                                                         if (kbd.x > 0)
826                                                                 kbd.x--;
827                                                         break;
828                                                 case 0x15:      /* ^U */
829                                                         kbd.x = 0;
830                                                         break;
831                                                 case '\n':
832                                                 case 0x04:      /* ^D */
833                                                         send = 1;
834                                                 default:
835                                                         if (ch != 0x04)
836                                                                 kbd.line[kbd.x++] = ch;
837                                                         break;
838                                         }
839                                 }
840                                 if (send || kbd.x == sizeof kbd.line) {
841                                         qwrite(lineq, kbd.line, kbd.x);
842                                         kbd.x = 0;
843                                 }
844                         }
845                         n = qread(lineq, buf, n);
846                         qunlock(&(&kbd)->qlock);
847                         poperror();
848                         return n;
849
850 #if 0
851                 case Qcputime:
852                         k = offset;
853                         if (k >= 6 * NUMSIZE)
854                                 return 0;
855                         if (k + n > 6 * NUMSIZE)
856                                 n = 6 * NUMSIZE - k;
857                         /* easiest to format in a separate buffer and copy out */
858                         for (i = 0; i < 6 && NUMSIZE * i < k + n; i++) {
859                                 l = current->time[i];
860                                 if (i == TReal)
861                                         l = MACHP(0)->ticks - l;
862                                 l = TK2MS(l);
863                                 consreadnum(0, tmp + NUMSIZE * i, NUMSIZE, l, NUMSIZE);
864                         }
865                         memmove(buf, tmp + k, n);
866                         return n;
867 #endif
868
869                 case Qkmesg:
870                         /*
871                          * This is unlocked to avoid tying up a process
872                          * that's writing to the buffer.  kmesg.n never
873                          * gets smaller, so worst case the reader will
874                          * see a slurred buffer.
875                          */
876                         if (off >= kmesg.n)
877                                 n = 0;
878                         else {
879                                 if (off + n > kmesg.n)
880                                         n = kmesg.n - off;
881                                 memmove(buf, kmesg.buf + off, n);
882                         }
883                         return n;
884
885                 case Qkprint:
886                         return qread(kprintoq, buf, n);
887
888                 case Qpgrpid:
889                         return consreadnum((uint32_t) offset, buf, n, current->pgrp->pgrpid,
890                                                            NUMSIZE);
891
892                 case Qpid:
893                         return consreadnum((uint32_t) offset, buf, n, current->pid,
894                                                            NUMSIZE);
895
896                 case Qppid:
897                         return consreadnum((uint32_t) offset, buf, n, current->ppid,
898                                                            NUMSIZE);
899
900                 case Qtime:
901                         return readtime((uint32_t) offset, buf, n);
902
903                 case Qbintime:
904                         return readbintime(buf, n);
905
906                 case Qhostowner:
907                         return consreadstr((uint32_t) offset, buf, n, eve.name);
908
909                 case Qhostdomain:
910                         return consreadstr((uint32_t) offset, buf, n, hostdomain);
911
912                 case Quser:
913                         return consreadstr((uint32_t) offset, buf, n, current->user.name);
914
915                 case Qnull:
916                         return 0;
917
918 #if 0
919                 case Qconfig:
920                         return consreadstr((uint32_t) offset, buf, n, configfile);
921
922                 case Qsysstat:
923                         b = kzmalloc(conf.nmach * (NUMSIZE * 11 + 1) + 1, 0);   /* +1 for NUL */
924                         bp = b;
925                         for (id = 0; id < 32; id++) {
926                                 if (active.machs & (1 << id)) {
927                                         mp = MACHP(id);
928                                         consreadnum(0, bp, NUMSIZE, id, NUMSIZE);
929                                         bp += NUMSIZE;
930                                         consreadnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
931                                         bp += NUMSIZE;
932                                         consreadnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
933                                         bp += NUMSIZE;
934                                         consreadnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
935                                         bp += NUMSIZE;
936                                         consreadnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
937                                         bp += NUMSIZE;
938                                         consreadnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
939                                         bp += NUMSIZE;
940                                         consreadnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
941                                         bp += NUMSIZE;
942                                         consreadnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
943                                         bp += NUMSIZE;
944                                         consreadnum(0, bp, NUMSIZE,
945                                                                 (mp->perf.avg_inidle * 100) / mp->perf.period,
946                                                                 NUMSIZE);
947                                         bp += NUMSIZE;
948                                         consreadnum(0, bp, NUMSIZE,
949                                                                 (mp->perf.avg_inintr * 100) / mp->perf.period,
950                                                                 NUMSIZE);
951                                         bp += NUMSIZE;
952                                         *bp++ = '\n';
953                                 }
954                         }
955                         if (waserror()) {
956                                 kfree(b);
957                                 nexterror();
958                         }
959                         n = consreadstr((uint32_t) offset, buf, n, b);
960                         kfree(b);
961                         poperror();
962                         return n;
963
964                 case Qswap:
965                         snprintf(tmp, sizeof tmp,
966                                          "%lud memory\n"
967                                          "%d pagesize\n"
968                                          "%lud kernel\n"
969                                          "%lud/%lud user\n"
970                                          "%lud/%lud swap\n"
971                                          "%lud/%lud kernel malloc\n"
972                                          "%lud/%lud kernel draw\n",
973                                          conf.npage * BY2PG,
974                                          BY2PG,
975                                          conf.npage - conf.upages,
976                                          palloc.user - palloc.freecount, palloc.user,
977                                          conf.nswap - swapalloc.free, conf.nswap,
978                                          mainmem->cursize, mainmem->maxsize,
979                                          imagmem->cursize, imagmem->maxsize);
980
981                         return consreadstr((uint32_t) offset, buf, n, tmp);
982 #endif
983
984                 case Qstdin:
985                         if (c->flag & O_NONBLOCK)
986                                 return qread_nonblock(cons_q, buf, n);
987                         else
988                                 return qread(cons_q, buf, n);
989                 case Qsysname:
990                         /* TODO: this is racy */
991                         if (sysname == NULL)
992                                 return 0;
993                         return consreadstr((uint32_t) offset, buf, n, sysname);
994
995                 case Qdrivers:
996                         b = kzmalloc(READSTR, 0);
997                         if (b == NULL)
998                                 error(ENOMEM, "allocation for /dev/drivers read failed");
999                         k = 0;
1000                         for (int i = 0; &devtab[i] < __devtabend; i++)
1001                                 k += snprintf(b + k, READSTR - k, "#%s\n", devtab[i].name);
1002                         if (waserror()) {
1003                                 kfree(b);
1004                                 nexterror();
1005                         }
1006                         n = consreadstr((uint32_t) offset, buf, n, b);
1007                         kfree(b);
1008                         poperror();
1009                         return n;
1010
1011                 case Qklog:
1012                         //return qread(klogq, buf, n);
1013                         /* the queue gives us some elasticity for log reading. */
1014                         if (!logqueue)
1015                                 logqueue = qopen(1 << 20, 0, 0, 0);
1016                         if (logqueue) {
1017                                 int ret;
1018                                 /* atomic sets/gets are not that important in this case. */
1019                                 reading_kmesg = 1;
1020                                 qwrite(logqueue, logbuffer, index);
1021                                 index = 0;
1022                                 ret = qread(logqueue, buf, n);
1023                                 reading_kmesg = 0;
1024                                 return ret;
1025                         }
1026                         break;
1027
1028                 case Qzero:
1029                         memset(buf, 0, n);
1030                         return n;
1031
1032                 case Qosversion:
1033                         snprintf(tmp, sizeof tmp, "2000");
1034                         n = consreadstr((uint32_t) offset, buf, n, tmp);
1035                         return n;
1036
1037                 default:
1038                         printd("consread %#llux\n", c->qid.path);
1039                         error(EINVAL, "bad QID in consread");
1040         }
1041         return -1;      /* never reached */
1042 }
1043
1044 static long conswrite(struct chan *c, void *va, long n, int64_t off)
1045 {
1046         ERRSTACK(1);
1047         char buf[256], ch;
1048         long l, bp;
1049         char *a;
1050         //Mach *mp;
1051         int id, fd;
1052         struct chan *swc;
1053         uint32_t offset;
1054         struct cmdbuf *cb;
1055         struct cmdtab *ct;
1056         int x;
1057         uint64_t rip, rsp, cr3, flags, vcpu;
1058         int ret;
1059
1060         a = va;
1061         offset = off;
1062
1063         switch ((uint32_t) c->qid.path) {
1064                 case Qcons:
1065                         /*
1066                          * Can't page fault in putstrn, so copy the data locally.
1067                          */
1068                         l = n;
1069                         while (l > 0) {
1070                                 bp = l;
1071                                 if (bp > sizeof buf)
1072                                         bp = sizeof buf;
1073                                 memmove(buf, a, bp);
1074                                 putstrn0(buf, bp, 1);
1075                                 a += bp;
1076                                 l -= bp;
1077                         }
1078                         break;
1079
1080                 /* TODO: have it take a command about just *how* to kill the kid? */
1081                 case Qkillkid:
1082                         killkid();
1083                         break;
1084
1085                 case Qconsctl:
1086                         if (n >= sizeof(buf))
1087                                 n = sizeof(buf) - 1;
1088                         strncpy(buf, a, n);
1089                         buf[n] = 0;
1090                         for (a = buf; a;) {
1091                                 if (strncmp(a, "rawon", 5) == 0) {
1092                                         kbd.raw = 1;
1093                                         /* clumsy hack - wake up reader */
1094                                         ch = 0;
1095                                         qwrite(kbdq, &ch, 1);
1096                                 } else if (strncmp(a, "rawoff", 6) == 0) {
1097                                         kbd.raw = 0;
1098                                 } else if (strncmp(a, "ctlpon", 6) == 0) {
1099                                         kbd.ctlpoff = 0;
1100                                 } else if (strncmp(a, "ctlpoff", 7) == 0) {
1101                                         kbd.ctlpoff = 1;
1102                                 }
1103                                 if ((a = strchr(a, ' ')) != NULL)
1104                                         a++;
1105                         }
1106                         break;
1107
1108                 case Qtime:
1109                         if (!iseve())
1110                                 error(EPERM, "Hodie Natus Est Radici Frater");
1111                         return writetime(a, n);
1112
1113                 case Qbintime:
1114                         if (!iseve())
1115                                 error(EPERM, ERROR_FIXME);
1116                         return writebintime(a, n);
1117
1118 #if 0
1119                 case Qhostowner:
1120                         return hostownerwrite(a, n);
1121
1122                 case Qhostdomain:
1123                         return hostdomainwrite(a, n);
1124
1125                 case Quser:
1126                         return userwrite(a, n);
1127 #endif
1128
1129                 case Qnull:
1130                         break;
1131
1132                 case Qconfig:
1133                         error(EPERM, "Cannot write to config QID");
1134                         break;
1135
1136                 case Qsysctl:
1137                         //if (!iseve()) error(EPERM, ERROR_FIXME);
1138                         cb = parsecmd(a, n);
1139                         if (cb->nf > 1)
1140                         printd("cons sysctl cmd %s\n", cb->f[0]);
1141
1142                 case Qreboot:
1143                         if (!iseve())
1144                                 error(EPERM, ERROR_FIXME);
1145                         cb = parsecmd(a, n);
1146
1147                         if (waserror()) {
1148                                 kfree(cb);
1149                                 nexterror();
1150                         }
1151                         ct = lookupcmd(cb, rebootmsg, ARRAY_SIZE(rebootmsg));
1152                         switch (ct->index) {
1153                                 case CMhalt:
1154                                         cpu_halt();
1155                                         break;
1156                                 case CMbroken:
1157                                         keepbroken = 1;
1158                                         break;
1159                                 case CMnobroken:
1160                                         keepbroken = 0;
1161                                         break;
1162                                 case CMreboot:
1163                                         reboot();
1164                                         break;
1165                                 case CMpanic:
1166                                         *(uint32_t *) 0 = 0;
1167                                         panic("/dev/reboot");
1168                                         break;
1169                         }
1170                         poperror();
1171                         kfree(cb);
1172                         break;
1173
1174 #if 0
1175                 case Qsysstat:
1176                         for (id = 0; id < 32; id++) {
1177                                 if (active.machs & (1 << id)) {
1178                                         mp = MACHP(id);
1179                                         mp->cs = 0;
1180                                         mp->intr = 0;
1181                                         mp->syscall = 0;
1182                                         mp->pfault = 0;
1183                                         mp->tlbfault = 0;
1184                                         mp->tlbpurge = 0;
1185                                 }
1186                         }
1187                         break;
1188
1189                 case Qswap:
1190                         if (n >= sizeof buf)
1191                                 error(EINVAL, "n is bigger than sizeof buf for Qswap");
1192                         memmove(buf, va, n);    /* so we can NUL-terminate */
1193                         buf[n] = 0;
1194                         /* start a pager if not already started */
1195                         if (strncmp(buf, "start", 5) == 0) {
1196                                 kickpager();
1197                                 break;
1198                         }
1199                         if (!iseve())
1200                                 error(EPERM, ERROR_FIXME);
1201                         if (buf[0] < '0' || '9' < buf[0])
1202                                 error(EINVAL, ERROR_FIXME);
1203                         fd = strtoul(buf, 0, 0);
1204                         swc = fdtochan(fd, -1, 1, 1);
1205                         setswapchan(swc);
1206                         break;
1207 #endif
1208
1209                 case Qstdout:
1210                 case Qstderr:
1211                         px_lock();
1212                         if (waserror()) {
1213                                 px_unlock();
1214                                 nexterror();
1215                         }
1216                         /* TODO: tty hack.  they are sending us an escape sequence, and the
1217                          * keyboard would try to print it (which it can't do yet).  The hack
1218                          * is even dirtier in that we only detect it if it is the first
1219                          * char, and we ignore everything else.  \033 is 0x1b. */
1220                         if (((char*)va)[0] != '\033')
1221                                 cputbuf(va, n);
1222                         poperror();
1223                         px_unlock();
1224                         return n;
1225                 case Qsysname:
1226                         /* TODO: this is racy */
1227                         if (offset != 0)
1228                                 error(EINVAL, ERROR_FIXME);
1229                         if (n <= 0 || n >= sizeof buf)
1230                                 error(EINVAL, ERROR_FIXME);
1231                         strncpy(buf, a, n);
1232                         buf[n] = 0;
1233                         if (buf[n - 1] == '\n')
1234                                 buf[n - 1] = 0;
1235                         kstrdup(&sysname, buf);
1236                         break;
1237
1238                 default:
1239                         printd("conswrite: %#llux\n", c->qid.path);
1240                         error(EINVAL, "bad QID in conswrite");
1241         }
1242         return n;
1243 }
1244
1245 static char *cons_chaninfo(struct chan *ch, char *ret, size_t ret_l)
1246 {
1247         switch ((uint32_t)ch->qid.path) {
1248         case Qstdin:
1249                 snprintf(ret, ret_l, "qio len: %d", qlen(cons_q));
1250                 break;
1251         default:
1252                 return devchaninfo(ch, ret, ret_l);
1253         }
1254         return ret;
1255 }
1256
1257 static void __consq_fire_taps(uint32_t srcid, long a0, long a1, long a2)
1258 {
1259         struct fd_tap *tap_i;
1260         int filter = a0;
1261
1262         spin_lock(&cons_q_lock);
1263         SLIST_FOREACH(tap_i, &cons_q_fd_taps, link)
1264                 fire_tap(tap_i, filter);
1265         spin_unlock(&cons_q_lock);
1266
1267 }
1268
1269 static void cons_q_wake_cb(struct queue *q, void *data, int filter)
1270 {
1271         /* TODO: taps can't fire from IRQ context, but the qiwrites for stdin come
1272          * from IRQ context.  So we need an RKM here. */
1273         send_kernel_message(core_id(), __consq_fire_taps, filter,
1274                             0, 0, KMSG_ROUTINE);
1275 }
1276
1277 static int tap_stdin(struct chan *c, struct fd_tap *tap, int cmd)
1278 {
1279         int ret;
1280
1281         /* We don't actually support HANGUP, but epoll implies it. */
1282         #define CONS_STDIN_TAPS (FDTAP_FILT_READABLE | FDTAP_FILT_HANGUP)
1283
1284         if (tap->filter & ~CONS_STDIN_TAPS) {
1285                 set_error(ENOSYS, "Unsupported #%s tap, must be %p", devname(),
1286                           CONS_STDIN_TAPS);
1287                 return -1;
1288         }
1289         spin_lock(&cons_q_lock);
1290         switch (cmd) {
1291         case FDTAP_CMD_ADD:
1292                 if (SLIST_EMPTY(&cons_q_fd_taps))
1293                         qio_set_wake_cb(cons_q, cons_q_wake_cb, 0);
1294                 SLIST_INSERT_HEAD(&cons_q_fd_taps, tap, link);
1295                 ret = 0;
1296                 break;
1297         case FDTAP_CMD_REM:
1298                 SLIST_REMOVE(&cons_q_fd_taps, tap, fd_tap, link);
1299                 if (SLIST_EMPTY(&cons_q_fd_taps))
1300                         qio_set_wake_cb(cons_q, 0, 0);
1301                 ret = 0;
1302                 break;
1303         default:
1304                 set_error(ENOSYS, "Unsupported #%s tap command %p", devname(), cmd);
1305                 ret = -1;
1306         }
1307         spin_unlock(&cons_q_lock);
1308         return ret;
1309 }
1310
1311 static int cons_tapfd(struct chan *c, struct fd_tap *tap, int cmd)
1312 {
1313         switch ((uint32_t)c->qid.path) {
1314         case Qstdin:
1315                 return tap_stdin(c, tap, cmd);
1316         default:
1317                 set_error(ENOSYS, "Can't tap #%s file type %d", devname(),
1318                           c->qid.path);
1319                 return -1;
1320         }
1321 }
1322
1323 struct dev consdevtab __devtab = {
1324         .name = "cons",
1325
1326         .reset = devreset,
1327         .init = consinit,
1328         .shutdown = devshutdown,
1329         .attach = consattach,
1330         .walk = conswalk,
1331         .stat = consstat,
1332         .open = consopen,
1333         .create = devcreate,
1334         .close = consclose,
1335         .read = consread,
1336         .bread = devbread,
1337         .write = conswrite,
1338         .bwrite = devbwrite,
1339         .remove = devremove,
1340         .wstat = devwstat,
1341         .power = devpower,
1342         .chaninfo = cons_chaninfo,
1343         .tapfd = cons_tapfd,
1344 };
1345
1346 static char *devname(void)
1347 {
1348         return consdevtab.name;
1349 }
1350
1351 static uint64_t uvorder = 0x0001020304050607ULL;
1352
1353 static uint8_t *le2int64_t(int64_t * to, uint8_t * f)
1354 {
1355         uint8_t *t, *o;
1356         int i;
1357
1358         t = (uint8_t *) to;
1359         o = (uint8_t *) & uvorder;
1360         for (i = 0; i < sizeof(int64_t); i++)
1361                 t[o[i]] = f[i];
1362         return f + sizeof(int64_t);
1363 }
1364
1365 static uint8_t *int64_t2le(uint8_t * t, int64_t from)
1366 {
1367         uint8_t *f, *o;
1368         int i;
1369
1370         f = (uint8_t *) & from;
1371         o = (uint8_t *) & uvorder;
1372         for (i = 0; i < sizeof(int64_t); i++)
1373                 t[i] = f[o[i]];
1374         return t + sizeof(int64_t);
1375 }
1376
1377 static long order = 0x00010203;
1378
1379 static uint8_t *le2long(long *to, uint8_t * f)
1380 {
1381         uint8_t *t, *o;
1382         int i;
1383
1384         t = (uint8_t *) & to;
1385         o = (uint8_t *) & order;
1386         for (i = 0; i < sizeof(long); i++)
1387                 t[o[i]] = f[i];
1388         return f + sizeof(long);
1389 }
1390
1391 static uint8_t *long2le(uint8_t * t, long from)
1392 {
1393         uint8_t *f, *o;
1394         int i;
1395
1396         f = (uint8_t *) & from;
1397         o = (uint8_t *) & order;
1398         for (i = 0; i < sizeof(long); i++)
1399                 t[i] = f[o[i]];
1400         return t + sizeof(long);
1401 }
1402
1403 char *Ebadtimectl = "bad time control";
1404
1405 /*
1406  *  like the old #c/time but with added info.  Return
1407  *
1408  *      secs    nanosecs        fastticks       fasthz
1409  */
1410 static int readtime(uint32_t off, char *buf, int n)
1411 {
1412         int64_t nsec, ticks;
1413         long sec;
1414         char str[7 * NUMSIZE];
1415
1416         if (fasthz == 0LL)
1417                 fasthz = __proc_global_info.tsc_freq;
1418 #if 0
1419         fastticks((uint64_t *) & fasthz);
1420         nsec = todget(&ticks);
1421 #endif
1422         ticks = read_tsc();
1423         nsec = tsc2nsec(ticks);
1424         sec = nsec / 1000000000ULL;
1425         snprintf(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
1426                          NUMSIZE - 1, sec,
1427                          VLNUMSIZE - 1, nsec, VLNUMSIZE - 1, ticks, VLNUMSIZE - 1, fasthz);
1428         return consreadstr(off, buf, n, str);
1429 }
1430
1431 /*
1432  *  set the time in seconds
1433  */
1434 static int writetime(char *buf, int n)
1435 {
1436         char b[13];
1437         long i;
1438         int64_t now;
1439
1440         if (n >= sizeof(b))
1441                 error(EINVAL, "bad size in writetime");
1442         strncpy(b, buf, n);
1443         b[n] = 0;
1444         i = strtol(b, 0, 0);
1445         if (i <= 0)
1446                 error(EINVAL, "Bad time in write");
1447         now = i * 1000000000LL;
1448 #if 0
1449         todset(now, 0, 0);
1450 #endif
1451         return n;
1452 }
1453
1454 /*
1455  *  read binary time info.  all numbers are little endian.
1456  *  ticks and nsec are syncronized.
1457  */
1458 static int readbintime(char *buf, int n)
1459 {
1460         int i;
1461         int64_t nsec, ticks;
1462         uint8_t *b = (uint8_t *) buf;
1463
1464         i = 0;
1465         if (fasthz == 0LL)
1466                 fasthz = __proc_global_info.tsc_freq;
1467 #if 0
1468         fastticks((uint64_t *) & fasthz);
1469         nsec = todget(&ticks);
1470 #endif
1471         ticks = read_tsc();
1472         nsec = tsc2nsec(ticks);
1473         if (n >= 3 * sizeof(uint64_t)) {
1474                 int64_t2le(b + 2 * sizeof(uint64_t), fasthz);
1475                 i += sizeof(uint64_t);
1476         }
1477         if (n >= 2 * sizeof(uint64_t)) {
1478                 int64_t2le(b + sizeof(uint64_t), ticks);
1479                 i += sizeof(uint64_t);
1480         }
1481         if (n >= 8) {
1482                 int64_t2le(b, nsec);
1483                 i += sizeof(int64_t);
1484         }
1485         return i;
1486 }
1487
1488 /*
1489  *  set any of the following
1490  *      - time in nsec
1491  *      - nsec trim applied over some seconds
1492  *      - clock frequency
1493  */
1494 static int writebintime(char *buf, int n)
1495 {
1496         uint8_t *p;
1497         int64_t delta = 0;
1498         long period = 0;
1499
1500         n--;
1501         p = (uint8_t *) buf + 1;
1502         switch (*buf) {
1503                 case 'n':
1504                         if (n < sizeof(int64_t))
1505                                 error(EINVAL, ERROR_FIXME);
1506                         le2int64_t(&delta, p);
1507 #if 0
1508                         todset(delta, 0, 0);
1509 #endif
1510                         break;
1511                 case 'd':
1512                         if (n < sizeof(int64_t) + sizeof(long))
1513                                 error(EINVAL, ERROR_FIXME);
1514                         p = le2int64_t(&delta, p);
1515                         le2long(&period, p);
1516 #if 0
1517                         todset(-1, delta, period);
1518 #endif
1519                         break;
1520                 case 'f':
1521                         if (n < sizeof(uint64_t))
1522                                 error(EINVAL, ERROR_FIXME);
1523                         le2int64_t(&fasthz, p);
1524                         if (fasthz <= 0)
1525                                 error(EINVAL, ERROR_FIXME);
1526 #if 0
1527                         todsetfreq(fasthz);
1528 #endif
1529                         break;
1530         }
1531         return n;
1532 }
1533
1534 /*
1535  * find_first_kid finds your immediate descendant. Not because we're
1536  * trying to give it a check from the estate, mind you. We're here on
1537  * much more unpleasant business. To make it easy to call this
1538  * multiple times without lots of fussy checking, we allow it to be
1539  * called with NULL pointers; hence find_first_kid(find_first_kid(x))
1540  * works even if x is chaste and will return NULL.
1541  */
1542 static struct proc *find_first_kid(struct proc *p)
1543 {
1544         struct proc *kid;
1545
1546         cv_lock(&p->child_wait);
1547         kid = TAILQ_FIRST(&p->children);
1548         if (kid) {
1549                 proc_incref(kid, 1);
1550                 proc_decref(p);
1551         }
1552         cv_unlock(&p->child_wait);
1553         return kid;
1554 }
1555
1556 /*
1557  * killkid manages population issues by killing your kids.  This is a
1558  * particular temporary (we think) function for ssh. As such, we are
1559  * going to make a Command Decision to never kill the top level
1560  * kid. We start on grandkids, in other words.  Hey, the parent/child
1561  * terminology was Ken's idea; go yell at him.  If you want, we can
1562  * rename this to DrownCuteKittens.
1563  *
1564  * This was hard to get right so it's way more verbose than you might think we need.
1565  * Sorry.
1566  */
1567 void killkid(void)
1568 {
1569         struct proc *check, *kid, *grandkid, *victim;
1570
1571         /* find first grandkid */
1572         proc_incref(current, 1);
1573         kid = find_first_kid(current);
1574         if (!kid) {
1575                 proc_decref(current);
1576                 return;
1577         }
1578         grandkid = find_first_kid(kid);
1579         if (!grandkid) {
1580                 proc_decref(kid);
1581                 return;
1582         }
1583         victim = grandkid;
1584         while (1) {
1585                 check = find_first_kid(victim);
1586                 if (!check)
1587                         break;
1588                 victim = check;
1589         }
1590         send_posix_signal(victim, SIGINT);
1591         proc_decref(victim);
1592 }
1593
1594 void cons_add_char(char c)
1595 {
1596         qiwrite(cons_q, &c, sizeof(char));
1597 }