diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-01-03 18:41:48 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-01-03 18:41:48 +0000 |
commit | 189731aad01e09db1807c78af421c615ed3a3242 (patch) | |
tree | 4cec623654b4e4e9da03bb00f36ea49755c8ca98 /sys/src/cmd/rc/unix.c | |
parent | c51a5cfa06dd982da839c4cfcba1610259d27e38 (diff) |
rc: make it portable (for UNIX)
Fixup remaining Plan9 dependencies (chartorune()).
Add Makefile for UNIX-like systems (tested with Linux and APE).
Make error printing consistent, use Errstr() explicitely.
Get rid of NSTATUS buffer limit, just malloc it.
Diffstat (limited to 'sys/src/cmd/rc/unix.c')
-rw-r--r-- | sys/src/cmd/rc/unix.c | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/sys/src/cmd/rc/unix.c b/sys/src/cmd/rc/unix.c new file mode 100644 index 000000000..05d883c36 --- /dev/null +++ b/sys/src/cmd/rc/unix.c @@ -0,0 +1,420 @@ +/* + * Unix versions of system-specific functions + * By convention, exported routines herein have names beginning with an + * upper case letter. + */ +#include "rc.h" +#include "exec.h" +#include "io.h" +#include "fns.h" +#include "getflags.h" + +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/wait.h> + +static void execfinit(void); + +builtin Builtin[] = { + "cd", execcd, + "whatis", execwhatis, + "eval", execeval, + "exec", execexec, /* but with popword first */ + "exit", execexit, + "shift", execshift, + "wait", execwait, + ".", execdot, + "flag", execflag, + "finit", execfinit, + 0 +}; + +char Rcmain[] = PREFIX "/lib/rcmain"; +char Fdprefix[] = "/dev/fd/"; + +char *Signame[NSIG]; + +#define SEP '\1' +extern char **environ; +static char **envp; + +static void +Xrdfn(void) +{ + char *s; + int len; + + for(;*envp;envp++){ + for(s=*envp;*s && *s!='(' && *s!='=';s++); + switch(*s){ + case '(': /* Bourne again */ + if(strncmp(s, "()fn ", 5)!=0) + continue; + s=estrdup(s+2); + len=strlen(s); + s[len++]='\n'; + envp++; + runq->pc--; /* re-execute */ + execcmds(openiocore(s, len), estrdup("*environ*"), runq->local, runq->redir); + runq->lex->qflag = 1; + return; + default: + continue; + } + } +} + +static void +execfinit(void) +{ + static union code rdfns[5]; + if(rdfns[0].i==0){ + rdfns[0].i = 1; + rdfns[1].s = "*rdfns*"; + rdfns[2].f = Xrdfn; + rdfns[3].f = Xreturn; + rdfns[4].f = 0; + } + poplist(); + envp=environ; + start(rdfns, 2, runq->local, runq->redir); +} + +static int +cmpenv(const void *aa, const void *ab) +{ + return strcmp(*(char**)aa, *(char**)ab); +} + +static char** +mkenv(void) +{ + char **env, **ep, *p, *q; + struct var **h, *v; + struct word *a; + int nvar = 0, nchr = 0, sep; + + /* + * Slightly kludgy loops look at locals then globals. + * locals no longer exist - geoff + */ + for(h = gvar-1; h != &gvar[NVAR]; h++) + for(v = h >= gvar? *h: runq->local; v ;v = v->next){ + if((v==vlook(v->name)) && v->val){ + nvar++; + nchr+=strlen(v->name)+1; + for(a = v->val;a;a = a->next) + nchr+=strlen(a->word)+1; + } + if(v->fn){ + nvar++; + nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8; + } + } + env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr); + ep = env; + p = (char *)&env[nvar+1]; + for(h = gvar-1; h != &gvar[NVAR]; h++) + for(v = h >= gvar? *h: runq->local;v;v = v->next){ + if((v==vlook(v->name)) && v->val){ + *ep++=p; + q = v->name; + while(*q) *p++=*q++; + sep='='; + for(a = v->val;a;a = a->next){ + *p++=sep; + sep = SEP; + q = a->word; + while(*q) *p++=*q++; + } + *p++='\0'; + } + if(v->fn){ + *ep++=p; + *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */ + *p++='f'; *p++='n'; *p++=' '; + q = v->name; + while(*q) *p++=*q++; + *p++=' '; + q = v->fn[v->pc-1].s; + while(*q) *p++=*q++; + *p++='\0'; + } + } + *ep = 0; + qsort((void *)env, nvar, sizeof ep[0], cmpenv); + return env; +} + +static word* +envval(char *s) +{ + char *t, c; + word *v; + for(t=s;*t&&*t!=SEP;t++); + c=*t; + *t='\0'; + v=newword(s, c=='\0'?(word*)0:envval(t+1)); + *t=c; + return v; +} + +void +Vinit(void) +{ + char *s; + + for(envp=environ;*envp;envp++){ + for(s=*envp;*s && *s!='(' && *s!='=';s++); + switch(*s){ + case '=': + *s='\0'; + setvar(*envp, envval(s+1)); + *s='='; + break; + default: continue; + } + } +} + +static void +sighandler(int sig) +{ + trap[sig]++; + ntrap++; +} + +void +Trapinit(void) +{ + int i; + + Signame[0] = "sigexit"; + +#ifdef SIGINT + Signame[SIGINT] = "sigint"; +#endif +#ifdef SIGTERM + Signame[SIGTERM] = "sigterm"; +#endif +#ifdef SIGHUP + Signame[SIGHUP] = "sighup"; +#endif +#ifdef SIGQUIT + Signame[SIGQUIT] = "sigquit"; +#endif +#ifdef SIGPIPE + Signame[SIGPIPE] = "sigpipe"; +#endif +#ifdef SIGUSR1 + Signame[SIGUSR1] = "sigusr1"; +#endif +#ifdef SIGUSR2 + Signame[SIGUSR2] = "sigusr2"; +#endif +#ifdef SIGBUS + Signame[SIGBUS] = "sigbus"; +#endif +#ifdef SIGWINCH + Signame[SIGWINCH] = "sigwinch"; +#endif + + for(i=1; i<NSIG; i++) if(Signame[i]){ +#ifdef SA_RESTART + struct sigaction a; + + sigaction(i, NULL, &a); + a.sa_flags &= ~SA_RESTART; + a.sa_handler = sighandler; + sigaction(i, &a, NULL); +#else + signal(i, sighandler); +#endif + } +} + +char* +Errstr(void) +{ + return strerror(errno); +} + +int +Waitfor(int pid) +{ + thread *p; + char num[12]; + int wpid, status; + + if(pid >= 0 && !havewaitpid(pid)) + return 0; + while((wpid = wait(&status))!=-1){ + delwaitpid(wpid); + inttoascii(num, WIFSIGNALED(status)?WTERMSIG(status)+1000:WEXITSTATUS(status)); + if(wpid==pid){ + setstatus(num); + return 0; + } + for(p = runq->ret;p;p = p->ret) + if(p->pid==wpid){ + p->pid=-1; + p->status = estrdup(num); + break; + } + } + if(Eintr()) return -1; + return 0; +} + +static char **nextenv; + +void +Updenv(void) +{ + if(nextenv){ + free(nextenv); + nextenv = NULL; + } + if(err) + flushio(err); +} + +void +Exec(char **argv) +{ + if(nextenv==NULL) nextenv=mkenv(); + execve(argv[0], argv+1, nextenv); +} + +int +Fork(void) +{ + Updenv(); + return fork(); +} + +void* +Opendir(char *name) +{ + return opendir(name); +} + +char* +Readdir(void *arg, int onlydirs) +{ + DIR *rd = arg; + struct dirent *ent = readdir(rd); + if(ent == NULL) + return 0; + return ent->d_name; +} + +void +Closedir(void *arg) +{ + DIR *rd = arg; + closedir(rd); +} + +long +Write(int fd, void *buf, long cnt) +{ + return write(fd, buf, cnt); +} + +long +Read(int fd, void *buf, long cnt) +{ + return read(fd, buf, cnt); +} + +long +Seek(int fd, long cnt, long whence) +{ + return lseek(fd, cnt, whence); +} + +int +Executable(char *file) +{ + return access(file, 01)==0; +} + +int +Open(char *file, int mode) +{ + static int tab[] = {O_RDONLY,O_WRONLY,O_RDWR,O_RDONLY}; + int fd = open(file, tab[mode&3]); + if(fd >= 0 && mode == 3) + unlink(file); + return fd; +} + +void +Close(int fd) +{ + close(fd); +} + +int +Creat(char *file) +{ + return creat(file, 0666L); +} + +int +Dup(int a, int b) +{ + return dup2(a, b); +} + +int +Dup1(int a) +{ + return dup(a); +} + +void +Exit(void) +{ + Updenv(); + exit(truestatus()?0:1); +} + +int +Eintr(void) +{ + return errno==EINTR; +} + +void +Noerror(void) +{ + errno=0; +} + +int +Isatty(int fd) +{ + return isatty(fd); +} + +void +Abort(void) +{ + abort(); +} + +int +Chdir(char *dir) +{ + return chdir(dir); +} + +void +Prompt(char *s) +{ + pstr(err, s); + flushio(err); +} |