Charles.Forsyth20060303644188019 years agoHistory
331 lines · 5.0 KB · C
RawDownload
#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; voidreadenv(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. */voidexportenv(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;} intwaitfor(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;} voidexpunge(int pid, char *msg){	if(strcmp(msg, "interrupt"))		kill(pid, SIGINT);	else		kill(pid, SIGHUP);} intexecsh(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;} intpipecmd(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;} voidExit(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 voidnotifyf(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);} voidcatchnotes(){	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);} intchgtime(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));} voidrcopy(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;	}} ulongmkmtime(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;}