cmux.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <thread.h>
  12. #include <keyboard.h>
  13. #include <fcall.h>
  14. #include <plumb.h>
  15. #include "dat.h"
  16. #include "fns.h"
  17. /*
  18. * WASHINGTON (AP) - The Food and Drug Administration warned
  19. * consumers Wednesday not to use ``Rio'' hair relaxer products
  20. * because they may cause severe hair loss or turn hair green....
  21. * The FDA urged consumers who have experienced problems with Rio
  22. * to notify their local FDA office, local health department or the
  23. * company at 1‑800‑543‑3002.
  24. */
  25. void resize(void);
  26. void move(void);
  27. void delete(void);
  28. void hide(void);
  29. void unhide(int);
  30. void newtile(int);
  31. void resized(void);
  32. Channel *exitchan; /* chan(int) */
  33. Channel *winclosechan; /* chan(Window*); */
  34. int threadrforkflag = 0; /* should be RFENVG but that hides rio from plumber */
  35. void mousethread(void*);
  36. void keyboardthread(void*);
  37. void winclosethread(void*);
  38. void deletethread(void*);
  39. void initcmd(void*);
  40. char *fontname;
  41. int mainpid;
  42. enum
  43. {
  44. New,
  45. Reshape,
  46. Move,
  47. Delete,
  48. Hide,
  49. Exit,
  50. };
  51. enum
  52. {
  53. Cut,
  54. Paste,
  55. Snarf,
  56. Plumb,
  57. Send,
  58. Scroll,
  59. };
  60. int Hidden = Exit+1;
  61. char *rcargv[] = { "rc", "-i", nil };
  62. char *kbdargv[] = { "rc", "-c", nil, nil };
  63. int errorshouldabort = 0;
  64. Console HardwareConsole = {
  65. .in = 0,
  66. .out = 1,
  67. };
  68. void
  69. usage(void)
  70. {
  71. print_func_entry();
  72. fprint(2, "usage: cmux [-k kbdcmd]\n");
  73. exits("usage");
  74. print_func_exit();
  75. }
  76. void
  77. threadmain(int argc, char *argv[])
  78. {
  79. char *kbdin, *s;
  80. char buf[256];
  81. kbdin = nil;
  82. maxtab = 0;
  83. ARGBEGIN{
  84. case 'k':
  85. if(kbdin != nil)
  86. usage();
  87. kbdin = ARGF();
  88. if(kbdin == nil)
  89. usage();
  90. break;
  91. break;
  92. }ARGEND;
  93. fmtinstall('W', winfmt);
  94. fmtinstall('f', fidfmt);
  95. mainpid = getpid();
  96. if(getwd(buf, sizeof buf) == nil)
  97. startdir = estrdup(".");
  98. else
  99. startdir = estrdup(buf);
  100. s = getenv("tabstop");
  101. if(s != nil)
  102. maxtab = strtol(s, nil, 0);
  103. if(maxtab == 0)
  104. maxtab = 4;
  105. free(s);
  106. if (0) {
  107. snarffd = open("/dev/snarf", OREAD|OCEXEC);
  108. } else {
  109. snarffd = -1;
  110. }
  111. if (0) {
  112. // mousectl = initmouse(nil, screen);
  113. if(mousectl == nil)
  114. error("can't find mouse");
  115. mouse = mousectl;
  116. }
  117. keyboardctl = initkeyboard(nil);
  118. if(keyboardctl == nil)
  119. error("can't find keyboard");
  120. exitchan = chancreate(sizeof(int), 0);
  121. winclosechan = chancreate(sizeof(Window*), 0);
  122. deletechan = chancreate(sizeof(char*), 0);
  123. timerinit();
  124. threadcreate(keyboardthread, nil, STACK);
  125. //threadcreate(mousethread, nil, STACK);
  126. filsys = filsysinit(xfidinit());
  127. if(filsys == nil)
  128. fprint(2, "cmux: can't create file system server: %r\n");
  129. else{
  130. errorshouldabort = 1; /* suicide if there's trouble after this */
  131. #if 0
  132. // proccreate(initcmd, nil, STACK);
  133. if(kbdin){
  134. kbdargv[2] = kbdin;
  135. //i = allocwindow(wscreen, r, Refbackup, DWhite);
  136. //wkeyboard = new(i, FALSE, scrolling, 0, nil, "/bin/rc", kbdargv);
  137. if(wkeyboard == nil)
  138. error("can't create keyboard window");
  139. }
  140. #endif
  141. wkeyboard = new(&HardwareConsole, 0, nil, "/bin/rc", nil);
  142. if(wkeyboard == nil)
  143. error("can't create session leader console");
  144. wcurrent(wkeyboard);
  145. threadnotify(shutdown, 1);
  146. recv(exitchan, nil);
  147. }
  148. killprocs();
  149. threadexitsall(nil);
  150. }
  151. /*
  152. * /dev/snarf updates when the file is closed, so we must open our own
  153. * fd here rather than use snarffd
  154. */
  155. void
  156. putsnarf(void)
  157. {
  158. print_func_entry();
  159. int fd, i, n;
  160. if(snarffd<0 || nsnarf==0) {
  161. print_func_exit();
  162. return;
  163. }
  164. fd = open("/dev/snarf", OWRITE);
  165. if(fd < 0) {
  166. print_func_exit();
  167. return;
  168. }
  169. /* snarf buffer could be huge, so fprint will truncate; do it in blocks */
  170. for(i=0; i<nsnarf; i+=n){
  171. n = nsnarf-i;
  172. if(n >= 256)
  173. n = 256;
  174. if(fprint(fd, "%.*S", n, snarf+i) < 0)
  175. break;
  176. }
  177. close(fd);
  178. print_func_exit();
  179. }
  180. void
  181. getsnarf(void)
  182. {
  183. print_func_entry();
  184. int i, n, nb, nulls;
  185. char *sn, buf[1024];
  186. if(snarffd < 0) {
  187. print_func_exit();
  188. return;
  189. }
  190. sn = nil;
  191. i = 0;
  192. seek(snarffd, 0, 0);
  193. while((n = read(snarffd, buf, sizeof buf)) > 0){
  194. sn = erealloc(sn, i+n+1);
  195. memmove(sn+i, buf, n);
  196. i += n;
  197. sn[i] = 0;
  198. }
  199. if(i > 0){
  200. snarf = runerealloc(snarf, i+1);
  201. cvttorunes(sn, i, snarf, &nb, &nsnarf, &nulls);
  202. free(sn);
  203. }
  204. print_func_exit();
  205. }
  206. void
  207. initcmd(void *arg)
  208. {
  209. print_func_entry();
  210. rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG);
  211. procexecl(nil, "/bin/rc", "rc", "-i", nil);
  212. fprint(2, "cmux: exec failed: %r\n");
  213. exits("exec");
  214. print_func_exit();
  215. }
  216. char *oknotes[] =
  217. {
  218. "delete",
  219. "hangup",
  220. "kill",
  221. "exit",
  222. nil
  223. };
  224. int
  225. shutdown(void * vacio, char *msg)
  226. {
  227. print_func_entry();
  228. int i;
  229. static Lock shutdownlk;
  230. killprocs();
  231. for(i=0; oknotes[i]; i++)
  232. if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0){
  233. lock(&shutdownlk); /* only one can threadexitsall */
  234. threadexitsall(msg);
  235. }
  236. fprint(2, "cmux %d: abort: %s\n", getpid(), msg);
  237. abort();
  238. exits(msg);
  239. print_func_exit();
  240. return 0;
  241. }
  242. void
  243. killprocs(void)
  244. {
  245. print_func_entry();
  246. int i;
  247. for(i=0; i<nwindow; i++)
  248. postnote(PNGROUP, window[i]->pid, "hangup");
  249. print_func_exit();
  250. }
  251. void
  252. keyboardthread(void* v)
  253. {
  254. print_func_entry();
  255. Rune buf[2][20], *rp;
  256. int n, i;
  257. threadsetname("keyboardthread");
  258. n = 0;
  259. for(;;){
  260. rp = buf[n];
  261. n = 1-n;
  262. recv(keyboardctl->c, rp);
  263. for(i=1; i<nelem(buf[0])-1; i++)
  264. if(nbrecv(keyboardctl->c, rp+i) <= 0)
  265. break;
  266. rp[i] = L'\0';
  267. if(input != nil)
  268. sendp(input->ck, rp);
  269. }
  270. print_func_exit();
  271. }
  272. /*
  273. * Used by /dev/kbdin
  274. */
  275. void
  276. keyboardsend(char *s, int cnt)
  277. {
  278. print_func_entry();
  279. Rune *r;
  280. int i, nb, nr;
  281. r = runemalloc(cnt);
  282. /* BUGlet: partial runes will be converted to error runes */
  283. cvttorunes(s, cnt, r, &nb, &nr, nil);
  284. for(i=0; i<nr; i++)
  285. send(keyboardctl->c, &r[i]);
  286. free(r);
  287. print_func_exit();
  288. }
  289. int
  290. portion(int x, int lo, int hi)
  291. {
  292. print_func_entry();
  293. x -= lo;
  294. hi -= lo;
  295. if(x < 20) {
  296. print_func_exit();
  297. return 0;
  298. }
  299. if(x > hi-20) {
  300. print_func_exit();
  301. return 2;
  302. }
  303. print_func_exit();
  304. return 1;
  305. }
  306. /* thread to allow fsysproc to synchronize window closing with main proc */
  307. void
  308. winclosethread(void* v)
  309. {
  310. print_func_entry();
  311. Window *w;
  312. threadsetname("winclosethread");
  313. for(;;){
  314. w = recvp(winclosechan);
  315. wclose(w);
  316. }
  317. print_func_exit();
  318. }
  319. /* thread to make Deleted windows that the client still holds disappear offscreen after an interval */
  320. void
  321. deletethread(void* v)
  322. {
  323. print_func_entry();
  324. char *s;
  325. threadsetname("deletethread");
  326. for(;;){
  327. s = recvp(deletechan);
  328. // i = namedimage(display, s);
  329. // freeimage(i);
  330. free(s);
  331. }
  332. print_func_exit();
  333. }
  334. void
  335. deletetimeoutproc(void *v)
  336. {
  337. print_func_entry();
  338. char *s;
  339. s = v;
  340. sleep(750); /* remove window from screen after 3/4 of a second */
  341. sendp(deletechan, s);
  342. print_func_exit();
  343. }
  344. void
  345. delete(void)
  346. {
  347. print_func_entry();
  348. // Window *w;
  349. fprint(2, "can't delete!\n");
  350. // w = nil; //pointto(TRUE);
  351. // if(w)
  352. // wsendctlmesg(w, Deleted, ZR, nil);
  353. print_func_exit();
  354. }
  355. Window*
  356. new(Console *i, int pid, char *dir, char *cmd, char **argv)
  357. {
  358. print_func_entry();
  359. Window *w;
  360. Mousectl *mc = nil; // someday.
  361. Channel *cm, *ck, *cctl, *cpid;
  362. void **arg;
  363. if(i == nil) {
  364. print_func_exit();
  365. return nil;
  366. }
  367. cm = chancreate(sizeof(Mouse), 0);
  368. ck = chancreate(sizeof(Rune*), 0);
  369. cctl = chancreate(sizeof(Wctlmesg), 4);
  370. cpid = chancreate(sizeof(int), 0);
  371. if(cm==nil || ck==nil || cctl==nil)
  372. error("new: channel alloc failed");
  373. mc = emalloc(sizeof(Mousectl));
  374. // NO. *mc = *mousectl;
  375. // NO. mc->c = cm;
  376. w = wmk(mc, ck, cctl);
  377. free(mc); /* wmk copies *mc */
  378. window = erealloc(window, ++nwindow*sizeof(Window*));
  379. window[nwindow-1] = w;
  380. threadcreate(winctl, w, 8192);
  381. if(pid == 0){
  382. arg = emalloc(5*sizeof(void*));
  383. arg[0] = w;
  384. arg[1] = cpid;
  385. arg[2] = cmd;
  386. if(argv == nil)
  387. arg[3] = rcargv;
  388. else
  389. arg[3] = argv;
  390. arg[4] = dir;
  391. proccreate(winshell, arg, 8192);
  392. pid = recvul(cpid);
  393. free(arg);
  394. }
  395. if(pid == 0){
  396. /* window creation failed */
  397. fprint(2, "not killing it\n"); //wsendctlmesg(w, Deleted, ZR, nil);
  398. chanfree(cpid);
  399. print_func_exit();
  400. return nil;
  401. }
  402. wsetpid(w, pid, 1);
  403. wsetname(w);
  404. if(dir)
  405. w->dir = estrdup(dir);
  406. chanfree(cpid);
  407. print_func_exit();
  408. return w;
  409. }