devcons.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "pool.h"
  8. #include <authsrv.h>
  9. void (*consdebug)(void) = nil;
  10. void (*screenputs)(char*, int) = nil;
  11. Queue* kbdq; /* unprocessed console input */
  12. Queue* lineq; /* processed console input */
  13. Queue* serialoq; /* serial console output */
  14. Queue* kprintoq; /* console output, for /dev/kprint */
  15. ulong kprintinuse; /* test and set whether /dev/kprint is open */
  16. int iprintscreenputs = 1;
  17. int panicking;
  18. static struct
  19. {
  20. QLock;
  21. int raw; /* true if we shouldn't process input */
  22. Ref ctl; /* number of opens to the control file */
  23. int x; /* index into line */
  24. char line[1024]; /* current input line */
  25. int count;
  26. int ctlpoff;
  27. /* a place to save up characters at interrupt time before dumping them in the queue */
  28. Lock lockputc;
  29. char istage[1024];
  30. char *iw;
  31. char *ir;
  32. char *ie;
  33. } kbd = {
  34. .iw = kbd.istage,
  35. .ir = kbd.istage,
  36. .ie = kbd.istage + sizeof(kbd.istage),
  37. };
  38. char *sysname;
  39. vlong fasthz;
  40. static void seedrand(void);
  41. static int readtime(ulong, char*, int);
  42. static int readbintime(char*, int);
  43. static int writetime(char*, int);
  44. static int writebintime(char*, int);
  45. enum
  46. {
  47. CMhalt,
  48. CMreboot,
  49. CMpanic,
  50. };
  51. Cmdtab rebootmsg[] =
  52. {
  53. CMhalt, "halt", 1,
  54. CMreboot, "reboot", 0,
  55. CMpanic, "panic", 0,
  56. };
  57. void
  58. printinit(void)
  59. {
  60. lineq = qopen(2*1024, 0, nil, nil);
  61. if(lineq == nil)
  62. panic("printinit");
  63. qnoblock(lineq, 1);
  64. }
  65. int
  66. consactive(void)
  67. {
  68. if(serialoq)
  69. return qlen(serialoq) > 0;
  70. return 0;
  71. }
  72. void
  73. prflush(void)
  74. {
  75. ulong now;
  76. now = m->ticks;
  77. while(consactive())
  78. if(m->ticks - now >= HZ)
  79. break;
  80. }
  81. /*
  82. * Log console output so it can be retrieved via /dev/kmesg.
  83. * This is good for catching boot-time messages after the fact.
  84. */
  85. struct {
  86. Lock lk;
  87. char buf[16384];
  88. uint n;
  89. } kmesg;
  90. static void
  91. kmesgputs(char *str, int n)
  92. {
  93. uint nn, d;
  94. ilock(&kmesg.lk);
  95. /* take the tail of huge writes */
  96. if(n > sizeof kmesg.buf){
  97. d = n - sizeof kmesg.buf;
  98. str += d;
  99. n -= d;
  100. }
  101. /* slide the buffer down to make room */
  102. nn = kmesg.n;
  103. if(nn + n >= sizeof kmesg.buf){
  104. d = nn + n - sizeof kmesg.buf;
  105. if(d)
  106. memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
  107. nn -= d;
  108. }
  109. /* copy the data in */
  110. memmove(kmesg.buf+nn, str, n);
  111. nn += n;
  112. kmesg.n = nn;
  113. iunlock(&kmesg.lk);
  114. }
  115. /*
  116. * Print a string on the console. Convert \n to \r\n for serial
  117. * line consoles. Locking of the queues is left up to the screen
  118. * or uart code. Multi-line messages to serial consoles may get
  119. * interspersed with other messages.
  120. */
  121. static void
  122. putstrn0(char *str, int n, int usewrite)
  123. {
  124. int m;
  125. char *t;
  126. if(!islo())
  127. usewrite = 0;
  128. /*
  129. * how many different output devices do we need?
  130. */
  131. kmesgputs(str, n);
  132. /*
  133. * if someone is reading /dev/kprint,
  134. * put the message there.
  135. * if not and there's an attached bit mapped display,
  136. * put the message there.
  137. *
  138. * if there's a serial line being used as a console,
  139. * put the message there.
  140. */
  141. if(kprintoq != nil && !qisclosed(kprintoq)){
  142. if(usewrite)
  143. qwrite(kprintoq, str, n);
  144. else
  145. qiwrite(kprintoq, str, n);
  146. }else if(screenputs != nil)
  147. screenputs(str, n);
  148. if(serialoq == nil){
  149. uartputs(str, n);
  150. return;
  151. }
  152. while(n > 0) {
  153. t = memchr(str, '\n', n);
  154. if(t && !kbd.raw) {
  155. m = t-str;
  156. if(usewrite){
  157. qwrite(serialoq, str, m);
  158. qwrite(serialoq, "\r\n", 2);
  159. } else {
  160. qiwrite(serialoq, str, m);
  161. qiwrite(serialoq, "\r\n", 2);
  162. }
  163. n -= m+1;
  164. str = t+1;
  165. } else {
  166. if(usewrite)
  167. qwrite(serialoq, str, n);
  168. else
  169. qiwrite(serialoq, str, n);
  170. break;
  171. }
  172. }
  173. }
  174. void
  175. putstrn(char *str, int n)
  176. {
  177. putstrn0(str, n, 0);
  178. }
  179. int noprint;
  180. int
  181. print(char *fmt, ...)
  182. {
  183. int n;
  184. va_list arg;
  185. char buf[PRINTSIZE];
  186. if(noprint)
  187. return -1;
  188. va_start(arg, fmt);
  189. n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
  190. va_end(arg);
  191. putstrn(buf, n);
  192. return n;
  193. }
  194. /*
  195. * Want to interlock iprints to avoid interlaced output on
  196. * multiprocessor, but don't want to deadlock if one processor
  197. * dies during print and another has something important to say.
  198. * Make a good faith effort.
  199. */
  200. static Lock iprintlock;
  201. static int
  202. iprintcanlock(Lock *l)
  203. {
  204. int i;
  205. for(i=0; i<1000; i++){
  206. if(canlock(l))
  207. return 1;
  208. if(l->m == MACHP(m->machno))
  209. return 0;
  210. microdelay(100);
  211. }
  212. return 0;
  213. }
  214. int
  215. iprint(char *fmt, ...)
  216. {
  217. int n, s, locked;
  218. va_list arg;
  219. char buf[PRINTSIZE];
  220. s = splhi();
  221. va_start(arg, fmt);
  222. n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
  223. va_end(arg);
  224. locked = iprintcanlock(&iprintlock);
  225. if(screenputs != nil && iprintscreenputs)
  226. screenputs(buf, n);
  227. uartputs(buf, n);
  228. if(locked)
  229. unlock(&iprintlock);
  230. splx(s);
  231. return n;
  232. }
  233. void
  234. panic(char *fmt, ...)
  235. {
  236. int n, s;
  237. va_list arg;
  238. char buf[PRINTSIZE];
  239. kprintoq = nil; /* don't try to write to /dev/kprint */
  240. if(panicking)
  241. for(;;);
  242. panicking = 1;
  243. s = splhi();
  244. strcpy(buf, "panic: ");
  245. va_start(arg, fmt);
  246. n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
  247. va_end(arg);
  248. iprint("%s\n", buf);
  249. if(consdebug)
  250. (*consdebug)();
  251. splx(s);
  252. prflush();
  253. buf[n] = '\n';
  254. putstrn(buf, n+1);
  255. dumpstack();
  256. exit(1);
  257. }
  258. /* libmp at least contains a few calls to sysfatal; simulate with panic */
  259. void
  260. sysfatal(char *fmt, ...)
  261. {
  262. char err[256];
  263. va_list arg;
  264. va_start(arg, fmt);
  265. vseprint(err, err + sizeof err, fmt, arg);
  266. va_end(arg);
  267. panic("sysfatal: %s", err);
  268. }
  269. void
  270. _assert(char *fmt)
  271. {
  272. panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
  273. }
  274. int
  275. pprint(char *fmt, ...)
  276. {
  277. int n;
  278. Chan *c;
  279. va_list arg;
  280. char buf[2*PRINTSIZE];
  281. if(up == nil || up->fgrp == nil)
  282. return 0;
  283. c = up->fgrp->fd[2];
  284. if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
  285. return 0;
  286. n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
  287. va_start(arg, fmt);
  288. n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
  289. va_end(arg);
  290. if(waserror())
  291. return 0;
  292. devtab[c->type]->write(c, buf, n, c->offset);
  293. poperror();
  294. lock(c);
  295. c->offset += n;
  296. unlock(c);
  297. return n;
  298. }
  299. static void
  300. echoscreen(char *buf, int n)
  301. {
  302. char *e, *p;
  303. char ebuf[128];
  304. int x;
  305. p = ebuf;
  306. e = ebuf + sizeof(ebuf) - 4;
  307. while(n-- > 0){
  308. if(p >= e){
  309. screenputs(ebuf, p - ebuf);
  310. p = ebuf;
  311. }
  312. x = *buf++;
  313. if(x == 0x15){
  314. *p++ = '^';
  315. *p++ = 'U';
  316. *p++ = '\n';
  317. } else
  318. *p++ = x;
  319. }
  320. if(p != ebuf)
  321. screenputs(ebuf, p - ebuf);
  322. }
  323. static void
  324. echoserialoq(char *buf, int n)
  325. {
  326. char *e, *p;
  327. char ebuf[128];
  328. int x;
  329. p = ebuf;
  330. e = ebuf + sizeof(ebuf) - 4;
  331. while(n-- > 0){
  332. if(p >= e){
  333. qiwrite(serialoq, ebuf, p - ebuf);
  334. p = ebuf;
  335. }
  336. x = *buf++;
  337. if(x == '\n'){
  338. *p++ = '\r';
  339. *p++ = '\n';
  340. } else if(x == 0x15){
  341. *p++ = '^';
  342. *p++ = 'U';
  343. *p++ = '\n';
  344. } else
  345. *p++ = x;
  346. }
  347. if(p != ebuf)
  348. qiwrite(serialoq, ebuf, p - ebuf);
  349. }
  350. static void
  351. echo(char *buf, int n)
  352. {
  353. static int ctrlt, pid;
  354. int x;
  355. char *e, *p;
  356. if(n == 0)
  357. return;
  358. e = buf+n;
  359. for(p = buf; p < e; p++){
  360. switch(*p){
  361. case 0x10: /* ^P */
  362. if(cpuserver && !kbd.ctlpoff){
  363. active.exiting = 1;
  364. return;
  365. }
  366. break;
  367. case 0x14: /* ^T */
  368. ctrlt++;
  369. if(ctrlt > 2)
  370. ctrlt = 2;
  371. continue;
  372. }
  373. if(ctrlt != 2)
  374. continue;
  375. /* ^T escapes */
  376. ctrlt = 0;
  377. switch(*p){
  378. case 'S':
  379. x = splhi();
  380. dumpstack();
  381. procdump();
  382. splx(x);
  383. return;
  384. case 's':
  385. dumpstack();
  386. return;
  387. case 'x':
  388. xsummary();
  389. ixsummary();
  390. mallocsummary();
  391. // memorysummary();
  392. pagersummary();
  393. return;
  394. case 'd':
  395. if(consdebug == nil)
  396. consdebug = rdb;
  397. else
  398. consdebug = nil;
  399. print("consdebug now %#p\n", consdebug);
  400. return;
  401. case 'D':
  402. if(consdebug == nil)
  403. consdebug = rdb;
  404. consdebug();
  405. return;
  406. case 'p':
  407. x = spllo();
  408. procdump();
  409. splx(x);
  410. return;
  411. case 'q':
  412. scheddump();
  413. return;
  414. case 'k':
  415. killbig("^t ^t k");
  416. return;
  417. case 'r':
  418. exit(0);
  419. return;
  420. }
  421. }
  422. qproduce(kbdq, buf, n);
  423. if(kbd.raw)
  424. return;
  425. kmesgputs(buf, n);
  426. if(screenputs != nil)
  427. echoscreen(buf, n);
  428. if(serialoq)
  429. echoserialoq(buf, n);
  430. }
  431. /*
  432. * Called by a uart interrupt for console input.
  433. *
  434. * turn '\r' into '\n' before putting it into the queue.
  435. */
  436. int
  437. kbdcr2nl(Queue*, int ch)
  438. {
  439. char *next;
  440. ilock(&kbd.lockputc); /* just a mutex */
  441. if(ch == '\r' && !kbd.raw)
  442. ch = '\n';
  443. next = kbd.iw+1;
  444. if(next >= kbd.ie)
  445. next = kbd.istage;
  446. if(next != kbd.ir){
  447. *kbd.iw = ch;
  448. kbd.iw = next;
  449. }
  450. iunlock(&kbd.lockputc);
  451. return 0;
  452. }
  453. /*
  454. * Put character, possibly a rune, into read queue at interrupt time.
  455. * Called at interrupt time to process a character.
  456. */
  457. int
  458. kbdputc(Queue*, int ch)
  459. {
  460. int i, n;
  461. char buf[3];
  462. Rune r;
  463. char *next;
  464. if(kbd.ir == nil)
  465. return 0; /* in case we're not inited yet */
  466. ilock(&kbd.lockputc); /* just a mutex */
  467. r = ch;
  468. n = runetochar(buf, &r);
  469. for(i = 0; i < n; i++){
  470. next = kbd.iw+1;
  471. if(next >= kbd.ie)
  472. next = kbd.istage;
  473. if(next == kbd.ir)
  474. break;
  475. *kbd.iw = buf[i];
  476. kbd.iw = next;
  477. }
  478. iunlock(&kbd.lockputc);
  479. return 0;
  480. }
  481. /*
  482. * we save up input characters till clock time to reduce
  483. * per character interrupt overhead.
  484. */
  485. static void
  486. kbdputcclock(void)
  487. {
  488. char *iw;
  489. /* this amortizes cost of qproduce */
  490. if(kbd.iw != kbd.ir){
  491. iw = kbd.iw;
  492. if(iw < kbd.ir){
  493. echo(kbd.ir, kbd.ie-kbd.ir);
  494. kbd.ir = kbd.istage;
  495. }
  496. if(kbd.ir != iw){
  497. echo(kbd.ir, iw-kbd.ir);
  498. kbd.ir = iw;
  499. }
  500. }
  501. }
  502. enum{
  503. Qdir,
  504. Qbintime,
  505. Qcons,
  506. Qconsctl,
  507. Qcputime,
  508. Qdrivers,
  509. Qkmesg,
  510. Qkprint,
  511. Qhostdomain,
  512. Qhostowner,
  513. Qnull,
  514. Qosversion,
  515. Qpgrpid,
  516. Qpid,
  517. Qppid,
  518. Qrandom,
  519. Qreboot,
  520. Qswap,
  521. Qsysname,
  522. Qsysstat,
  523. Qtime,
  524. Quser,
  525. Qzero,
  526. };
  527. enum
  528. {
  529. VLNUMSIZE= 22,
  530. };
  531. static Dirtab consdir[]={
  532. ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
  533. "bintime", {Qbintime}, 24, 0664,
  534. "cons", {Qcons}, 0, 0660,
  535. "consctl", {Qconsctl}, 0, 0220,
  536. "cputime", {Qcputime}, 6*NUMSIZE, 0444,
  537. "drivers", {Qdrivers}, 0, 0444,
  538. "hostdomain", {Qhostdomain}, DOMLEN, 0664,
  539. "hostowner", {Qhostowner}, 0, 0664,
  540. "kmesg", {Qkmesg}, 0, 0440,
  541. "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
  542. "null", {Qnull}, 0, 0666,
  543. "osversion", {Qosversion}, 0, 0444,
  544. "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
  545. "pid", {Qpid}, NUMSIZE, 0444,
  546. "ppid", {Qppid}, NUMSIZE, 0444,
  547. "random", {Qrandom}, 0, 0444,
  548. "reboot", {Qreboot}, 0, 0664,
  549. "swap", {Qswap}, 0, 0664,
  550. "sysname", {Qsysname}, 0, 0664,
  551. "sysstat", {Qsysstat}, 0, 0666,
  552. "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
  553. "user", {Quser}, 0, 0666,
  554. "zero", {Qzero}, 0, 0444,
  555. };
  556. int
  557. readnum(ulong off, char *buf, ulong n, ulong val, int size)
  558. {
  559. char tmp[64];
  560. snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
  561. tmp[size-1] = ' ';
  562. if(off >= size)
  563. return 0;
  564. if(off+n > size)
  565. n = size-off;
  566. memmove(buf, tmp+off, n);
  567. return n;
  568. }
  569. int
  570. readstr(ulong off, char *buf, ulong n, char *str)
  571. {
  572. int size;
  573. size = strlen(str);
  574. if(off >= size)
  575. return 0;
  576. if(off+n > size)
  577. n = size-off;
  578. memmove(buf, str+off, n);
  579. return n;
  580. }
  581. static void
  582. consinit(void)
  583. {
  584. todinit();
  585. randominit();
  586. /*
  587. * at 115200 baud, the 1024 char buffer takes 56 ms to process,
  588. * processing it every 22 ms should be fine
  589. */
  590. addclock0link(kbdputcclock, 22);
  591. }
  592. static Chan*
  593. consattach(char *spec)
  594. {
  595. return devattach('c', spec);
  596. }
  597. static Walkqid*
  598. conswalk(Chan *c, Chan *nc, char **name, int nname)
  599. {
  600. return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
  601. }
  602. static int
  603. consstat(Chan *c, uchar *dp, int n)
  604. {
  605. return devstat(c, dp, n, consdir, nelem(consdir), devgen);
  606. }
  607. static Chan*
  608. consopen(Chan *c, int omode)
  609. {
  610. c->aux = nil;
  611. c = devopen(c, omode, consdir, nelem(consdir), devgen);
  612. switch((ulong)c->qid.path){
  613. case Qconsctl:
  614. incref(&kbd.ctl);
  615. break;
  616. case Qkprint:
  617. if(tas(&kprintinuse) != 0){
  618. c->flag &= ~COPEN;
  619. error(Einuse);
  620. }
  621. if(kprintoq == nil){
  622. kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
  623. if(kprintoq == nil){
  624. c->flag &= ~COPEN;
  625. error(Enomem);
  626. }
  627. qnoblock(kprintoq, 1);
  628. }else
  629. qreopen(kprintoq);
  630. c->iounit = qiomaxatomic;
  631. break;
  632. }
  633. return c;
  634. }
  635. static void
  636. consclose(Chan *c)
  637. {
  638. switch((ulong)c->qid.path){
  639. /* last close of control file turns off raw */
  640. case Qconsctl:
  641. if(c->flag&COPEN){
  642. if(decref(&kbd.ctl) == 0)
  643. kbd.raw = 0;
  644. }
  645. break;
  646. /* close of kprint allows other opens */
  647. case Qkprint:
  648. if(c->flag & COPEN){
  649. kprintinuse = 0;
  650. qhangup(kprintoq, nil);
  651. }
  652. break;
  653. }
  654. }
  655. static long
  656. consread(Chan *c, void *buf, long n, vlong off)
  657. {
  658. ulong l;
  659. Mach *mp;
  660. char *b, *bp, ch;
  661. char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
  662. int i, k, id, send;
  663. vlong offset = off;
  664. if(n <= 0)
  665. return n;
  666. switch((ulong)c->qid.path){
  667. case Qdir:
  668. return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
  669. case Qcons:
  670. qlock(&kbd);
  671. if(waserror()) {
  672. qunlock(&kbd);
  673. nexterror();
  674. }
  675. while(!qcanread(lineq)){
  676. if(qread(kbdq, &ch, 1) == 0)
  677. continue;
  678. send = 0;
  679. if(ch == 0){
  680. /* flush output on rawoff -> rawon */
  681. if(kbd.x > 0)
  682. send = !qcanread(kbdq);
  683. }else if(kbd.raw){
  684. kbd.line[kbd.x++] = ch;
  685. send = !qcanread(kbdq);
  686. }else{
  687. switch(ch){
  688. case '\b':
  689. if(kbd.x > 0)
  690. kbd.x--;
  691. break;
  692. case 0x15: /* ^U */
  693. kbd.x = 0;
  694. break;
  695. case '\n':
  696. case 0x04: /* ^D */
  697. send = 1;
  698. default:
  699. if(ch != 0x04)
  700. kbd.line[kbd.x++] = ch;
  701. break;
  702. }
  703. }
  704. if(send || kbd.x == sizeof kbd.line){
  705. qwrite(lineq, kbd.line, kbd.x);
  706. kbd.x = 0;
  707. }
  708. }
  709. n = qread(lineq, buf, n);
  710. qunlock(&kbd);
  711. poperror();
  712. return n;
  713. case Qcputime:
  714. k = offset;
  715. if(k >= 6*NUMSIZE)
  716. return 0;
  717. if(k+n > 6*NUMSIZE)
  718. n = 6*NUMSIZE - k;
  719. /* easiest to format in a separate buffer and copy out */
  720. for(i=0; i<6 && NUMSIZE*i<k+n; i++){
  721. l = up->time[i];
  722. if(i == TReal)
  723. l = MACHP(0)->ticks - l;
  724. l = TK2MS(l);
  725. readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
  726. }
  727. memmove(buf, tmp+k, n);
  728. return n;
  729. case Qkmesg:
  730. /*
  731. * This is unlocked to avoid tying up a process
  732. * that's writing to the buffer. kmesg.n never
  733. * gets smaller, so worst case the reader will
  734. * see a slurred buffer.
  735. */
  736. if(off >= kmesg.n)
  737. n = 0;
  738. else{
  739. if(off+n > kmesg.n)
  740. n = kmesg.n - off;
  741. memmove(buf, kmesg.buf+off, n);
  742. }
  743. return n;
  744. case Qkprint:
  745. return qread(kprintoq, buf, n);
  746. case Qpgrpid:
  747. return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
  748. case Qpid:
  749. return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
  750. case Qppid:
  751. return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
  752. case Qtime:
  753. return readtime((ulong)offset, buf, n);
  754. case Qbintime:
  755. return readbintime(buf, n);
  756. case Qhostowner:
  757. return readstr((ulong)offset, buf, n, eve);
  758. case Qhostdomain:
  759. return readstr((ulong)offset, buf, n, hostdomain);
  760. case Quser:
  761. return readstr((ulong)offset, buf, n, up->user);
  762. case Qnull:
  763. return 0;
  764. case Qsysstat:
  765. b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
  766. bp = b;
  767. for(id = 0; id < 32; id++) {
  768. if(active.machs & (1<<id)) {
  769. mp = MACHP(id);
  770. readnum(0, bp, NUMSIZE, id, NUMSIZE);
  771. bp += NUMSIZE;
  772. readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
  773. bp += NUMSIZE;
  774. readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
  775. bp += NUMSIZE;
  776. readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
  777. bp += NUMSIZE;
  778. readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
  779. bp += NUMSIZE;
  780. readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
  781. bp += NUMSIZE;
  782. readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
  783. bp += NUMSIZE;
  784. readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
  785. bp += NUMSIZE;
  786. readnum(0, bp, NUMSIZE,
  787. (mp->perf.avg_inidle*100)/mp->perf.period,
  788. NUMSIZE);
  789. bp += NUMSIZE;
  790. readnum(0, bp, NUMSIZE,
  791. (mp->perf.avg_inintr*100)/mp->perf.period,
  792. NUMSIZE);
  793. bp += NUMSIZE;
  794. *bp++ = '\n';
  795. }
  796. }
  797. if(waserror()){
  798. free(b);
  799. nexterror();
  800. }
  801. n = readstr((ulong)offset, buf, n, b);
  802. free(b);
  803. poperror();
  804. return n;
  805. case Qswap:
  806. snprint(tmp, sizeof tmp,
  807. "%lud memory\n"
  808. "%d pagesize\n"
  809. "%lud kernel\n"
  810. "%lud/%lud user\n"
  811. "%lud/%lud swap\n"
  812. "%lud/%lud kernel malloc\n"
  813. "%lud/%lud kernel draw\n",
  814. conf.npage*BY2PG,
  815. BY2PG,
  816. conf.npage-conf.upages,
  817. palloc.user-palloc.freecount, palloc.user,
  818. conf.nswap-swapalloc.free, conf.nswap,
  819. mainmem->cursize, mainmem->maxsize,
  820. imagmem->cursize, imagmem->maxsize);
  821. return readstr((ulong)offset, buf, n, tmp);
  822. case Qsysname:
  823. if(sysname == nil)
  824. return 0;
  825. return readstr((ulong)offset, buf, n, sysname);
  826. case Qrandom:
  827. return randomread(buf, n);
  828. case Qdrivers:
  829. b = malloc(READSTR);
  830. if(b == nil)
  831. error(Enomem);
  832. n = 0;
  833. for(i = 0; devtab[i] != nil; i++)
  834. n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc, devtab[i]->name);
  835. if(waserror()){
  836. free(b);
  837. nexterror();
  838. }
  839. n = readstr((ulong)offset, buf, n, b);
  840. free(b);
  841. poperror();
  842. return n;
  843. case Qzero:
  844. memset(buf, 0, n);
  845. return n;
  846. case Qosversion:
  847. snprint(tmp, sizeof tmp, "2000");
  848. n = readstr((ulong)offset, buf, n, tmp);
  849. return n;
  850. default:
  851. print("consread %#llux\n", c->qid.path);
  852. error(Egreg);
  853. }
  854. return -1; /* never reached */
  855. }
  856. static long
  857. conswrite(Chan *c, void *va, long n, vlong off)
  858. {
  859. char buf[256], ch;
  860. long l, bp;
  861. char *a;
  862. Mach *mp;
  863. int id, fd;
  864. Chan *swc;
  865. ulong offset;
  866. Cmdbuf *cb;
  867. Cmdtab *ct;
  868. a = va;
  869. offset = off;
  870. switch((ulong)c->qid.path){
  871. case Qcons:
  872. /*
  873. * Can't page fault in putstrn, so copy the data locally.
  874. */
  875. l = n;
  876. while(l > 0){
  877. bp = l;
  878. if(bp > sizeof buf)
  879. bp = sizeof buf;
  880. memmove(buf, a, bp);
  881. putstrn0(buf, bp, 1);
  882. a += bp;
  883. l -= bp;
  884. }
  885. break;
  886. case Qconsctl:
  887. if(n >= sizeof(buf))
  888. n = sizeof(buf)-1;
  889. strncpy(buf, a, n);
  890. buf[n] = 0;
  891. for(a = buf; a;){
  892. if(strncmp(a, "rawon", 5) == 0){
  893. kbd.raw = 1;
  894. /* clumsy hack - wake up reader */
  895. ch = 0;
  896. qwrite(kbdq, &ch, 1);
  897. } else if(strncmp(a, "rawoff", 6) == 0){
  898. kbd.raw = 0;
  899. } else if(strncmp(a, "ctlpon", 6) == 0){
  900. kbd.ctlpoff = 0;
  901. } else if(strncmp(a, "ctlpoff", 7) == 0){
  902. kbd.ctlpoff = 1;
  903. }
  904. if(a = strchr(a, ' '))
  905. a++;
  906. }
  907. break;
  908. case Qtime:
  909. if(!iseve())
  910. error(Eperm);
  911. return writetime(a, n);
  912. case Qbintime:
  913. if(!iseve())
  914. error(Eperm);
  915. return writebintime(a, n);
  916. case Qhostowner:
  917. return hostownerwrite(a, n);
  918. case Qhostdomain:
  919. return hostdomainwrite(a, n);
  920. case Quser:
  921. return userwrite(a, n);
  922. case Qnull:
  923. break;
  924. case Qreboot:
  925. if(!iseve())
  926. error(Eperm);
  927. cb = parsecmd(a, n);
  928. if(waserror()) {
  929. free(cb);
  930. nexterror();
  931. }
  932. ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
  933. switch(ct->index) {
  934. case CMhalt:
  935. reboot(nil, 0, 0);
  936. break;
  937. case CMreboot:
  938. rebootcmd(cb->nf-1, cb->f+1);
  939. break;
  940. case CMpanic:
  941. *(ulong*)0=0;
  942. panic("/dev/reboot");
  943. }
  944. poperror();
  945. free(cb);
  946. break;
  947. case Qsysstat:
  948. for(id = 0; id < 32; id++) {
  949. if(active.machs & (1<<id)) {
  950. mp = MACHP(id);
  951. mp->cs = 0;
  952. mp->intr = 0;
  953. mp->syscall = 0;
  954. mp->pfault = 0;
  955. mp->tlbfault = 0;
  956. mp->tlbpurge = 0;
  957. }
  958. }
  959. break;
  960. case Qswap:
  961. if(n >= sizeof buf)
  962. error(Egreg);
  963. memmove(buf, va, n); /* so we can NUL-terminate */
  964. buf[n] = 0;
  965. /* start a pager if not already started */
  966. if(strncmp(buf, "start", 5) == 0){
  967. kickpager();
  968. break;
  969. }
  970. if(!iseve())
  971. error(Eperm);
  972. if(buf[0]<'0' || '9'<buf[0])
  973. error(Ebadarg);
  974. fd = strtoul(buf, 0, 0);
  975. swc = fdtochan(fd, -1, 1, 1);
  976. setswapchan(swc);
  977. break;
  978. case Qsysname:
  979. if(offset != 0)
  980. error(Ebadarg);
  981. if(n <= 0 || n >= sizeof buf)
  982. error(Ebadarg);
  983. strncpy(buf, a, n);
  984. buf[n] = 0;
  985. if(buf[n-1] == '\n')
  986. buf[n-1] = 0;
  987. kstrdup(&sysname, buf);
  988. break;
  989. default:
  990. print("conswrite: %#llux\n", c->qid.path);
  991. error(Egreg);
  992. }
  993. return n;
  994. }
  995. Dev consdevtab = {
  996. 'c',
  997. "cons",
  998. devreset,
  999. consinit,
  1000. devshutdown,
  1001. consattach,
  1002. conswalk,
  1003. consstat,
  1004. consopen,
  1005. devcreate,
  1006. consclose,
  1007. consread,
  1008. devbread,
  1009. conswrite,
  1010. devbwrite,
  1011. devremove,
  1012. devwstat,
  1013. };
  1014. static ulong randn;
  1015. static void
  1016. seedrand(void)
  1017. {
  1018. if(!waserror()){
  1019. randomread((void*)&randn, sizeof(randn));
  1020. poperror();
  1021. }
  1022. }
  1023. int
  1024. nrand(int n)
  1025. {
  1026. if(randn == 0)
  1027. seedrand();
  1028. randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
  1029. return (randn>>16) % n;
  1030. }
  1031. int
  1032. rand(void)
  1033. {
  1034. nrand(1);
  1035. return randn;
  1036. }
  1037. static uvlong uvorder = 0x0001020304050607ULL;
  1038. static uchar*
  1039. le2vlong(vlong *to, uchar *f)
  1040. {
  1041. uchar *t, *o;
  1042. int i;
  1043. t = (uchar*)to;
  1044. o = (uchar*)&uvorder;
  1045. for(i = 0; i < sizeof(vlong); i++)
  1046. t[o[i]] = f[i];
  1047. return f+sizeof(vlong);
  1048. }
  1049. static uchar*
  1050. vlong2le(uchar *t, vlong from)
  1051. {
  1052. uchar *f, *o;
  1053. int i;
  1054. f = (uchar*)&from;
  1055. o = (uchar*)&uvorder;
  1056. for(i = 0; i < sizeof(vlong); i++)
  1057. t[i] = f[o[i]];
  1058. return t+sizeof(vlong);
  1059. }
  1060. static long order = 0x00010203;
  1061. static uchar*
  1062. le2long(long *to, uchar *f)
  1063. {
  1064. uchar *t, *o;
  1065. int i;
  1066. t = (uchar*)to;
  1067. o = (uchar*)&order;
  1068. for(i = 0; i < sizeof(long); i++)
  1069. t[o[i]] = f[i];
  1070. return f+sizeof(long);
  1071. }
  1072. static uchar*
  1073. long2le(uchar *t, long from)
  1074. {
  1075. uchar *f, *o;
  1076. int i;
  1077. f = (uchar*)&from;
  1078. o = (uchar*)&order;
  1079. for(i = 0; i < sizeof(long); i++)
  1080. t[i] = f[o[i]];
  1081. return t+sizeof(long);
  1082. }
  1083. char *Ebadtimectl = "bad time control";
  1084. /*
  1085. * like the old #c/time but with added info. Return
  1086. *
  1087. * secs nanosecs fastticks fasthz
  1088. */
  1089. static int
  1090. readtime(ulong off, char *buf, int n)
  1091. {
  1092. vlong nsec, ticks;
  1093. long sec;
  1094. char str[7*NUMSIZE];
  1095. nsec = todget(&ticks);
  1096. if(fasthz == 0LL)
  1097. fastticks((uvlong*)&fasthz);
  1098. sec = nsec/1000000000ULL;
  1099. snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
  1100. NUMSIZE-1, sec,
  1101. VLNUMSIZE-1, nsec,
  1102. VLNUMSIZE-1, ticks,
  1103. VLNUMSIZE-1, fasthz);
  1104. return readstr(off, buf, n, str);
  1105. }
  1106. /*
  1107. * set the time in seconds
  1108. */
  1109. static int
  1110. writetime(char *buf, int n)
  1111. {
  1112. char b[13];
  1113. long i;
  1114. vlong now;
  1115. if(n >= sizeof(b))
  1116. error(Ebadtimectl);
  1117. strncpy(b, buf, n);
  1118. b[n] = 0;
  1119. i = strtol(b, 0, 0);
  1120. if(i <= 0)
  1121. error(Ebadtimectl);
  1122. now = i*1000000000LL;
  1123. todset(now, 0, 0);
  1124. return n;
  1125. }
  1126. /*
  1127. * read binary time info. all numbers are little endian.
  1128. * ticks and nsec are syncronized.
  1129. */
  1130. static int
  1131. readbintime(char *buf, int n)
  1132. {
  1133. int i;
  1134. vlong nsec, ticks;
  1135. uchar *b = (uchar*)buf;
  1136. i = 0;
  1137. if(fasthz == 0LL)
  1138. fastticks((uvlong*)&fasthz);
  1139. nsec = todget(&ticks);
  1140. if(n >= 3*sizeof(uvlong)){
  1141. vlong2le(b+2*sizeof(uvlong), fasthz);
  1142. i += sizeof(uvlong);
  1143. }
  1144. if(n >= 2*sizeof(uvlong)){
  1145. vlong2le(b+sizeof(uvlong), ticks);
  1146. i += sizeof(uvlong);
  1147. }
  1148. if(n >= 8){
  1149. vlong2le(b, nsec);
  1150. i += sizeof(vlong);
  1151. }
  1152. return i;
  1153. }
  1154. /*
  1155. * set any of the following
  1156. * - time in nsec
  1157. * - nsec trim applied over some seconds
  1158. * - clock frequency
  1159. */
  1160. static int
  1161. writebintime(char *buf, int n)
  1162. {
  1163. uchar *p;
  1164. vlong delta;
  1165. long period;
  1166. n--;
  1167. p = (uchar*)buf + 1;
  1168. switch(*buf){
  1169. case 'n':
  1170. if(n < sizeof(vlong))
  1171. error(Ebadtimectl);
  1172. le2vlong(&delta, p);
  1173. todset(delta, 0, 0);
  1174. break;
  1175. case 'd':
  1176. if(n < sizeof(vlong)+sizeof(long))
  1177. error(Ebadtimectl);
  1178. p = le2vlong(&delta, p);
  1179. le2long(&period, p);
  1180. todset(-1, delta, period);
  1181. break;
  1182. case 'f':
  1183. if(n < sizeof(uvlong))
  1184. error(Ebadtimectl);
  1185. le2vlong(&fasthz, p);
  1186. todsetfreq(fasthz);
  1187. break;
  1188. }
  1189. return n;
  1190. }