#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;
}
syntax highlighted by Code2HTML, v. 0.9.1