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:
Ryan C. Gordon committed 2016-10-17 17:00:32 -04:00
1 parent 7dcce0cbd8
commit cbffb2ff60
3 files changed
+142 -123

No files matched your search

+125 -106
View File
@@ -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
View File
@@ -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
View File
@@ -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] == '=')) {