blob: c63d3cefd0246d4644ba8a9e2758eb349beea255 [file] [log] [blame]
#define NOPLAN9DEFINES
#include "mk.h"
#include <sys/wait.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/time.h>
char *shell = "/bin/sh";
char *shellname = "sh";
extern char **environ;
static void
mkperror(char *s)
{
fprint(2, "%s: %r\n", s);
}
void
readenv(void)
{
char **p, *s;
Word *w;
for(p = environ; *p; p++){
/* rsc 5/5/2004 -- This misparses fn#cd={whatever}
s = shname(*p);
if(*s == '=') {
*s = 0;
w = newword(s+1);
} else
w = newword("");
*/
s = strchr(*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*)"")->u.ptr = "";
}
}
/*
* 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, Shell *sh)
{
int i;
char **p;
static char buf[16384];
p = 0;
for(i = 0; e->name; e++, i++) {
p = (char**) Realloc(p, (i+2)*sizeof(char*));
if(e->values)
snprint(buf, sizeof buf, "%s=%s", e->name, wtos(e->values, sh->iws));
else
snprint(buf, sizeof buf, "%s=", e->name);
p[i] = strdup(buf);
}
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 mypid;
int
shargv(Word *cmd, int extra, char ***pargv)
{
char **argv;
int i, n;
Word *w;
n = 0;
for(w=cmd; w; w=w->next)
n++;
argv = Malloc((n+extra+1)*sizeof(argv[0]));
i = 0;
for(w=cmd; w; w=w->next)
argv[i++] = w->s;
argv[n] = 0;
*pargv = argv;
return n;
}
int
execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)
{
char *p, **argv;
int tot, n, pid, in[2], out[2];
if(buf && pipe(out) < 0){
mkperror("pipe");
Exit();
}
pid = fork();
mypid = getpid();
if(pid < 0){
mkperror("mk fork");
Exit();
}
if(pid == 0){
if(buf)
close(out[0]);
if(pipe(in) < 0){
mkperror("pipe");
Exit();
}
pid = fork();
if(pid < 0){
mkperror("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, sh);
n = shargv(shellcmd, 1, &argv);
argv[n++] = args;
argv[n] = 0;
execvp(argv[0], argv);
mkperror(shell);
_exit(1);
}
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]);
_exit(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, Shell *sh, Word *shellcmd)
{
int pid, pfd[2];
int n;
char **argv;
if(DEBUG(D_EXEC))
fprint(1, "pipecmd='%s'\n", cmd);/**/
if(fd && pipe(pfd) < 0){
mkperror("pipe");
Exit();
}
pid = fork();
if(pid < 0){
mkperror("mk fork");
Exit();
}
if(pid == 0){
if(fd){
close(pfd[0]);
dup2(pfd[1], 1);
close(pfd[1]);
}
if(e)
exportenv(e, sh);
n = shargv(shellcmd, 2, &argv);
argv[n++] = "-c";
argv[n++] = cmd;
argv[n] = 0;
execvp(argv[0], argv);
mkperror(shell);
_exit(1);
}
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(void)
{
int i;
for(i = 0; sigmsgs[i].msg; i++)
signal(sigmsgs[i].sig, notifyf);
}
char*
maketmp(int *pfd)
{
static char temp[] = "/tmp/mkargXXXXXX";
static char buf[100];
int fd;
strcpy(buf, temp);
fd = mkstemp(buf);
if(fd < 0)
return 0;
*pfd = fd;
return buf;
}
int
chgtime(char *name)
{
if(access(name, 0) >= 0)
return utimes(name, 0);
return close(creat(name, 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;
}
}
unsigned long
mkmtime(char *name)
{
struct stat st;
if(stat(name, &st) < 0)
return 0;
return st.st_mtime;
}