mesg.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  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 "sam.h"
  10. Header h;
  11. uchar indata[DATASIZE];
  12. uchar outdata[2*DATASIZE+3]; /* room for overflow message */
  13. uchar *inp;
  14. uchar *outp;
  15. uchar *outmsg = outdata;
  16. Posn cmdpt;
  17. Posn cmdptadv;
  18. Buffer snarfbuf;
  19. int waitack;
  20. int outbuffered;
  21. int tversion;
  22. int inshort(void);
  23. long inlong(void);
  24. vlong invlong(void);
  25. int inmesg(Tmesg);
  26. void outshort(int);
  27. void outlong(long);
  28. void outvlong(vlong);
  29. void outcopy(int, void*);
  30. void outsend(void);
  31. void outstart(Hmesg);
  32. void setgenstr(File*, Posn, Posn);
  33. #ifdef DEBUG
  34. char *hname[] = {
  35. [Hversion] "Hversion",
  36. [Hbindname] "Hbindname",
  37. [Hcurrent] "Hcurrent",
  38. [Hnewname] "Hnewname",
  39. [Hmovname] "Hmovname",
  40. [Hgrow] "Hgrow",
  41. [Hcheck0] "Hcheck0",
  42. [Hcheck] "Hcheck",
  43. [Hunlock] "Hunlock",
  44. [Hdata] "Hdata",
  45. [Horigin] "Horigin",
  46. [Hunlockfile] "Hunlockfile",
  47. [Hsetdot] "Hsetdot",
  48. [Hgrowdata] "Hgrowdata",
  49. [Hmoveto] "Hmoveto",
  50. [Hclean] "Hclean",
  51. [Hdirty] "Hdirty",
  52. [Hcut] "Hcut",
  53. [Hsetpat] "Hsetpat",
  54. [Hdelname] "Hdelname",
  55. [Hclose] "Hclose",
  56. [Hsetsnarf] "Hsetsnarf",
  57. [Hsnarflen] "Hsnarflen",
  58. [Hack] "Hack",
  59. [Hexit] "Hexit",
  60. [Hplumb] "Hplumb",
  61. };
  62. char *tname[] = {
  63. [Tversion] "Tversion",
  64. [Tstartcmdfile] "Tstartcmdfile",
  65. [Tcheck] "Tcheck",
  66. [Trequest] "Trequest",
  67. [Torigin] "Torigin",
  68. [Tstartfile] "Tstartfile",
  69. [Tworkfile] "Tworkfile",
  70. [Ttype] "Ttype",
  71. [Tcut] "Tcut",
  72. [Tpaste] "Tpaste",
  73. [Tsnarf] "Tsnarf",
  74. [Tstartnewfile] "Tstartnewfile",
  75. [Twrite] "Twrite",
  76. [Tclose] "Tclose",
  77. [Tlook] "Tlook",
  78. [Tsearch] "Tsearch",
  79. [Tsend] "Tsend",
  80. [Tdclick] "Tdclick",
  81. [Tstartsnarf] "Tstartsnarf",
  82. [Tsetsnarf] "Tsetsnarf",
  83. [Tack] "Tack",
  84. [Texit] "Texit",
  85. [Tplumb] "Tplumb",
  86. };
  87. void
  88. journal(int out, char *s)
  89. {
  90. static int fd = 0;
  91. if(fd <= 0)
  92. fd = create("/tmp/sam.out", 1, 0666L);
  93. fprint(fd, "%s%s\n", out? "out: " : "in: ", s);
  94. }
  95. void
  96. journaln(int out, long n)
  97. {
  98. char buf[32];
  99. snprint(buf, sizeof(buf), "%ld", n);
  100. journal(out, buf);
  101. }
  102. void
  103. journalv(int out, vlong v)
  104. {
  105. char buf[32];
  106. sprint(buf, sizeof(buf), "%lld", v);
  107. journal(out, buf);
  108. }
  109. #else
  110. #define journal(a, b)
  111. #define journaln(a, b)
  112. #define journalv(a, b)
  113. #endif
  114. int
  115. rcvchar(void){
  116. static uchar buf[64];
  117. static int i, nleft = 0;
  118. if(nleft <= 0){
  119. nleft = read(0, (char *)buf, sizeof buf);
  120. if(nleft <= 0)
  121. return -1;
  122. i = 0;
  123. }
  124. --nleft;
  125. return buf[i++];
  126. }
  127. int
  128. rcv(void){
  129. int c;
  130. static int state = 0;
  131. static int count = 0;
  132. static int i = 0;
  133. while((c=rcvchar()) != -1)
  134. switch(state){
  135. case 0:
  136. h.type = c;
  137. state++;
  138. break;
  139. case 1:
  140. h.count0 = c;
  141. state++;
  142. break;
  143. case 2:
  144. h.count1 = c;
  145. count = h.count0|(h.count1<<8);
  146. i = 0;
  147. if(count > DATASIZE)
  148. panic("count>DATASIZE");
  149. if(count == 0)
  150. goto zerocount;
  151. state++;
  152. break;
  153. case 3:
  154. indata[i++] = c;
  155. if(i == count){
  156. zerocount:
  157. indata[i] = 0;
  158. state = count = 0;
  159. return inmesg(h.type);
  160. }
  161. break;
  162. }
  163. return 0;
  164. }
  165. File *
  166. whichfile(int tag)
  167. {
  168. int i;
  169. for(i = 0; i<file.nused; i++)
  170. if(file.filepptr[i]->tag==tag)
  171. return file.filepptr[i];
  172. hiccough((char *)0);
  173. return 0;
  174. }
  175. int
  176. inmesg(Tmesg type)
  177. {
  178. Rune buf[1025];
  179. char cbuf[64];
  180. int i, m;
  181. short s;
  182. long l, l1;
  183. vlong v;
  184. File *f;
  185. Posn p0, p1, p;
  186. Range r;
  187. String *str;
  188. char *c, *wdir;
  189. Rune *rp;
  190. Plumbmsg *pm;
  191. if(type > TMAX)
  192. panic("inmesg");
  193. journal(0, tname[type]);
  194. inp = indata;
  195. switch(type){
  196. default:
  197. fprint(2, "unknown type %d\n", type);
  198. panic("rcv unknown");
  199. case Tversion:
  200. tversion = inshort();
  201. journaln(0, tversion);
  202. break;
  203. case Tstartcmdfile:
  204. v = invlong(); /* for 64-bit pointers */
  205. journalv(0, v);
  206. Strdupl(&genstr, samname);
  207. cmd = newfile();
  208. cmd->unread = 0;
  209. outTsv(Hbindname, cmd->tag, v);
  210. outTs(Hcurrent, cmd->tag);
  211. logsetname(cmd, &genstr);
  212. cmd->rasp = listalloc('P');
  213. cmd->mod = 0;
  214. if(cmdstr.n){
  215. loginsert(cmd, 0L, cmdstr.s, cmdstr.n);
  216. Strdelete(&cmdstr, 0L, (Posn)cmdstr.n);
  217. }
  218. fileupdate(cmd, FALSE, TRUE);
  219. outT0(Hunlock);
  220. break;
  221. case Tcheck:
  222. /* go through whichfile to check the tag */
  223. outTs(Hcheck, whichfile(inshort())->tag);
  224. break;
  225. case Trequest:
  226. f = whichfile(inshort());
  227. p0 = inlong();
  228. p1 = p0+inshort();
  229. journaln(0, p0);
  230. journaln(0, p1-p0);
  231. if(f->unread)
  232. panic("Trequest: unread");
  233. if(p1>f->Buffer.nc)
  234. p1 = f->Buffer.nc;
  235. if(p0>f->Buffer.nc) /* can happen e.g. scrolling during command */
  236. p0 = f->Buffer.nc;
  237. if(p0 == p1){
  238. i = 0;
  239. r.p1 = r.p2 = p0;
  240. }else{
  241. r = rdata(f->rasp, p0, p1-p0);
  242. i = r.p2-r.p1;
  243. bufread(&f->Buffer, r.p1, buf, i);
  244. }
  245. buf[i]=0;
  246. outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1));
  247. break;
  248. case Torigin:
  249. s = inshort();
  250. l = inlong();
  251. l1 = inlong();
  252. journaln(0, l1);
  253. lookorigin(whichfile(s), l, l1);
  254. break;
  255. case Tstartfile:
  256. termlocked++;
  257. f = whichfile(inshort());
  258. if(!f->rasp) /* this might be a duplicate message */
  259. f->rasp = listalloc('P');
  260. current(f);
  261. outTsv(Hbindname, f->tag, invlong()); /* for 64-bit pointers */
  262. outTs(Hcurrent, f->tag);
  263. journaln(0, f->tag);
  264. if(f->unread)
  265. load(f);
  266. else{
  267. if(f->Buffer.nc>0){
  268. rgrow(f->rasp, 0L, f->Buffer.nc);
  269. outTsll(Hgrow, f->tag, 0L, f->Buffer.nc);
  270. }
  271. outTs(Hcheck0, f->tag);
  272. moveto(f, f->dot.r);
  273. }
  274. break;
  275. case Tworkfile:
  276. i = inshort();
  277. f = whichfile(i);
  278. current(f);
  279. f->dot.r.p1 = inlong();
  280. f->dot.r.p2 = inlong();
  281. f->tdot = f->dot.r;
  282. journaln(0, i);
  283. journaln(0, f->dot.r.p1);
  284. journaln(0, f->dot.r.p2);
  285. break;
  286. case Ttype:
  287. f = whichfile(inshort());
  288. p0 = inlong();
  289. journaln(0, p0);
  290. journal(0, (char*)inp);
  291. str = tmpcstr((char*)inp);
  292. i = str->n;
  293. loginsert(f, p0, str->s, str->n);
  294. if(fileupdate(f, FALSE, FALSE))
  295. seq++;
  296. if(f==cmd && p0==f->Buffer.nc-i && i>0 && str->s[i-1]=='\n'){
  297. freetmpstr(str);
  298. termlocked++;
  299. termcommand();
  300. }else
  301. freetmpstr(str);
  302. f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */
  303. f->tdot = f->dot.r;
  304. break;
  305. case Tcut:
  306. f = whichfile(inshort());
  307. p0 = inlong();
  308. p1 = inlong();
  309. journaln(0, p0);
  310. journaln(0, p1);
  311. logdelete(f, p0, p1);
  312. if(fileupdate(f, FALSE, FALSE))
  313. seq++;
  314. f->dot.r.p1 = f->dot.r.p2 = p0;
  315. f->tdot = f->dot.r; /* terminal knows the value of dot already */
  316. break;
  317. case Tpaste:
  318. f = whichfile(inshort());
  319. p0 = inlong();
  320. journaln(0, p0);
  321. for(l=0; l<snarfbuf.nc; l+=m){
  322. m = snarfbuf.nc-l;
  323. if(m>BLOCKSIZE)
  324. m = BLOCKSIZE;
  325. bufread(&snarfbuf, l, genbuf, m);
  326. loginsert(f, p0, tmprstr(genbuf, m)->s, m);
  327. }
  328. if(fileupdate(f, FALSE, TRUE))
  329. seq++;
  330. f->dot.r.p1 = p0;
  331. f->dot.r.p2 = p0+snarfbuf.nc;
  332. f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */
  333. telldot(f);
  334. outTs(Hunlockfile, f->tag);
  335. break;
  336. case Tsnarf:
  337. i = inshort();
  338. p0 = inlong();
  339. p1 = inlong();
  340. snarf(whichfile(i), p0, p1, &snarfbuf, 0);
  341. break;
  342. case Tstartnewfile:
  343. v = invlong();
  344. Strdupl(&genstr, empty);
  345. f = newfile();
  346. f->rasp = listalloc('P');
  347. outTsv(Hbindname, f->tag, v);
  348. logsetname(f, &genstr);
  349. outTs(Hcurrent, f->tag);
  350. current(f);
  351. load(f);
  352. break;
  353. case Twrite:
  354. termlocked++;
  355. i = inshort();
  356. journaln(0, i);
  357. f = whichfile(i);
  358. addr.r.p1 = 0;
  359. addr.r.p2 = f->Buffer.nc;
  360. if(f->name.s[0] == 0)
  361. error(Enoname);
  362. Strduplstr(&genstr, &f->name);
  363. writef(f);
  364. break;
  365. case Tclose:
  366. termlocked++;
  367. i = inshort();
  368. journaln(0, i);
  369. f = whichfile(i);
  370. current(f);
  371. trytoclose(f);
  372. /* if trytoclose fails, will error out */
  373. delete(f);
  374. break;
  375. case Tlook:
  376. f = whichfile(inshort());
  377. termlocked++;
  378. p0 = inlong();
  379. p1 = inlong();
  380. journaln(0, p0);
  381. journaln(0, p1);
  382. setgenstr(f, p0, p1);
  383. for(l = 0; l<genstr.n; l++){
  384. i = genstr.s[l];
  385. if(utfrune(".*+?(|)\\[]^$", i)){
  386. str = tmpcstr("\\");
  387. Strinsert(&genstr, str, l++);
  388. freetmpstr(str);
  389. }
  390. }
  391. Straddc(&genstr, '\0');
  392. nextmatch(f, &genstr, p1, 1);
  393. moveto(f, sel.p[0]);
  394. break;
  395. case Tsearch:
  396. termlocked++;
  397. if(curfile == 0)
  398. error(Enofile);
  399. if(lastpat.s[0] == 0)
  400. panic("Tsearch");
  401. nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1);
  402. moveto(curfile, sel.p[0]);
  403. break;
  404. case Tsend:
  405. termlocked++;
  406. inshort(); /* ignored */
  407. p0 = inlong();
  408. p1 = inlong();
  409. setgenstr(cmd, p0, p1);
  410. bufreset(&snarfbuf);
  411. bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n);
  412. outTl(Hsnarflen, genstr.n);
  413. if(genstr.s[genstr.n-1] != '\n')
  414. Straddc(&genstr, '\n');
  415. loginsert(cmd, cmd->Buffer.nc, genstr.s, genstr.n);
  416. fileupdate(cmd, FALSE, TRUE);
  417. cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->Buffer.nc;
  418. telldot(cmd);
  419. termcommand();
  420. break;
  421. case Tdclick:
  422. f = whichfile(inshort());
  423. p1 = inlong();
  424. doubleclick(f, p1);
  425. f->tdot.p1 = f->tdot.p2 = p1;
  426. telldot(f);
  427. outTs(Hunlockfile, f->tag);
  428. break;
  429. case Tstartsnarf:
  430. if (snarfbuf.nc <= 0) { /* nothing to export */
  431. outTs(Hsetsnarf, 0);
  432. break;
  433. }
  434. c = 0;
  435. i = 0;
  436. m = snarfbuf.nc;
  437. if(m > SNARFSIZE) {
  438. m = SNARFSIZE;
  439. dprint("?warning: snarf buffer truncated\n");
  440. }
  441. rp = malloc(m*sizeof(Rune));
  442. if(rp){
  443. bufread(&snarfbuf, 0, rp, m);
  444. c = Strtoc(tmprstr(rp, m));
  445. free(rp);
  446. i = strlen(c);
  447. }
  448. outTs(Hsetsnarf, i);
  449. if(c){
  450. Write(1, c, i);
  451. free(c);
  452. } else
  453. dprint("snarf buffer too long\n");
  454. break;
  455. case Tsetsnarf:
  456. m = inshort();
  457. if(m > SNARFSIZE)
  458. error(Etoolong);
  459. c = malloc(m+1);
  460. if(c){
  461. for(i=0; i<m; i++)
  462. c[i] = rcvchar();
  463. c[m] = 0;
  464. str = tmpcstr(c);
  465. free(c);
  466. bufreset(&snarfbuf);
  467. bufinsert(&snarfbuf, (Posn)0, str->s, str->n);
  468. freetmpstr(str);
  469. outT0(Hunlock);
  470. }
  471. break;
  472. case Tack:
  473. waitack = 0;
  474. break;
  475. case Tplumb:
  476. f = whichfile(inshort());
  477. p0 = inlong();
  478. p1 = inlong();
  479. pm = emalloc(sizeof(Plumbmsg));
  480. pm->src = strdup("sam");
  481. pm->dst = 0;
  482. /* construct current directory */
  483. c = Strtoc(&f->name);
  484. if(c[0] == '/')
  485. pm->wdir = c;
  486. else{
  487. wdir = emalloc(1024);
  488. getwd(wdir, 1024);
  489. pm->wdir = emalloc(1024);
  490. snprint(pm->wdir, 1024, "%s/%s", wdir, c);
  491. cleanname(pm->wdir);
  492. free(wdir);
  493. free(c);
  494. }
  495. c = strrchr(pm->wdir, '/');
  496. if(c)
  497. *c = '\0';
  498. pm->type = strdup("text");
  499. if(p1 > p0)
  500. pm->attr = nil;
  501. else{
  502. p = p0;
  503. while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i!='\t' && i!='\n')
  504. p0--;
  505. while(p1<f->Buffer.nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n')
  506. p1++;
  507. sprint(cbuf, "click=%ld", p-p0);
  508. pm->attr = plumbunpackattr(cbuf);
  509. }
  510. if(p0==p1 || p1-p0>=BLOCKSIZE){
  511. plumbfree(pm);
  512. break;
  513. }
  514. setgenstr(f, p0, p1);
  515. pm->data = Strtoc(&genstr);
  516. pm->ndata = strlen(pm->data);
  517. c = plumbpack(pm, &i);
  518. if(c != 0){
  519. outTs(Hplumb, i);
  520. Write(1, c, i);
  521. free(c);
  522. }
  523. plumbfree(pm);
  524. break;
  525. case Texit:
  526. exits(0);
  527. }
  528. return TRUE;
  529. }
  530. void
  531. snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok)
  532. {
  533. Posn l;
  534. int i;
  535. if(!emptyok && p1==p2)
  536. return;
  537. bufreset(buf);
  538. /* Stage through genbuf to avoid compaction problems (vestigial) */
  539. if(p2 > f->Buffer.nc){
  540. fprint(2, "bad snarf addr p1=%ld p2=%ld f->Buffer.nc=%d\n", p1, p2, f->Buffer.nc); /*ZZZ should never happen, can remove */
  541. p2 = f->Buffer.nc;
  542. }
  543. for(l=p1; l<p2; l+=i){
  544. i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;
  545. bufread(&f->Buffer, l, genbuf, i);
  546. bufinsert(buf, buf->nc, tmprstr(genbuf, i)->s, i);
  547. }
  548. }
  549. int
  550. inshort(void)
  551. {
  552. ushort n;
  553. n = inp[0] | (inp[1]<<8);
  554. inp += 2;
  555. return n;
  556. }
  557. long
  558. inlong(void)
  559. {
  560. ulong n;
  561. n = inp[0] | (inp[1]<<8) | (inp[2]<<16) | (inp[3]<<24);
  562. inp += 4;
  563. return n;
  564. }
  565. vlong
  566. invlong(void)
  567. {
  568. vlong v;
  569. v = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4];
  570. v = (v<<16) | (inp[3]<<8) | inp[2];
  571. v = (v<<16) | (inp[1]<<8) | inp[0];
  572. inp += 8;
  573. return v;
  574. }
  575. void
  576. setgenstr(File *f, Posn p0, Posn p1)
  577. {
  578. if(p0 != p1){
  579. if(p1-p0 >= TBLOCKSIZE)
  580. error(Etoolong);
  581. Strinsure(&genstr, p1-p0);
  582. bufread(&f->Buffer, p0, genbuf, p1-p0);
  583. memmove(genstr.s, genbuf, RUNESIZE*(p1-p0));
  584. genstr.n = p1-p0;
  585. }else{
  586. if(snarfbuf.nc == 0)
  587. error(Eempty);
  588. if(snarfbuf.nc > TBLOCKSIZE)
  589. error(Etoolong);
  590. bufread(&snarfbuf, (Posn)0, genbuf, snarfbuf.nc);
  591. Strinsure(&genstr, snarfbuf.nc);
  592. memmove(genstr.s, genbuf, RUNESIZE*snarfbuf.nc);
  593. genstr.n = snarfbuf.nc;
  594. }
  595. }
  596. void
  597. outT0(Hmesg type)
  598. {
  599. outstart(type);
  600. outsend();
  601. }
  602. void
  603. outTl(Hmesg type, long l)
  604. {
  605. outstart(type);
  606. outlong(l);
  607. outsend();
  608. }
  609. void
  610. outTs(Hmesg type, int s)
  611. {
  612. outstart(type);
  613. journaln(1, s);
  614. outshort(s);
  615. outsend();
  616. }
  617. void
  618. outS(String *s)
  619. {
  620. char *c;
  621. int i;
  622. c = Strtoc(s);
  623. i = strlen(c);
  624. outcopy(i, c);
  625. if(i > 99)
  626. c[99] = 0;
  627. journaln(1, i);
  628. journal(1, c);
  629. free(c);
  630. }
  631. void
  632. outTsS(Hmesg type, int s1, String *s)
  633. {
  634. outstart(type);
  635. outshort(s1);
  636. outS(s);
  637. outsend();
  638. }
  639. void
  640. outTslS(Hmesg type, int s1, Posn l1, String *s)
  641. {
  642. outstart(type);
  643. outshort(s1);
  644. journaln(1, s1);
  645. outlong(l1);
  646. journaln(1, l1);
  647. outS(s);
  648. outsend();
  649. }
  650. void
  651. outTS(Hmesg type, String *s)
  652. {
  653. outstart(type);
  654. outS(s);
  655. outsend();
  656. }
  657. void
  658. outTsllS(Hmesg type, int s1, Posn l1, Posn l2, String *s)
  659. {
  660. outstart(type);
  661. outshort(s1);
  662. outlong(l1);
  663. outlong(l2);
  664. journaln(1, l1);
  665. journaln(1, l2);
  666. outS(s);
  667. outsend();
  668. }
  669. void
  670. outTsll(Hmesg type, int s, Posn l1, Posn l2)
  671. {
  672. outstart(type);
  673. outshort(s);
  674. outlong(l1);
  675. outlong(l2);
  676. journaln(1, l1);
  677. journaln(1, l2);
  678. outsend();
  679. }
  680. void
  681. outTsl(Hmesg type, int s, Posn l)
  682. {
  683. outstart(type);
  684. outshort(s);
  685. outlong(l);
  686. journaln(1, l);
  687. outsend();
  688. }
  689. void
  690. outTsv(Hmesg type, int s, vlong v)
  691. {
  692. outstart(type);
  693. outshort(s);
  694. outvlong(v);
  695. journalv(1, v);
  696. outsend();
  697. }
  698. void
  699. outstart(Hmesg type)
  700. {
  701. journal(1, hname[type]);
  702. outmsg[0] = type;
  703. outp = outmsg+3;
  704. }
  705. void
  706. outcopy(int count, void *data)
  707. {
  708. memmove(outp, data, count);
  709. outp += count;
  710. }
  711. void
  712. outshort(int s)
  713. {
  714. *outp++ = s;
  715. *outp++ = s>>8;
  716. }
  717. void
  718. outlong(long l)
  719. {
  720. *outp++ = l;
  721. *outp++ = l>>8;
  722. *outp++ = l>>16;
  723. *outp++ = l>>24;
  724. }
  725. void
  726. outvlong(vlong v)
  727. {
  728. int i;
  729. for(i = 0; i < 8; i++){
  730. *outp++ = v;
  731. v >>= 8;
  732. }
  733. }
  734. void
  735. outsend(void)
  736. {
  737. int outcount;
  738. if(outp >= outdata+nelem(outdata))
  739. panic("outsend");
  740. outcount = outp-outmsg;
  741. outcount -= 3;
  742. outmsg[1] = outcount;
  743. outmsg[2] = outcount>>8;
  744. outmsg = outp;
  745. if(!outbuffered){
  746. outcount = outmsg-outdata;
  747. if (write(1, (char*) outdata, outcount) != outcount)
  748. rescue();
  749. outmsg = outdata;
  750. return;
  751. }
  752. }
  753. int
  754. needoutflush(void)
  755. {
  756. return outmsg >= outdata+DATASIZE;
  757. }
  758. void
  759. outflush(void)
  760. {
  761. if(outmsg == outdata)
  762. return;
  763. outbuffered = 0;
  764. /* flow control */
  765. outT0(Hack);
  766. waitack = 1;
  767. do
  768. if(rcv() == 0){
  769. rescue();
  770. exits("eof");
  771. }
  772. while(waitack);
  773. outmsg = outdata;
  774. outbuffered = 1;
  775. }