Rev 5198 | Rev 6074 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6068 | serge | 1 | /* |
2 | * crtdll.c |
||
3 | * This file has no copyright assigned and is placed in the Public Domain. |
||
4 | * This file is a part of the mingw-runtime package. |
||
5 | * No warranty is given; refer to the file DISCLAIMER within the package. |
||
6 | * |
||
7 | * Source code for the shared libc startup proceedures. This code is compiled |
||
8 | * to make libc.dll, which should be located in the library path. |
||
9 | * |
||
10 | */ |
||
4349 | Serge | 11 | |
12 | #include <_ansi.h> |
||
13 | #include |
||
14 | #include |
||
15 | #include |
||
16 | #include |
||
17 | #include |
||
18 | #include |
||
19 | #include |
||
20 | #include |
||
21 | |||
22 | struct app_hdr |
||
23 | { |
||
24 | char banner[8]; |
||
25 | int version; |
||
26 | int start; |
||
27 | int iend; |
||
28 | int memsize; |
||
29 | int stacktop; |
||
30 | char *cmdline; |
||
31 | char *path; |
||
32 | int reserved; |
||
33 | void *__idata_start; |
||
34 | void *__idata_end; |
||
35 | int (*main)(int argc, char **argv, char **envp); |
||
36 | }; |
||
37 | |||
5190 | serge | 38 | void _pei386_runtime_relocator (void); |
39 | void init_loader(void *libc_image); |
||
40 | void init_reent(); |
||
4349 | Serge | 41 | |
5190 | serge | 42 | int link_app(); |
4349 | Serge | 43 | void* get_entry_point(void *raw); |
44 | int (*entry)(int, char **, char **); |
||
45 | |||
5190 | serge | 46 | char* __appenv; |
47 | int __appenv_size; |
||
4349 | Serge | 48 | |
5190 | serge | 49 | extern char _tls_map[128]; |
4349 | Serge | 50 | |
51 | char * __libc_getenv(const char *name) |
||
52 | { |
||
53 | return NULL; |
||
54 | } |
||
55 | |||
5190 | serge | 56 | static int split_cmdline(char *cmdline, char **argv) |
57 | { |
||
58 | enum quote_state |
||
59 | { |
||
60 | QUOTE_NONE, /* no " active in current parm */ |
||
61 | QUOTE_DELIMITER, /* " was first char and must be last */ |
||
62 | QUOTE_STARTED /* " was seen, look for a match */ |
||
63 | }; |
||
4349 | Serge | 64 | |
5190 | serge | 65 | enum quote_state state; |
66 | unsigned int argc; |
||
67 | char *p = cmdline; |
||
68 | char *new_arg, *start; |
||
4349 | Serge | 69 | |
5190 | serge | 70 | argc = 0; |
4349 | Serge | 71 | |
5190 | serge | 72 | for(;;) |
73 | { |
||
74 | /* skip over spaces and tabs */ |
||
75 | if ( *p ) |
||
76 | { |
||
77 | while (*p == ' ' || *p == '\t') |
||
78 | ++p; |
||
79 | } |
||
4349 | Serge | 80 | |
5190 | serge | 81 | if (*p == '\0') |
82 | break; |
||
83 | |||
84 | state = QUOTE_NONE; |
||
85 | if( *p == '\"' ) |
||
86 | { |
||
87 | p++; |
||
88 | state = QUOTE_DELIMITER; |
||
89 | } |
||
90 | new_arg = start = p; |
||
91 | for (;;) |
||
92 | { |
||
93 | if( *p == '\"' ) |
||
94 | { |
||
95 | p++; |
||
96 | if( state == QUOTE_NONE ) |
||
97 | { |
||
98 | state = QUOTE_STARTED; |
||
99 | } |
||
100 | else |
||
101 | { |
||
102 | state = QUOTE_NONE; |
||
103 | } |
||
104 | continue; |
||
105 | } |
||
106 | |||
107 | if( *p == ' ' || *p == '\t' ) |
||
108 | { |
||
109 | if( state == QUOTE_NONE ) |
||
110 | { |
||
111 | break; |
||
112 | } |
||
113 | } |
||
114 | |||
115 | if( *p == '\0' ) |
||
116 | break; |
||
117 | |||
118 | if( *p == '\\' ) |
||
119 | { |
||
120 | if( p[1] == '\"' ) |
||
121 | { |
||
122 | ++p; |
||
123 | if( p[-2] == '\\' ) |
||
124 | { |
||
125 | continue; |
||
126 | } |
||
127 | } |
||
128 | } |
||
129 | if( argv ) |
||
130 | { |
||
131 | *(new_arg++) = *p; |
||
132 | } |
||
133 | ++p; |
||
134 | }; |
||
135 | |||
136 | if( argv ) |
||
137 | { |
||
138 | argv[ argc ] = start; |
||
139 | ++argc; |
||
140 | |||
141 | /* |
||
142 | The *new = '\0' is req'd in case there was a \" to " |
||
143 | translation. It must be after the *p check against |
||
144 | '\0' because new and p could point to the same char |
||
145 | in which case the scan would be terminated too soon. |
||
146 | */ |
||
147 | |||
148 | if( *p == '\0' ) |
||
149 | { |
||
150 | *new_arg = '\0'; |
||
151 | break; |
||
152 | } |
||
153 | *new_arg = '\0'; |
||
154 | ++p; |
||
155 | } |
||
156 | else |
||
157 | { |
||
158 | ++argc; |
||
159 | if( *p == '\0' ) |
||
160 | { |
||
161 | break; |
||
162 | } |
||
163 | ++p; |
||
164 | } |
||
165 | } |
||
166 | |||
167 | return argc; |
||
168 | }; |
||
169 | |||
4349 | Serge | 170 | void __attribute__((noreturn)) |
171 | libc_crt_startup (void *libc_base) |
||
172 | { |
||
173 | struct app_hdr *header = NULL; |
||
5190 | serge | 174 | int retval = 0; |
4349 | Serge | 175 | |
5190 | serge | 176 | char **argv; |
177 | int argc; |
||
4349 | Serge | 178 | |
179 | _pei386_runtime_relocator(); |
||
180 | |||
181 | memset(_tls_map, 0xFF, 32*4); |
||
182 | _tls_map[0] = 0xE0; |
||
183 | init_reent(); |
||
4921 | Serge | 184 | init_stdio(); |
6068 | serge | 185 | __do_global_ctors(); |
4349 | Serge | 186 | |
187 | // __appenv = load_file("/sys/system.env", &__appenv_size); |
||
188 | |||
189 | init_loader(libc_base); |
||
190 | |||
191 | if( link_app() == 0) |
||
192 | goto done; |
||
193 | |||
194 | if( header->cmdline[0] != 0) |
||
195 | { |
||
5190 | serge | 196 | argc = split_cmdline(header->cmdline, NULL) + 1; |
197 | argv = alloca((argc+1)*sizeof(char*)); |
||
198 | argv[0] = header->path; |
||
199 | |||
200 | split_cmdline(header->cmdline, argv + 1); |
||
4349 | Serge | 201 | } |
5190 | serge | 202 | else |
203 | { |
||
204 | argc = 1; |
||
205 | argv = alloca((argc+1)*sizeof(char*)); |
||
206 | argv[0] = header->path; |
||
207 | } |
||
208 | argv[argc] = NULL; |
||
4349 | Serge | 209 | |
5190 | serge | 210 | retval = header->main(argc, argv, NULL); |
4349 | Serge | 211 | done: |
212 | exit (retval); |
||
213 | } |
||
214 |