Initialize the PIB at startup.
Otherwise, it won't be available to DLL init code when run before the main executable starts. Fixes Watcom C's wlink.exe crashing because it gets a NULL command line.
This commit is contained in:
1 parent
7dcce0cbd8
commit
cbffb2ff60
3 files changed
+142
-123
No files matched your search
+125
-106
@@ -341,106 +341,6 @@ static void deinitOs2Tib(const uint16 selector)
|
||||
|
||||
static __attribute__((noreturn)) void runLxModule(LxModule *lxmod, const int argc, char **argv, char **envp)
|
||||
{
|
||||
// Eventually, the environment table looks like this (double-null to terminate list): var1=a\0var2=b\0var3=c\0\0
|
||||
// The command line looks like this: \0argv0\0argv1 argv2 argvN\0\0
|
||||
// Between env and cmd is the exe name: argv0\0
|
||||
|
||||
size_t len = 1;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
int needs_escape = 0;
|
||||
int num_backslashes = 0;
|
||||
for (const char *arg = argv[i]; *arg; arg++) {
|
||||
const char ch = *arg;
|
||||
if ((ch == ' ') || (ch == '\t'))
|
||||
needs_escape = 1;
|
||||
else if ((ch == '\\') || (ch == '\"'))
|
||||
num_backslashes++;
|
||||
len++;
|
||||
} // for
|
||||
|
||||
if (needs_escape) {
|
||||
len += 2 + num_backslashes;
|
||||
} // if
|
||||
|
||||
len++; // terminator
|
||||
} // for
|
||||
|
||||
len += strlen(argv[0]) + 1; // for the exe name.
|
||||
|
||||
const char *default_os2path = "PATH=C:\\home\\icculus\\Dropbox\\emx\\bin;C:\\home\\icculus"; // !!! FIXME: noooooope.
|
||||
for (int i = 0; envp[i]; i++) {
|
||||
const char *str = envp[i];
|
||||
if (strncmp(str, "PATH=", 5) == 0) {
|
||||
if (!GLoaderState->subprocess)
|
||||
str = default_os2path;
|
||||
} else if (strncmp(str, "IS_2INE=", 8) == 0) {
|
||||
continue;
|
||||
} // if
|
||||
len += strlen(str) + 1;
|
||||
} // for
|
||||
|
||||
len += 4; // null terminators.
|
||||
|
||||
char *env = (char *) malloc(len);
|
||||
if (!env) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
} // if
|
||||
|
||||
char *ptr = env;
|
||||
for (int i = 0; envp[i]; i++) {
|
||||
const char *str = envp[i];
|
||||
if (strncmp(str, "PATH=", 5) == 0) {
|
||||
if (!GLoaderState->subprocess)
|
||||
str = default_os2path;
|
||||
} else if (strncmp(str, "IS_2INE=", 8) == 0) {
|
||||
continue;
|
||||
} // if
|
||||
|
||||
strcpy(ptr, str);
|
||||
ptr += strlen(str) + 1;
|
||||
}
|
||||
*(ptr++) = '\0';
|
||||
|
||||
// put the exe name between the environment and the command line.
|
||||
strcpy(ptr, argv[0]);
|
||||
ptr += strlen(argv[0]) + 1;
|
||||
|
||||
char *cmd = ptr;
|
||||
strcpy(ptr, argv[0]);
|
||||
ptr += strlen(argv[0]);
|
||||
*(ptr++) = '\0';
|
||||
for (int i = 1; i < argc; i++) {
|
||||
int needs_escape = 0;
|
||||
for (const char *arg = argv[i]; *arg; arg++) {
|
||||
const char ch = *arg;
|
||||
if ((ch == ' ') || (ch == '\t'))
|
||||
needs_escape = 1;
|
||||
} // for
|
||||
|
||||
if (needs_escape) {
|
||||
*(ptr++) = '"';
|
||||
for (const char *arg = argv[i]; *arg; arg++) {
|
||||
const char ch = *arg;
|
||||
if ((ch == '\\') || (ch == '\n'))
|
||||
*(ptr++) = '\\';
|
||||
*(ptr++) = ch;
|
||||
} // for
|
||||
*(ptr++) = '"';
|
||||
} else {
|
||||
for (const char *arg = argv[i]; *arg; arg++)
|
||||
*(ptr++) = *arg;
|
||||
} // if
|
||||
|
||||
if (i < (argc-1))
|
||||
*(ptr++) = ' ';
|
||||
} // for
|
||||
|
||||
*(ptr++) = '\0';
|
||||
|
||||
lxmod->env = env;
|
||||
lxmod->cmd = cmd;
|
||||
|
||||
uint8 *stack = (uint8 *) ((size_t) lxmod->esp);
|
||||
stack -= sizeof (LxTIB) + sizeof (LxTIB2); // skip the TIB data.
|
||||
|
||||
@@ -472,7 +372,9 @@ static __attribute__((noreturn)) void runLxModule(LxModule *lxmod, const int arg
|
||||
"pushl %%eax \n\t" // call _exit() with whatever is in %eax.
|
||||
"call _exit \n\t"
|
||||
: // no outputs
|
||||
: "a" (cmd), "c" (env), "d" (lxmod), "S" (stack), "D" (lxmod->eip)
|
||||
: "a" (GLoaderState->pib.pib_pchcmd),
|
||||
"c" (GLoaderState->pib.pib_pchenv),
|
||||
"d" (lxmod), "S" (stack), "D" (lxmod->eip)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
@@ -906,8 +808,9 @@ static LxModule *loadLxModule(const char *fname, uint8 *exe, uint32 exelen, int
|
||||
*ptr = '\0';
|
||||
} // if
|
||||
|
||||
if (!isDLL) { // !!! FIXME: mutex?
|
||||
if (!isDLL) {
|
||||
GLoaderState->main_module = retval;
|
||||
GLoaderState->pib.pib_hmte = retval;
|
||||
} // else if
|
||||
|
||||
const char *modname = retval->name;
|
||||
@@ -1312,6 +1215,118 @@ static LxModule *loadLxModuleByModuleNameInternal(const char *modname, const int
|
||||
return retval;
|
||||
} // loadLxModuleByModuleNameInternal
|
||||
|
||||
static void initPib(LxPIB *pib, const int argc, char **argv, char **envp)
|
||||
{
|
||||
// !!! FIXME: this is incomplete.
|
||||
memset(pib, '\0', sizeof (*pib));
|
||||
|
||||
// Eventually, the environment table looks like this (double-null to terminate list): var1=a\0var2=b\0var3=c\0\0
|
||||
// The command line looks like this: \0argv0\0argv1 argv2 argvN\0\0
|
||||
// Between env and cmd is the exe name: argv0\0
|
||||
|
||||
size_t len = 1;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
int needs_escape = 0;
|
||||
int num_backslashes = 0;
|
||||
for (const char *arg = argv[i]; *arg; arg++) {
|
||||
const char ch = *arg;
|
||||
if ((ch == ' ') || (ch == '\t'))
|
||||
needs_escape = 1;
|
||||
else if ((ch == '\\') || (ch == '\"'))
|
||||
num_backslashes++;
|
||||
len++;
|
||||
} // for
|
||||
|
||||
if (needs_escape) {
|
||||
len += 2 + num_backslashes;
|
||||
} // if
|
||||
|
||||
len++; // terminator
|
||||
} // for
|
||||
|
||||
len += strlen(argv[0]) + 1; // for the exe name.
|
||||
|
||||
const char *default_os2path = "PATH=C:\\home\\icculus\\Dropbox\\emx\\bin;C:\\WATCOM\\binp;C:\\home\\icculus"; // !!! FIXME: noooooope.
|
||||
for (int i = 0; envp[i]; i++) {
|
||||
const char *str = envp[i];
|
||||
if (strncmp(str, "PATH=", 5) == 0) {
|
||||
if (!GLoaderState->subprocess)
|
||||
str = default_os2path;
|
||||
} else if (strncmp(str, "IS_2INE=", 8) == 0) {
|
||||
continue;
|
||||
} // if
|
||||
len += strlen(str) + 1;
|
||||
} // for
|
||||
|
||||
len += 4; // null terminators.
|
||||
|
||||
char *env = (char *) malloc(len);
|
||||
if (!env) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
} // if
|
||||
|
||||
char *ptr = env;
|
||||
for (int i = 0; envp[i]; i++) {
|
||||
const char *str = envp[i];
|
||||
if (strncmp(str, "PATH=", 5) == 0) {
|
||||
if (!GLoaderState->subprocess)
|
||||
str = default_os2path;
|
||||
} else if (strncmp(str, "IS_2INE=", 8) == 0) {
|
||||
continue;
|
||||
} // if
|
||||
|
||||
strcpy(ptr, str);
|
||||
ptr += strlen(str) + 1;
|
||||
}
|
||||
*(ptr++) = '\0';
|
||||
|
||||
// put the exe name between the environment and the command line.
|
||||
strcpy(ptr, argv[0]);
|
||||
ptr += strlen(argv[0]) + 1;
|
||||
|
||||
char *cmd = ptr;
|
||||
strcpy(ptr, argv[0]);
|
||||
ptr += strlen(argv[0]);
|
||||
*(ptr++) = '\0';
|
||||
for (int i = 1; i < argc; i++) {
|
||||
int needs_escape = 0;
|
||||
for (const char *arg = argv[i]; *arg; arg++) {
|
||||
const char ch = *arg;
|
||||
if ((ch == ' ') || (ch == '\t'))
|
||||
needs_escape = 1;
|
||||
} // for
|
||||
|
||||
if (needs_escape) {
|
||||
*(ptr++) = '"';
|
||||
for (const char *arg = argv[i]; *arg; arg++) {
|
||||
const char ch = *arg;
|
||||
if ((ch == '\\') || (ch == '\n'))
|
||||
*(ptr++) = '\\';
|
||||
*(ptr++) = ch;
|
||||
} // for
|
||||
*(ptr++) = '"';
|
||||
} else {
|
||||
for (const char *arg = argv[i]; *arg; arg++)
|
||||
*(ptr++) = *arg;
|
||||
} // if
|
||||
|
||||
if (i < (argc-1))
|
||||
*(ptr++) = ' ';
|
||||
} // for
|
||||
|
||||
*(ptr++) = '\0';
|
||||
|
||||
pib->pib_ulpid = (uint32) getpid();
|
||||
pib->pib_ulppid = (uint32) getppid();
|
||||
pib->pib_pchcmd = cmd;
|
||||
pib->pib_pchenv = env;
|
||||
//pib->pib_hmte is filled in later during loadLxModule()
|
||||
// !!! FIXME: uint32 pib_flstatus;
|
||||
// !!! FIXME: uint32 pib_ultype;
|
||||
} // initPib
|
||||
|
||||
|
||||
static LxModule *loadLxModuleByModuleName(const char *modname)
|
||||
{
|
||||
return loadLxModuleByModuleNameInternal(modname, 0);
|
||||
@@ -1330,16 +1345,20 @@ int main(int argc, char **argv, char **envp)
|
||||
GLoaderState->deinitOs2Tib = deinitOs2Tib;
|
||||
GLoaderState->loadModule = loadLxModuleByModuleName;
|
||||
|
||||
LxModule *lxmod = loadLxModuleByPath(envr ? envr : argv[1]);
|
||||
if (!lxmod) {
|
||||
return 1;
|
||||
}
|
||||
const char *modulename = GLoaderState->subprocess ? envr : argv[1];
|
||||
|
||||
// standalone, drop argv[0]. As a subprocess, keep it.
|
||||
if (!GLoaderState->subprocess) {
|
||||
argc--;
|
||||
argv++;
|
||||
} // if
|
||||
|
||||
initPib(&GLoaderState->pib, argc, argv, envp);
|
||||
|
||||
LxModule *lxmod = loadLxModuleByPath(modulename);
|
||||
if (!lxmod) {
|
||||
return 1;
|
||||
}
|
||||
runLxModule(lxmod, argc, argv, envp);
|
||||
|
||||
return 1; // you shouldn't hit this, but if you do, report failure.
|
||||
|
||||
+13
-2
@@ -155,8 +155,6 @@ struct LxModule
|
||||
uint32 eip;
|
||||
uint32 esp;
|
||||
int initialized;
|
||||
char *env;
|
||||
char *cmd;
|
||||
char *os2path; // absolute path to module, in OS/2 format
|
||||
// !!! FIXME: put this elsewhere?
|
||||
uint32 signal_exception_focus_count;
|
||||
@@ -183,6 +181,18 @@ typedef struct LxTIB
|
||||
uint32 tib_version;
|
||||
uint32 tib_ordinal;
|
||||
} LxTIB;
|
||||
|
||||
typedef struct LxPIB
|
||||
{
|
||||
uint32 pib_ulpid;
|
||||
uint32 pib_ulppid;
|
||||
void *pib_hmte;
|
||||
char *pib_pchcmd;
|
||||
char *pib_pchenv;
|
||||
uint32 pib_flstatus;
|
||||
uint32 pib_ultype;
|
||||
} LxPIB;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define LXTIBSIZE (sizeof (LxTIB) + sizeof (LxTIB2))
|
||||
@@ -191,6 +201,7 @@ typedef struct LxLoaderState
|
||||
{
|
||||
LxModule *loaded_modules;
|
||||
LxModule *main_module;
|
||||
LxPIB pib;
|
||||
int subprocess;
|
||||
int running;
|
||||
uint16 (*initOs2Tib)(uint8 *tibspace, void *_topOfStack, const size_t stacklen, const uint32 tid);
|
||||
|
||||
+4
-15
@@ -265,22 +265,11 @@ APIRET DosGetInfoBlocks(PTIB *pptib, PPIB *pppib)
|
||||
{
|
||||
TRACE_NATIVE("DosGetInfoBlocks(%p, %p)", pptib, pppib);
|
||||
|
||||
if (pptib != NULL) {
|
||||
if (pptib != NULL)
|
||||
*pptib = getTib();
|
||||
} // if
|
||||
|
||||
if (pppib != NULL) {
|
||||
static PIB pib;
|
||||
if (pib.pib_ulpid == 0) {
|
||||
// !!! FIXME: this is seriously incomplete.
|
||||
pib.pib_hmte = (HMODULE) GLoaderState->main_module;
|
||||
pib.pib_ulpid = (uint32) getpid();
|
||||
pib.pib_ulppid = (uint32) getppid();
|
||||
pib.pib_pchcmd = GLoaderState->main_module->cmd;
|
||||
pib.pib_pchenv = GLoaderState->main_module->env;
|
||||
} // if
|
||||
*pppib = &pib;
|
||||
} // if
|
||||
if (pppib != NULL)
|
||||
*pppib = (PPIB) &GLoaderState->pib;
|
||||
|
||||
return 0;
|
||||
} // DosGetInfoBlocks
|
||||
@@ -382,7 +371,7 @@ APIRET DosScanEnv(PSZ name, PSZ *outval)
|
||||
{
|
||||
TRACE_NATIVE("DosScanEnv('%s', %p)", name, outval);
|
||||
|
||||
char *env = GLoaderState->main_module->env;
|
||||
char *env = GLoaderState->pib.pib_pchenv;
|
||||
const size_t len = strlen(name);
|
||||
while (*env) {
|
||||
if ((strncmp(env, name, len) == 0) && (env[len] == '=')) {
|
||||
|
||||
Reference in new issue
Block a user