📄 devcons.c
字号:
#include "u.h"#include "lib.h"#include "dat.h"#include "fns.h"#include "error.h"#include "keyboard.h"void (*consdebug)(void) = 0;void (*screenputs)(char*, int) = 0;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 */int iprintscreenputs = 0;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; 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 = { { 0 }, 0, 0, 0, { 0 }, 0, 0, { 0 }, { 0 }, kbd.istage, kbd.istage, 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, 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);}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; va_list arg; char buf[PRINTSIZE]; kprintoq = nil; /* don't try to write to /dev/kprint */ if(panicking) for(;;); panicking = 1; 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'; uartputs(buf, n+1); if(consdebug) (*consdebug)(); spllo(); prflush(); 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; 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(); pagersummary(); return; case 'd': if(consdebug == 0) consdebug = rdb; else consdebug = 0; print("consdebug now 0x%p\n", consdebug); return; case 'D': if(consdebug == 0) consdebug = rdb; consdebug(); return; case 'p': x = spllo(); procdump(); splx(x); return; case 'q': scheddump(); return; case 'k': killbig(); return; case 'r': exit(0); return; } } qproduce(kbdq, buf, n); if(kbd.raw) return; if(screenputs != 0) 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, "sysstat", {Qsysstat}, 0, 0666, "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664, "user", {Quser}, 0, 0666, "zero", {Qzero}, 0, 0444,};char secstorebuf[65536];Dirtab *secstoretab = &consdir[Qsecstore];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){ todinit(); randominit(); /* * at 115200 baud, the 1024 char buffer takes 56 ms to process, * processing it every 22 ms should be fine *//* addclock0link(kbdputcclock, 22); */}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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -