Charles.Forsyth20060303644188019 years agoHistory
363 lines · 5.7 KB · C
RawDownload
#include	"mk.h" char 	*shell =	"/bin/rc";char 	*shellname =	"rc"; static	Word	*encodenulls(char*, int); voidreadenv(void){	char *p;	int envf, f;	Dir *e;	char nam[1024];	int i, n, len;	Word *w; 	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 != '\0'; 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 */voidexportenv(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 from environment */				/* we could remove it from the symbol table				 * too, but we're in the child copy, and it				 * would still remain in the parent's table.				 */			remove(nam);			delword(e->values);			e->values = 0;		/* memory leak */			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, "\0", 1) != 1)						perror(nam);				}				if (write(f, w->s, n) != n)					perror(nam);			}		}		close(f);	}} intwaitfor(char *msg){	Waitmsg *w;	int pid; 	if((w=wait()) == nil)		return -1;	strecpy(msg, msg+ERRMAX, w->msg);	pid = w->pid;	free(w);	return pid;} voidexpunge(int pid, char *msg){	postnote(PNPROC, pid, msg);} 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 = rfork(RFPROC|RFFDG|RFENVG);	if(pid < 0){		perror("mk rfork");		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){			dup(in[0], 0);			if(buf){				dup(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]);		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 = rfork(RFPROC|RFFDG|RFENVG);	if(pid < 0){		perror("mk fork");		Exit();	}	if(pid == 0){		if(fd){			close(pfd[0]);			dup(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(waitpid() >= 0)		;	exits("error");} intnotifyf(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;} voidcatchnotes(){	atnotify(notifyf, 1);} char*maketmp(void){	static char temp[] = "/tmp/mkargXXXXXX"; 	mktemp(temp);	return temp;} intchgtime(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));} 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 *membername(char *s, int, char*){	return s;}