#include "u.h"#include "lib.h"#include "dat.h"#include "fns.h"#include "error.h" #include "keyboard.h" #include <authsrv.h> #undef write#undef read void (*screenputs)(char*, int) = 0; Queue* kbdq; /* unprocessed console input */Queue* lineq; /* processed console input */Queue* kprintoq; /* console output, for /dev/kprint */int kprintinuse; /* test and set whether /dev/kprint is open */ int panicking; struct{ int exiting; int machs;} active; static struct{ QLock lk; int raw; /* true if we shouldn't process input */ int ctl; /* number of opens to the control file */ int x; /* index into line */ char line[1024]; /* current input line */ int count; /* a place to save up characters at interrupt time before dumping them in the queue */ Lock lockputc; char istage[1024]; char *iw; char *ir; char *ie;} kbd = { { 0 }, 0, 0, 0, { 0 }, 0, { 0 }, { 0 }, kbd.istage, kbd.istage, kbd.istage + sizeof(kbd.istage),}; char *sysname;vlong fasthz = 1000; static int readtime(ulong, char*, int);static int readbintime(char*, int);static int writetime(char*, int);static int writebintime(char*, int); enum{ CMreboot, CMpanic,}; Cmdtab rebootmsg[] ={ CMreboot, "reboot", 0, CMpanic, "panic", 0,}; intreturn0(void *v){ return 0;} voidprintinit(void){ lineq = qopen(2*1024, 0, 0, nil); if(lineq == nil) panic("printinit"); qnoblock(lineq, 1); kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1);} static voidkmesgputs(char *str, int n){ uint nn, d; ilock(&kmesg.lk); /* take the tail of huge writes */ if(n > sizeof kmesg.buf){ d = n - sizeof kmesg.buf; str += d; n -= d; } /* slide the buffer down to make room */ nn = kmesg.n; if(nn + n >= sizeof kmesg.buf){ d = nn + n - sizeof kmesg.buf; if(d) memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d); nn -= d; } /* copy the data in */ memmove(kmesg.buf+nn, str, n); nn += n; kmesg.n = nn; iunlock(&kmesg.lk);} /* * Print a string on the console. Convert \n to \r\n for serial * line consoles. Locking of the queues is left up to the screen * or uart code. Multi-line messages to serial consoles may get * interspersed with other messages. */static voidputstrn0(char *str, int n, int usewrite){ /* * how many different output devices do we need? */ kmesgputs(str, n); /* * if someone is reading /dev/kprint, * put the message there. * if not and there's an attached bit mapped display, * put the message there. * * if there's a serial line being used as a console, * put the message there. */ if(kprintoq != nil && !qisclosed(kprintoq)){ if(usewrite) qwrite(kprintoq, str, n); else qiwrite(kprintoq, str, n); }else if(screenputs != 0) screenputs(str, n); else write(1, str, n);} voidputstrn(char *str, int n){ putstrn0(str, n, 0);} intprint(char *fmt, ...){ int n; va_list arg; char buf[PRINTSIZE]; va_start(arg, fmt); n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); putstrn(buf, n); return n;} voidpanic(char *fmt, ...){ int n; va_list arg; char buf[PRINTSIZE]; kprintoq = nil; /* don't try to write to /dev/kprint */ if(panicking++) for(;;) osyield(); splhi(); strcpy(buf, "panic: "); va_start(arg, fmt); n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; va_end(arg); buf[n] = '\n'; spllo(); putstrn(buf, n+1); while(screenputs != 0) osyield(); setterm(0); exit(1);} intpprint(char *fmt, ...){ int n; Chan *c; va_list arg; char buf[2*PRINTSIZE]; if(up == nil || up->fgrp == nil) return 0; c = up->fgrp->fd[2]; if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) return 0; n = sprint(buf, "%s %lud: ", up->text, up->pid); va_start(arg, fmt); n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); if(waserror()) return 0; devtab[c->type]->write(c, buf, n, c->offset); poperror(); lock(&c->ref.lk); c->offset += n; unlock(&c->ref.lk); return n;} static voidechoscreen(char *buf, int n){ char *e, *p; char ebuf[128]; int x; p = ebuf; e = ebuf + sizeof(ebuf) - 4; while(n-- > 0){ if(p >= e){ screenputs(ebuf, p - ebuf); p = ebuf; } x = *buf++; if(x == 0x15){ *p++ = '^'; *p++ = 'U'; *p++ = '\n'; } else *p++ = x; } if(p != ebuf) screenputs(ebuf, p - ebuf);} static voidecho(char *buf, int n){ qproduce(kbdq, buf, n); if(kbd.raw) return; if(screenputs != 0) echoscreen(buf, n); else write(1, buf, n);} staticvoid_kbdputc(int c){ Rune r; char buf[UTFmax]; int n; r = c; n = runetochar(buf, &r); if(n == 0) return; echo(buf, n);} /* _kbdputc, but with compose translation */intkbdputc(Queue *q, int c){ int i; static int collecting, nk; static Rune kc[5]; if(c == Kalt){ collecting = 1; nk = 0; return 0; } if(!collecting){ _kbdputc(c); return 0; } kc[nk++] = c; c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return 0; if(c != -1) /* valid sequence */ _kbdputc(c); else for(i=0; i<nk; i++) _kbdputc(kc[i]); nk = 0; collecting = 0; return 0;} enum{ Qdir, Qbintime, Qcons, Qconsctl, Qcputime, Qdrivers, Qkmesg, Qkprint, Qhostdomain, Qhostowner, Qnull, Qosversion, Qpgrpid, Qpid, Qppid, Qrandom, Qreboot, Qshowfile, Qsnarf, Qsysname, Qsysstat, Qtime, Quser, Qzero,}; enum{ VLNUMSIZE= 22,}; static Dirtab consdir[]={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "bintime", {Qbintime}, 24, 0664, "cons", {Qcons}, 0, 0660, "consctl", {Qconsctl}, 0, 0220, "cputime", {Qcputime}, 6*NUMSIZE, 0444, "drivers", {Qdrivers}, 0, 0444, "hostdomain", {Qhostdomain}, DOMLEN, 0664, "hostowner", {Qhostowner}, 0, 0664, "kmesg", {Qkmesg}, 0, 0440, "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440, "null", {Qnull}, 0, 0666, "osversion", {Qosversion}, 0, 0444, "pgrpid", {Qpgrpid}, NUMSIZE, 0444, "pid", {Qpid}, NUMSIZE, 0444, "ppid", {Qppid}, NUMSIZE, 0444, "random", {Qrandom}, 0, 0444, "reboot", {Qreboot}, 0, 0664, "showfile", {Qshowfile}, 0, 0220, "snarf", {Qsnarf}, 0, 0666, "sysname", {Qsysname}, 0, 0664, "sysstat", {Qsysstat}, 0, 0666, "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664, "user", {Quser}, 0, 0666, "zero", {Qzero}, 0, 0444,}; Dirtab *snarftab = &consdir[Qsnarf]; intreadnum(ulong off, char *buf, ulong n, ulong val, int size){ char tmp[64]; snprint(tmp, sizeof(tmp), "%*.0lud", size-1, val); tmp[size-1] = ' '; if(off >= size) return 0; if(off+n > size) n = size-off; memmove(buf, tmp+off, n); return n;} intreadstr(ulong off, char *buf, ulong n, char *str){ int size; size = strlen(str); if(off >= size) return 0; if(off+n > size) n = size-off; memmove(buf, str+off, n); return n;} static voidconsinit(void){ randominit();} static Chan*consattach(char *spec){ return devattach('c', spec);} static Walkqid*conswalk(Chan *c, Chan *nc, char **name, int nname){ return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);} static intconsstat(Chan *c, uchar *dp, int n){ return devstat(c, dp, n, consdir, nelem(consdir), devgen);} static Chan*consopen(Chan *c, int omode){ c->aux = nil; c = devopen(c, omode, consdir, nelem(consdir), devgen); switch((ulong)c->qid.path){ case Qconsctl: qlock(&kbd.lk); kbd.ctl++; qunlock(&kbd.lk); break; case Qkprint: if(tas(&kprintinuse) != 0){ c->flag &= ~COPEN; error(Einuse); } if(kprintoq == nil){ kprintoq = qopen(8*1024, Qcoalesce, 0, 0); if(kprintoq == nil){ c->flag &= ~COPEN; error(Enomem); } qnoblock(kprintoq, 1); }else qreopen(kprintoq); c->iounit = qiomaxatomic; break; case Qsnarf: if(omode == ORDWR) error(Eperm); if(omode == OREAD) c->aux = strdup(""); else c->aux = mallocz(SnarfSize, 1); break; } return c;} static voidconsclose(Chan *c){ switch((ulong)c->qid.path){ /* last close of control file turns off raw */ case Qconsctl: if(c->flag&COPEN){ qlock(&kbd.lk); if(--kbd.ctl == 0) kbd.raw = 0; if(screenputs == 0) setterm(kbd.raw); qunlock(&kbd.lk); } break; /* close of kprint allows other opens */ case Qkprint:Lines 1–500 of 956. Load more
#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "keyboard.h" #include <authsrv.h> #undef write #undef read void (*screenputs)(char*, int) = 0; Queue* kbdq; /* unprocessed console input */ Queue* lineq; /* processed console input */ Queue* kprintoq; /* console output, for /dev/kprint */ int kprintinuse; /* test and set whether /dev/kprint is open */ int panicking; struct { int exiting; int machs; } active; static struct { QLock lk; int raw; /* true if we shouldn't process input */ int ctl; /* number of opens to the control file */ int x; /* index into line */ char line[1024]; /* current input line */ int count; /* a place to save up characters at interrupt time before dumping them in the queue */ Lock lockputc; char istage[1024]; char *iw; char *ir; char *ie; } kbd = { { 0 }, 0, 0, 0, { 0 }, 0, { 0 }, { 0 }, kbd.istage, kbd.istage, kbd.istage + sizeof(kbd.istage), }; char *sysname; vlong fasthz = 1000; static int readtime(ulong, char*, int); static int readbintime(char*, int); static int writetime(char*, int); static int writebintime(char*, int); enum { CMreboot, CMpanic, }; Cmdtab rebootmsg[] = { CMreboot, "reboot", 0, CMpanic, "panic", 0, }; int return0(void *v) { return 0; } void printinit(void) { lineq = qopen(2*1024, 0, 0, nil); if(lineq == nil) panic("printinit"); qnoblock(lineq, 1); kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); } static void kmesgputs(char *str, int n) { uint nn, d; ilock(&kmesg.lk); /* take the tail of huge writes */ if(n > sizeof kmesg.buf){ d = n - sizeof kmesg.buf; str += d; n -= d; } /* slide the buffer down to make room */ nn = kmesg.n; if(nn + n >= sizeof kmesg.buf){ d = nn + n - sizeof kmesg.buf; if(d) memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d); nn -= d; } /* copy the data in */ memmove(kmesg.buf+nn, str, n); nn += n; kmesg.n = nn; iunlock(&kmesg.lk); } /* * Print a string on the console. Convert \n to \r\n for serial * line consoles. Locking of the queues is left up to the screen * or uart code. Multi-line messages to serial consoles may get * interspersed with other messages. */ static void putstrn0(char *str, int n, int usewrite) { /* * how many different output devices do we need? */ kmesgputs(str, n); /* * if someone is reading /dev/kprint, * put the message there. * if not and there's an attached bit mapped display, * put the message there. * * if there's a serial line being used as a console, * put the message there. */ if(kprintoq != nil && !qisclosed(kprintoq)){ if(usewrite) qwrite(kprintoq, str, n); else qiwrite(kprintoq, str, n); }else if(screenputs != 0) screenputs(str, n); else write(1, str, n); } void putstrn(char *str, int n) { putstrn0(str, n, 0); } int print(char *fmt, ...) { int n; va_list arg; char buf[PRINTSIZE]; va_start(arg, fmt); n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); putstrn(buf, n); return n; } void panic(char *fmt, ...) { int n; va_list arg; char buf[PRINTSIZE]; kprintoq = nil; /* don't try to write to /dev/kprint */ if(panicking++) for(;;) osyield(); splhi(); strcpy(buf, "panic: "); va_start(arg, fmt); n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; va_end(arg); buf[n] = '\n'; spllo(); putstrn(buf, n+1); while(screenputs != 0) osyield(); setterm(0); exit(1); } int pprint(char *fmt, ...) { int n; Chan *c; va_list arg; char buf[2*PRINTSIZE]; if(up == nil || up->fgrp == nil) return 0; c = up->fgrp->fd[2]; if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) return 0; n = sprint(buf, "%s %lud: ", up->text, up->pid); va_start(arg, fmt); n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); if(waserror()) return 0; devtab[c->type]->write(c, buf, n, c->offset); poperror(); lock(&c->ref.lk); c->offset += n; unlock(&c->ref.lk); return n; } static void echoscreen(char *buf, int n) { char *e, *p; char ebuf[128]; int x; p = ebuf; e = ebuf + sizeof(ebuf) - 4; while(n-- > 0){ if(p >= e){ screenputs(ebuf, p - ebuf); p = ebuf; } x = *buf++; if(x == 0x15){ *p++ = '^'; *p++ = 'U'; *p++ = '\n'; } else *p++ = x; } if(p != ebuf) screenputs(ebuf, p - ebuf); } static void echo(char *buf, int n) { qproduce(kbdq, buf, n); if(kbd.raw) return; if(screenputs != 0) echoscreen(buf, n); else write(1, buf, n); } static void _kbdputc(int c) { Rune r; char buf[UTFmax]; int n; r = c; n = runetochar(buf, &r); if(n == 0) return; echo(buf, n); } /* _kbdputc, but with compose translation */ int kbdputc(Queue *q, int c) { int i; static int collecting, nk; static Rune kc[5]; if(c == Kalt){ collecting = 1; nk = 0; return 0; } if(!collecting){ _kbdputc(c); return 0; } kc[nk++] = c; c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return 0; if(c != -1) /* valid sequence */ _kbdputc(c); else for(i=0; i<nk; i++) _kbdputc(kc[i]); nk = 0; collecting = 0; return 0; } enum{ Qdir, Qbintime, Qcons, Qconsctl, Qcputime, Qdrivers, Qkmesg, Qkprint, Qhostdomain, Qhostowner, Qnull, Qosversion, Qpgrpid, Qpid, Qppid, Qrandom, Qreboot, Qshowfile, Qsnarf, Qsysname, Qsysstat, Qtime, Quser, Qzero, }; enum { VLNUMSIZE= 22, }; static Dirtab consdir[]={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "bintime", {Qbintime}, 24, 0664, "cons", {Qcons}, 0, 0660, "consctl", {Qconsctl}, 0, 0220, "cputime", {Qcputime}, 6*NUMSIZE, 0444, "drivers", {Qdrivers}, 0, 0444, "hostdomain", {Qhostdomain}, DOMLEN, 0664, "hostowner", {Qhostowner}, 0, 0664, "kmesg", {Qkmesg}, 0, 0440, "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440, "null", {Qnull}, 0, 0666, "osversion", {Qosversion}, 0, 0444, "pgrpid", {Qpgrpid}, NUMSIZE, 0444, "pid", {Qpid}, NUMSIZE, 0444, "ppid", {Qppid}, NUMSIZE, 0444, "random", {Qrandom}, 0, 0444, "reboot", {Qreboot}, 0, 0664, "showfile", {Qshowfile}, 0, 0220, "snarf", {Qsnarf}, 0, 0666, "sysname", {Qsysname}, 0, 0664, "sysstat", {Qsysstat}, 0, 0666, "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664, "user", {Quser}, 0, 0666, "zero", {Qzero}, 0, 0444, }; Dirtab *snarftab = &consdir[Qsnarf]; int readnum(ulong off, char *buf, ulong n, ulong val, int size) { char tmp[64]; snprint(tmp, sizeof(tmp), "%*.0lud", size-1, val); tmp[size-1] = ' '; if(off >= size) return 0; if(off+n > size) n = size-off; memmove(buf, tmp+off, n); return n; } int readstr(ulong off, char *buf, ulong n, char *str) { int size; size = strlen(str); if(off >= size) return 0; if(off+n > size) n = size-off; memmove(buf, str+off, n); return n; } static void consinit(void) { randominit(); } static Chan* consattach(char *spec) { return devattach('c', spec); } static Walkqid* conswalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen); } static int consstat(Chan *c, uchar *dp, int n) { return devstat(c, dp, n, consdir, nelem(consdir), devgen); } static Chan* consopen(Chan *c, int omode) { c->aux = nil; c = devopen(c, omode, consdir, nelem(consdir), devgen); switch((ulong)c->qid.path){ case Qconsctl: qlock(&kbd.lk); kbd.ctl++; qunlock(&kbd.lk); break; case Qkprint: if(tas(&kprintinuse) != 0){ c->flag &= ~COPEN; error(Einuse); } if(kprintoq == nil){ kprintoq = qopen(8*1024, Qcoalesce, 0, 0); if(kprintoq == nil){ c->flag &= ~COPEN; error(Enomem); } qnoblock(kprintoq, 1); }else qreopen(kprintoq); c->iounit = qiomaxatomic; break; case Qsnarf: if(omode == ORDWR) error(Eperm); if(omode == OREAD) c->aux = strdup(""); else c->aux = mallocz(SnarfSize, 1); break; } return c; } static void consclose(Chan *c) { switch((ulong)c->qid.path){ /* last close of control file turns off raw */ case Qconsctl: if(c->flag&COPEN){ qlock(&kbd.lk); if(--kbd.ctl == 0) kbd.raw = 0; if(screenputs == 0) setterm(kbd.raw); qunlock(&kbd.lk); } break; /* close of kprint allows other opens */ case Qkprint: