Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Plan 9 versions of system-specific functions
3
 *	By convention, exported routines herein have names beginning with an
4
 *	upper case letter.
5
 */
6
#include "rc.h"
7
#include "exec.h"
8
#include "io.h"
9
#include "fns.h"
10
#include "getflags.h"
11
char *Signame[] = {
12
	"sigexit",	"sighup",	"sigint",	"sigquit",
13
	"sigalrm",	"sigkill",	"sigfpe",	"sigterm",
14
 
15
};
16
char *syssigname[] = {
17
	"exit",		/* can't happen */
18
	"hangup",
19
	"interrupt",
20
	"quit",		/* can't happen */
21
	"alarm",
22
	"kill",
23
	"sys: fp: ",
24
	"term",
25
 
26
};
27
char *Rcmain = "/rc/lib/rcmain";
28
char *Fdprefix = "/fd/";
29
 
30
void execfinit(void);
31
void execbind(void);
32
 
33
builtin Builtin[] = {
34
	"cd",		execcd,
35
	"whatis",	execwhatis,
36
	"eval",		execeval,
37
	"exec",		execexec,	/* but with popword first */
38
	"exit",		execexit,
39
	"shift",	execshift,
40
	"wait",		execwait,
41
	".",		execdot,
42
	"finit",	execfinit,
43
	"flag",		execflag,
44
 
45
};
46
 
47
void
48
Vinit(void)
49
{
50
	int dir, f, len;
51
	word *val;
52
	char *buf, *s;
53
	Dir *ent;
54
	int i, nent;
55
	char envname[256];
56
	dir = open("/env", OREAD);
57
	if(dir<0){
58
		pfmt(err, "rc: can't open /env: %r\n");
59
		return;
60
	}
61
	ent = nil;
62
	for(;;){
63
		nent = dirread(dir, &ent);
64
		if(nent <= 0)
65
			break;
66
		for(i = 0; i<nent; i++){
67
			len = ent[i].length;
68
			if(len && strncmp(ent[i].name, "fn#", 3)!=0){
69
				snprint(envname, sizeof envname, "/env/%s", ent[i].name);
70
				if((f = open(envname, 0))>=0){
71
					buf = emalloc((int)len+1);
72
					read(f, buf, (long)len);
73
					val = 0;
74
					/* Charitably add a 0 at the end if need be */
75
					if(buf[len-1])
76
						buf[len++]='\0';
77
					s = buf+len-1;
78
					for(;;){
79
						while(s!=buf && s[-1]!='\0') --s;
80
						val = newword(s, val);
81
						if(s==buf)
82
							break;
83
						--s;
84
					}
85
					setvar(ent[i].name, val);
86
					vlook(ent[i].name)->changed = 0;
87
					close(f);
88
					efree(buf);
89
				}
90
			}
91
		}
92
		free(ent);
93
	}
94
	close(dir);
95
}
96
int envdir;
97
 
98
void
99
Xrdfn(void)
100
{
101
	int f, len;
102
	static Dir *ent, *allocent;
103
	static int nent;
104
	Dir *e;
105
	char envname[256];
106
 
107
	for(;;){
108
		if(nent == 0){
109
			free(allocent);
110
			nent = dirread(envdir, &allocent);
111
			ent = allocent;
112
		}
113
		if(nent <= 0)
114
			break;
115
		while(nent){
116
			e = ent++;
117
			nent--;
118
			len = e->length;
119
			if(len && strncmp(e->name, "fn#", 3)==0){
120
				snprint(envname, sizeof envname, "/env/%s", e->name);
121
				if((f = open(envname, 0))>=0){
122
					execcmds(openfd(f));
123
					return;
124
				}
125
			}
126
		}
127
	}
128
	close(envdir);
129
	Xreturn();
130
}
131
union code rdfns[4];
132
 
133
void
134
execfinit(void)
135
{
136
	static int first = 1;
137
	if(first){
138
		rdfns[0].i = 1;
139
		rdfns[1].f = Xrdfn;
140
		rdfns[2].f = Xjump;
141
		rdfns[3].i = 1;
142
		first = 0;
143
	}
144
	Xpopm();
145
	envdir = open("/env", 0);
146
	if(envdir<0){
147
		pfmt(err, "rc: can't open /env: %r\n");
148
		return;
149
	}
150
	start(rdfns, 1, runq->local);
151
}
152
 
153
int
154
Waitfor(int pid, int persist)
155
{
156
	thread *p;
157
	Waitmsg *w;
158
	char errbuf[ERRMAX];
159
 
160
	while((w = wait()) != nil){
161
		if(w->pid==pid){
162
			setstatus(w->msg);
163
			free(w);
164
			return 0;
165
		}
166
		for(p = runq->ret;p;p = p->ret)
167
			if(p->pid==w->pid){
168
				p->pid=-1;
169
				strcpy(p->status, w->msg);
170
			}
171
		free(w);
172
	}
173
 
174
	errstr(errbuf, sizeof errbuf);
175
	if(strcmp(errbuf, "interrupted")==0) return -1;
176
	return 0;
177
}
178
 
179
char*
180
*mkargv(word *a)
181
{
182
	char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
183
	char **argp = argv+1;	/* leave one at front for runcoms */
184
	for(;a;a = a->next) *argp++=a->word;
185
	*argp = 0;
186
	return argv;
187
}
188
 
189
void
190
addenv(var *v)
191
{
192
	char envname[256];
193
	word *w;
194
	int f;
195
	io *fd;
196
	if(v->changed){
197
		v->changed = 0;
198
		snprint(envname, sizeof envname, "/env/%s", v->name);
199
		if((f = Creat(envname))<0)
200
			pfmt(err, "rc: can't open %s: %r\n", envname);
201
		else{
202
			for(w = v->val;w;w = w->next)
203
				write(f, w->word, strlen(w->word)+1L);
204
			close(f);
205
		}
206
	}
207
	if(v->fnchanged){
208
		v->fnchanged = 0;
209
		snprint(envname, sizeof envname, "/env/fn#%s", v->name);
210
		if((f = Creat(envname))<0)
211
			pfmt(err, "rc: can't open %s: %r\n", envname);
212
		else{
213
			if(v->fn){
214
				fd = openfd(f);
215
				pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
216
				closeio(fd);
217
			}
218
			close(f);
219
		}
220
	}
221
}
222
 
223
void
224
updenvlocal(var *v)
225
{
226
	if(v){
227
		updenvlocal(v->next);
228
		addenv(v);
229
	}
230
}
231
 
232
void
233
Updenv(void)
234
{
235
	var *v, **h;
236
	for(h = gvar;h!=&gvar[NVAR];h++)
237
		for(v=*h;v;v = v->next)
238
			addenv(v);
239
	if(runq)
240
		updenvlocal(runq->local);
241
}
242
 
243
int
244
ForkExecute(char *file, char **argv, int sin, int sout, int serr)
245
{
246
	int pid;
247
 
248
{int i;
249
fprint(2, "forkexec %s", file);
250
for(i = 0; argv[i]; i++)fprint(2, " %s", argv[i]);
251
fprint(2, " %d %d %d\n", sin, sout, serr);
252
}
253
	if(access(file, 1) != 0)
254
		return -1;
255
fprint(2, "forking\n");
256
	switch(pid = fork()){
257
	case -1:
258
		return -1;
259
	case 0:
260
		if(sin >= 0)
261
			dup(sin, 0);
262
		else
263
			close(0);
264
		if(sout >= 0)
265
			dup(sout, 1);
266
		else
267
			close(1);
268
		if(serr >= 0)
269
			dup(serr, 2);
270
		else
271
			close(2);
272
fprint(2, "execing\n");
273
		exec(file, argv);
274
fprint(2, "exec: %r\n");
275
		exits(file);
276
	}
277
	return pid;
278
}
279
 
280
void
281
Execute(word *args, word *path)
282
{
283
	char **argv = mkargv(args);
284
	char file[1024];
285
	int nc;
286
	Updenv();
287
	for(;path;path = path->next){
288
		nc = strlen(path->word);
289
		if(nc<1024){
290
			strcpy(file, path->word);
291
			if(file[0]){
292
				strcat(file, "/");
293
				nc++;
294
			}
295
			if(nc+strlen(argv[1])<1024){
296
				strcat(file, argv[1]);
297
				exec(file, argv+1);
298
			}
299
			else werrstr("command name too long");
300
		}
301
	}
302
	rerrstr(file, sizeof file);
303
	pfmt(err, "%s: %s\n", argv[1], file);
304
	efree((char *)argv);
305
}
306
#define	NDIR	256		/* shoud be a better way */
307
 
308
int
309
Globsize(char *p)
310
{
311
	int isglob = 0, globlen = NDIR+1;
312
	for(;*p;p++){
313
		if(*p==GLOB){
314
			p++;
315
			if(*p!=GLOB)
316
				isglob++;
317
			globlen+=*p=='*'?NDIR:1;
318
		}
319
		else
320
			globlen++;
321
	}
322
	return isglob?globlen:0;
323
}
324
#define	NFD	50
325
#define	NDBUF	32
326
struct{
327
	Dir	*dbuf;
328
	int	i;
329
	int	n;
330
}dir[NFD];
331
 
332
int
333
Opendir(char *name)
334
{
335
	Dir *db;
336
	int f;
337
	f = open(name, 0);
338
	if(f==-1)
339
		return f;
340
	db = dirfstat(f);
341
	if(db!=nil && (db->mode&DMDIR)){
342
		if(f<NFD){
343
			dir[f].i = 0;
344
			dir[f].n = 0;
345
		}
346
		free(db);
347
		return f;
348
	}
349
	free(db);
350
	close(f);
351
	return -1;
352
}
353
 
354
static int
355
trimdirs(Dir *d, int nd)
356
{
357
	int r, w;
358
 
359
	for(r=w=0; r<nd; r++)
360
		if(d[r].mode&DMDIR)
361
			d[w++] = d[r];
362
	return w;
363
}
364
 
365
/*
366
 * onlydirs is advisory -- it means you only
367
 * need to return the directories.  it's okay to
368
 * return files too (e.g., on unix where you can't
369
 * tell during the readdir), but that just makes 
370
 * the globber work harder.
371
 */
372
int
373
Readdir(int f, void *p, int onlydirs)
374
{
375
	int n;
376
 
377
	if(f<0 || f>=NFD)
378
		return 0;
379
Again:
380
	if(dir[f].i==dir[f].n){	/* read */
381
		free(dir[f].dbuf);
382
		dir[f].dbuf = 0;
383
		n = dirread(f, &dir[f].dbuf);
384
		if(n>0){
385
			if(onlydirs){
386
				n = trimdirs(dir[f].dbuf, n);
387
				if(n == 0)
388
					goto Again;
389
			}	
390
			dir[f].n = n;
391
		}else
392
			dir[f].n = 0;
393
		dir[f].i = 0;
394
	}
395
	if(dir[f].i == dir[f].n)
396
		return 0;
397
	strcpy(p, dir[f].dbuf[dir[f].i].name);
398
	dir[f].i++;
399
	return 1;
400
}
401
 
402
void
403
Closedir(int f)
404
{
405
	if(f>=0 && f<NFD){
406
		free(dir[f].dbuf);
407
		dir[f].i = 0;
408
		dir[f].n = 0;
409
		dir[f].dbuf = 0;
410
	}
411
	close(f);
412
}
413
int interrupted = 0;
414
void
415
notifyf(void*, char *s)
416
{
417
	int i;
418
	for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
419
		if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
420
		goto Out;
421
	}
422
	pfmt(err, "rc: note: %s\n", s);
423
	noted(NDFLT);
424
	return;
425
Out:
426
	if(strcmp(s, "interrupt")!=0 || trap[i]==0){
427
		trap[i]++;
428
		ntrap++;
429
	}
430
	if(ntrap>=32){	/* rc is probably in a trap loop */
431
		pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
432
		abort();
433
	}
434
	noted(NCONT);
435
}
436
 
437
void
438
Trapinit(void)
439
{
440
	notify(notifyf);
441
}
442
 
443
void
444
Unlink(char *name)
445
{
446
	remove(name);
447
}
448
 
449
long
450
Write(int fd, void *buf, long cnt)
451
{
452
	return write(fd, buf, (long)cnt);
453
}
454
 
455
long
456
Read(int fd, void *buf, long cnt)
457
{
458
	return read(fd, buf, cnt);
459
}
460
 
461
long
462
Seek(int fd, long cnt, long whence)
463
{
464
	return seek(fd, cnt, whence);
465
}
466
 
467
int
468
Executable(char *file)
469
{
470
	Dir *statbuf;
471
	int ret;
472
 
473
	statbuf = dirstat(file);
474
	if(statbuf == nil)
475
		return 0;
476
	ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
477
	free(statbuf);
478
	return ret;
479
}
480
 
481
int
482
Creat(char *file)
483
{
484
	return create(file, 1, 0666L);
485
}
486
 
487
int
488
Dup(int a, int b)
489
{
490
	return dup(a, b);
491
}
492
 
493
int
494
Dup1(int)
495
{
496
	return -1;
497
}
498
 
499
void
500
Exit(char *stat)
501
{
502
	Updenv();
503
	setstatus(stat);
504
	exits(truestatus()?"":getstatus());
505
}
506
 
507
int
508
Eintr(void)
509
{
510
	return interrupted;
511
}
512
 
513
void
514
Noerror(void)
515
{
516
	interrupted = 0;
517
}
518
 
519
int
520
Isatty(int fd)
521
{
522
	Dir *d1, *d2;
523
	int ret;
524
 
525
	d1 = dirfstat(fd);
526
	if(d1 == nil)
527
		return 0;
528
	if(strncmp(d1->name, "ptty", 4)==0){	/* fwd complaints to philw */
529
		free(d1);
530
		return 1;
531
	}
532
	d2 = dirstat("/dev/cons");
533
	if(d2 == nil){
534
		free(d1);
535
		return 0;
536
	}
537
	ret = (d1->type==d2->type&&d1->dev==d2->dev&&d1->qid.path==d2->qid.path);
538
	free(d1);
539
	free(d2);
540
	return ret;
541
}
542
 
543
void
544
Abort(void)
545
{
546
	pfmt(err, "aborting\n");
547
	flush(err);
548
	Exit("aborting");
549
}
550
 
551
void
552
Memcpy(void *a, void *b, long n)
553
{
554
	memmove(a, b, n);
555
}
556
 
557
void*
558
Malloc(ulong n)
559
{
560
	return malloc(n);
561
}