devcon.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include "lib9.h"
  2. #include "sys.h"
  3. #include "error.h"
  4. #include "keyboard.h"
  5. enum
  6. {
  7. Qdir,
  8. Qauth,
  9. Qauthcheck,
  10. Qauthent,
  11. Qcons,
  12. Qconsctl,
  13. Qcpunote,
  14. Qhostowner,
  15. Qkey,
  16. Qnull,
  17. Qsnarf,
  18. Qsysname,
  19. Quser
  20. };
  21. Dirtab contab[] =
  22. {
  23. "authenticate", {Qauth}, 0, 0666,
  24. "authcheck", {Qauthcheck}, 0, 0666,
  25. "authenticator", {Qauthent}, 0, 0666,
  26. "cons", {Qcons}, 0, 0666,
  27. "consctl", {Qconsctl}, 0, 0222,
  28. "cpunote", {Qcpunote}, 0, 0444,
  29. "hostowner", {Qhostowner}, NAMELEN, 0664,
  30. "key", {Qkey}, DESKEYLEN, 0622,
  31. "null", {Qnull}, 0, 0666,
  32. "snarf", {Qsnarf}, 0, 0666,
  33. "sysname", {Qsysname}, 0, 0444,
  34. "user", {Quser}, NAMELEN, 0666,
  35. };
  36. Dirtab *snarftab = &contab[9];
  37. #define Ncontab (sizeof(contab)/sizeof(contab[0]))
  38. void (*screenputs)(char*, int);
  39. static Qlock locked;
  40. Queue* kbdq; /* unprocessed console input */
  41. static Queue* lineq; /* processed console input */
  42. char sysname[3*NAMELEN];
  43. static struct
  44. {
  45. Qlock q;
  46. int raw; /* true if we shouldn't process input */
  47. int ctl; /* number of opens to the control file */
  48. int x; /* index into line */
  49. char line[1024]; /* current input line */
  50. Rune c;
  51. int count;
  52. } kbd;
  53. void
  54. coninit(void)
  55. {
  56. canqlock(&locked);
  57. kbdq = qopen(1024, 0, 0, 0);
  58. if(kbdq == 0)
  59. panic("no memory");
  60. lineq = qopen(1024, 0, 0, 0);
  61. if(lineq == 0)
  62. panic("no memory");
  63. }
  64. Chan*
  65. conattach(void *spec)
  66. {
  67. return devattach('c', spec);
  68. }
  69. Chan*
  70. conclone(Chan *c, Chan *nc)
  71. {
  72. return devclone(c, nc);
  73. }
  74. int
  75. conwalk(Chan *c, char *name)
  76. {
  77. return devwalk(c, name, contab, Ncontab, devgen);
  78. }
  79. void
  80. constat(Chan *c, char *db)
  81. {
  82. devstat(c, db, contab, Ncontab, devgen);
  83. }
  84. Chan*
  85. conopen(Chan *c, int omode)
  86. {
  87. switch(c->qid.path & ~CHDIR){
  88. case Qdir:
  89. if(omode != OREAD)
  90. error(Eisdir);
  91. c->mode = omode;
  92. c->flag |= COPEN;
  93. c->offset = 0;
  94. return c;
  95. case Qconsctl:
  96. qlock(&kbd.q);
  97. kbd.ctl++;
  98. qunlock(&kbd.q);
  99. break;
  100. case Qsnarf:
  101. if(omode == ORDWR)
  102. error(Eperm);
  103. if(omode == OREAD)
  104. c->u.aux = strdup("");
  105. else
  106. c->u.aux = mallocz(SnarfSize);
  107. break;
  108. }
  109. return devopen(c, omode, contab, Ncontab, devgen);
  110. }
  111. void
  112. concreate(Chan *c, char *name, int omode, ulong perm)
  113. {
  114. error(Eperm);
  115. }
  116. void
  117. conremove(Chan *c)
  118. {
  119. error(Eperm);
  120. }
  121. void
  122. conwstat(Chan *c, char *dp)
  123. {
  124. error(Eperm);
  125. }
  126. void
  127. conclose(Chan *c)
  128. {
  129. switch(c->qid.path) {
  130. case Qconsctl:
  131. if(c->flag&COPEN) {
  132. qlock(&kbd.q);
  133. kbd.ctl++;
  134. kbd.raw = 0;
  135. qunlock(&kbd.q);
  136. }
  137. case Qauth:
  138. case Qauthcheck:
  139. case Qauthent:
  140. authclose(c);
  141. break;
  142. case Qsnarf:
  143. if(c->mode == OWRITE)
  144. clipwrite(c->u.aux, strlen(c->u.aux));
  145. free(c->u.aux);
  146. break;
  147. }
  148. }
  149. long
  150. conread(Chan *c, void *va, long count, ulong offset)
  151. {
  152. int n, ch, eol;
  153. char *cbuf = va;
  154. if(c->qid.path & CHDIR)
  155. return devdirread(c, va, count, contab, Ncontab, devgen);
  156. switch(c->qid.path) {
  157. default:
  158. error(Egreg);
  159. case Qauth:
  160. return authread(c, cbuf, count);
  161. case Qauthent:
  162. return authentread(c, cbuf, count);
  163. case Qcons:
  164. qlock(&kbd.q);
  165. if(waserror()){
  166. qunlock(&kbd.q);
  167. nexterror();
  168. }
  169. if(kbd.raw) {
  170. if(qcanread(lineq))
  171. n = qread(lineq, va, count);
  172. else {
  173. /* read as much as possible */
  174. do{
  175. n = qread(kbdq, cbuf, count);
  176. count -= n;
  177. cbuf += n;
  178. } while(count>0 && qcanread(kbdq));
  179. n = cbuf-(char*)va;
  180. }
  181. } else {
  182. while(!qcanread(lineq)) {
  183. qread(kbdq, &kbd.line[kbd.x], 1);
  184. ch = kbd.line[kbd.x];
  185. if(kbd.raw){
  186. qiwrite(lineq, kbd.line, kbd.x+1);
  187. kbd.x = 0;
  188. continue;
  189. }
  190. eol = 0;
  191. switch(ch) {
  192. case '\b':
  193. if(kbd.x)
  194. kbd.x--;
  195. break;
  196. case 0x15:
  197. kbd.x = 0;
  198. break;
  199. case '\n':
  200. case 0x04:
  201. eol = 1;
  202. default:
  203. kbd.line[kbd.x++] = ch;
  204. break;
  205. }
  206. if(kbd.x == sizeof(kbd.line) || eol){
  207. if(ch == 0x04)
  208. kbd.x--;
  209. qwrite(lineq, kbd.line, kbd.x);
  210. kbd.x = 0;
  211. }
  212. }
  213. n = qread(lineq, va, count);
  214. }
  215. qunlock(&kbd.q);
  216. poperror();
  217. return n;
  218. case Qcpunote:
  219. /*
  220. * We don't need to actually do anything here, on
  221. * the assumption that any drawterm users are going
  222. * to be running a window system (rio) that will
  223. * take care of interrupts for us. The notes are
  224. * only necessary for cpu windows, not cpu window systems.
  225. */
  226. qlock(&locked);
  227. return 0;
  228. case Qhostowner:
  229. return readstr(offset, va, count, eve);
  230. case Qkey:
  231. return keyread(va, count, offset);
  232. case Qnull:
  233. return 0;
  234. case Qsysname:
  235. return readstr(offset, va, count, sysname);
  236. case Quser:
  237. return readstr(offset, va, count, up->user);
  238. case Qsnarf:
  239. if(offset == 0) {
  240. free(c->u.aux);
  241. c->u.aux = clipread();
  242. }
  243. if(c->u.aux == nil)
  244. return 0;
  245. return readstr(offset, va, count, c->u.aux);
  246. }
  247. }
  248. long
  249. conwrite(Chan *c, void *va, long count, ulong offset)
  250. {
  251. char buf[32];
  252. char *a = va;
  253. if(c->qid.path & CHDIR)
  254. error(Eperm);
  255. switch(c->qid.path) {
  256. default:
  257. error(Egreg);
  258. case Qauth:
  259. return authwrite(c, a, count);
  260. case Qauthcheck:
  261. return authcheck(c, a, count);
  262. case Qauthent:
  263. return authentwrite(c, a, count);
  264. case Qcons:
  265. if(screenputs){
  266. screenputs(a, count);
  267. return count;
  268. }else
  269. return write(1, va, count);
  270. case Qconsctl:
  271. if(count >= sizeof(buf))
  272. count = sizeof(buf)-1;
  273. strncpy(buf, va, count);
  274. buf[count] = 0;
  275. if(strncmp(buf, "rawon", 5) == 0) {
  276. kbd.raw = 1;
  277. return count;
  278. }
  279. else
  280. if(strncmp(buf, "rawoff", 6) == 0) {
  281. kbd.raw = 0;
  282. return count;
  283. }
  284. error(Ebadctl);
  285. case Qhostowner:
  286. return hostownerwrite(a, count);
  287. case Qkey:
  288. return keywrite(a, count);
  289. case Qnull:
  290. return count;
  291. case Qsnarf:
  292. if(offset+count >= SnarfSize)
  293. error(Etoobig);
  294. snarftab->qid.vers++;
  295. memmove((uchar*)(c->u.aux)+offset, va, count);
  296. return count;
  297. }
  298. }
  299. int
  300. nrand(int n)
  301. {
  302. static ulong randn = 0;
  303. /* ticks() always starts at 0, so we need another seed */
  304. if (randn == 0)
  305. randn = time(0);
  306. randn = randn*1103515245 + 12345 + ticks();
  307. return (randn>>16) % n;
  308. }
  309. static void
  310. echo(Rune r, char *buf, int n)
  311. {
  312. static int ctrlt;
  313. /*
  314. * ^t hack BUG
  315. */
  316. if(ctrlt == 2){
  317. ctrlt = 0;
  318. switch(r){
  319. case 0x14:
  320. break; /* pass it on */
  321. case 'r':
  322. exits(0);
  323. break;
  324. }
  325. }
  326. else if(r == 0x14){
  327. ctrlt++;
  328. return;
  329. }
  330. ctrlt = 0;
  331. if(kbd.raw)
  332. return;
  333. /*
  334. * finally, the actual echoing
  335. */
  336. if(r == 0x15){
  337. buf = "^U\n";
  338. n = 3;
  339. }
  340. screenputs(buf, n);
  341. }
  342. /*
  343. * Put character, possibly a rune, into read queue at interrupt time.
  344. * Called at interrupt time to process a character.
  345. */
  346. static
  347. void
  348. _kbdputc(int c)
  349. {
  350. Rune r;
  351. char buf[UTFmax];
  352. int n;
  353. r = c;
  354. n = runetochar(buf, &r);
  355. if(n == 0)
  356. return;
  357. echo(r, buf, n);
  358. kbd.c = r;
  359. qproduce(kbdq, buf, n);
  360. }
  361. /* _kbdputc, but with compose translation */
  362. void
  363. kbdputc(int c)
  364. {
  365. int i;
  366. static int collecting, nk;
  367. static Rune kc[5];
  368. if(c == Kalt){
  369. collecting = 1;
  370. nk = 0;
  371. return;
  372. }
  373. if(!collecting){
  374. _kbdputc(c);
  375. return;
  376. }
  377. kc[nk++] = c;
  378. c = latin1(kc, nk);
  379. if(c < -1) /* need more keystrokes */
  380. return;
  381. if(c != -1) /* valid sequence */
  382. _kbdputc(c);
  383. else
  384. for(i=0; i<nk; i++)
  385. _kbdputc(kc[i]);
  386. nk = 0;
  387. collecting = 0;
  388. }