2016-01-18 03:22:44 +01:00
|
|
|
/*
|
|
|
|
* crtdll.c
|
|
|
|
* This file has no copyright assigned and is placed in the Public Domain.
|
|
|
|
* This file is a part of the mingw-runtime package.
|
|
|
|
* No warranty is given; refer to the file DISCLAIMER within the package.
|
|
|
|
*
|
|
|
|
* Source code for the shared libc startup proceedures. This code is compiled
|
|
|
|
* to make libc.dll, which should be located in the library path.
|
|
|
|
*
|
|
|
|
*/
|
2013-12-15 09:09:20 +01:00
|
|
|
|
|
|
|
#include <_ansi.h>
|
|
|
|
#include <reent.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <sys/kos_io.h>
|
|
|
|
|
|
|
|
struct app_hdr
|
|
|
|
{
|
|
|
|
char banner[8];
|
|
|
|
int version;
|
|
|
|
int start;
|
|
|
|
int iend;
|
|
|
|
int memsize;
|
|
|
|
int stacktop;
|
|
|
|
char *cmdline;
|
|
|
|
char *path;
|
2016-01-18 18:02:08 +01:00
|
|
|
int __subsystem__;
|
2013-12-15 09:09:20 +01:00
|
|
|
void *__idata_start;
|
|
|
|
void *__idata_end;
|
|
|
|
int (*main)(int argc, char **argv, char **envp);
|
|
|
|
};
|
|
|
|
|
2016-09-27 22:37:49 +02:00
|
|
|
extern void _pei386_runtime_relocator (void);
|
|
|
|
extern void init_loader(void *libc_image);
|
2016-11-03 20:02:07 +01:00
|
|
|
extern void init_global_reent(void);
|
2016-09-27 22:37:49 +02:00
|
|
|
extern void init_stdio(void);
|
|
|
|
|
|
|
|
extern void __init_conio(void);
|
|
|
|
extern void __fini_conio(void);
|
|
|
|
extern int link_app(void);
|
|
|
|
extern void* get_entry_point(void *raw);
|
|
|
|
|
|
|
|
extern void tls_init(void);
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
char* __appenv;
|
|
|
|
int __appenv_size;
|
2013-12-15 09:09:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
char * __libc_getenv(const char *name)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
static int split_cmdline(char *cmdline, char **argv)
|
|
|
|
{
|
|
|
|
enum quote_state
|
|
|
|
{
|
|
|
|
QUOTE_NONE, /* no " active in current parm */
|
|
|
|
QUOTE_DELIMITER, /* " was first char and must be last */
|
|
|
|
QUOTE_STARTED /* " was seen, look for a match */
|
|
|
|
};
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
enum quote_state state;
|
|
|
|
unsigned int argc;
|
|
|
|
char *p = cmdline;
|
|
|
|
char *new_arg, *start;
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
argc = 0;
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
/* skip over spaces and tabs */
|
|
|
|
if ( *p )
|
|
|
|
{
|
|
|
|
while (*p == ' ' || *p == '\t')
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p == '\0')
|
|
|
|
break;
|
|
|
|
|
|
|
|
state = QUOTE_NONE;
|
|
|
|
if( *p == '\"' )
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
state = QUOTE_DELIMITER;
|
|
|
|
}
|
|
|
|
new_arg = start = p;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if( *p == '\"' )
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
if( state == QUOTE_NONE )
|
|
|
|
{
|
|
|
|
state = QUOTE_STARTED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
state = QUOTE_NONE;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( *p == ' ' || *p == '\t' )
|
|
|
|
{
|
|
|
|
if( state == QUOTE_NONE )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( *p == '\0' )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if( *p == '\\' )
|
|
|
|
{
|
|
|
|
if( p[1] == '\"' )
|
|
|
|
{
|
|
|
|
++p;
|
|
|
|
if( p[-2] == '\\' )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( argv )
|
|
|
|
{
|
|
|
|
*(new_arg++) = *p;
|
|
|
|
}
|
|
|
|
++p;
|
|
|
|
};
|
|
|
|
|
|
|
|
if( argv )
|
|
|
|
{
|
|
|
|
argv[ argc ] = start;
|
|
|
|
++argc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
The *new = '\0' is req'd in case there was a \" to "
|
|
|
|
translation. It must be after the *p check against
|
|
|
|
'\0' because new and p could point to the same char
|
|
|
|
in which case the scan would be terminated too soon.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if( *p == '\0' )
|
|
|
|
{
|
|
|
|
*new_arg = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*new_arg = '\0';
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++argc;
|
|
|
|
if( *p == '\0' )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return argc;
|
|
|
|
};
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2016-09-27 22:37:49 +02:00
|
|
|
__attribute__((noreturn))
|
|
|
|
void libc_crt_startup (void *libc_base)
|
2013-12-15 09:09:20 +01:00
|
|
|
{
|
2016-09-27 22:37:49 +02:00
|
|
|
struct app_hdr *header = NULL;
|
2013-12-15 09:09:20 +01:00
|
|
|
int retval = 0;
|
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
char **argv;
|
|
|
|
int argc;
|
|
|
|
|
2013-12-15 09:09:20 +01:00
|
|
|
_pei386_runtime_relocator();
|
|
|
|
|
2016-09-27 22:37:49 +02:00
|
|
|
tls_init();
|
2016-11-03 20:02:07 +01:00
|
|
|
init_global_reent();
|
2014-05-11 00:12:19 +02:00
|
|
|
init_stdio();
|
2016-01-18 18:02:08 +01:00
|
|
|
|
|
|
|
if(header->__subsystem__ == 3)
|
|
|
|
__init_conio();
|
|
|
|
|
2013-12-15 09:09:20 +01:00
|
|
|
// __appenv = load_file("/sys/system.env", &__appenv_size);
|
|
|
|
|
|
|
|
init_loader(libc_base);
|
|
|
|
|
|
|
|
if( link_app() == 0)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if( header->cmdline[0] != 0)
|
|
|
|
{
|
2014-11-27 02:02:55 +01:00
|
|
|
argc = split_cmdline(header->cmdline, NULL) + 1;
|
|
|
|
argv = alloca((argc+1)*sizeof(char*));
|
|
|
|
argv[0] = header->path;
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
split_cmdline(header->cmdline, argv + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
argc = 1;
|
|
|
|
argv = alloca((argc+1)*sizeof(char*));
|
|
|
|
argv[0] = header->path;
|
|
|
|
}
|
|
|
|
argv[argc] = NULL;
|
2013-12-15 09:09:20 +01:00
|
|
|
|
2014-11-27 02:02:55 +01:00
|
|
|
retval = header->main(argc, argv, NULL);
|
2013-12-15 09:09:20 +01:00
|
|
|
done:
|
2016-01-18 18:02:08 +01:00
|
|
|
if(header->__subsystem__ == 3)
|
|
|
|
__fini_conio();
|
|
|
|
|
2013-12-15 09:09:20 +01:00
|
|
|
exit (retval);
|
|
|
|
}
|
|
|
|
|