Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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