wind.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. #define MOVEIT if(0)
  18. enum
  19. {
  20. HiWater = 640000, /* max size of history */
  21. LoWater = 400000, /* min size of history after max'ed */
  22. MinWater = 20000, /* room to leave available when reallocating */
  23. };
  24. //static int topped;
  25. static int id;
  26. Window*
  27. wmk(Mousectl *mc, Channel *ck, Channel *cctl)
  28. {
  29. print_func_entry();
  30. Window *w;
  31. w = emalloc(sizeof(Window));
  32. // NO. w->mc = nil; // *mc;
  33. w->ck = ck;
  34. w->cctl = cctl;
  35. w->conswrite = chancreate(sizeof(Conswritemesg), 0);
  36. w->consread = chancreate(sizeof(Consreadmesg), 0);
  37. w->mouseread = chancreate(sizeof(Mousereadmesg), 0);
  38. w->wctlread = chancreate(sizeof(Consreadmesg), 0);
  39. w->id = ++id;
  40. w->notefd = -1;
  41. w->dir = estrdup(startdir);
  42. w->label = estrdup("<unnamed>");
  43. incref(w); /* ref will be removed after mounting; avoids delete before ready to be deleted */
  44. print_func_exit();
  45. return w;
  46. }
  47. void
  48. wsetname(Window *w)
  49. {
  50. print_func_entry();
  51. int i, n;
  52. char err[ERRMAX];
  53. n = sprint(w->name, "window.%d.%d", w->id, w->namecount++);
  54. for(i='A'; i<='Z'; i++){
  55. // if(nameimage(w->i, w->name, 1) > 0)
  56. // return;
  57. errstr(err, sizeof err);
  58. if(strcmp(err, "image name in use") != 0)
  59. break;
  60. w->name[n] = i;
  61. w->name[n+1] = 0;
  62. }
  63. w->name[0] = 0;
  64. fprint(2, "rio: setname failed: %s\n", err);
  65. print_func_exit();
  66. }
  67. int
  68. wclose(Window *w)
  69. {
  70. print_func_entry();
  71. int i;
  72. i = decref(w);
  73. if(i > 0) {
  74. print_func_exit();
  75. return 0;
  76. }
  77. if(i < 0)
  78. error("negative ref count");
  79. if(!w->deleted)
  80. wclosewin(w);
  81. wsendctlmesg(w, Exited, nil);
  82. print_func_exit();
  83. return 1;
  84. }
  85. void
  86. winctl(void *arg)
  87. {
  88. print_func_entry();
  89. Rune *rp, *bp, *kbdr;
  90. int nr, nb, c, wid, i, npart, lastb;
  91. char *s, *t, part[3];
  92. Window *w;
  93. Mousestate *mp, m;
  94. enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT };
  95. Alt alts[NWALT+1];
  96. int walt;
  97. Mousereadmesg mrm;
  98. Conswritemesg cwm;
  99. Consreadmesg crm;
  100. Consreadmesg cwrm;
  101. Stringpair pair;
  102. Wctlmesg wcm;
  103. char buf[4*12+1];
  104. w = arg;
  105. snprint(buf, sizeof buf, "winctl-id%d", w->id);
  106. threadsetname(buf);
  107. mrm.cm = chancreate(sizeof(Mouse), 0);
  108. cwm.cw = chancreate(sizeof(Stringpair), 0);
  109. crm.c1 = chancreate(sizeof(Stringpair), 0);
  110. crm.c2 = chancreate(sizeof(Stringpair), 0);
  111. cwrm.c1 = chancreate(sizeof(Stringpair), 0);
  112. cwrm.c2 = chancreate(sizeof(Stringpair), 0);
  113. alts[WKey].c = w->ck;
  114. alts[WKey].v = &kbdr;
  115. alts[WKey].op = CHANRCV;
  116. alts[WMouse].c = w->mc.c;
  117. alts[WMouse].v = &w->mc.Mouse;
  118. alts[WMouse].op = CHANNOP; // XXXCHANRCV;
  119. alts[WMouseread].c = w->mouseread;
  120. alts[WMouseread].v = &mrm;
  121. alts[WMouseread].op = CHANNOP; // XXXCHANSND;
  122. alts[WCtl].c = w->cctl;
  123. alts[WCtl].v = &wcm;
  124. alts[WCtl].op = CHANRCV;
  125. alts[WCwrite].c = w->conswrite;
  126. alts[WCwrite].v = &cwm;
  127. alts[WCwrite].op = CHANSND;
  128. alts[WCread].c = w->consread;
  129. alts[WCread].v = &crm;
  130. alts[WCread].op = CHANSND;
  131. alts[WWread].c = w->wctlread;
  132. alts[WWread].v = &cwrm;
  133. alts[WWread].op = CHANSND;
  134. alts[NWALT].op = CHANEND;
  135. npart = 0;
  136. lastb = -1;
  137. for(;;){
  138. // TODO: mouses
  139. if(0 && w->mouseopen && w->mouse.counter != w->mouse.lastcounter)
  140. alts[WMouseread].op = CHANSND;
  141. else
  142. alts[WMouseread].op = CHANNOP;
  143. if(w->deleted || !w->wctlready)
  144. alts[WWread].op = CHANNOP;
  145. else
  146. alts[WWread].op = CHANSND;
  147. /* this code depends on NL and EOT fitting in a single byte */
  148. /* kind of expensive for each loop; worth precomputing? */
  149. /*if(w->holding)
  150. alts[WCread].op = CHANNOP;
  151. else*/ if(npart || (w->rawing && w->nraw>0))
  152. alts[WCread].op = CHANSND;
  153. else
  154. {
  155. alts[WCread].op = CHANNOP;
  156. for(i=w->qh; i<w->nr; i++){
  157. c = w->run[i];
  158. if(c=='\n' || c=='\004'){
  159. alts[WCread].op = CHANSND;
  160. break;
  161. }
  162. }
  163. }
  164. walt = alt(alts);
  165. switch(walt){
  166. case WKey:
  167. for(i=0; kbdr[i]!=L'\0'; i++)
  168. wkeyctl(w, kbdr[i]);
  169. //wkeyctl(w, r);
  170. /// while(nbrecv(w->ck, &r))
  171. //wkeyctl(w, r);
  172. break;
  173. case WMouse:
  174. if(w->mouseopen) {
  175. w->mouse.counter++;
  176. /* queue click events */
  177. if(!w->mouse.qfull && lastb != w->mc.buttons) { /* add to ring */
  178. mp = &w->mouse.queue[w->mouse.wi];
  179. if(++w->mouse.wi == nelem(w->mouse.queue))
  180. w->mouse.wi = 0;
  181. if(w->mouse.wi == w->mouse.ri)
  182. w->mouse.qfull = TRUE;
  183. mp->Mouse = w->mc.Mouse;
  184. mp->counter = w->mouse.counter;
  185. lastb = w->mc.buttons;
  186. }
  187. } else
  188. fprint(2, "MOUSECTL\n"); //wmousectl(w);
  189. break;
  190. case WMouseread:
  191. /* send a queued event or, if the queue is empty, the current state */
  192. /* if the queue has filled, we discard all the events it contained. */
  193. /* the intent is to discard frantic clicking by the user during long latencies. */
  194. w->mouse.qfull = FALSE;
  195. if(w->mouse.wi != w->mouse.ri) {
  196. m = w->mouse.queue[w->mouse.ri];
  197. if(++w->mouse.ri == nelem(w->mouse.queue))
  198. w->mouse.ri = 0;
  199. } else
  200. m = (Mousestate){w->mc.Mouse, w->mouse.counter};
  201. w->mouse.lastcounter = m.counter;
  202. send(mrm.cm, &m.Mouse);
  203. continue;
  204. case WCtl:
  205. exits("WCtl can't do");
  206. #if 0
  207. if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){
  208. chanfree(crm.c1);
  209. chanfree(crm.c2);
  210. chanfree(mrm.cm);
  211. chanfree(cwm.cw);
  212. chanfree(cwrm.c1);
  213. chanfree(cwrm.c2);
  214. threadexits(nil);
  215. }
  216. #endif
  217. continue;
  218. case WCwrite:
  219. recv(cwm.cw, &pair);
  220. rp = pair.s;
  221. nr = pair.ns;
  222. bp = rp;
  223. for(i=0; i<nr; i++) {
  224. // See rio for the run conversion crap. For now, I'm not going to
  225. // worry about it. This is designed to target Akaros too.
  226. fprint(/*w->Console->out*/1, "%c", *bp++);
  227. }
  228. free(rp);
  229. break;
  230. case WCread:
  231. recv(crm.c1, &pair);
  232. t = pair.s;
  233. nb = pair.ns;
  234. i = npart;
  235. npart = 0;
  236. if(i)
  237. memmove(t, part, i);
  238. while(i<nb && (w->qh<w->nr || w->nraw>0)){
  239. if(w->qh == w->nr){
  240. wid = runetochar(t+i, &w->raw[0]);
  241. w->nraw--;
  242. runemove(w->raw, w->raw+1, w->nraw);
  243. }else
  244. wid = runetochar(t+i, &w->run[w->qh++]);
  245. c = t[i]; /* knows break characters fit in a byte */
  246. i += wid;
  247. if(!w->rawing && (c == '\n' || c=='\004')){
  248. if(c == '\004')
  249. i--;
  250. break;
  251. }
  252. }
  253. if(i==nb && w->qh<w->nr && w->run[w->qh]=='\004')
  254. w->qh++;
  255. if(i > nb){
  256. npart = i-nb;
  257. memmove(part, t+nb, npart);
  258. i = nb;
  259. }
  260. pair.s = t;
  261. pair.ns = i;
  262. send(crm.c2, &pair);
  263. continue;
  264. case WWread:
  265. w->wctlready = 0;
  266. recv(cwrm.c1, &pair);
  267. if(w->deleted)
  268. pair.ns = sprint(pair.s, "");
  269. else{
  270. s = "visible";
  271. for(i=0; i<nhidden; i++)
  272. if(hidden[i] == w){
  273. s = "hidden";
  274. break;
  275. }
  276. t = "notcurrent";
  277. if(w == input)
  278. t = "current";
  279. pair.ns = snprint(pair.s, pair.ns, "%s %s ",t, s);
  280. }
  281. send(cwrm.c2, &pair);
  282. continue;
  283. }
  284. }
  285. print_func_exit();
  286. }
  287. uint
  288. winsert(Window *w, Rune *r, int n, uint q0)
  289. {
  290. uint m;
  291. if(n == 0)
  292. return q0;
  293. if(w->nr+n>HiWater && q0>=w->org && q0>=w->qh){
  294. m = min(HiWater-LoWater, min(w->org, w->qh));
  295. w->org -= m;
  296. w->qh -= m;
  297. if(w->q0 > m)
  298. w->q0 -= m;
  299. else
  300. w->q0 = 0;
  301. if(w->q1 > m)
  302. w->q1 -= m;
  303. else
  304. w->q1 = 0;
  305. w->nr -= m;
  306. runemove(w->run, w->run+m, w->nr);
  307. q0 -= m;
  308. }
  309. if(w->nr+n > w->maxr){
  310. /*
  311. * Minimize realloc breakage:
  312. * Allocate at least MinWater
  313. * Double allocation size each time
  314. * But don't go much above HiWater
  315. */
  316. m = max(min(2*(w->nr+n), HiWater), w->nr+n)+MinWater;
  317. if(m > HiWater)
  318. m = max(HiWater+MinWater, w->nr+n);
  319. if(m > w->maxr){
  320. w->run = runerealloc(w->run, m);
  321. w->maxr = m;
  322. }
  323. }
  324. runemove(w->run+q0+n, w->run+q0, w->nr-q0);
  325. runemove(w->run+q0, r, n);
  326. w->nr += n;
  327. /* if output touches, advance selection, not qh; works best for keyboard and output */
  328. // TODO don't know if we might want this for displaying text.
  329. if(q0 <= w->q1)
  330. w->q1 += n;
  331. if(q0 <= w->q0)
  332. w->q0 += n;
  333. if(q0 < w->qh)
  334. w->qh += n;
  335. if(q0 < w->org)
  336. w->org += n;
  337. return q0;
  338. }
  339. void
  340. wkeyctl(Window *w, Rune r)
  341. {
  342. uint q0;
  343. if(r == 0)
  344. return;
  345. if(w->deleted)
  346. return;
  347. fprint(2, "wkyctl: skipping all ctl chars\n");
  348. #if 0
  349. uint q0 ,q1;
  350. int n, nb, nr;
  351. Rune *rp;
  352. int *notefd;
  353. /* navigation keys work only when mouse is not open */
  354. if(!w->mouseopen)
  355. switch(r){
  356. case Kdown:
  357. n = w->maxlines/3;
  358. goto case_Down;
  359. case Kscrollonedown:
  360. n = mousescrollsize(w->maxlines);
  361. if(n <= 0)
  362. n = 1;
  363. goto case_Down;
  364. case Kpgdown:
  365. n = 2*w->maxlines/3;
  366. case_Down:
  367. q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+n*w->font->height));
  368. wsetorigin(w, q0, TRUE);
  369. return;
  370. case Kup:
  371. n = w->maxlines/3;
  372. goto case_Up;
  373. case Kscrolloneup:
  374. n = mousescrollsize(w->maxlines);
  375. if(n <= 0)
  376. n = 1;
  377. goto case_Up;
  378. case Kpgup:
  379. n = 2*w->maxlines/3;
  380. case_Up:
  381. q0 = wbacknl(w, w->org, n);
  382. wsetorigin(w, q0, TRUE);
  383. return;
  384. case Kleft:
  385. if(w->q0 > 0){
  386. q0 = w->q0-1;
  387. wsetselect(w, q0, q0);
  388. wshow(w, q0);
  389. }
  390. return;
  391. case Kright:
  392. if(w->q1 < w->nr){
  393. q1 = w->q1+1;
  394. wsetselect(w, q1, q1);
  395. wshow(w, q1);
  396. }
  397. return;
  398. case Khome:
  399. wshow(w, 0);
  400. return;
  401. case Kend:
  402. wshow(w, w->nr);
  403. return;
  404. case 0x01: /* ^A: beginning of line */
  405. if(w->q0==0 || w->q0==w->qh || w->run[w->q0-1]=='\n')
  406. return;
  407. nb = wbswidth(w, 0x15 /* ^U */);
  408. wsetselect(w, w->q0-nb, w->q0-nb);
  409. wshow(w, w->q0);
  410. return;
  411. case 0x05: /* ^E: end of line */
  412. q0 = w->q0;
  413. while(q0 < w->nr && w->run[q0]!='\n')
  414. q0++;
  415. wsetselect(w, q0, q0);
  416. wshow(w, w->q0);
  417. return;
  418. }
  419. if(w->rawing && (w->q0==w->nr || w->mouseopen)){
  420. waddraw(w, &r, 1);
  421. return;
  422. }
  423. if(r==0x1B || (w->holding && r==0x7F)){ /* toggle hold */
  424. if(w->holding)
  425. --w->holding;
  426. else
  427. w->holding++;
  428. wrepaint(w);
  429. if(r == 0x1B)
  430. return;
  431. }
  432. if(r != 0x7F){
  433. wsnarf(w);
  434. wcut(w);
  435. }
  436. switch(r){
  437. case 0x7F: /* send interrupt */
  438. w->qh = w->nr;
  439. wshow(w, w->qh);
  440. notefd = emalloc(sizeof(int));
  441. *notefd = w->notefd;
  442. proccreate(interruptproc, notefd, 4096);
  443. return;
  444. case 0x06: /* ^F: file name completion */
  445. case Kins: /* Insert: file name completion */
  446. rp = namecomplete(w);
  447. if(rp == nil)
  448. return;
  449. nr = runestrlen(rp);
  450. q0 = w->q0;
  451. q0 = winsert(w, rp, nr, q0);
  452. wshow(w, q0+nr);
  453. free(rp);
  454. return;
  455. case 0x08: /* ^H: erase character */
  456. case 0x15: /* ^U: erase line */
  457. case 0x17: /* ^W: erase word */
  458. if(w->q0==0 || w->q0==w->qh)
  459. return;
  460. nb = wbswidth(w, r);
  461. q1 = w->q0;
  462. q0 = q1-nb;
  463. if(q0 < w->org){
  464. q0 = w->org;
  465. nb = q1-q0;
  466. }
  467. if(nb > 0){
  468. wdelete(w, q0, q0+nb);
  469. wsetselect(w, q0, q0);
  470. }
  471. return;
  472. }
  473. wshow(w, q0+1);
  474. #endif
  475. /* otherwise ordinary character; just insert */
  476. q0 = w->q0;
  477. q0 = winsert(w, &r, 1, q0);
  478. }
  479. void
  480. waddraw(Window *w, Rune *r, int nr)
  481. {
  482. print_func_entry();
  483. w->raw = runerealloc(w->raw, w->nraw+nr);
  484. runemove(w->raw+w->nraw, r, nr);
  485. w->nraw += nr;
  486. print_func_exit();
  487. }
  488. /*
  489. * Need to do this in a separate proc because if process we're interrupting
  490. * is dying and trying to print tombstone, kernel is blocked holding p->debug lock.
  491. */
  492. void
  493. interruptproc(void *v)
  494. {
  495. print_func_entry();
  496. int *notefd;
  497. notefd = v;
  498. write(*notefd, "interrupt", 9);
  499. free(notefd);
  500. print_func_exit();
  501. }
  502. //static Window *clickwin;
  503. //static uint clickmsec;
  504. //static Window *selectwin;
  505. //static uint selectq;
  506. void
  507. wsendctlmesg(Window *w, int type, Console *image)
  508. {
  509. print_func_entry();
  510. Wctlmesg wcm;
  511. wcm.type = type;
  512. send(w->cctl, &wcm);
  513. print_func_exit();
  514. }
  515. int
  516. wctlmesg(Window *w, int m, Console *i)
  517. {
  518. print_func_entry();
  519. switch(m){
  520. default:
  521. error("unknown control message");
  522. break;
  523. case Wakeup:
  524. break;
  525. case Rawon:
  526. break;
  527. case Rawoff:
  528. if(w->deleted)
  529. break;
  530. while(w->nraw > 0){
  531. //wkeyctl(w, w->raw[0]);
  532. --w->nraw;
  533. runemove(w->raw, w->raw+1, w->nraw);
  534. }
  535. break;
  536. case Holdon:
  537. case Holdoff:
  538. if(w->deleted)
  539. break;
  540. break;
  541. case Deleted:
  542. if(w->deleted)
  543. break;
  544. write(w->notefd, "hangup", 6);
  545. proccreate(deletetimeoutproc, estrdup(w->name), 4096);
  546. wclosewin(w);
  547. break;
  548. case Exited:
  549. close(w->notefd);
  550. chanfree(w->mc.c);
  551. chanfree(w->ck);
  552. chanfree(w->cctl);
  553. chanfree(w->conswrite);
  554. chanfree(w->consread);
  555. chanfree(w->mouseread);
  556. chanfree(w->wctlread);
  557. free(w->raw);
  558. free(w->run);
  559. free(w->dir);
  560. free(w->label);
  561. free(w);
  562. break;
  563. }
  564. print_func_exit();
  565. return m;
  566. }
  567. void
  568. wcurrent(Window *w)
  569. {
  570. print_func_entry();
  571. if (0) {
  572. Window *oi;
  573. if(wkeyboard!=nil && w==wkeyboard) {
  574. print_func_exit();
  575. return;
  576. }
  577. oi = input;
  578. input = w;
  579. if(w != oi){
  580. if(oi){
  581. oi->wctlready = 1;
  582. wsendctlmesg(oi, Wakeup, nil);
  583. }
  584. if(w){
  585. w->wctlready = 1;
  586. wsendctlmesg(w, Wakeup, nil);
  587. }
  588. }
  589. }
  590. input = w;
  591. print_func_exit();
  592. }
  593. Window*
  594. wtop(void)
  595. {
  596. print_func_entry();
  597. exits("wtop!");
  598. #if 0
  599. Window *w;
  600. w = wpointto(pt);
  601. if(w){
  602. if(w->topped == topped)
  603. return nil;
  604. topwindow(w->i);
  605. wcurrent(w);
  606. w->topped = ++topped;
  607. }
  608. #endif
  609. print_func_exit();
  610. return nil;
  611. }
  612. Window*
  613. wlookid(int id)
  614. {
  615. print_func_entry();
  616. int i;
  617. fprint(2, "%d:", id);
  618. for(i=0; i<nwindow; i++)
  619. if(window[i]->id == id) {
  620. fprint(2, "FOUND @%p", window[i]);
  621. print_func_exit();
  622. return window[i];
  623. }
  624. fprint(2, "NOT FOUND;");
  625. print_func_exit();
  626. return nil;
  627. }
  628. void
  629. wclosewin(Window *w)
  630. {
  631. print_func_entry();
  632. int i;
  633. w->deleted = TRUE;
  634. if(w == input){
  635. input = nil;
  636. }
  637. if(w == wkeyboard)
  638. wkeyboard = nil;
  639. for(i=0; i<nhidden; i++)
  640. if(hidden[i] == w){
  641. --nhidden;
  642. memmove(hidden+i, hidden+i+1, (nhidden-i)*sizeof(hidden[0]));
  643. hidden[nhidden] = nil;
  644. break;
  645. }
  646. for(i=0; i<nwindow; i++)
  647. if(window[i] == w){
  648. --nwindow;
  649. memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*));
  650. w->deleted = TRUE;
  651. print_func_exit();
  652. return;
  653. }
  654. error("unknown window in closewin");
  655. print_func_exit();
  656. }
  657. void
  658. wsetpid(Window *w, int pid, int dolabel)
  659. {
  660. print_func_entry();
  661. char buf[128];
  662. int fd;
  663. w->pid = pid;
  664. if(dolabel){
  665. sprint(buf, "rc %d", pid);
  666. free(w->label);
  667. w->label = estrdup(buf);
  668. }
  669. sprint(buf, "/proc/%d/notepg", pid);
  670. fd = open(buf, OWRITE|OCEXEC);
  671. if(w->notefd > 0)
  672. close(w->notefd);
  673. w->notefd = fd;
  674. print_func_exit();
  675. }
  676. void
  677. winshell(void *args)
  678. {
  679. print_func_entry();
  680. Window *w;
  681. Channel *pidc;
  682. void **arg;
  683. char *cmd, *dir;
  684. char **argv;
  685. arg = args;
  686. w = arg[0];
  687. pidc = arg[1];
  688. cmd = arg[2];
  689. argv = arg[3];
  690. dir = arg[4];
  691. rfork(RFNAMEG|RFFDG|RFENVG);
  692. if(filsysmount(filsys, w->id) < 0){
  693. fprint(2, "mount failed: %r\n");
  694. sendul(pidc, 0);
  695. threadexits("mount failed");
  696. }
  697. close(0);
  698. if(open("/dev/cons", OREAD) < 0){
  699. fprint(2, "can't open /dev/cons: %r\n");
  700. sendul(pidc, 0);
  701. threadexits("/dev/cons");
  702. }
  703. close(1);
  704. if(open("/dev/cons", OWRITE) < 0){
  705. fprint(2, "can't open /dev/cons: %r\n");
  706. sendul(pidc, 0);
  707. threadexits("open"); /* BUG? was terminate() */
  708. }
  709. if(wclose(w) == 0){ /* remove extra ref hanging from creation */
  710. notify(nil);
  711. dup(1, 2);
  712. if(dir)
  713. chdir(dir);
  714. procexec(pidc, cmd, argv);
  715. _exits("exec failed");
  716. }
  717. print_func_exit();
  718. }
  719. int
  720. winfmt(Fmt *f)
  721. {
  722. Window *w;
  723. w = va_arg(f->args, Window*);
  724. if (w < (void *)4096)
  725. return fmtprint(f, "BOGUS w!: %p", w);
  726. return fmtprint(f, "%p: %s", w, w->label);
  727. }