diff options
Diffstat (limited to 'utils/mk/Posix.c')
| -rw-r--r-- | utils/mk/Posix.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/utils/mk/Posix.c b/utils/mk/Posix.c new file mode 100644 index 00000000..63ad17f5 --- /dev/null +++ b/utils/mk/Posix.c @@ -0,0 +1,331 @@ +#include "mk.h" +#include <dirent.h> +#include <signal.h> +#include <sys/wait.h> +#include <utime.h> +#include <stdio.h> + +char *shell = "/bin/sh"; +char *shellname = "sh"; + +extern char **environ; + +void +readenv(void) +{ + char **p, *s; + Word *w; + + for(p = environ; *p; p++){ + s = shname(*p); + if(*s == '=') { + *s = 0; + w = newword(s+1); + } else + w = newword(""); + if (symlook(*p, S_INTERNAL, 0)) + continue; + s = strdup(*p); + setvar(s, (void *)w); + symlook(s, S_EXPORTED, (void*)"")->value = (void*)""; + } +} + +/* + * done on child side of fork, so parent's env is not affected + * and we don't care about freeing memory because we're going + * to exec immediately after this. + */ +void +exportenv(Envy *e) +{ + int i; + char **p; + char *values; + + p = 0; + for(i = 0; e->name; e++, i++) { + p = (char**) Realloc(p, (i+2)*sizeof(char*)); + if (e->values) + values = wtos(e->values, IWS); + else + values = ""; + p[i] = malloc(strlen(e->name) + strlen(values) + 2); + sprint(p[i], "%s=%s", e->name, values); + } + p[i] = 0; + environ = p; +} + +int +waitfor(char *msg) +{ + int status; + int pid; + + *msg = 0; + pid = wait(&status); + if(pid > 0) { + if(status&0x7f) { + if(status&0x80) + snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f); + else + snprint(msg, ERRMAX, "signal %d", status&0x7f); + } else if(status&0xff00) + snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff); + } + return pid; +} + +void +expunge(int pid, char *msg) +{ + if(strcmp(msg, "interrupt")) + kill(pid, SIGINT); + else + kill(pid, SIGHUP); +} + +int +execsh(char *args, char *cmd, Bufblock *buf, Envy *e) +{ + char *p; + int tot, n, pid, in[2], out[2]; + + if(buf && pipe(out) < 0){ + perror("pipe"); + Exit(); + } + pid = fork(); + if(pid < 0){ + perror("mk fork"); + Exit(); + } + if(pid == 0){ + if(buf) + close(out[0]); + if(pipe(in) < 0){ + perror("pipe"); + Exit(); + } + pid = fork(); + if(pid < 0){ + perror("mk fork"); + Exit(); + } + if(pid != 0){ + dup2(in[0], 0); + if(buf){ + dup2(out[1], 1); + close(out[1]); + } + close(in[0]); + close(in[1]); + if (e) + exportenv(e); + if(shflags) + execl(shell, shellname, shflags, args, nil); + else + execl(shell, shellname, args, nil); + perror(shell); + _exits("exec"); + } + close(out[1]); + close(in[0]); + if(DEBUG(D_EXEC)) + fprint(1, "starting: %s\n", cmd); + p = cmd+strlen(cmd); + while(cmd < p){ + n = write(in[1], cmd, p-cmd); + if(n < 0) + break; + cmd += n; + } + close(in[1]); + _exits(0); + } + if(buf){ + close(out[1]); + tot = 0; + for(;;){ + if (buf->current >= buf->end) + growbuf(buf); + n = read(out[0], buf->current, buf->end-buf->current); + if(n <= 0) + break; + buf->current += n; + tot += n; + } + if (tot && buf->current[-1] == '\n') + buf->current--; + close(out[0]); + } + return pid; +} + +int +pipecmd(char *cmd, Envy *e, int *fd) +{ + int pid, pfd[2]; + + if(DEBUG(D_EXEC)) + fprint(1, "pipecmd='%s'\n", cmd);/**/ + + if(fd && pipe(pfd) < 0){ + perror("pipe"); + Exit(); + } + pid = fork(); + if(pid < 0){ + perror("mk fork"); + Exit(); + } + if(pid == 0){ + if(fd){ + close(pfd[0]); + dup2(pfd[1], 1); + close(pfd[1]); + } + if(e) + exportenv(e); + if(shflags) + execl(shell, shellname, shflags, "-c", cmd, nil); + else + execl(shell, shellname, "-c", cmd, nil); + perror(shell); + _exits("exec"); + } + if(fd){ + close(pfd[1]); + *fd = pfd[0]; + } + return pid; +} + +void +Exit(void) +{ + while(wait(0) >= 0) + ; + exits("error"); +} + +static struct +{ + int sig; + char *msg; +} sigmsgs[] = +{ + SIGALRM, "alarm", + SIGFPE, "sys: fp: fptrap", + SIGPIPE, "sys: write on closed pipe", + SIGILL, "sys: trap: illegal instruction", + SIGSEGV, "sys: segmentation violation", + 0, 0 +}; + +static void +notifyf(int sig) +{ + int i; + + for(i = 0; sigmsgs[i].msg; i++) + if(sigmsgs[i].sig == sig) + killchildren(sigmsgs[i].msg); + + /* should never happen */ + signal(sig, SIG_DFL); + kill(getpid(), sig); +} + +void +catchnotes() +{ + int i; + + for(i = 0; sigmsgs[i].msg; i++) + signal(sigmsgs[i].sig, notifyf); +} + +char* +maketmp(void) +{ + static char temp[L_tmpnam]; + + return tmpnam(temp); +} + +int +chgtime(char *name) +{ + Dir *sbuf; + struct utimbuf u; + + if((sbuf = dirstat(name)) != nil) { + u.actime = sbuf->atime; + free(sbuf); + u.modtime = time(0); + return utime(name, &u); + } + return close(create(name, OWRITE, 0666)); +} + +void +rcopy(char **to, Resub *match, int n) +{ + int c; + char *p; + + *to = match->s.sp; /* stem0 matches complete target */ + for(to++, match++; --n > 0; to++, match++){ + if(match->s.sp && match->e.ep){ + p = match->e.ep; + c = *p; + *p = 0; + *to = strdup(match->s.sp); + *p = c; + } + else + *to = 0; + } +} + +ulong +mkmtime(char *name) +{ + Dir *buf; + ulong t; + + buf = dirstat(name); + if(buf == nil) + return 0; + t = buf->mtime; + free(buf); + return t; +} + + +char *stab; + +char * +membername(char *s, int fd, char *sz) +{ + long t; + char *p, *q; + + if(s[0] == '/' && s[1] == '\0'){ /* long file name string table */ + t = atol(sz); + if(t&01) t++; + stab = malloc(t); + read(fd, stab, t); + return nil; + } + else if(s[0] == '/' && stab != nil) { /* index into string table */ + p = stab+atol(s+1); + q = strchr(p, '/'); + if (q) + *q = 0; /* terminate string here */ + return p; + }else + return s; +} |
