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
 * Unix 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 "io.h"
8
#include "exec.h"
9
#include "getflags.h"
10
#include <errno.h>
11
 
12
char *Rcmain = "/usr/lib/rcmain";
13
char *Fdprefix = "/dev/fd/";
14
 
15
void execfinit(void);
16
 
17
struct builtin Builtin[] = {
18
	"cd",		execcd,
19
	"whatis",	execwhatis,
20
	"eval",		execeval,
21
	"exec",		execexec,	/* but with popword first */
22
	"exit",		execexit,
23
	"shift",	execshift,
24
	"wait",		execwait,
25
	"umask",	execumask,
26
	".",		execdot,
27
	"finit",	execfinit,
28
	"flag",		execflag,
29
 
30
};
31
#define	SEP	'\1'
32
char **environp;
33
 
34
struct word*
35
enval(s)
36
register char *s;
37
{
38
	char *t, c;
39
	struct word *v;
40
	for(t = s;*t && *t!=SEP;t++);
41
	c=*t;
42
	*t='\0';
43
	v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
44
	*t = c;
45
	return v;
46
}
47
 
48
void
49
Vinit(void)
50
{
51
	extern char **environ;
52
	char *s;
53
	char **env = environ;
54
	environp = env;
55
	for(;*env;env++){
56
		for(s=*env;*s && *s!='(' && *s!='=';s++);
57
		switch(*s){
58
		case '\0':
59
			pfmt(err, "environment %q?\n", *env);
60
			break;
61
		case '=':
62
			*s='\0';
63
			setvar(*env, enval(s+1));
64
			*s='=';
65
			break;
66
		case '(':	/* ignore functions for now */
67
			break;
68
		}
69
	}
70
}
71
 
72
char **envp;
73
 
74
void
75
Xrdfn(void)
76
{
77
	char *s;
78
	int len;
79
	for(;*envp;envp++){
80
		for(s=*envp;*s && *s!='(' && *s!='=';s++);
81
		switch(*s){
82
		case '\0':
83
			pfmt(err, "environment %q?\n", *envp);
84
			break;
85
		case '=':	/* ignore variables */
86
			break;
87
		case '(':		/* Bourne again */
88
			s=*envp+3;
89
			envp++;
90
			len = strlen(s);
91
			s[len]='\n';
92
			execcmds(opencore(s, len+1));
93
			s[len]='\0';
94
			return;
95
		}
96
	}
97
	Xreturn();
98
}
99
 
100
union code rdfns[4];
101
 
102
void
103
execfinit(void)
104
{
105
	static int first = 1;
106
	if(first){
107
		rdfns[0].i = 1;
108
		rdfns[1].f = Xrdfn;
109
		rdfns[2].f = Xjump;
110
		rdfns[3].i = 1;
111
		first = 0;
112
	}
113
	Xpopm();
114
	envp = environp;
115
	start(rdfns, 1, runq->local);
116
}
117
 
118
int
119
cmpenv(const void *aa, const void *ab)
120
{
121
	char **a = aa, **b = ab;
122
 
123
	return strcmp(*a, *b);
124
}
125
 
126
char **
127
mkenv(void)
128
{
129
	char **env, **ep, *p, *q;
130
	struct var **h, *v;
131
	struct word *a;
132
	int nvar = 0, nchr = 0, sep;
133
 
134
	/*
135
	 * Slightly kludgy loops look at locals then globals.
136
	 * locals no longer exist - geoff
137
	 */
138
	for(h = gvar-1; h != &gvar[NVAR]; h++)
139
	for(v = h >= gvar? *h: runq->local; v ;v = v->next){
140
		if((v==vlook(v->name)) && v->val){
141
			nvar++;
142
			nchr+=strlen(v->name)+1;
143
			for(a = v->val;a;a = a->next)
144
				nchr+=strlen(a->word)+1;
145
		}
146
		if(v->fn){
147
			nvar++;
148
			nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
149
		}
150
	}
151
	env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
152
	ep = env;
153
	p = (char *)&env[nvar+1];
154
	for(h = gvar-1; h != &gvar[NVAR]; h++)
155
	for(v = h >= gvar? *h: runq->local;v;v = v->next){
156
		if((v==vlook(v->name)) && v->val){
157
			*ep++=p;
158
			q = v->name;
159
			while(*q) *p++=*q++;
160
			sep='=';
161
			for(a = v->val;a;a = a->next){
162
				*p++=sep;
163
				sep = SEP;
164
				q = a->word;
165
				while(*q) *p++=*q++;
166
			}
167
			*p++='\0';
168
		}
169
		if(v->fn){
170
			*ep++=p;
171
			*p++='#'; *p++='('; *p++=')';	/* to fool Bourne */
172
			*p++='f'; *p++='n'; *p++=' ';
173
			q = v->name;
174
			while(*q) *p++=*q++;
175
			*p++=' ';
176
			q = v->fn[v->pc-1].s;
177
			while(*q) *p++=*q++;
178
			*p++='\0';
179
		}
180
	}
181
	*ep = 0;
182
	qsort((void *)env, nvar, sizeof ep[0], cmpenv);
183
	return env;	
184
}
185
char *sigmsg[] = {
186
/*  0 normal  */ 0,
187
/*  1 SIGHUP  */ "Hangup",
188
/*  2 SIGINT  */ 0,
189
/*  3 SIGQUIT */ "Quit",
190
/*  4 SIGILL  */ "Illegal instruction",
191
/*  5 SIGTRAP */ "Trace/BPT trap",
192
/*  6 SIGIOT  */ "abort",
193
/*  7 SIGEMT  */ "EMT trap",
194
/*  8 SIGFPE  */ "Floating exception",
195
/*  9 SIGKILL */ "Killed",
196
/* 10 SIGBUS  */ "Bus error",
197
/* 11 SIGSEGV */ "Memory fault",
198
/* 12 SIGSYS  */ "Bad system call",
199
/* 13 SIGPIPE */ 0,
200
/* 14 SIGALRM */ "Alarm call",
201
/* 15 SIGTERM */ "Terminated",
202
/* 16 unused  */ "signal 16",
203
/* 17 SIGSTOP */ "Process stopped",
204
/* 18 unused  */ "signal 18",
205
/* 19 SIGCONT */ "Process continued",
206
/* 20 SIGCHLD */ "Child death",
207
};
208
 
209
void
210
Waitfor(int pid, int persist)
211
{
212
	int wpid, sig;
213
	struct thread *p;
214
	int wstat;
215
	char wstatstr[12];
216
 
217
	for(;;){
218
		errno = 0;
219
		wpid = wait(&wstat);
220
		if(errno==EINTR && persist)
221
			continue;
222
		if(wpid==-1)
223
			break;
224
		sig = wstat&0177;
225
		if(sig==0177){
226
			pfmt(err, "trace: ");
227
			sig = (wstat>>8)&0177;
228
		}
229
		if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
230
			if(pid!=wpid)
231
				pfmt(err, "%d: ", wpid);
232
			if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))
233
				pfmt(err, "%s", sigmsg[sig]);
234
			else if(sig==0177) pfmt(err, "stopped by ptrace");
235
			else pfmt(err, "signal %d", sig);
236
			if(wstat&0200)pfmt(err, " -- core dumped");
237
			pfmt(err, "\n");
238
		}
239
		wstat = sig?sig+1000:(wstat>>8)&0xFF;
240
		if(wpid==pid){
241
			inttoascii(wstatstr, wstat);
242
			setstatus(wstatstr);
243
			break;
244
		}
245
		else{
246
			for(p = runq->ret;p;p = p->ret)
247
				if(p->pid==wpid){
248
					p->pid=-1;
249
					inttoascii(p->status, wstat);
250
					break;
251
				}
252
		}
253
	}
254
}
255
 
256
char **
257
mkargv(a)
258
register struct word *a;
259
{
260
	char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
261
	char **argp = argv+1;	/* leave one at front for runcoms */
262
 
263
	for(;a;a = a->next)
264
		*argp++=a->word;
265
	*argp = 0;
266
	return argv;
267
}
268
 
269
void
270
Updenv(void)
271
{
272
}
273
 
274
void
275
Execute(struct word *args, struct word *path)
276
{
277
	char *msg="not found";
278
	int txtbusy = 0;
279
	char **env = mkenv();
280
	char **argv = mkargv(args);
281
	char file[512];
282
 
283
	for(;path;path = path->next){
284
		strcpy(file, path->word);
285
		if(file[0])
286
			strcat(file, "/");
287
		strcat(file, argv[1]);
288
ReExec:
289
		execve(file, argv+1, env);
290
		switch(errno){
291
		case ENOEXEC:
292
			pfmt(err, "%s: Bourne again\n", argv[1]);
293
			argv[0]="sh";
294
			argv[1] = strdup(file);
295
			execve("/bin/sh", argv, env);
296
			goto Bad;
297
		case ETXTBSY:
298
			if(++txtbusy!=5){
299
				sleep(txtbusy);
300
				goto ReExec;
301
			}
302
			msg="text busy"; goto Bad;
303
		case EACCES:
304
			msg="no access";
305
			break;
306
		case ENOMEM:
307
			msg="not enough memory"; goto Bad;
308
		case E2BIG:
309
			msg="too big"; goto Bad;
310
		}
311
	}
312
Bad:
313
	pfmt(err, "%s: %s\n", argv[1], msg);
314
	efree((char *)env);
315
	efree((char *)argv);
316
}
317
 
318
#define	NDIR	14		/* should get this from param.h */
319
 
320
Globsize(p)
321
register char *p;
322
{
323
	int isglob = 0, globlen = NDIR+1;
324
	for(;*p;p++){
325
		if(*p==GLOB){
326
			p++;
327
			if(*p!=GLOB)
328
				isglob++;
329
			globlen+=*p=='*'?NDIR:1;
330
		}
331
		else
332
			globlen++;
333
	}
334
	return isglob?globlen:0;
335
}
336
 
337
#include <sys/types.h>
338
#include <dirent.h>
339
 
340
#define	NDIRLIST	50
341
 
342
DIR *dirlist[NDIRLIST];
343
 
344
Opendir(name)
345
char *name;
346
{
347
	DIR **dp;
348
	for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
349
		if(*dp==0){
350
			*dp = opendir(name);
351
			return *dp?dp-dirlist:-1;
352
		}
353
	return -1;
354
}
355
 
356
int
357
Readdir(int f, char *p, int onlydirs)
358
{
359
	struct dirent *dp = readdir(dirlist[f]);
360
 
361
	if(dp==0)
362
		return 0;
363
	strcpy(p, dp->d_name);
364
	return 1;
365
}
366
 
367
void
368
Closedir(int f)
369
{
370
	closedir(dirlist[f]);
371
	dirlist[f] = 0;
372
}
373
 
374
char *Signame[] = {
375
	"sigexit",	"sighup",	"sigint",	"sigquit",
376
	"sigill",	"sigtrap",	"sigiot",	"sigemt",
377
	"sigfpe",	"sigkill",	"sigbus",	"sigsegv",
378
	"sigsys",	"sigpipe",	"sigalrm",	"sigterm",
379
	"sig16",	"sigstop",	"sigtstp",	"sigcont",
380
	"sigchld",	"sigttin",	"sigttou",	"sigtint",
381
	"sigxcpu",	"sigxfsz",	"sig26",	"sig27",
382
	"sig28",	"sig29",	"sig30",	"sig31",
383
	0,
384
};
385
 
386
void
387
gettrap(int sig)
388
{
389
	signal(sig, gettrap);
390
	trap[sig]++;
391
	ntrap++;
392
	if(ntrap>=NSIG){
393
		pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
394
		signal(SIGABRT, (void (*)())0);
395
		kill(getpid(), SIGABRT);
396
	}
397
}
398
 
399
void
400
Trapinit(void)
401
{
402
	int i;
403
	void (*sig)();
404
 
405
	if(1 || flag['d']){	/* wrong!!! */
406
		sig = signal(SIGINT, gettrap);
407
		if(sig==SIG_IGN)
408
			signal(SIGINT, SIG_IGN);
409
	}
410
	else{
411
		for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
412
			sig = signal(i, gettrap);
413
			if(sig==SIG_IGN)
414
				signal(i, SIG_IGN);
415
		}
416
	}
417
}
418
 
419
Unlink(name)
420
char *name;
421
{
422
	return unlink(name);
423
}
424
Write(fd, buf, cnt)
425
char *buf;
426
{
427
	return write(fd, buf, cnt);
428
}
429
Read(fd, buf, cnt)
430
char *buf;
431
{
432
	return read(fd, buf, cnt);
433
}
434
Seek(fd, cnt, whence)
435
long cnt;
436
{
437
	return lseek(fd, cnt, whence);
438
}
439
Executable(file)
440
char *file;
441
{
442
	return(access(file, 01)==0);
443
}
444
Creat(file)
445
char *file;
446
{
447
	return creat(file, 0666);
448
}
449
Dup(a, b){
450
	return dup2(a, b);
451
}
452
Dup1(a){
453
	return dup(a);
454
}
455
/*
456
 * Wrong:  should go through components of a|b|c and return the maximum.
457
 */
458
void
459
Exit(char *stat)
460
{
461
	int n = 0;
462
 
463
	while(*stat){
464
		if(*stat!='|'){
465
			if(*stat<'0' || '9'<*stat)
466
				exit(1);
467
			else n = n*10+*stat-'0';
468
		}
469
		stat++;
470
	}
471
	exit(n);
472
}
473
Eintr(){
474
	return errno==EINTR;
475
}
476
 
477
void
478
Noerror()
479
{
480
	errno = 0;
481
}
482
Isatty(fd){
483
	return isatty(fd);
484
}
485
 
486
void
487
Abort()
488
{
489
	abort();
490
}
491
 
492
void
493
execumask(void)		/* wrong -- should fork before writing */
494
{
495
	int m;
496
	struct io out[1];
497
	switch(count(runq->argv->words)){
498
	default:
499
		pfmt(err, "Usage: umask [umask]\n");
500
		setstatus("umask usage");
501
		poplist();
502
		return;
503
	case 2:
504
		umask(octal(runq->argv->words->next->word));
505
		break;
506
	case 1: 
507
		umask(m = umask(0));
508
		out->fd = mapfd(1);
509
		out->bufp = out->buf;
510
		out->ebuf=&out->buf[NBUF];
511
		out->strp = 0;
512
		pfmt(out, "%o\n", m);
513
		break;
514
	}
515
	setstatus("");
516
	poplist();
517
}
518
 
519
void
520
Memcpy(a, b, n)
521
char *a, *b;
522
{
523
	memmove(a, b, n);
524
}
525
 
526
void*
527
Malloc(unsigned long n)
528
{
529
	return (void *)malloc(n);
530
}
531
 
532
void
533
errstr(char *buf, int len)
534
{
535
	strncpy(buf, strerror(errno), len);
536
}
537
 
538
int
539
needsrcquote(int c)
540
{
541
	if(c <= ' ')
542
		return 1;
543
	if(strchr("`^#*[]=|\\?${}()'<>&;", c))
544
		return 1;
545
	return 0;
546
}
547
 
548
int
549
rfork(int bits)
550
{
551
	return fork();
552
}
553
 
554
int *waitpids;
555
int nwaitpids;
556
 
557
void
558
addwaitpid(int pid)
559
{
560
	waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
561
	if(waitpids == 0)
562
		panic("Can't realloc %d waitpids", nwaitpids+1);
563
	waitpids[nwaitpids++] = pid;
564
}
565
 
566
void
567
delwaitpid(int pid)
568
{
569
	int r, w;
570
 
571
	for(r=w=0; r<nwaitpids; r++)
572
		if(waitpids[r] != pid)
573
			waitpids[w++] = waitpids[r];
574
	nwaitpids = w;
575
}
576
 
577
void
578
clearwaitpids(void)
579
{
580
	nwaitpids = 0;
581
}
582
 
583
int
584
havewaitpid(int pid)
585
{
586
	int i;
587
 
588
	for(i=0; i<nwaitpids; i++)
589
		if(waitpids[i] == pid)
590
			return 1;
591
	return 0;
592
}