]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rc/unix.c
rc: change plan9 envname limit to 128, cleanup
[plan9front.git] / sys / src / cmd / rc / unix.c
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
29 struct word*
30 enval(s)
31 register char *s;
32 {
33         char *t, c;
34         struct word *v;
35         for(t = s;*t && *t!=SEP;t++);
36         c=*t;
37         *t='\0';
38         v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
39         *t = c;
40         return v;
41 }
42 Vinit(){
43         extern char **environ;
44         char *s;
45         char **env = environ;
46         environp = env;
47         for(;*env;env++){
48                 for(s=*env;*s && *s!='(' && *s!='=';s++);
49                 switch(*s){
50                 case '\0':
51                         pfmt(err, "environment %q?\n", *env);
52                         break;
53                 case '=':
54                         *s='\0';
55                         setvar(*env, enval(s+1));
56                         *s='=';
57                         break;
58                 case '(':       /* ignore functions for now */
59                         break;
60                 }
61         }
62 }
63 char **envp;
64 Xrdfn(){
65         char *s;
66         int len;
67         for(;*envp;envp++){
68                 for(s=*envp;*s && *s!='(' && *s!='=';s++);
69                 switch(*s){
70                 case '\0':
71                         pfmt(err, "environment %q?\n", *envp);
72                         break;
73                 case '=':       /* ignore variables */
74                         break;
75                 case '(':               /* Bourne again */
76                         s=*envp+3;
77                         envp++;
78                         len = strlen(s);
79                         s[len]='\n';
80                         execcmds(opencore(s, len+1));
81                         s[len]='\0';
82                         return;
83                 }
84         }
85         Xreturn();
86 }
87 union code rdfns[4];
88 execfinit(){
89         static int first = 1;
90         if(first){
91                 rdfns[0].i = 1;
92                 rdfns[1].f = Xrdfn;
93                 rdfns[2].f = Xjump;
94                 rdfns[3].i = 1;
95                 first = 0;
96         }
97         Xpopm();
98         envp = environp;
99         start(rdfns, 1, runq->local);
100 }
101 cmpenv(a, b)
102 char **a, **b;
103 {
104         return strcmp(*a, *b);
105 }
106
107 char*
108 *mkenv()
109 {
110         char **env, **ep, *p, *q;
111         struct var **h, *v;
112         struct word *a;
113         int nvar = 0, nchr = 0, sep;
114         /*
115          * Slightly kludgy loops look at locals then globals
116          */
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){
119                         nvar++;
120                         nchr+=strlen(v->name)+1;
121                         for(a = v->val;a;a = a->next)
122                                 nchr+=strlen(a->word)+1;
123                 }
124                 if(v->fn){
125                         nvar++;
126                         nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
127                 }
128         }
129         env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
130         ep = env;
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){
134                         *ep++=p;
135                         q = v->name;
136                         while(*q) *p++=*q++;
137                         sep='=';
138                         for(a = v->val;a;a = a->next){
139                                 *p++=sep;
140                                 sep = SEP;
141                                 q = a->word;
142                                 while(*q) *p++=*q++;
143                         }
144                         *p++='\0';
145                 }
146                 if(v->fn){
147                         *ep++=p;
148                         *p++='#'; *p++='('; *p++=')';   /* to fool Bourne */
149                         *p++='f'; *p++='n'; *p++=' ';
150                         q = v->name;
151                         while(*q) *p++=*q++;
152                         *p++=' ';
153                         q = v->fn[v->pc-1].s;
154                         while(*q) *p++=*q++;
155                         *p++='\0';
156                 }
157         }
158         *ep = 0;
159         qsort((char *)env, nvar, sizeof ep[0], cmpenv);
160         return env;     
161 }
162 char *sigmsg[] = {
163 /*  0 normal  */ 0,
164 /*  1 SIGHUP  */ "Hangup",
165 /*  2 SIGINT  */ 0,
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",
176 /* 13 SIGPIPE */ 0,
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",
184 };
185 Waitfor(pid, persist){
186         int wpid, sig;
187         struct thread *p;
188         int wstat;
189         char wstatstr[12];
190         for(;;){
191                 errno = 0;
192                 wpid = wait(&wstat);
193                 if(errno==EINTR && persist)
194                         continue;
195                 if(wpid==-1)
196                         break;
197                 sig = wstat&0177;
198                 if(sig==0177){
199                         pfmt(err, "trace: ");
200                         sig = (wstat>>8)&0177;
201                 }
202                 if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
203                         if(pid!=wpid)
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");
210                         pfmt(err, "\n");
211                 }
212                 wstat = sig?sig+1000:(wstat>>8)&0xFF;
213                 if(wpid==pid){
214                         inttoascii(wstatstr, wstat);
215                         setstatus(wstatstr);
216                         break;
217                 }
218                 else{
219                         for(p = runq->ret;p;p = p->ret)
220                                 if(p->pid==wpid){
221                                         p->pid=-1;
222                                         inttoascii(p->status, wstat);
223                                         break;
224                                 }
225                 }
226         }
227 }
228
229 char*
230 *mkargv(a)
231 register struct word *a;
232 {
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;
236         *argp = 0;
237         return argv;
238 }
239 Updenv(){}
240 Execute(args, path)
241 register struct word *args, *path;
242 {
243         char *msg="not found";
244         int txtbusy = 0;
245         char **env = mkenv();
246         char **argv = mkargv(args);
247         char file[512];
248         for(;path;path = path->next){
249                 strcpy(file, path->word);
250                 if(file[0])
251                         strcat(file, "/");
252                 strcat(file, argv[1]);
253         ReExec:
254                 execve(file, argv+1, env);
255                 switch(errno){
256                 case ENOEXEC:
257                         pfmt(err, "%s: Bourne again\n", argv[1]);
258                         argv[0]="sh";
259                         argv[1] = strdup(file);
260                         execve("/bin/sh", argv, env);
261                         goto Bad;
262                 case ETXTBSY:
263                         if(++txtbusy!=5){
264                                 sleep(txtbusy);
265                                 goto ReExec;
266                         }
267                         msg="text busy"; goto Bad;
268                 case EACCES:
269                         msg="no access";
270                         break;
271                 case ENOMEM:
272                         msg="not enough memory"; goto Bad;
273                 case E2BIG:
274                         msg="too big"; goto Bad;
275                 }
276         }
277 Bad:
278         pfmt(err, "%s: %s\n", argv[1], msg);
279         efree((char *)env);
280         efree((char *)argv);
281 }
282 #define NDIR    14              /* should get this from param.h */
283 Globsize(p)
284 register char *p;
285 {
286         int isglob = 0, globlen = NDIR+1;
287         for(;*p;p++){
288                 if(*p==GLOB){
289                         p++;
290                         if(*p!=GLOB)
291                                 isglob++;
292                         globlen+=*p=='*'?NDIR:1;
293                 }
294                 else
295                         globlen++;
296         }
297         return isglob?globlen:0;
298 }
299 #include <sys/types.h>
300 #include <ndir.h>
301 #define NDIRLIST        50
302 DIR *dirlist[NDIRLIST];
303 Opendir(name)
304 char *name;
305 {
306         DIR **dp;
307         for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
308                 if(*dp==0){
309                         *dp = opendir(name);
310                         return *dp?dp-dirlist:-1;
311                 }
312         return -1;
313 }
314 Readdir(f, p, onlydirs)
315 int f;
316 void *p;
317 int onlydirs;           /* ignored, just advisory */
318 {
319         struct direct *dp = readdir(dirlist[f]);
320         if(dp==0)
321                 return 0;
322         strcpy(p, dp->d_name);
323         return 1;
324 }
325 Closedir(f){
326         closedir(dirlist[f]);
327         dirlist[f] = 0;
328 }
329 char *Signame[] = {
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",
338         0,
339 };
340
341 int
342 gettrap(sig)
343 {
344         signal(sig, gettrap);
345         trap[sig]++;
346         ntrap++;
347         if(ntrap>=NSIG){
348                 pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
349                 signal(SIGIOT, (int (*)())0);
350                 kill(getpid(), SIGIOT);
351         }
352 }
353 Trapinit(){
354         int i;
355         int (*sig)();
356         if(1 || flag['d']){     /* wrong!!! */
357                 sig = signal(SIGINT, gettrap);
358                 if(sig==SIG_IGN)
359                         signal(SIGINT, SIG_IGN);
360         }
361         else{
362                 for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
363                         sig = signal(i, gettrap);
364                         if(sig==SIG_IGN)
365                                 signal(i, SIG_IGN);
366                 }
367         }
368 }
369 Unlink(name)
370 char *name;
371 {
372         return unlink(name);
373 }
374 Write(fd, buf, cnt)
375 void *buf;
376 {
377         return write(fd, buf, cnt);
378 }
379 Read(fd, buf, cnt)
380 void *buf;
381 {
382         return read(fd, buf, cnt);
383 }
384 Seek(fd, cnt, whence)
385 long cnt;
386 {
387         return lseek(fd, cnt, whence);
388 }
389 Executable(file)
390 char *file;
391 {
392         return(access(file, 01)==0);
393 }
394 Creat(file)
395 char *file;
396 {
397         return creat(file, 0666);
398 }
399 Dup(a, b){
400         return dup2(a, b);
401 }
402 Dup1(a){
403         return dup(a);
404 }
405 /*
406  * Wrong:  should go through components of a|b|c and return the maximum.
407  */
408 Exit(stat)
409 register char *stat;
410 {
411         int n = 0;
412         while(*stat){
413                 if(*stat!='|'){
414                         if(*stat<'0' || '9'<*stat)
415                                 exit(1);
416                         else n = n*10+*stat-'0';
417                 }
418                 stat++;
419         }
420         exit(n);
421 }
422 Eintr(){
423         return errno==EINTR;
424 }
425 Noerror(){
426         errno = 0;
427 }
428 Isatty(fd){
429         return isatty(fd);
430 }
431 Abort(){
432         abort();
433 }
434 execumask(){            /* wrong -- should fork before writing */
435         int m;
436         struct io out[1];
437         switch(count(runq->argv->words)){
438         default:
439                 pfmt(err, "Usage: umask [umask]\n");
440                 setstatus("umask usage");
441                 poplist();
442                 return;
443         case 2:
444                 umask(octal(runq->argv->words->next->word));
445                 break;
446         case 1: 
447                 umask(m = umask(0));
448                 out->fd = mapfd(1);
449                 out->bufp = out->buf;
450                 out->ebuf=&out->buf[NBUF];
451                 out->strp = 0;
452                 pfmt(out, "%o\n", m);
453                 break;
454         }
455         setstatus("");
456         poplist();
457 }
458 Memcpy(a, b, n)
459 void *a, *b;
460 long n;
461 {
462         memmove(a, b, n);
463 }
464
465 void*
466 Malloc(n)
467 {
468         return (void *)malloc(n);
469 }
470
471 void*
472 Realloc(void *p, ulong n)
473 {
474         return realloc(p, n);
475 }