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