📄 devcons.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"void (*consdebug)(void) = nil;Queue* kbdq; /* unprocessed console input */Queue* lineq; /* processed console input */Queue* printq; /* console output */static struct{ QLock; 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 */ Rune c; int count; int repeat; int ctlpoff;} kbd;char sysname[NAMELEN];vlong fasthz;static ulong randomread(void*, ulong);static void randominit(void);static void seedrand(void);static int readtime(ulong, char*, int);static int readbintime(char*, int);static int writetime(char*, int);static int writebintime(char*, int);voidprintinit(void){ lineq = qopen(2*1024, 0, 0, 0); if(lineq == nil) panic("printinit"); qnoblock(lineq, 1);}intconsactive(void){ if(printq) return qlen(printq) > 0; return 0;}voidprflush(void){ while(consactive()) ;}/* * 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){ int m; char *t; char buf[PRINTSIZE+2]; /* * if there's an attached bit mapped display, * put the message there. screenputs is defined * as a null macro for systems that have no such * display. */ screenputs(str, n); /* * if there's a serial line being used as a console, * put the message there. */ if(printq == 0) return; while(n > 0) { t = memchr(str, '\n', n); if(t) { m = t - str; memmove(buf, str, m); buf[m] = '\r'; buf[m+1] = '\n'; if(usewrite) qwrite(printq, buf, m+2); else qiwrite(printq, buf, m+2); str = t + 1; n -= m + 1; } else { if(usewrite) qwrite(printq, str, n); else qiwrite(printq, str, n); break; } }}voidputstrn(char *str, int n){ putstrn0(str, n, 0);}intsnprint(char *s, int n, char *fmt, ...){ va_list arg; va_start(arg, fmt); n = doprint(s, s+n, fmt, arg) - s; va_end(arg); return n;}intsprint(char *s, char *fmt, ...){ int n; va_list arg; va_start(arg, fmt); n = doprint(s, s+PRINTSIZE, fmt, arg) - s; va_end(arg); return n;}int noprint;intprint(char *fmt, ...){ int n; va_list arg; char buf[PRINTSIZE]; if(noprint) return -1; va_start(arg, fmt); n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); putstrn(buf, n); return n;}intiprint(char *fmt, ...){ int n, s; va_list arg; char buf[PRINTSIZE]; s = splhi(); va_start(arg, fmt); n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); serialputs(buf, n);// screenputs(buf, n); splx(s); return n;}voidpanic(char *fmt, ...){ int n; va_list arg; char buf[PRINTSIZE]; splhi(); strcpy(buf, "panic: "); va_start(arg, fmt); n = doprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; va_end(arg); buf[n] = '\n'; serialputs(buf, n+1); if(consdebug) consdebug(); putstrn(buf, n+1); spllo(); prflush(); dumpstack(); exit(1);}void_assert(char *fmt){ panic("assert failed: %s", fmt);}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 = doprint(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); c->offset += n; unlock(c); return n;}voidecho(Rune r, char *buf, int n){ static int ctrlt, pid; extern ulong etext; int x; /* * ^p hack */ if(r==0x10 && cpuserver && !kbd.ctlpoff){ lock(&active); active.exiting = 1; unlock(&active); } /* * ^t hack BUG */ if(ctrlt == 2){ ctrlt = 0; switch(r){ case 0x14: break; /* pass it on */ case 's': dumpstack(); break; case 'x': xsummary(); ixsummary(); mallocsummary(); pagersummary(); break; case 'd': if(consdebug == nil) consdebug = rdb; else consdebug = nil; print("consdebug now 0x%p\n", consdebug); return; case 'D': if(consdebug == nil) consdebug = rdb; consdebug(); return; case 'p': x = spllo(); procdump(); splx(x); return; case 'q': scheddump(); break; case 'k': if(!cpuserver) killbig(); break; case 'r': exit(0); break; } } else if(r == 0x14){ ctrlt++; return; } ctrlt = 0; if(kbd.raw) return; /* * finally, the actual echoing */ if(r == '\n'){ if(printq) qiwrite(printq, "\r", 1); } else if(r == 0x15){ buf = "^U\n"; n = 3; } screenputs(buf, n); if(printq) qiwrite(printq, 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){ if(ch == '\r') ch = '\n'; return kbdputc(q, ch);}/* * Put character, possibly a rune, into read queue at interrupt time. * Called at interrupt time to process a character. */intkbdputc(Queue*, int ch){ int n; char buf[3]; Rune r; r = ch; n = runetochar(buf, &r); if(n == 0) return 0; echo(r, buf, n); kbd.c = r; qproduce(kbdq, buf, n); return 0;}voidkbdrepeat(int rep){ kbd.repeat = rep; kbd.count = 0;}voidkbdclock(void){ if(kbd.repeat == 0) return; if(kbd.repeat==1 && ++kbd.count>HZ){ kbd.repeat = 2; kbd.count = 0; return; } if(++kbd.count&1) kbdputc(kbdq, kbd.c);}enum{ Qdir, Qauth, Qauthcheck, Qauthent, Qbintime, Qcons, Qconsctl, Qcputime, Qdrivers, Qkey, Qhostdomain, Qhostowner, Qnull, Qpgrpid, Qpid, Qppid, Qrandom, Qreboot, Qswap, Qsysname, Qsysstat, Qtime, Quser, Qzero,};enum{ VLNUMSIZE= 22,};static Dirtab consdir[]={ "authenticate", {Qauth}, 0, 0666, "authcheck", {Qauthcheck}, 0, 0666, "authenticator", {Qauthent}, 0, 0666, "bintime", {Qbintime}, 24, 0664, "cons", {Qcons}, 0, 0660, "consctl", {Qconsctl}, 0, 0220, "cputime", {Qcputime}, 6*NUMSIZE, 0444, "drivers", {Qdrivers}, 0, 0644, "hostdomain", {Qhostdomain}, DOMLEN, 0664, "hostowner", {Qhostowner}, NAMELEN, 0664, "key", {Qkey}, DESKEYLEN, 0622, "null", {Qnull}, 0, 0666, "pgrpid", {Qpgrpid}, NUMSIZE, 0444, "pid", {Qpid}, NUMSIZE, 0444, "ppid", {Qppid}, NUMSIZE, 0444, "random", {Qrandom}, 0, 0664, "reboot", {Qreboot}, 0, 0664, "swap", {Qswap}, 0, 0664, "sysname", {Qsysname}, 0, 0664, "sysstat", {Qsysstat}, 0, 0666, "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664, "user", {Quser}, NAMELEN, 0666, "zero", {Qzero}, 0, 0444,};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();}static Chan*consattach(char *spec){ return devattach('c', spec);}static intconswalk(Chan *c, char *name){ return devwalk(c, name, consdir, nelem(consdir), devgen);}static voidconsstat(Chan *c, char *dp){ devstat(c, dp, consdir, nelem(consdir), devgen);}static Chan*consopen(Chan *c, int omode){ c->aux = 0; switch(c->qid.path){ case Qconsctl: if(!iseve()) error(Eperm); qlock(&kbd); kbd.ctl++; qunlock(&kbd); break; } return devopen(c, omode, consdir, nelem(consdir), devgen);}static voidconsclose(Chan *c){ /* last close of control file turns off raw */ switch(c->qid.path){ case Qconsctl: if(c->flag&COPEN){ qlock(&kbd); if(--kbd.ctl == 0) kbd.raw = 0; qunlock(&kbd); } break; case Qauth: case Qauthcheck: case Qauthent: authclose(c); }}static longconsread(Chan *c, void *buf, long n, vlong off){ ulong l; Mach *mp; char *b, *bp; char tmp[128]; /* must be >= 6*NUMSIZE */ char *cbuf = buf; int ch, i, k, id, eol; vlong offset = off; if(n <= 0) return n; switch(c->qid.path & ~CHDIR){ case Qdir: return devdirread(c, buf, n, consdir, nelem(consdir), devgen); case Qcons: qlock(&kbd); if(waserror()) { qunlock(&kbd); nexterror(); } if(kbd.raw) { if(qcanread(lineq)) n = qread(lineq, buf, n); else { /* read as much as possible */ do { i = qread(kbdq, cbuf, n); cbuf += i; n -= i; } while (n>0 && qcanread(kbdq)); n = cbuf - (char*)buf; } } else { while(!qcanread(lineq)) { qread(kbdq, &kbd.line[kbd.x], 1); ch = kbd.line[kbd.x]; if(kbd.raw){ qiwrite(lineq, kbd.line, kbd.x+1); kbd.x = 0; continue; } eol = 0; switch(ch){ case '\b': if(kbd.x) kbd.x--; break; case 0x15: kbd.x = 0; break; case '\n': case 0x04: eol = 1; default: kbd.line[kbd.x++] = ch; break; } if(kbd.x == sizeof(kbd.line) || eol){ if(ch == 0x04) kbd.x--; qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, buf, n); } qunlock(&kbd); poperror(); return n; case Qcputime: k = offset; if(k >= 6*NUMSIZE) return 0; if(k+n > 6*NUMSIZE) n = 6*NUMSIZE - k; /* easiest to format in a separate buffer and copy out */ for(i=0; i<6 && NUMSIZE*i<k+n; i++){ l = up->time[i]; if(i == TReal) l = MACHP(0)->ticks - l; l = TK2MS(l); readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } memmove(buf, tmp+k, n); return n; case Qpgrpid:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -