mesg.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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. str = tmpcstr("\\");
  366. Strinsert(&genstr, str, l++);
  367. freetmpstr(str);
  368. }
  369. }
  370. Straddc(&genstr, '\0');
  371. nextmatch(f, &genstr, p1, 1);
  372. moveto(f, sel.p[0]);
  373. break;
  374. case Tsearch:
  375. termlocked++;
  376. if(curfile == 0)
  377. error(Enofile);
  378. if(lastpat.s[0] == 0)
  379. panic("Tsearch");
  380. nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1);
  381. moveto(curfile, sel.p[0]);
  382. break;
  383. case Tsend:
  384. termlocked++;
  385. inshort(); /* ignored */
  386. p0 = inlong();
  387. p1 = inlong();
  388. setgenstr(cmd, p0, p1);
  389. bufreset(&snarfbuf);
  390. bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n);
  391. outTl(Hsnarflen, genstr.n);
  392. if(genstr.s[genstr.n-1] != '\n')
  393. Straddc(&genstr, '\n');
  394. loginsert(cmd, cmd->nc, genstr.s, genstr.n);
  395. fileupdate(cmd, FALSE, TRUE);
  396. cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;
  397. telldot(cmd);
  398. termcommand();
  399. break;
  400. case Tdclick:
  401. f = whichfile(inshort());
  402. p1 = inlong();
  403. doubleclick(f, p1);
  404. f->tdot.p1 = f->tdot.p2 = p1;
  405. telldot(f);
  406. outTs(Hunlockfile, f->tag);
  407. break;
  408. case Tstartsnarf:
  409. if (snarfbuf.nc <= 0) { /* nothing to export */
  410. outTs(Hsetsnarf, 0);
  411. break;
  412. }
  413. c = 0;
  414. i = 0;
  415. m = snarfbuf.nc;
  416. if(m > SNARFSIZE) {
  417. m = SNARFSIZE;
  418. dprint("?warning: snarf buffer truncated\n");
  419. }
  420. rp = malloc(m*sizeof(Rune));
  421. if(rp){
  422. bufread(&snarfbuf, 0, rp, m);
  423. c = Strtoc(tmprstr(rp, m));
  424. free(rp);
  425. i = strlen(c);
  426. }
  427. outTs(Hsetsnarf, i);
  428. if(c){
  429. Write(1, c, i);
  430. free(c);
  431. } else
  432. dprint("snarf buffer too long\n");
  433. break;
  434. case Tsetsnarf:
  435. m = inshort();
  436. if(m > SNARFSIZE)
  437. error(Etoolong);
  438. c = malloc(m+1);
  439. if(c){
  440. for(i=0; i<m; i++)
  441. c[i] = rcvchar();
  442. c[m] = 0;
  443. str = tmpcstr(c);
  444. free(c);
  445. bufreset(&snarfbuf);
  446. bufinsert(&snarfbuf, (Posn)0, str->s, str->n);
  447. freetmpstr(str);
  448. outT0(Hunlock);
  449. }
  450. break;
  451. case Tack:
  452. waitack = 0;
  453. break;
  454. case Tplumb:
  455. f = whichfile(inshort());
  456. p0 = inlong();
  457. p1 = inlong();
  458. pm = emalloc(sizeof(Plumbmsg));
  459. pm->src = strdup("sam");
  460. pm->dst = 0;
  461. /* construct current directory */
  462. c = Strtoc(&f->name);
  463. if(c[0] == '/')
  464. pm->wdir = c;
  465. else{
  466. wdir = emalloc(1024);
  467. getwd(wdir, 1024);
  468. pm->wdir = emalloc(1024);
  469. snprint(pm->wdir, 1024, "%s/%s", wdir, c);
  470. cleanname(pm->wdir);
  471. free(wdir);
  472. free(c);
  473. }
  474. c = strrchr(pm->wdir, '/');
  475. if(c)
  476. *c = '\0';
  477. pm->type = strdup("text");
  478. if(p1 > p0)
  479. pm->attr = nil;
  480. else{
  481. p = p0;
  482. while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i!='\t' && i!='\n')
  483. p0--;
  484. while(p1<f->nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n')
  485. p1++;
  486. sprint(cbuf, "click=%ld", p-p0);
  487. pm->attr = plumbunpackattr(cbuf);
  488. }
  489. if(p0==p1 || p1-p0>=BLOCKSIZE){
  490. plumbfree(pm);
  491. break;
  492. }
  493. setgenstr(f, p0, p1);
  494. pm->data = Strtoc(&genstr);
  495. pm->ndata = strlen(pm->data);
  496. c = plumbpack(pm, &i);
  497. if(c != 0){
  498. outTs(Hplumb, i);
  499. Write(1, c, i);
  500. free(c);
  501. }
  502. plumbfree(pm);
  503. break;
  504. case Texit:
  505. exits(0);
  506. }
  507. return TRUE;
  508. }
  509. void
  510. snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok)
  511. {
  512. Posn l;
  513. int i;
  514. if(!emptyok && p1==p2)
  515. return;
  516. bufreset(buf);
  517. /* Stage through genbuf to avoid compaction problems (vestigial) */
  518. if(p2 > f->nc){
  519. fprint(2, "bad snarf addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
  520. p2 = f->nc;
  521. }
  522. for(l=p1; l<p2; l+=i){
  523. i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;
  524. bufread(f, l, genbuf, i);
  525. bufinsert(buf, buf->nc, tmprstr(genbuf, i)->s, i);
  526. }
  527. }
  528. int
  529. inshort(void)
  530. {
  531. ushort n;
  532. n = inp[0] | (inp[1]<<8);
  533. inp += 2;
  534. return n;
  535. }
  536. long
  537. inlong(void)
  538. {
  539. ulong n;
  540. n = inp[0] | (inp[1]<<8) | (inp[2]<<16) | (inp[3]<<24);
  541. inp += 4;
  542. return n;
  543. }
  544. long
  545. invlong(void)
  546. {
  547. ulong n;
  548. n = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4];
  549. n = (n<<16) | (inp[3]<<8) | inp[2];
  550. n = (n<<16) | (inp[1]<<8) | inp[0];
  551. inp += 8;
  552. return n;
  553. }
  554. void
  555. setgenstr(File *f, Posn p0, Posn p1)
  556. {
  557. if(p0 != p1){
  558. if(p1-p0 >= TBLOCKSIZE)
  559. error(Etoolong);
  560. Strinsure(&genstr, p1-p0);
  561. bufread(f, p0, genbuf, p1-p0);
  562. memmove(genstr.s, genbuf, RUNESIZE*(p1-p0));
  563. genstr.n = p1-p0;
  564. }else{
  565. if(snarfbuf.nc == 0)
  566. error(Eempty);
  567. if(snarfbuf.nc > TBLOCKSIZE)
  568. error(Etoolong);
  569. bufread(&snarfbuf, (Posn)0, genbuf, snarfbuf.nc);
  570. Strinsure(&genstr, snarfbuf.nc);
  571. memmove(genstr.s, genbuf, RUNESIZE*snarfbuf.nc);
  572. genstr.n = snarfbuf.nc;
  573. }
  574. }
  575. void
  576. outT0(Hmesg type)
  577. {
  578. outstart(type);
  579. outsend();
  580. }
  581. void
  582. outTl(Hmesg type, long l)
  583. {
  584. outstart(type);
  585. outlong(l);
  586. outsend();
  587. }
  588. void
  589. outTs(Hmesg type, int s)
  590. {
  591. outstart(type);
  592. journaln(1, s);
  593. outshort(s);
  594. outsend();
  595. }
  596. void
  597. outS(String *s)
  598. {
  599. char *c;
  600. int i;
  601. c = Strtoc(s);
  602. i = strlen(c);
  603. outcopy(i, c);
  604. if(i > 99)
  605. c[99] = 0;
  606. journaln(1, i);
  607. journal(1, c);
  608. free(c);
  609. }
  610. void
  611. outTsS(Hmesg type, int s1, String *s)
  612. {
  613. outstart(type);
  614. outshort(s1);
  615. outS(s);
  616. outsend();
  617. }
  618. void
  619. outTslS(Hmesg type, int s1, Posn l1, String *s)
  620. {
  621. outstart(type);
  622. outshort(s1);
  623. journaln(1, s1);
  624. outlong(l1);
  625. journaln(1, l1);
  626. outS(s);
  627. outsend();
  628. }
  629. void
  630. outTS(Hmesg type, String *s)
  631. {
  632. outstart(type);
  633. outS(s);
  634. outsend();
  635. }
  636. void
  637. outTsllS(Hmesg type, int s1, Posn l1, Posn l2, String *s)
  638. {
  639. outstart(type);
  640. outshort(s1);
  641. outlong(l1);
  642. outlong(l2);
  643. journaln(1, l1);
  644. journaln(1, l2);
  645. outS(s);
  646. outsend();
  647. }
  648. void
  649. outTsll(Hmesg type, int s, Posn l1, Posn l2)
  650. {
  651. outstart(type);
  652. outshort(s);
  653. outlong(l1);
  654. outlong(l2);
  655. journaln(1, l1);
  656. journaln(1, l2);
  657. outsend();
  658. }
  659. void
  660. outTsl(Hmesg type, int s, Posn l)
  661. {
  662. outstart(type);
  663. outshort(s);
  664. outlong(l);
  665. journaln(1, l);
  666. outsend();
  667. }
  668. void
  669. outTsv(Hmesg type, int s, Posn l)
  670. {
  671. outstart(type);
  672. outshort(s);
  673. outvlong((void*)l);
  674. journaln(1, l);
  675. outsend();
  676. }
  677. void
  678. outstart(Hmesg type)
  679. {
  680. journal(1, hname[type]);
  681. outmsg[0] = type;
  682. outp = outmsg+3;
  683. }
  684. void
  685. outcopy(int count, void *data)
  686. {
  687. memmove(outp, data, count);
  688. outp += count;
  689. }
  690. void
  691. outshort(int s)
  692. {
  693. *outp++ = s;
  694. *outp++ = s>>8;
  695. }
  696. void
  697. outlong(long l)
  698. {
  699. *outp++ = l;
  700. *outp++ = l>>8;
  701. *outp++ = l>>16;
  702. *outp++ = l>>24;
  703. }
  704. void
  705. outvlong(void *v)
  706. {
  707. int i;
  708. ulong l;
  709. l = (ulong) v;
  710. for(i = 0; i < 8; i++, l >>= 8)
  711. *outp++ = l;
  712. }
  713. void
  714. outsend(void)
  715. {
  716. int outcount;
  717. outcount = outp-outmsg;
  718. outcount -= 3;
  719. outmsg[1] = outcount;
  720. outmsg[2] = outcount>>8;
  721. outmsg = outp;
  722. if(!noflush){
  723. outcount = outmsg-outdata;
  724. if (write(1, (char*) outdata, outcount) != outcount)
  725. rescue();
  726. outmsg = outdata;
  727. return;
  728. }
  729. if(outmsg < outdata+DATASIZE)
  730. return;
  731. outflush();
  732. }
  733. void
  734. outflush(void)
  735. {
  736. if(outmsg == outdata)
  737. return;
  738. noflush = 0;
  739. outT0(Hack);
  740. waitack = 1;
  741. do
  742. if(rcv() == 0){
  743. rescue();
  744. exits("eof");
  745. }
  746. while(waitack);
  747. outmsg = outdata;
  748. noflush = 1;
  749. }