#include #include #include #include #include #include "go32.h" #include "dpmi.h" /*#include "process.h"*/ #if 1 #define P_WAIT 1 #define P_NOWAIT 2 /* always generates error */ #define P_OVERLAY 3 #endif extern const char **environ; #define environ ((const char **)environ) #define scan_ptr() \ char const **ptr; \ for (ptr = &argv0; *ptr; ptr++); \ ptr = (char const **)(*++ptr); int execl(const char *path, const char *argv0, ...) { return spawnve(P_OVERLAY, path, &argv0, environ); } int execle(const char *path, const char *argv0, ... /*, const char **envp */) { scan_ptr(); return spawnve(P_OVERLAY, path, &argv0, ptr); } int execlp(const char *path, const char *argv0, ...) { return spawnvpe(P_OVERLAY, path, &argv0, environ); } int execlpe(const char *path, const char *argv0, ... /*, const char **envp */) { scan_ptr(); return spawnvpe(P_OVERLAY, path, &argv0, ptr); } /*-------------------------------------------------*/ int execv(const char *path, const char **argv) { return spawnve(P_OVERLAY, path, argv, environ); } int execve(const char *path, const char **argv, const char **envp) { return spawnve(P_OVERLAY, path, argv, envp); } int execvp(const char *path, const char **argv) { return spawnvpe(P_OVERLAY, path, argv, environ); } int execvpe(const char *path, const char **argv, const char **envp) { return spawnvpe(P_OVERLAY, path, argv, envp); } /*-------------------------------------------------*/ int spawnl(int mode, const char *path, const char *argv0, ...) { return spawnve(mode, path, &argv0, environ); } int spawnle(int mode, const char *path, const char *argv0, ... /*, const char **envp */) { scan_ptr(); return spawnve(mode, path, &argv0, ptr); } int spawnlp(int mode, const char *path, const char *argv0, ...) { return spawnvpe(mode, path, &argv0, environ); } int spawnlpe(int mode, const char *path, const char *argv0, ... /*, const char **envp */) { scan_ptr(); return spawnvpe(mode, path, &argv0, ptr); } /*-------------------------------------------------*/ typedef struct { u_short eseg; u_short argoff; u_short argseg; u_short fcb1_off; u_short fcb1_seg; u_short fcb2_off; u_short fcb2_seg; } Execp; static Execp parm; static u_long tbuf; static u_long talloc(size_t amt) { u_long rv = tbuf; tbuf += amt; return rv; } static int direct_exec_tail(const char *program, const char *args, const char **envp) { _go32_dpmi_registers r; u_long program_la; u_long arg_la; u_long parm_la; u_long env_la, env_e_la; char arg_header[3]; int i; program_la = talloc(strlen(program)+1); arg_la = talloc(strlen(args)+3); parm_la = talloc(sizeof(Execp)); dosmemput(program, strlen(program)+1, program_la); arg_header[0] = strlen(args); arg_header[1] = '\r'; dosmemput(arg_header, 1, arg_la); dosmemput(args, strlen(args), arg_la+1); dosmemput(arg_header+1, 1, arg_la+1+strlen(args)); do { env_la = talloc(1); } while (env_la & 15); talloc(-1); for (i=0; envp[i]; i++) { env_e_la = talloc(strlen(envp[i])+1); dosmemput(envp[i], strlen(envp[i])+1, env_e_la); } arg_header[0] = 0; arg_header[1] = 1; arg_header[2] = 0; dosmemput(arg_header, 3, talloc(3)); env_e_la = talloc(strlen(program)+1); dosmemput(program, strlen(program)+1, env_e_la); parm.eseg = env_la / 16; parm.argseg = arg_la / 16; parm.argoff = arg_la & 15; dosmemput(&parm, sizeof(parm), parm_la); memset(&r, 0, sizeof(r)); r.x.ax = 0x4b00; r.x.ds = program_la / 16; r.x.dx = program_la & 15; r.x.es = parm_la / 16; r.x.bx = parm_la & 15; _go32_dpmi_simulate_int(0x21, &r); if (r.x.flags & 1) { errno = r.x.ax; return -1; } memset(&r, 0, sizeof(r)); r.h.ah = 0x4d; _go32_dpmi_simulate_int(0x21, &r); if (r.x.flags & 1) { errno = r.x.ax; return -1; } return r.x.ax; } static int direct_exec(const char *program, const char **argv, const char **envp) { int i, arglen; char *args, *argp; tbuf = _go32_info_block.linear_address_of_transfer_buffer; arglen = 0; for (i=1; argv[i]; i++) arglen += strlen(argv[i]) + 1; args = (char *)malloc(arglen+1); argp = args; for (i=1; argv[i]; i++) { const char *p = argv[i]; if (argp - args > 125) break; *argp++ = ' '; while (*p) { if (argp - args > 125) break; *argp++ = *p++; } } *argp = 0; return direct_exec_tail(program, args, envp); } typedef struct { char magic[16]; int struct_length; char go32[16]; } StubInfo; #define STUB_INFO_MAGIC "StubInfoMagic!!" static int go32_exec(const char *program, const char **argv, const char **envp) { int is_stubbed = 0; int found_si = 0; StubInfo si; unsigned short header[3]; int pf, has_dot, i; char *go32, *sip; const char *pp, *pe; char rpath[80], *rp; int stub_offset, argc; int si_la, rm_la, rm_seg; short *rm_argv; char cmdline[34]; pf = open(program, O_RDONLY|O_BINARY); read(pf, header, sizeof(header)); if (header[0] == 0x010b || header[0] == 0x014c) { is_stubbed = 1; } else if (header[0] == 0x5a4d) { int header_offset = (long)header[2]*512L; if (header[1]) header_offset += (long)header[1] - 512L; lseek(pf, header_offset - 4, 0); read(pf, &stub_offset, 4); header[0] = 0; read(pf, header, sizeof(header)); if (header[0] == 0x010b) is_stubbed = 1; if (header[0] == 0x014c) is_stubbed = 1; lseek(pf, stub_offset, 0); read(pf, &si, sizeof(si)); if (memcmp(STUB_INFO_MAGIC, si.magic, 16) == 0) found_si = 1; } if (!is_stubbed) { close(pf); return direct_exec(program, argv, envp); } if (found_si) go32 = si.go32; else go32 = "go32.exe"; has_dot = 0; for (i=0; go32[i]; i++) if (go32[i] == '.') has_dot = 1; if (!has_dot) strcpy(go32+i, ".exe"); for (i=0; envp[i]; i++) if (strncmp(envp[i], "PATH=", 5) == 0) pp = envp[i]+5; strcpy(rpath, go32); while (access(rpath, 0)) { char *ptr; rp = rpath; for (pe=pp; *pe && *pe != ';'; pe++) *rp++ = *pe; pp = pe+1; if (rp > rpath && rp[-1] != '/' && rp[-1] != '\\' && rp[-1] != ':') *rp++ = '/'; for (ptr = go32; *ptr; ptr++) *rp++ = *ptr; *rp = 0; if (access(rpath, 0) == 0) break; if (*pe == 0) return direct_exec(program, argv, envp); /* give up and just run it */ } if (found_si) { lseek(pf, stub_offset, 0); sip = (char *)malloc(si.struct_length); read(pf, sip, si.struct_length); } close(pf); argv[0] = program; /* since that's where we really found it */ tbuf = _go32_info_block.linear_address_of_transfer_buffer; if (found_si) { si_la = talloc(si.struct_length); dosmemput(sip, si.struct_length, si_la); free(sip); } for (argc=0; argv[argc]; argc++); rm_la = talloc(2*(argc+1)); rm_seg = (_go32_info_block.linear_address_of_transfer_buffer >> 4) & 0xffff; rm_argv = (short *)malloc((argc+1) * sizeof(short)); for (i=0; i