mesg.c 14 KB

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