mesg.c 14 KB

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