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