Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Maybe `simple' is a misnomer.
3
 */
4
#include "rc.h"
5
#include "getflags.h"
6
#include "exec.h"
7
#include "io.h"
8
#include "fns.h"
9
/*
10
 * Search through the following code to see if we're just going to exit.
11
 */
12
int
13
exitnext(void){
14
	union code *c=&runq->code[runq->pc];
15
	while(c->f==Xpopredir) c++;
16
	return c->f==Xexit;
17
}
18
 
19
void
20
Xsimple(void)
21
{
22
	word *a;
23
	thread *p = runq;
24
	var *v;
25
	struct builtin *bp;
26
	int pid;
27
	globlist();
28
	a = runq->argv->words;
29
	if(a==0){
30
		Xerror1("empty argument list");
31
		return;
32
	}
33
	if(flag['x'])
34
		pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
35
	v = gvlook(a->word);
36
	if(v->fn)
37
		execfunc(v);
38
	else{
39
		if(strcmp(a->word, "builtin")==0){
40
			if(count(a)==1){
41
				pfmt(err, "builtin: empty argument list\n");
42
				setstatus("empty arg list");
43
				poplist();
44
				return;
45
			}
46
			a = a->next;
47
			popword();
48
		}
49
		for(bp = Builtin;bp->name;bp++)
50
			if(strcmp(a->word, bp->name)==0){
51
				(*bp->fnc)();
52
				return;
53
			}
54
		if(exitnext()){
55
			/* fork and wait is redundant */
56
			pushword("exec");
57
			execexec();
58
			Xexit();
59
		}
60
		else{
61
			flush(err);
62
			Updenv();	/* necessary so changes don't go out again */
63
			if((pid = execforkexec()) < 0){
64
				Xerror("try again");
65
				return;
66
			}
67
 
68
			/* interrupts don't get us out */
69
			poplist();
70
			while(Waitfor(pid, 1) < 0)
71
				;
72
		}
73
	}
74
}
75
struct word nullpath = { "", 0};
76
 
77
void
78
doredir(redir *rp)
79
{
80
	if(rp){
81
		doredir(rp->next);
82
		switch(rp->type){
83
		case ROPEN:
84
			if(rp->from!=rp->to){
85
				Dup(rp->from, rp->to);
86
				close(rp->from);
87
			}
88
			break;
89
		case RDUP:
90
			Dup(rp->from, rp->to);
91
			break;
92
		case RCLOSE:
93
			close(rp->from);
94
			break;
95
		}
96
	}
97
}
98
 
99
word*
100
searchpath(char *w)
101
{
102
	word *path;
103
	if(strncmp(w, "/", 1)==0
104
	|| strncmp(w, "#", 1)==0
105
	|| strncmp(w, "./", 2)==0
106
	|| strncmp(w, "../", 3)==0
107
	|| (path = vlook("path")->val)==0)
108
		path=&nullpath;
109
	return path;
110
}
111
 
112
void
113
execexec(void)
114
{
115
	popword();	/* "exec" */
116
	if(runq->argv->words==0){
117
		Xerror1("empty argument list");
118
		return;
119
	}
120
	doredir(runq->redir);
121
	Execute(runq->argv->words, searchpath(runq->argv->words->word));
122
	poplist();
123
}
124
 
125
void
126
execfunc(var *func)
127
{
128
	word *starval;
129
	popword();
130
	starval = runq->argv->words;
131
	runq->argv->words = 0;
132
	poplist();
133
	start(func->fn, func->pc, runq->local);
134
	runq->local = newvar(strdup("*"), runq->local);
135
	runq->local->val = starval;
136
	runq->local->changed = 1;
137
}
138
 
139
int
140
dochdir(char *word)
141
{
142
	/* report to /dev/wdir if it exists and we're interactive */
143
	static int wdirfd = -2;
144
	if(chdir(word)<0) return -1;
145
	if(flag['i']!=0){
146
		if(wdirfd==-2)	/* try only once */
147
			wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
148
		if(wdirfd>=0) {
149
			fcntl(wdirfd, F_SETFD, FD_CLOEXEC);
150
			write(wdirfd, word, strlen(word));
151
		}
152
	}
153
	return 1;
154
}
155
 
156
static char *
157
appfile(char *dir, char *comp)
158
{
159
	int dirlen, complen;
160
	char *s, *p;
161
 
162
	dirlen = strlen(dir);
163
	complen = strlen(comp);
164
	s = emalloc(dirlen + 1 + complen + 1);
165
	memmove(s, dir, dirlen);
166
	p = s + dirlen;
167
	*p++ = '/';
168
	memmove(p, comp, complen);
169
	p[complen] = '\0';
170
	return s;
171
}
172
 
173
void
174
execcd(void)
175
{
176
	word *a = runq->argv->words;
177
	word *cdpath;
178
	char *dir;
179
 
180
	setstatus("can't cd");
181
	cdpath = vlook("cdpath")->val;
182
	switch(count(a)){
183
	default:
184
		pfmt(err, "Usage: cd [directory]\n");
185
		break;
186
	case 2:
187
		if(a->next->word[0]=='/' || cdpath==0)
188
			cdpath = &nullpath;
189
		for(; cdpath; cdpath = cdpath->next){
190
			if(cdpath->word[0] != '\0')
191
				dir = appfile(cdpath->word, a->next->word);
192
			else
193
				dir = strdup(a->next->word);
194
 
195
			if(dochdir(dir) >= 0){
196
				if(cdpath->word[0] != '\0' &&
197
				    strcmp(cdpath->word, ".") != 0)
198
					pfmt(err, "%s\n", dir);
199
				free(dir);
200
				setstatus("");
201
				break;
202
			}
203
			free(dir);
204
		}
205
		if(cdpath==0)
206
			pfmt(err, "Can't cd %s: %r\n", a->next->word);
207
		break;
208
	case 1:
209
		a = vlook("home")->val;
210
		if(count(a)>=1){
211
			if(dochdir(a->word)>=0)
212
				setstatus("");
213
			else
214
				pfmt(err, "Can't cd %s: %r\n", a->word);
215
		}
216
		else
217
			pfmt(err, "Can't cd -- $home empty\n");
218
		break;
219
	}
220
	poplist();
221
}
222
 
223
void
224
execexit(void)
225
{
226
	switch(count(runq->argv->words)){
227
	default:
228
		pfmt(err, "Usage: exit [status]\nExiting anyway\n");
229
	case 2:
230
		setstatus(runq->argv->words->next->word);
231
	case 1:	Xexit();
232
	}
233
}
234
 
235
void
236
execshift(void)
237
{
238
	int n;
239
	word *a;
240
	var *star;
241
	switch(count(runq->argv->words)){
242
	default:
243
		pfmt(err, "Usage: shift [n]\n");
244
		setstatus("shift usage");
245
		poplist();
246
		return;
247
	case 2:
248
		n = atoi(runq->argv->words->next->word);
249
		break;
250
	case 1:
251
		n = 1;
252
		break;
253
	}
254
	star = vlook("*");
255
	for(;n && star->val;--n){
256
		a = star->val->next;
257
		efree(star->val->word);
258
		efree((char *)star->val);
259
		star->val = a;
260
		star->changed = 1;
261
	}
262
	setstatus("");
263
	poplist();
264
}
265
 
266
int
267
octal(char *s)
268
{
269
	int n = 0;
270
	while(*s==' ' || *s=='\t' || *s=='\n') s++;
271
	while('0'<=*s && *s<='7') n = n*8+*s++-'0';
272
	return n;
273
}
274
 
275
int
276
mapfd(int fd)
277
{
278
	redir *rp;
279
	for(rp = runq->redir;rp;rp = rp->next){
280
		switch(rp->type){
281
		case RCLOSE:
282
			if(rp->from==fd)
283
				fd=-1;
284
			break;
285
		case RDUP:
286
		case ROPEN:
287
			if(rp->to==fd)
288
				fd = rp->from;
289
			break;
290
		}
291
	}
292
	return fd;
293
}
294
union code rdcmds[4];
295
 
296
void
297
execcmds(io *f)
298
{
299
	static int first = 1;
300
	if(first){
301
		rdcmds[0].i = 1;
302
		rdcmds[1].f = Xrdcmds;
303
		rdcmds[2].f = Xreturn;
304
		first = 0;
305
	}
306
	start(rdcmds, 1, runq->local);
307
	runq->cmdfd = f;
308
	runq->iflast = 0;
309
}
310
 
311
void
312
execeval(void)
313
{
314
	char *cmdline, *s, *t;
315
	int len = 0;
316
	word *ap;
317
	if(count(runq->argv->words)<=1){
318
		Xerror1("Usage: eval cmd ...");
319
		return;
320
	}
321
	eflagok = 1;
322
	for(ap = runq->argv->words->next;ap;ap = ap->next)
323
		len+=1+strlen(ap->word);
324
	cmdline = emalloc(len);
325
	s = cmdline;
326
	for(ap = runq->argv->words->next;ap;ap = ap->next){
327
		for(t = ap->word;*t;) *s++=*t++;
328
		*s++=' ';
329
	}
330
	s[-1]='\n';
331
	poplist();
332
	execcmds(opencore(cmdline, len));
333
	efree(cmdline);
334
}
335
union code dotcmds[14];
336
 
337
void
338
execdot(void)
339
{
340
	int iflag = 0;
341
	int fd;
342
	list *av;
343
	thread *p = runq;
344
	char *zero, *file;
345
	word *path;
346
	static int first = 1;
347
 
348
	if(first){
349
		dotcmds[0].i = 1;
350
		dotcmds[1].f = Xmark;
351
		dotcmds[2].f = Xword;
352
		dotcmds[3].s="0";
353
		dotcmds[4].f = Xlocal;
354
		dotcmds[5].f = Xmark;
355
		dotcmds[6].f = Xword;
356
		dotcmds[7].s="*";
357
		dotcmds[8].f = Xlocal;
358
		dotcmds[9].f = Xrdcmds;
359
		dotcmds[10].f = Xunlocal;
360
		dotcmds[11].f = Xunlocal;
361
		dotcmds[12].f = Xreturn;
362
		first = 0;
363
	}
364
	else
365
		eflagok = 1;
366
	popword();
367
	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
368
		iflag = 1;
369
		popword();
370
	}
371
	/* get input file */
372
	if(p->argv->words==0){
373
		Xerror1("Usage: . [-i] file [arg ...]");
374
		return;
375
	}
376
	zero = strdup(p->argv->words->word);
377
	popword();
378
	fd = -1;
379
	for(path = searchpath(zero); path; path = path->next){
380
		if(path->word[0] != '\0')
381
			file = appfile(path->word, zero);
382
		else
383
			file = strdup(zero);
384
 
385
		fd = open(file, 0);
386
		free(file);
387
		if(fd >= 0)
388
			break;
389
		if(strcmp(file, "/dev/stdin")==0){	/* for sun & ucb */
390
			fd = Dup1(0);
391
			if(fd>=0)
392
				break;
393
		}
394
	}
395
	if(fd<0){
396
		pfmt(err, "%s: ", zero);
397
		setstatus("can't open");
398
		Xerror(".: can't open");
399
		return;
400
	}
401
	/* set up for a new command loop */
402
	start(dotcmds, 1, (struct var *)0);
403
	pushredir(RCLOSE, fd, 0);
404
	runq->cmdfile = zero;
405
	runq->cmdfd = openfd(fd);
406
	runq->iflag = iflag;
407
	runq->iflast = 0;
408
	/* push $* value */
409
	pushlist();
410
	runq->argv->words = p->argv->words;
411
	/* free caller's copy of $* */
412
	av = p->argv;
413
	p->argv = av->next;
414
	efree((char *)av);
415
	/* push $0 value */
416
	pushlist();
417
	pushword(zero);
418
	ndot++;
419
}
420
 
421
void
422
execflag(void)
423
{
424
	char *letter, *val;
425
	switch(count(runq->argv->words)){
426
	case 2:
427
		setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
428
		break;
429
	case 3:
430
		letter = runq->argv->words->next->word;
431
		val = runq->argv->words->next->next->word;
432
		if(strlen(letter)==1){
433
			if(strcmp(val, "+")==0){
434
				flag[(uchar)letter[0]] = flagset;
435
				break;
436
			}
437
			if(strcmp(val, "-")==0){
438
				flag[(uchar)letter[0]] = 0;
439
				break;
440
			}
441
		}
442
	default:
443
		Xerror1("Usage: flag [letter] [+-]");
444
		return;
445
	}
446
	poplist();
447
}
448
 
449
void
450
execwhatis(void){	/* mildly wrong -- should fork before writing */
451
	word *a, *b, *path;
452
	var *v;
453
	struct builtin *bp;
454
	char *file;
455
	struct io out[1];
456
	int found, sep;
457
	a = runq->argv->words->next;
458
	if(a==0){
459
		Xerror1("Usage: whatis name ...");
460
		return;
461
	}
462
	setstatus("");
463
	memset(out, 0, sizeof out);
464
	out->fd = mapfd(1);
465
	out->bufp = out->buf;
466
	out->ebuf = &out->buf[NBUF];
467
	out->strp = 0;
468
	for(;a;a = a->next){
469
		v = vlook(a->word);
470
		if(v->val){
471
			pfmt(out, "%s=", a->word);
472
			if(v->val->next==0)
473
				pfmt(out, "%q\n", v->val->word);
474
			else{
475
				sep='(';
476
				for(b = v->val;b && b->word;b = b->next){
477
					pfmt(out, "%c%q", sep, b->word);
478
					sep=' ';
479
				}
480
				pfmt(out, ")\n");
481
			}
482
			found = 1;
483
		}
484
		else
485
			found = 0;
486
		v = gvlook(a->word);
487
		if(v->fn)
488
			pfmt(out, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
489
		else{
490
			for(bp = Builtin;bp->name;bp++)
491
				if(strcmp(a->word, bp->name)==0){
492
					pfmt(out, "builtin %s\n", a->word);
493
					break;
494
				}
495
			if(!bp->name){
496
				for(path = searchpath(a->word); path;
497
				    path = path->next){
498
					if(path->word[0] != '\0')
499
						file = appfile(path->word,
500
							a->word);
501
					else
502
						file = strdup(a->word);
503
					if(Executable(file)){
504
						pfmt(out, "%s\n", file);
505
						free(file);
506
						break;
507
					}
508
					free(file);
509
				}
510
				if(!path && !found){
511
					pfmt(err, "%s: not found\n", a->word);
512
					setstatus("not found");
513
				}
514
			}
515
		}
516
	}
517
	poplist();
518
	flush(err);
519
}
520
 
521
void
522
execwait(void)
523
{
524
	switch(count(runq->argv->words)){
525
	default:
526
		Xerror1("Usage: wait [pid]");
527
		return;
528
	case 2:
529
		Waitfor(atoi(runq->argv->words->next->word), 0);
530
		break;
531
	case 1:
532
		Waitfor(-1, 0);
533
		break;
534
	}
535
	poplist();
536
}