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