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