2 * Unix versions of system-specific functions
3 * By convention, exported routines herein have names beginning with an
9 char Rcmain[]="/usr/lib/rcmain";
10 char Fdprefix[]="/dev/fd/";
11 int execumask(), execfinit();
12 struct builtin Builtin[] = {
16 "exec", execexec, /* but with popword first */
35 for(t = s;*t && *t!=SEP;t++);
38 v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
43 extern char **environ;
48 for(s=*env;*s && *s!='(' && *s!='=';s++);
51 pfmt(err, "environment %q?\n", *env);
55 setvar(*env, enval(s+1));
58 case '(': /* ignore functions for now */
68 for(s=*envp;*s && *s!='(' && *s!='=';s++);
71 pfmt(err, "environment %q?\n", *envp);
73 case '=': /* ignore variables */
75 case '(': /* Bourne again */
80 execcmds(opencore(s, len+1));
99 start(rdfns, 1, runq->local);
104 return strcmp(*a, *b);
110 char **env, **ep, *p, *q;
113 int nvar = 0, nchr = 0, sep;
115 * Slightly kludgy loops look at locals then globals
117 for(h = var-1;h!=&var[NVAR];h++) for(v = h>=var?*h:runq->local;v;v = v->next){
118 if((v==vlook(v->name)) && v->val){
120 nchr+=strlen(v->name)+1;
121 for(a = v->val;a;a = a->next)
122 nchr+=strlen(a->word)+1;
126 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
129 env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
131 p = (char *)&env[nvar+1];
132 for(h = var-1;h!=&var[NVAR];h++) for(v = h>=var?*h:runq->local;v;v = v->next){
133 if((v==vlook(v->name)) && v->val){
138 for(a = v->val;a;a = a->next){
148 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
149 *p++='f'; *p++='n'; *p++=' ';
153 q = v->fn[v->pc-1].s;
159 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
164 /* 1 SIGHUP */ "Hangup",
166 /* 3 SIGQUIT */ "Quit",
167 /* 4 SIGILL */ "Illegal instruction",
168 /* 5 SIGTRAP */ "Trace/BPT trap",
169 /* 6 SIGIOT */ "abort",
170 /* 7 SIGEMT */ "EMT trap",
171 /* 8 SIGFPE */ "Floating exception",
172 /* 9 SIGKILL */ "Killed",
173 /* 10 SIGBUS */ "Bus error",
174 /* 11 SIGSEGV */ "Memory fault",
175 /* 12 SIGSYS */ "Bad system call",
177 /* 14 SIGALRM */ "Alarm call",
178 /* 15 SIGTERM */ "Terminated",
179 /* 16 unused */ "signal 16",
180 /* 17 SIGSTOP */ "Process stopped",
181 /* 18 unused */ "signal 18",
182 /* 19 SIGCONT */ "Process continued",
183 /* 20 SIGCHLD */ "Child death",
185 Waitfor(pid, persist){
193 if(errno==EINTR && persist)
199 pfmt(err, "trace: ");
200 sig = (wstat>>8)&0177;
202 if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
204 pfmt(err, "%d: ", wpid);
205 if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))
206 pfmt(err, "%s", sigmsg[sig]);
207 else if(sig==0177) pfmt(err, "stopped by ptrace");
208 else pfmt(err, "signal %d", sig);
209 if(wstat&0200)pfmt(err, " -- core dumped");
212 wstat = sig?sig+1000:(wstat>>8)&0xFF;
214 inttoascii(wstatstr, wstat);
219 for(p = runq->ret;p;p = p->ret)
222 inttoascii(p->status, wstat);
231 register struct word *a;
233 char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
234 char **argp = argv+1; /* leave one at front for runcoms */
235 for(;a;a = a->next) *argp++=a->word;
241 register struct word *args, *path;
243 char *msg="not found";
245 char **env = mkenv();
246 char **argv = mkargv(args);
248 for(;path;path = path->next){
249 strcpy(file, path->word);
252 strcat(file, argv[1]);
254 execve(file, argv+1, env);
257 pfmt(err, "%s: Bourne again\n", argv[1]);
259 argv[1] = strdup(file);
260 execve("/bin/sh", argv, env);
267 msg="text busy"; goto Bad;
272 msg="not enough memory"; goto Bad;
274 msg="too big"; goto Bad;
278 pfmt(err, "%s: %s\n", argv[1], msg);
282 #define NDIR 14 /* should get this from param.h */
286 int isglob = 0, globlen = NDIR+1;
292 globlen+=*p=='*'?NDIR:1;
297 return isglob?globlen:0;
299 #include <sys/types.h>
302 DIR *dirlist[NDIRLIST];
307 for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
310 return *dp?dp-dirlist:-1;
314 Readdir(f, p, onlydirs)
317 int onlydirs; /* ignored, just advisory */
319 struct direct *dp = readdir(dirlist[f]);
322 strcpy(p, dp->d_name);
326 closedir(dirlist[f]);
330 "sigexit", "sighup", "sigint", "sigquit",
331 "sigill", "sigtrap", "sigiot", "sigemt",
332 "sigfpe", "sigkill", "sigbus", "sigsegv",
333 "sigsys", "sigpipe", "sigalrm", "sigterm",
334 "sig16", "sigstop", "sigtstp", "sigcont",
335 "sigchld", "sigttin", "sigttou", "sigtint",
336 "sigxcpu", "sigxfsz", "sig26", "sig27",
337 "sig28", "sig29", "sig30", "sig31",
344 signal(sig, gettrap);
348 pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
349 signal(SIGIOT, (int (*)())0);
350 kill(getpid(), SIGIOT);
356 if(1 || flag['d']){ /* wrong!!! */
357 sig = signal(SIGINT, gettrap);
359 signal(SIGINT, SIG_IGN);
362 for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
363 sig = signal(i, gettrap);
377 return write(fd, buf, cnt);
382 return read(fd, buf, cnt);
384 Seek(fd, cnt, whence)
387 return lseek(fd, cnt, whence);
392 return(access(file, 01)==0);
397 return creat(file, 0666);
406 * Wrong: should go through components of a|b|c and return the maximum.
414 if(*stat<'0' || '9'<*stat)
416 else n = n*10+*stat-'0';
434 execumask(){ /* wrong -- should fork before writing */
437 switch(count(runq->argv->words)){
439 pfmt(err, "Usage: umask [umask]\n");
440 setstatus("umask usage");
444 umask(octal(runq->argv->words->next->word));
449 out->bufp = out->buf;
450 out->ebuf=&out->buf[NBUF];
452 pfmt(out, "%o\n", m);
468 return (void *)malloc(n);
472 Realloc(void *p, ulong n)
474 return realloc(p, n);