summaryrefslogtreecommitdiff
path: root/utils/mk/Nt.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/mk/Nt.c')
-rw-r--r--utils/mk/Nt.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/utils/mk/Nt.c b/utils/mk/Nt.c
new file mode 100644
index 00000000..002807bb
--- /dev/null
+++ b/utils/mk/Nt.c
@@ -0,0 +1,442 @@
+#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);
+
+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;
+}
+
+int
+waitfor(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;
+}
+
+void
+expunge(int pid, char *msg)
+{
+/*
+ if(strcmp(msg, "interrupt"))
+ kill(pid, SIGINT);
+ else
+ kill(pid, SIGHUP);
+*/
+}
+
+HANDLE
+duphandle(HANDLE h)
+{
+ HANDLE r;
+
+ if(DuplicateHandle(GetCurrentProcess(), h,
+ GetCurrentProcess(), &r, DUPLICATE_SAME_ACCESS,
+ 1, DUPLICATE_SAME_ACCESS) == FALSE) {
+ perror("dup handle");
+ Exit();
+ }
+
+ return r;
+}
+
+void
+childadd(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 WINAPI
+spinoff(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;
+}
+
+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;
+}
+
+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;
+}
+
+int
+chgtime(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));
+}
+
+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;
+ }
+}
+
+ulong
+mkmtime(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;
+}