#include "mk.h" #include #include #define Arc My_Arc /* avoid name conflicts */ #undef DELETE #include enum { Nchild = 100, }; char *rootdir = "c:\\usr\\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); void readenv(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; } void dirtime(char *dir, char *path) { Dir d; void *t; char buf[4096]; HANDLE handle; WIN32_FIND_DATA wfd; snprint(buf, sizeof(buf), "%s/*.*", dir); handle = FindFirstFile(buf, &wfd); if(handle == INVALID_HANDLE_VALUE) return; do { sprint(buf, "%s%s", path, wfd.cFileName); if(dirstat(buf, &d) < 0) continue; t = (void *)d.mtime; if (!t) /* zero mode file */ continue; if(symlook(buf, S_TIME, 0)) continue; symlook(strdup(buf), S_TIME, t)->value = t; } while(FindNextFile(handle, &wfd) == TRUE); FindClose(handle); } int waitfor(char *msg) { int pid, n, i, r, code; HANDLE tab[Nchild]; for(i=0,n=0; i=n) { perror("wait failed"); exits("wait failed"); } for(i=0; ivalue))->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; } int execsh(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 WINAPI writecmd(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; } int pipecmd(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; } void Exit(void) { while(waitfor(0) != -1) ; exits("error"); } void catchnotes() { } char* maketmp(void) { static char temp[] = "mkargXXX.XXX"; mktemp(temp); return temp; } int chgtime(char *name) { Dir sbuf; struct utimbuf u; if(mkdirstat(name, &sbuf) >= 0){ u.actime = sbuf.atime; u.modtime = time(0); return utime(name, &u); } 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; } } int mkdirstat(char *name, Dir *buf) { int c, n, ret; n = strlen(name)-1; c = name[n]; if(c == '/' || c == '\\') name[n] = 0; ret = dirstat(name, buf); name[n] = c; return ret; }