adict.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <thread.h>
  5. #include "win.h"
  6. #include "adict.h"
  7. char *prog = "adict";
  8. char *lprog = "/bin/adict";
  9. char *xprog = "/bin/dict";
  10. char *dict, *pattern, *curaddr[MAXMATCH], *curone, *args[6], buffer[80];
  11. char abuffer[80], fbuffer[80], pbuffer[80];
  12. int curindex, count, Eopen, Mopen;
  13. Win Mwin, Ewin, Dwin;
  14. void openwin(char*, char*, Win*, int);
  15. void handle(Win*, int);
  16. void rexec(void*);
  17. void pexec(void*);
  18. int getaddr(char*);
  19. void
  20. usage(void)
  21. {
  22. threadprint(2, "usage: %s [-d dictname] [pattern]\n", argv0);
  23. threadexitsall(nil);
  24. }
  25. void
  26. threadmain(int argc, char** argv)
  27. {
  28. ARGBEGIN{
  29. case 'd':
  30. dict = strdup(ARGF());
  31. break;
  32. default:
  33. usage();
  34. }ARGEND
  35. /* if running as other name, note that fact */
  36. if(access(argv0, AEXIST) == 0)
  37. lprog = argv0;
  38. switch(argc){
  39. case 1:
  40. pattern = pbuffer;
  41. strcpy(pattern,argv[0]);
  42. if(dict == nil)
  43. dict = "oed";
  44. break;
  45. case 0:
  46. break;
  47. default:
  48. usage();
  49. }
  50. if ((dict == nil) && (pattern == nil))
  51. openwin(prog,"", &Dwin, Dictwin);
  52. if (pattern == nil)
  53. openwin(prog,"",&Ewin, Entrywin);
  54. if ((count = getaddr(pattern)) <= 1)
  55. openwin(prog,"Prev Next", &Ewin, Entrywin);
  56. else
  57. openwin(prog, "", &Mwin, Matchwin);
  58. }
  59. static int
  60. procrexec(char *xprog, ...)
  61. {
  62. int fpipe[2];
  63. void *rexarg[4];
  64. Channel *c;
  65. va_list va;
  66. int i;
  67. char *p;
  68. pipe(fpipe);
  69. va_start(va, xprog);
  70. p = xprog;
  71. for(i=0; p && i+1<nelem(args); i++){
  72. args[i] = p;
  73. p = va_arg(va, char*);
  74. }
  75. args[i] = nil;
  76. c = chancreate(sizeof(ulong), 0);
  77. rexarg[0] = xprog;
  78. rexarg[1] = args;
  79. rexarg[2] = fpipe;
  80. rexarg[3] = c;
  81. proccreate(rexec, rexarg, 8192);
  82. recvul(c);
  83. chanfree(c);
  84. close(fpipe[1]);
  85. return fpipe[0];
  86. }
  87. int
  88. getaddr(char *pattern)
  89. {
  90. /* Get char offset into dictionary of matches. */
  91. int fd, i;
  92. Biobuf inbuf;
  93. char *bufptr;
  94. char *obuf;
  95. if (pattern == nil) {
  96. curone = nil;
  97. curindex = 0;
  98. curaddr[curindex] = nil;
  99. return 0;
  100. }
  101. sprint(buffer,"/%s/A", pattern);
  102. fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
  103. Binit(&inbuf, fd, OREAD);
  104. i = 0;
  105. curindex = 0;
  106. while ((bufptr = Brdline(&inbuf, '\n')) != nil && (i < (MAXMATCH-1))) {
  107. bufptr[Blinelen(&inbuf)-1] = 0;
  108. obuf=bufptr;
  109. while (bufptr[0] != '#' && bufptr[0] != 0) bufptr++;
  110. if(bufptr[0] == 0)
  111. print("whoops buf «%s»\n", obuf);
  112. curaddr[i] = malloc(strlen(bufptr));
  113. strcpy(curaddr[i], bufptr);
  114. i++;
  115. }
  116. curaddr[i] = nil;
  117. if (i == MAXMATCH)
  118. threadprint(2, "Too many matches!\n");
  119. Bterm(&inbuf);
  120. close(fd);
  121. curone = curaddr[curindex];
  122. return(i);
  123. }
  124. char*
  125. getpattern(char *addr)
  126. {
  127. /* Get the pattern corresponding to an absolute address.*/
  128. int fd;
  129. char *res, *t;
  130. res = nil;
  131. sprint(buffer,"%sh", addr);
  132. fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
  133. if (read(fd, pbuffer, 80) > 80)
  134. threadprint(2, "Error in getting addres from dict.\n");
  135. else {
  136. t = pbuffer;
  137. /* remove trailing whitespace, newline */
  138. if (t != nil){
  139. while(*t != 0 && *t != '\n')
  140. t++;
  141. if(t == 0 && t > pbuffer)
  142. t--;
  143. while(t >= pbuffer && (*t==' ' || *t=='\n' || *t=='\t' || *t=='\r'))
  144. *t-- = 0;
  145. }
  146. res = pbuffer;
  147. }
  148. close(fd);
  149. return(res);
  150. }
  151. char*
  152. chgaddr(int dir)
  153. {
  154. /* Increment or decrement the current address (curone). */
  155. int fd;
  156. char *res, *t;
  157. res = nil;
  158. if (dir < 0)
  159. sprint(buffer,"%s-a", curone);
  160. else
  161. sprint(buffer,"%s+a", curone);
  162. fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
  163. if (read(fd, abuffer, 80) > 80)
  164. threadprint(2, "Error in getting addres from dict.\n");
  165. else {
  166. res = abuffer;
  167. while (*res != '#') res++;
  168. t = res;
  169. while ((*t != '\n') && (t != nil)) t++;
  170. if (t != nil) *t = 0;
  171. }
  172. close(fd);
  173. return(res);
  174. }
  175. void
  176. dispdicts(Win *cwin)
  177. {
  178. /* Display available dictionaries in window. */
  179. int fd, nb, i;
  180. char buf[1024], *t;
  181. fd = procrexec(xprog, "-d", "?", nil);
  182. wreplace(cwin, "0,$","",0); /* Clear window */
  183. while ((nb = read(fd, buf, 1024)) > 0) {
  184. t = buf;
  185. i = 0;
  186. if (strncmp("Usage", buf, 5) == 0) { /* Remove first line. */
  187. while (t[0] != '\n') {
  188. t++;
  189. i++;
  190. }
  191. t++;
  192. i++;
  193. }
  194. wwritebody(cwin, t, nb-i);
  195. }
  196. close(fd);
  197. wclean(cwin);
  198. }
  199. void
  200. dispentry(Win *cwin)
  201. {
  202. /* Display the current selection in window. */
  203. int fd, nb;
  204. char buf[BUFSIZE];
  205. if (curone == nil) {
  206. if (pattern != nil) {
  207. sprint(buf,"Pattern not found.\n");
  208. wwritebody(cwin, buf, 19);
  209. wclean(cwin);
  210. }
  211. return;
  212. }
  213. sprint(buffer,"%sp", curone);
  214. fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
  215. wreplace(cwin, "0,$","",0); /* Clear window */
  216. while ((nb = read(fd, buf, BUFSIZE)) > 0) {
  217. wwritebody(cwin, buf, nb);
  218. }
  219. close(fd);
  220. wclean(cwin);
  221. }
  222. void
  223. dispmatches(Win *cwin)
  224. {
  225. /* Display the current matches. */
  226. int fd, nb;
  227. char buf[BUFSIZE];
  228. sprint(buffer,"/%s/H", pattern);
  229. fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
  230. while ((nb = read(fd, buf, BUFSIZE)) > 0)
  231. wwritebody(cwin, buf, nb);
  232. close(fd);
  233. wclean(cwin);
  234. }
  235. char*
  236. format(char *s)
  237. {
  238. /* Format a string to be written in window tag. Acme doesn't like */
  239. /* non alpha-num's in the tag line. */
  240. char *t, *h;
  241. t = fbuffer;
  242. if (s == nil) {
  243. *t = 0;
  244. return t;
  245. }
  246. strcpy(t, s);
  247. h = t;
  248. while (*t != 0) {
  249. if (!(((*t >= 'a') && (*t <= 'z')) ||
  250. ((*t >= 'A') && (*t <= 'Z')) ||
  251. ((*t >= '0') && (*t <= '9'))))
  252. *t = '_';
  253. t++;
  254. }
  255. if (strlen(h) > MAXTAG)
  256. h[MAXTAG] = 0;
  257. if (strcmp(s,h) == 0) return s;
  258. return h;
  259. }
  260. void
  261. openwin(char *name, char *buttons, Win *twin, int wintype)
  262. {
  263. char buf[80];
  264. wnew(twin);
  265. if (wintype == Dictwin)
  266. sprint(buf,"%s",name);
  267. else
  268. if ((wintype == Entrywin) && (count > 1))
  269. sprint(buf,"%s/%s/%s/%d",name, dict, format(pattern), curindex+1);
  270. else
  271. sprint(buf,"%s/%s/%s",name, dict, format(pattern));
  272. wname(twin, buf);
  273. wtagwrite(twin, buttons, strlen(buttons));
  274. wclean(twin);
  275. wdormant(twin);
  276. if (wintype == Dictwin)
  277. dispdicts(twin);
  278. if (wintype == Matchwin) {
  279. Mopen = True;
  280. dispmatches(twin);
  281. }
  282. if (wintype == Entrywin) {
  283. Eopen = True;
  284. dispentry(twin);
  285. }
  286. handle(twin, wintype);
  287. }
  288. void
  289. vopenwin(void *v)
  290. {
  291. void **arg;
  292. char *name, *buttons;
  293. Win *twin;
  294. int wintype;
  295. arg = v;
  296. name = arg[0];
  297. buttons = arg[1];
  298. twin = arg[2];
  299. wintype = (int)arg[3];
  300. sendul(arg[4], 0);
  301. openwin(name, buttons, twin, wintype);
  302. threadexits(nil);
  303. }
  304. void
  305. procopenwin(char *name, char *buttons, Win *twin, int wintype)
  306. {
  307. void *arg[5];
  308. Channel *c;
  309. c = chancreate(sizeof(ulong), 0);
  310. arg[0] = name;
  311. arg[1] = buttons;
  312. arg[2] = twin;
  313. arg[3] = (void*)wintype;
  314. arg[4] = c;
  315. proccreate(vopenwin, arg, 8192);
  316. recvul(c);
  317. chanfree(c);
  318. }
  319. void
  320. rexec(void *v)
  321. {
  322. void **arg;
  323. char *prog;
  324. char **args;
  325. int *fd;
  326. Channel *c;
  327. arg = v;
  328. prog = arg[0];
  329. args = arg[1];
  330. fd = arg[2];
  331. c = arg[3];
  332. rfork(RFENVG|RFFDG);
  333. dup(fd[1], 1);
  334. close(fd[1]);
  335. close(fd[0]);
  336. procexec(c, prog, args);
  337. threadprint(2, "Remote pipe execution failed: %s %r\n", prog);
  338. abort();
  339. threadexits(nil);
  340. }
  341. void
  342. pexec(void *v)
  343. {
  344. void **arg;
  345. char *prog;
  346. char **args;
  347. Channel *c;
  348. arg = v;
  349. prog = arg[0];
  350. args = arg[1];
  351. c = arg[2];
  352. procexec(c, prog, args);
  353. threadprint(2, "Remote execution failed: %s %r\n", prog);
  354. abort();
  355. threadexits(nil);
  356. }
  357. void
  358. procpexec(char *prog, char **args)
  359. {
  360. void *rexarg[4];
  361. Channel *c;
  362. c = chancreate(sizeof(ulong), 0);
  363. rexarg[0] = prog;
  364. rexarg[1] = args;
  365. rexarg[2] = c;
  366. proccreate(pexec, rexarg, 8192);
  367. recvul(c);
  368. chanfree(c);
  369. }
  370. void
  371. kill(void)
  372. {
  373. /* Kill all processes related to this one. */
  374. int fd;
  375. sprint(buffer, "/proc/%d/notepg", getpid());
  376. fd = open(buffer, OWRITE);
  377. rfork(RFNOTEG);
  378. write(fd, "kill", 4);
  379. }
  380. int
  381. command(char *com, Win *w, int wintype)
  382. {
  383. char *buf;
  384. if (strncmp(com, "Del", 3) == 0) {
  385. switch(wintype){
  386. case Entrywin:
  387. if (wdel(w)) {
  388. Eopen = False;
  389. threadexits(nil);
  390. }
  391. break;
  392. case Dictwin:
  393. if (wdel(w))
  394. threadexits(nil);
  395. break;
  396. case Matchwin:
  397. kill();
  398. if (Eopen)
  399. if (~wdel(&Ewin)) /* Remove the entry window */
  400. wdel(&Ewin);
  401. if (!wdel(w))
  402. wdel(w);
  403. threadexits(nil);
  404. break;
  405. }
  406. return True;
  407. }
  408. if (strncmp(com, "Next", 4) == 0){
  409. if (curone != nil) {
  410. curone = chgaddr(1);
  411. buf = getpattern(curone);
  412. sprint(buffer,"%s/%s/%s", prog, dict, format(buf));
  413. wname(w, buffer);
  414. dispentry(w);
  415. }
  416. return True;
  417. }
  418. if (strncmp(com, "Prev",4) == 0){
  419. if (curone != nil) {
  420. curone = chgaddr(-1);
  421. buf = getpattern(curone);
  422. sprint(buffer,"%s/%s/%s", prog, dict, format(buf));
  423. wname(w, buffer);
  424. dispentry(w);
  425. }
  426. return True;
  427. }
  428. if (strncmp(com, "Nmatch",6) == 0){
  429. if (curaddr[++curindex] == nil)
  430. curindex = 0;
  431. curone = curaddr[curindex];
  432. if (curone != nil) {
  433. sprint(buffer,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1);
  434. wname(w, buffer);
  435. dispentry(w);
  436. }
  437. return True;
  438. }
  439. return False;
  440. }
  441. void
  442. handle(Win *w, int wintype)
  443. {
  444. Event e, e2, ea, etoss;
  445. char *s, *t, buf[80];
  446. int tmp, na;
  447. while (True) {
  448. wevent(w, &e);
  449. switch(e.c2){
  450. default:
  451. /* threadprint(2,"unknown message %c%c\n", e.c1, e.c2); */
  452. break;
  453. case 'i':
  454. /* threadprint(2,"'%s' inserted in tag at %d\n", e.b, e.q0);*/
  455. break;
  456. case 'I':
  457. /* threadprint(2,"'%s' inserted in body at %d\n", e.b, e.q0);*/
  458. break;
  459. case 'd':
  460. /* threadprint(2, "'%s' deleted in tag at %d\n", e.b, e.q0);*/
  461. break;
  462. case 'D':
  463. /* threadprint(2, "'%s' deleted in body at %d\n", e.b, e.q0);*/
  464. break;
  465. case 'x':
  466. case 'X': /* Execute command. */
  467. if (e.flag & 2)
  468. wevent(w, &e2);
  469. if(e.flag & 8){
  470. wevent(w, &ea);
  471. wevent(w, &etoss);
  472. na = ea.nb;
  473. } else
  474. na = 0;
  475. s = e.b;
  476. if ((e.flag & 2) && e.nb == 0)
  477. s = e2.b;
  478. if(na){
  479. t = malloc(strlen(s)+1+na+1);
  480. snprint(t, strlen(s)+1+na+1, "%s %s", s, ea.b);
  481. s = t;
  482. }
  483. /* if it's a long message, it can't be for us anyway */
  484. if(!command(s, w, wintype)) /* send it back */
  485. wwriteevent(w, &e);
  486. if(na)
  487. free(s);
  488. break;
  489. case 'l':
  490. case 'L': /* Look for something. */
  491. if (e.flag & 2)
  492. wevent(w, &e);
  493. wclean(w); /* Set clean bit. */
  494. if (wintype == Dictwin) {
  495. strcpy(buf, e.b);
  496. args[0] = lprog;
  497. args[1] = "-d";
  498. args[2] = buf;
  499. args[3] = nil;
  500. procpexec(lprog, args); /* New adict with chosen dict. */
  501. }
  502. if (wintype == Entrywin) {
  503. strcpy(buf, e.b);
  504. args[0] = lprog;
  505. args[1] = "-d";
  506. args[2] = dict;
  507. args[3] = buf;
  508. args[4] = nil;
  509. procpexec(lprog, args); /* New adict with chosen pattern. */
  510. }
  511. if (wintype == Matchwin) {
  512. tmp = atoi(e.b) - 1;
  513. if ((tmp >= 0) && (tmp < MAXMATCH) && (curaddr[tmp] != nil)) {
  514. curindex = tmp;
  515. curone = curaddr[curindex];
  516. /* Display selected match. */
  517. if (Eopen) {
  518. sprint(buf,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1);
  519. wname(&Ewin, buf);
  520. dispentry(&Ewin);
  521. }
  522. else
  523. procopenwin(prog,"Nmatch Prev Next", &Ewin, Entrywin);
  524. }
  525. }
  526. break;
  527. }
  528. }
  529. }