#include #include #include #include #include "fdtab.h" #include "util.h" /* * derived from inferno's rcsh/Nt.c */ /* * windows quoting rules - I think * Words are seperated by space or tab * Words containing a space or tab can be quoted using " * 2N backslashes + " ==> N backslashes and end quote * 2N+1 backslashes + " ==> N backslashes + literal " * N backslashes not followed by " ==> N backslashes */ static char * dblquote(char *cmd, char *s) { int nb; char *p; for(p=s; *p; p++) if(*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '"') break; if(*p == 0){ /* easy case */ strcpy(cmd, s); return cmd+(p-s); } *cmd++ = '"'; for(;;) { for(nb=0; *s=='\\'; nb++) *cmd++ = *s++; if(*s == 0) { /* trailing backslashes -> 2N */ while(nb-- > 0) *cmd++ = '\\'; break; } if(*s == '"') { /* literal quote -> 2N+1 backslashes */ while(nb-- > 0) *cmd++ = '\\'; *cmd++ = '\\'; /* escape the quote */ } *cmd++ = *s++; } *cmd++ = '"'; *cmd = 0; return cmd; } static char * proccmd(char **argv) { int i, n; char *cmd, *p; /* conservatively calculate length of command; * backslash expansion can cause growth in dblquote(). */ for(i=0,n=0; argv[i]; i++) { n += 2*strlen(argv[i]); } n++; cmd = malloc(n); for(i=0,p=cmd; argv[i]; i++) { p = dblquote(p, argv[i]); *p++ = ' '; } if(p != cmd) p--; *p = 0; return cmd; } static WCHAR * exportenv(char **e) { int i, j, n; WCHAR *buf; if(e == 0 || *e == 0) return 0; winsortenv(e); buf = 0; n = 0; for(i = 0; *e; e++, i++) { j = utflen(*e)+1; buf = realloc(buf, sizeof(WCHAR)*(n+j)); winutftowstr(buf+n, *e, j); // fprint(2, "export: %*s\n", j, *e); n += j; } /* final null */ buf = realloc(buf, sizeof(Rune)*(n+1)); buf[n] = 0; return buf; } static char** getshargs(char *shell, char *script, char *shargv[]) { char **v; char *sh, *p; long shsz; int i, n; p = strrchr(shell, '/'); if (p==nil) sh = shell; else sh = p+1; for (n=0; shargv[n]!=nil;) n++; shsz = strlen(sh)+1; v = malloc((n+1+1) * sizeof(char*) + shsz + strlen(script)+1); if (v==nil) return nil; for (i=1; i<=n; i++) v[i+1] = shargv[i]; p = (char*)&v[i+1]; v[0] = p; strcpy(p, sh); p += shsz; v[1] = p; strcpy(p, script); return v; } int lookupexe(char path[], char *file, char ***argvp, int search) { int found, full; char *shell; char *p, *q, buf[MAX_PATH]; char **argv; full = file[0] == '\\' || file[0] == '/' || file[0] == '.' || winisdrvspec(file); found = winexecpath(path, file, &shell); if(!found && !full && search) { p = getenv("PATH"); for(; p && *p; p = q){ q = strchr(p, ';'); if(q) *q = 0; snprint(buf, sizeof(buf), "%s/%s", p, file); if(q) *q++ = ';'; found = winexecpath(path, buf, &shell); if(found) break; } } if(!found) { werrstr("file not found"); return -1; } argv = *argvp; if (shell!=nil) { // fprint(2, "look shell %s %s\n", shell, path); argv = getshargs(shell, path, argv); if (argv==nil) { free(shell); werrstr("could not assemble shell command line"); return -1; } found = winexecpath(path, shell, nil); if(!found) { werrstr("interpreter not found: %s", shell); free(shell); return -1; } free(shell); } if (argvp!=nil) *argvp = argv; return 0; } static HANDLE fdexport(int fd, int i, int tx, int *fused) { Fd *f; HANDLE l, r, hr, hw; SECURITY_ATTRIBUTES seca; seca = (SECURITY_ATTRIBUTES) { .nLength= sizeof seca, .lpSecurityDescriptor= NULL, .bInheritHandle= TRUE, }; f = fdtget(fd); if (f!=nil) switch (f->type) { case Fdtypefile: case Fdtypestd: case Fdtypecons: if (DuplicateHandle(GetCurrentProcess(), f->h, GetCurrentProcess(), &r, DUPLICATE_SAME_ACCESS, 1, DUPLICATE_SAME_ACCESS)) { // fprint(2, "duphan %p->%p\n", f->h, r); return r; } break; case Fdtypedevnull: fd = -1; case Fdtypepipecl: case Fdtypepipesrv: case Fdtypesock: if (!CreatePipe(&hr, &hw, &seca, 0)) break; if (tx) { l = hw; r = hr; } else { l = hr; r = hw; } SetHandleInformation(l, HANDLE_FLAG_INHERIT, 0); if (fd!=-1) *fused |= 1<