#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "error.h" #include <authsrv.h> /* minimal set from keyboard.h */enum { KF= 0xF000, /* Rune: beginning of private Unicode space */ Kalt= KF|0x15,}; void (*consdebug)(void) = nil;void (*screenputs)(char*, int) = nil; Queue* kbdq; /* unprocessed console input */Queue* lineq; /* processed console input */Queue* serialoq; /* serial console output */Queue* kprintoq; /* console output, for /dev/kprint */long kprintinuse; /* test and set whether /dev/kprint is open */Lock kprintlock;int iprintscreenputs = 0; int panicking; 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; int ctlpoff; /* 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 = { .iw = kbd.istage, .ir = kbd.istage, .ie = kbd.istage + sizeof(kbd.istage),}; char *sysname;vlong fasthz; 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, nil, nil); if(lineq == nil) panic("printinit"); qnoblock(lineq, 1); kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1);} intconsactive(void){ if(serialoq) return qlen(serialoq) > 0; return 0;} voidprflush(void){/* ulong now; now = m->ticks; while(consactive()) if(m->ticks - now >= HZ) break;*/} /* * 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){ /* * 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 != nil) screenputs(str, n);} voidputstrn(char *str, int n){ putstrn0(str, n, 0);} int noprint; intprint(char *fmt, ...){ int n; va_list arg; char buf[PRINTSIZE]; if(noprint) return -1; 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, s; va_list arg; char buf[PRINTSIZE]; kprintoq = nil; /* don't try to write to /dev/kprint */ if(panicking) for(;;); panicking = 1; s = splhi(); strcpy(buf, "panic: "); va_start(arg, fmt); n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; va_end(arg); uartputs(buf, n+1); if(consdebug) (*consdebug)(); spllo(); prflush(); buf[n] = '\n'; putstrn(buf, n+1); dumpstack(); 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 voidechoserialoq(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){ qiwrite(serialoq, ebuf, p - ebuf); p = ebuf; } x = *buf++; if(x == '\n'){ *p++ = '\r'; *p++ = '\n'; } else if(x == 0x15){ *p++ = '^'; *p++ = 'U'; *p++ = '\n'; } else *p++ = x; } if(p != ebuf) qiwrite(serialoq, ebuf, p - ebuf);} static voidecho(char *buf, int n){ static int ctrlt; int x; char *e, *p; if(n == 0) return; e = buf+n; for(p = buf; p < e; p++){ switch(*p){ case 0x10: /* ^P */ if(cpuserver && !kbd.ctlpoff){ active.exiting = 1; return; } break; case 0x14: /* ^T */ ctrlt++; if(ctrlt > 2) ctrlt = 2; continue; } if(ctrlt != 2) continue; /* ^T escapes */ ctrlt = 0; switch(*p){ case 'S': x = splhi(); dumpstack(); procdump(); splx(x); return; case 's': dumpstack(); return; case 'x': xsummary(); ixsummary(); mallocsummary(); // memorysummary(); pagersummary(); return; case 'd': if(consdebug == nil) consdebug = rdb; else consdebug = nil; print("consdebug now %#p\n", consdebug); return; case 'D': if(consdebug == nil) consdebug = rdb; consdebug(); return; case 'p': x = spllo(); procdump(); splx(x); return; case 'q': scheddump(); return; case 'k': killbig("^t ^t k"); return; // case 'r': // exit(0); // return; } } qproduce(kbdq, buf, n); if(kbd.raw) return; if(screenputs != nil) echoscreen(buf, n); if(serialoq) echoserialoq(buf, n);} /* * Called by a uart interrupt for console input. * * turn '\r' into '\n' before putting it into the queue. */intkbdcr2nl(Queue *q, int ch){ char *next; USED(q); ilock(&kbd.lockputc); /* just a mutex */ if(ch == '\r' && !kbd.raw) ch = '\n'; next = kbd.iw+1; if(next >= kbd.ie) next = kbd.istage; if(next != kbd.ir){ *kbd.iw = ch; kbd.iw = next; } iunlock(&kbd.lockputc); return 0;}staticvoid_kbdputc(int c){ Rune r; char buf[UTFmax]; int n; r = c; n = runetochar(buf, &r); if(n == 0) return; echo(buf, n);// kbd.c = r;// qproduce(kbdq, 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, Qcpunote, Qcputime, Qdrivers, Qkprint, Qhostdomain, Qhostowner, Qnull, Qosversion, Qpgrpid, Qpid, Qppid, Qrandom, Qreboot, Qsecstore, Qshowfile, Qsnarf, Qswap, 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, "cpunote", {Qcpunote}, 0, 0444, "cputime", {Qcputime}, 6*NUMSIZE, 0444, "drivers", {Qdrivers}, 0, 0444, "hostdomain", {Qhostdomain}, DOMLEN, 0664, "hostowner", {Qhostowner}, 0, 0664, "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, "secstore", {Qsecstore}, 0, 0666, "showfile", {Qshowfile}, 0, 0220, "snarf", {Qsnarf}, 0, 0666, "swap", {Qswap}, 0, 0664, "sysname", {Qsysname}, 0, 0664,Lines 1–500 of 1188. Load more
#include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "error.h" #include <authsrv.h> /* minimal set from keyboard.h */ enum { KF= 0xF000, /* Rune: beginning of private Unicode space */ Kalt= KF|0x15, }; void (*consdebug)(void) = nil; void (*screenputs)(char*, int) = nil; Queue* kbdq; /* unprocessed console input */ Queue* lineq; /* processed console input */ Queue* serialoq; /* serial console output */ Queue* kprintoq; /* console output, for /dev/kprint */ long kprintinuse; /* test and set whether /dev/kprint is open */ Lock kprintlock; int iprintscreenputs = 0; int panicking; 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; int ctlpoff; /* 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 = { .iw = kbd.istage, .ir = kbd.istage, .ie = kbd.istage + sizeof(kbd.istage), }; char *sysname; vlong fasthz; 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, nil, nil); if(lineq == nil) panic("printinit"); qnoblock(lineq, 1); kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); } int consactive(void) { if(serialoq) return qlen(serialoq) > 0; return 0; } void prflush(void) { /* ulong now; now = m->ticks; while(consactive()) if(m->ticks - now >= HZ) break; */ } /* * 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) { /* * 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 != nil) screenputs(str, n); } void putstrn(char *str, int n) { putstrn0(str, n, 0); } int noprint; int print(char *fmt, ...) { int n; va_list arg; char buf[PRINTSIZE]; if(noprint) return -1; 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, s; va_list arg; char buf[PRINTSIZE]; kprintoq = nil; /* don't try to write to /dev/kprint */ if(panicking) for(;;); panicking = 1; s = splhi(); strcpy(buf, "panic: "); va_start(arg, fmt); n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; va_end(arg); uartputs(buf, n+1); if(consdebug) (*consdebug)(); spllo(); prflush(); buf[n] = '\n'; putstrn(buf, n+1); dumpstack(); 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 echoserialoq(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){ qiwrite(serialoq, ebuf, p - ebuf); p = ebuf; } x = *buf++; if(x == '\n'){ *p++ = '\r'; *p++ = '\n'; } else if(x == 0x15){ *p++ = '^'; *p++ = 'U'; *p++ = '\n'; } else *p++ = x; } if(p != ebuf) qiwrite(serialoq, ebuf, p - ebuf); } static void echo(char *buf, int n) { static int ctrlt; int x; char *e, *p; if(n == 0) return; e = buf+n; for(p = buf; p < e; p++){ switch(*p){ case 0x10: /* ^P */ if(cpuserver && !kbd.ctlpoff){ active.exiting = 1; return; } break; case 0x14: /* ^T */ ctrlt++; if(ctrlt > 2) ctrlt = 2; continue; } if(ctrlt != 2) continue; /* ^T escapes */ ctrlt = 0; switch(*p){ case 'S': x = splhi(); dumpstack(); procdump(); splx(x); return; case 's': dumpstack(); return; case 'x': xsummary(); ixsummary(); mallocsummary(); // memorysummary(); pagersummary(); return; case 'd': if(consdebug == nil) consdebug = rdb; else consdebug = nil; print("consdebug now %#p\n", consdebug); return; case 'D': if(consdebug == nil) consdebug = rdb; consdebug(); return; case 'p': x = spllo(); procdump(); splx(x); return; case 'q': scheddump(); return; case 'k': killbig("^t ^t k"); return; // case 'r': // exit(0); // return; } } qproduce(kbdq, buf, n); if(kbd.raw) return; if(screenputs != nil) echoscreen(buf, n); if(serialoq) echoserialoq(buf, n); } /* * Called by a uart interrupt for console input. * * turn '\r' into '\n' before putting it into the queue. */ int kbdcr2nl(Queue *q, int ch) { char *next; USED(q); ilock(&kbd.lockputc); /* just a mutex */ if(ch == '\r' && !kbd.raw) ch = '\n'; next = kbd.iw+1; if(next >= kbd.ie) next = kbd.istage; if(next != kbd.ir){ *kbd.iw = ch; kbd.iw = next; } iunlock(&kbd.lockputc); return 0; } 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); // kbd.c = r; // qproduce(kbdq, 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, Qcpunote, Qcputime, Qdrivers, Qkprint, Qhostdomain, Qhostowner, Qnull, Qosversion, Qpgrpid, Qpid, Qppid, Qrandom, Qreboot, Qsecstore, Qshowfile, Qsnarf, Qswap, 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, "cpunote", {Qcpunote}, 0, 0444, "cputime", {Qcputime}, 6*NUMSIZE, 0444, "drivers", {Qdrivers}, 0, 0444, "hostdomain", {Qhostdomain}, DOMLEN, 0664, "hostowner", {Qhostowner}, 0, 0664, "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, "secstore", {Qsecstore}, 0, 0666, "showfile", {Qshowfile}, 0, 0220, "snarf", {Qsnarf}, 0, 0666, "swap", {Qswap}, 0, 0664, "sysname", {Qsysname}, 0, 0664,