adict.c 11 KB

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