#include "mk.h" Channel *wchan; char *shell = "/bin/rc"; char *shellname = "rc"; static int nexec, nwait; static char envsep; static Word *encodenulls(char*, int); void readenv(void) { char *p; int envf, f; Dir *e; char nam[1024]; int i, n, len; Word *w; wchan = threadwaitchan(); if(1) //pm_conf.ostype == PmOsPlan9) envsep = '\0'; else envsep = '\01'; // rfork(RFENVG); /* use copy of the current environment variables */ envf = open("/env", OREAD); if(envf < 0) return; while((n = dirread(envf, &e)) > 0){ for(i = 0; i < n; i++){ len = e[i].length; /* don't import funny names, NULL values, * or internal mk variables */ if(len <= 0 || *shname(e[i].name) != '\0') continue; if (symlook(e[i].name, S_INTERNAL, 0)) continue; sprint(nam, "/env/%s", e[i].name); f = open(nam, OREAD); if(f < 0) continue; p = Malloc(len+1); if(read(f, p, len) != len){ perror(nam); close(f); continue; } close(f); if (p[len-1] == 0) len--; else p[len] = 0; w = encodenulls(p, len); free(p); p = strdup(e[i].name); setvar(p, (void *) w); symlook(p, S_EXPORTED, (void*)"")->value = (void*)""; } free(e); } close(envf); } /* break string of values into words at 01's or nulls*/ static Word * encodenulls(char *s, int n) { Word *w, *head; char *cp; head = w = 0; while (n-- > 0) { for (cp = s; *cp && *cp != envsep; cp++) n--; *cp = 0; if (w) { w->next = newword(s); w = w->next; } else head = w = newword(s); s = cp+1; } if (!head) head = newword(""); return head; } /* as well as 01's, change blanks to nulls, so that rc will * treat the words as separate arguments */ void exportenv(Envy *e) { int f, n, hasvalue, first; Word *w; Symtab *sy; char nam[256]; for(;e->name; e++){ sy = symlook(e->name, S_VAR, 0); if (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0) hasvalue = 0; else hasvalue = 1; if(sy == 0 && !hasvalue) /* non-existant null symbol */ continue; sprint(nam, "/env/%s", e->name); if (sy != 0 && !hasvalue){ remove(nam); e->values = 0; symdel(e->name, S_VAR); continue; } f = create(nam, OWRITE, 0666L); if(f < 0) { fprint(2, "can't create %s, f=%d\n", nam, f); perror(nam); continue; } first = 1; for (w = e->values; w; w = w->next) { n = strlen(w->s); if (n) { if(first) first = 0; else{ if (write (f, &envsep, 1) != 1) perror(nam); } if (write(f, w->s, n) != n) perror(nam); } } close(f); } } int waitfor(char *msg) { Waitmsg *w; int pid; if(nwait >= nexec) return -1; Again: if((w=recvp(wchan)) == nil) return -1; strecpy(msg, msg+ERRMAX, w->msg); pid = w->pid; free(w); if(strcmp(msg, "libthread procexec") == 0) goto Again; nwait++; return pid; } void expunge(int pid, char *msg) { postnote(PNPROC, pid, msg); } static void writecmd(void *a) { struct {char *cmd; int fd;} *arg; char *p, *e; int n; threadnowait(); arg = a; p = arg->cmd; e = p+strlen(p); while(p < e){ n = write(arg->fd, p, e-p); if(n <= 0) break; p += n; } free(arg->cmd); close(arg->fd); free(arg); } static void execproc(void *a) { struct { char *cmd; char *argv[4]; int fd[2]; Channel *cpid; } *arg; arg = a; rfork(RFFDG); dup(arg->fd[0], 0); if(arg->fd[1] != 1) dup(arg->fd[1], 1); nexec++; procexec(arg->cpid, arg->cmd, arg->argv); threadexits(nil); } int execsh(char *args, char *cmd, Bufblock *buf, Envy *e) { int tot, n, in[2], out[2]; int i, pid; struct { char *cmd; int fd;} *wt; struct { char *cmd; char *argv[4]; int fd[2]; Channel *cpid; } et; out[1] = 1; if(buf && pipe(out) < 0) { perror("pipe"); Exit(); } if(pipe(in) < 0){ perror("pipe"); Exit(); } wt = malloc(sizeof(*wt)); wt->cmd = strdup(cmd); wt->fd = in[1]; proccreate(writecmd, wt, 8192); if(e) exportenv(e); i=0; et.argv[i++] = shellname; if(shflags) et.argv[i++] = shflags; if(args) et.argv[i++] = args; et.argv[i] = 0; et.cmd = shell; et.fd[0] = in[0]; et.fd[1] = out[1]; et.cpid = chancreate(sizeof(ulong), 0); if(proccreate(execproc, &et, 8192) < 0) sysfatal("proccreate %s failed: %r", shell); pid = recvul(et.cpid); if(pid == ~0) sysfatal("procexec failed\n"); chanfree(et.cpid); close(in[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; } static void pipeexecproc(void *a) { struct { char *cmd; int fd[2]; Channel *cpid; } *arg; arg = a; rfork(RFFDG); if(arg->fd[0] != 0) dup(arg->fd[0], 0); if(arg->fd[1] != 1) dup(arg->fd[1], 1); nexec++; if(shflags) procexecl(arg->cpid, shell, shellname, shflags, "-c", arg->cmd, nil); else procexecl(arg->cpid, shell, shellname, "-c", arg->cmd, nil); threadexits(nil); } int pipecmd(char *cmd, Envy *e, int *fd) { int pid; struct { char *cmd; int fd[2]; Channel *cpid; } a; if(DEBUG(D_EXEC)) fprint(1, "pipecmd='%s'\n", cmd);/**/ if(e) exportenv(e); a.fd[0] = 0; a.fd[1] = 1; if(fd && pipe(a.fd) < 0){ perror("pipe"); Exit(); } a.cpid = chancreate(sizeof(ulong), 0); if(proccreate(pipeexecproc, &a, 8192) < 0) sysfatal("proccreate failed: %r\n"); pid = recvul(a.cpid); if(pid == ~0) sysfatal("procexec failed\n"); if(fd){ close(fd[1]); *fd = fd[0]; } return pid; } void Exit(void) { threadexitsall("error"); } int notifyf(void *a, char *msg) { static int nnote; USED(a); if(++nnote > 100){ /* until andrew fixes his program */ fprint(2, "mk: too many notes\n"); notify(0); abort(); } if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0) return 0; killchildren(msg); return -1; } void catchnotes() { atnotify(notifyf, 1); } char* maketmp(void) { static char temp[] = "/tmp/mkargXXXXXX"; mktemp(temp); return temp; } int chgtime(char *name) { Dir sbuf; if(access(name, AEXIST) >= 0) { nulldir(&sbuf); sbuf.mtime = time((long *)0); return dirwstat(name, &sbuf); } 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; }