Charles.Forsyth20060303644188019 years agoHistory
442 lines · 7.2 KB · C
RawDownload
#include	"mk.h"#include	<signal.h>#include	<sys/utime.h> #define Arc	My_Arc		/* avoid name conflicts */#undef DELETE #include	<windows.h> enum {	Nchild	= 100,}; char *rootdir =		"c:\\users\\inferno";char *shell =		"Nt\\386\\bin\\rcsh.exe";	/* Path relative to root */ typedef struct Child	Child; struct Child {	int	pid;	HANDLE	handle;}; static Child child[Nchild]; extern char **environ; DWORD WINAPI writecmd(LPVOID a); 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 = "";	}} char *exportenv(Envy *e){	int i, n;	char *buf, *v; 	buf = 0;	n = 0;	for(i = 0; e->name; e++, i++) {			/* word separator is shell-dependent */		if(e->values)			v = wtos(e->values, IWS);		else			v = "";		buf = Realloc(buf, n+strlen(e->name)+1+strlen(v)+1);				n += sprint(buf+n, "%s=%s", e->name, v);		n++;	/* skip over null */		if(e->values)			free(v);	}	/* final null */	buf = Realloc(buf, n+1);	buf[n] = 0; 	return buf;} intwaitfor(char *msg){	int pid, n, i, r, code;	HANDLE tab[Nchild]; 	for(i=0,n=0; i<Nchild; i++)		if(child[i].handle != 0)			tab[n++] = child[i].handle; 	if(n == 0)		return -1; 	r = WaitForMultipleObjects(n, tab, 0, INFINITE); 	r -= WAIT_OBJECT_0;	if(r<0 || r>=n) {		perror("wait failed");		exits("wait failed");	} 	for(i=0; i<Nchild; i++)		if(child[i].handle == tab[r])			break;	if(i == Nchild){		snprint(msg, ERRMAX, "unknown child (%lux)", tab[r]);		return -1;	} 	if(msg) {		*msg = 0;		if(GetExitCodeProcess(child[i].handle, &code) == FALSE)			snprint(msg, ERRMAX, "unknown exit code");		else if(code != 0)			snprint(msg, ERRMAX, "exit(%d)", code);	} 	CloseHandle(child[i].handle);	child[i].handle = 0;	pid = child[i].pid;	child[i].pid = 0; 	return pid;} voidexpunge(int pid, char *msg){/*	if(strcmp(msg, "interrupt"))		kill(pid, SIGINT);	else		kill(pid, SIGHUP);*/} HANDLEduphandle(HANDLE h){	HANDLE r; 	if(DuplicateHandle(GetCurrentProcess(), h,			GetCurrentProcess(), &r, DUPLICATE_SAME_ACCESS,			1, DUPLICATE_SAME_ACCESS) == FALSE) {		perror("dup handle");		Exit();	} 	return r;} voidchildadd(HANDLE h, int pid){	int i;		for(i=0; i<Nchild; i++) {		if(child[i].handle == 0) {			child[i].handle = h;			child[i].pid = pid;			return;		}	}	perror("child table full");	Exit();} static DWORD WINAPIspinoff(HANDLE in, HANDLE out, char *args, char *cmd, Envy *e){	char args2[4096], path[MAX_PATH], *s, *eb;	STARTUPINFO si;	PROCESS_INFORMATION pi;	Symtab *sym;  		/* set up the full path of the shell */	sym = symlook("MKSH", S_VAR, 0);	if(sym){		strncpy(path, ((Word*)(sym->value))->s, sizeof(path));		path[MAX_PATH-1] = 0;	}else{		sym = symlook("ROOT", S_VAR, 0);		if(sym)			rootdir = ((Word*)(sym->value))->s;		snprint(path, sizeof(path), "%s\\%s", rootdir, shell);	}		/* convert to backslash notation */	for(s = strchr(path,'/'); s; s = strchr(s+1, '/'))			*s = '\\'; 	s = args2;	s += snprint(args2, sizeof(args2)-1, "%s", path);	if(shflags)		s += snprint(s, args2+sizeof(args2)-s-1, " %s", shflags);	if(args)		s += snprint(s, args2+sizeof(args2)-s-1, " %s", args);	if(cmd)		s += snprint(s, args2+sizeof(args2)-s-1, " \"%s\"", cmd); 	memset(&si, 0, sizeof(si));	si.cb = sizeof(si);	si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;	si.wShowWindow = SW_SHOW; 	if (e)		eb = exportenv(e);	else		eb = 0;	si.hStdInput = duphandle(in);	si.hStdOutput = duphandle(out);	si.hStdError = duphandle(GetStdHandle(STD_ERROR_HANDLE));	if(CreateProcess(path, args2, 0, 0, 1, 0, eb, 0, &si, &pi) == FALSE) {		perror("can't find shell");		Exit();	} 	free(eb); 	CloseHandle(si.hStdInput);	CloseHandle(si.hStdOutput);	CloseHandle(si.hStdError); 	childadd(pi.hProcess, pi.dwProcessId);	return pi.dwProcessId;} intexecsh(char *args, char *cmd, Bufblock *buf, Envy *e){	int tot, n, tid, pid;	HANDLE outin, outout, inout, inin;	struct { char *cmd; HANDLE handle; } *arg; 	if(buf == 0)		outout = GetStdHandle(STD_OUTPUT_HANDLE);	else	if(CreatePipe(&outin, &outout, 0, 0) == FALSE){		perror("pipe");		Exit();	} 	if(CreatePipe(&inin, &inout, 0, 0) == FALSE){		perror("pipe");		Exit();	} 	arg = malloc(sizeof(*arg));	arg->cmd = strdup(cmd);	arg->handle = inout;	if(CreateThread(0, 0, writecmd, arg, 0, &tid) == FALSE) {		perror("spawn writecmd");		Exit();	} 	pid = spinoff(inin, outout, args, 0, e);	CloseHandle(inin); 	if(DEBUG(D_EXEC))		fprint(1, "starting: %s\n", cmd); 	if(buf){		CloseHandle(outout);		tot = 0;		for(;;){			if (buf->current >= buf->end)				growbuf(buf);			if(ReadFile(outin, buf->current, buf->end-buf->current, &n, 0) == FALSE)				break;			buf->current += n;			tot += n;		}		if (tot && buf->current[-1] == '\n')			buf->current--;		CloseHandle(outin);	} 	return pid;} static DWORD WINAPIwritecmd(LPVOID a){	struct {char *cmd; HANDLE handle;} *arg;	char *cmd, *p;	int n; 	arg = a;	cmd = arg->cmd;	p = cmd+strlen(cmd);	while(cmd < p){		if(WriteFile(arg->handle, cmd, p-cmd, &n, 0) == FALSE)			break;		cmd += n;	}	 	free(arg->cmd);	CloseHandle(arg->handle);	free(arg);	ExitThread(0);	return 0;} intpipecmd(char *cmd, Envy *e, int *fd){	int pid;	HANDLE pipein, pipeout; 	if(fd){		if(CreatePipe(&pipein, &pipeout, 0, 0) == FALSE){			perror("pipe");			Exit();		}	} else 		pipeout = GetStdHandle(STD_OUTPUT_HANDLE);  	pid = spinoff(GetStdHandle(STD_INPUT_HANDLE), pipeout, "-c", cmd, e); 	if(fd){		CloseHandle(pipeout);		*fd = _open_osfhandle((long)pipein, 0);	}	return pid;} voidExit(void){	while(waitfor(0) != -1)		;	exits("error");} voidcatchnotes(){} char*maketmp(void){	static char temp[] = "mkargXXX.XXX"; 	mktemp(temp);	return temp;} Dir*mkdirstat(char *name){	int c, n, ret;	Dir *buf; 	n = strlen(name)-1;	c = name[n];	if(c == '/' || c == '\\')		name[n] = 0;	buf = dirstat(name);	name[n] = c;	return buf;} intchgtime(char *name){	Dir *sbuf;	struct utimbuf u; 	if((sbuf = mkdirstat(name)) != nil){		u.actime = sbuf->atime;		u.modtime = time(0);		free(sbuf);		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;	int n;	char *s; 	n = strlen(name)-1;	if(n >= 0 && (name[n] == '/' || name[n] == '\\')){		s = strdup(name);		s[n] = 0;	}else		s = name;	buf = dirstat(s);	if(buf == nil){		if(s != name)			free(s);		return 0;	}	t = buf->mtime;	free(buf);	if(s != name)		free(s);	return t;} char *stab; char *membername(char *s, int fd, char *sz){	long t; 	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 */		return stab+atol(s+1);	else		return s;}