Rev 9952 | 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 | |||
21 | struct app_hdr |
||
22 | { |
||
23 | char banner[8]; |
||
24 | int version; |
||
25 | int start; |
||
26 | int iend; |
||
27 | int memsize; |
||
28 | int stacktop; |
||
29 | char *cmdline; |
||
30 | char *path; |
||
6074 | serge | 31 | int __subsystem__; |
4349 | Serge | 32 | void *__idata_start; |
33 | void *__idata_end; |
||
34 | int (*main)(int argc, char **argv, char **envp); |
||
35 | }; |
||
36 | |||
9959 | turbocat | 37 | #define ENV_SIZE 16 |
38 | /* TODO: Make it dynamic?* */ |
||
39 | static char* __environ[ENV_SIZE] = {0}; |
||
40 | char **environ = &__environ[0]; |
||
41 | |||
6536 | serge | 42 | extern void _pei386_runtime_relocator (void); |
43 | extern void init_loader(void *libc_image); |
||
6664 | serge | 44 | extern void init_global_reent(void); |
6536 | serge | 45 | extern void init_stdio(void); |
4349 | Serge | 46 | |
6536 | serge | 47 | extern void __init_conio(void); |
48 | extern void __fini_conio(void); |
||
49 | extern int link_app(void); |
||
50 | extern void* get_entry_point(void *raw); |
||
51 | |||
52 | extern void tls_init(void); |
||
53 | |||
9959 | turbocat | 54 | void init_environ(void) |
55 | { |
||
56 | ksys_ufile_t envfile = _ksys_load_file("/sys/settings/system.env"); |
||
57 | if (!envfile.data || !envfile.size) |
||
58 | return; |
||
4349 | Serge | 59 | |
9959 | turbocat | 60 | char *pch = strtok((char*)envfile.data, " \n\t"); |
61 | for (size_t env_pos = 0; pch != NULL && env_pos < ENV_SIZE-1; env_pos++) |
||
62 | { |
||
63 | environ[env_pos] = pch; |
||
64 | pch = strtok(NULL, " \n\t"); |
||
65 | } |
||
4349 | Serge | 66 | } |
67 | |||
5190 | serge | 68 | static int split_cmdline(char *cmdline, char **argv) |
69 | { |
||
70 | enum quote_state |
||
71 | { |
||
72 | QUOTE_NONE, /* no " active in current parm */ |
||
73 | QUOTE_DELIMITER, /* " was first char and must be last */ |
||
74 | QUOTE_STARTED /* " was seen, look for a match */ |
||
75 | }; |
||
4349 | Serge | 76 | |
5190 | serge | 77 | enum quote_state state; |
78 | unsigned int argc; |
||
79 | char *p = cmdline; |
||
80 | char *new_arg, *start; |
||
4349 | Serge | 81 | |
5190 | serge | 82 | argc = 0; |
4349 | Serge | 83 | |
5190 | serge | 84 | for(;;) |
85 | { |
||
86 | /* skip over spaces and tabs */ |
||
87 | if ( *p ) |
||
88 | { |
||
89 | while (*p == ' ' || *p == '\t') |
||
90 | ++p; |
||
91 | } |
||
4349 | Serge | 92 | |
5190 | serge | 93 | if (*p == '\0') |
94 | break; |
||
95 | |||
96 | state = QUOTE_NONE; |
||
97 | if( *p == '\"' ) |
||
98 | { |
||
99 | p++; |
||
100 | state = QUOTE_DELIMITER; |
||
101 | } |
||
102 | new_arg = start = p; |
||
103 | for (;;) |
||
104 | { |
||
105 | if( *p == '\"' ) |
||
106 | { |
||
107 | p++; |
||
108 | if( state == QUOTE_NONE ) |
||
109 | { |
||
110 | state = QUOTE_STARTED; |
||
111 | } |
||
112 | else |
||
113 | { |
||
114 | state = QUOTE_NONE; |
||
115 | } |
||
116 | continue; |
||
117 | } |
||
118 | |||
119 | if( *p == ' ' || *p == '\t' ) |
||
120 | { |
||
121 | if( state == QUOTE_NONE ) |
||
122 | { |
||
123 | break; |
||
124 | } |
||
125 | } |
||
126 | |||
127 | if( *p == '\0' ) |
||
128 | break; |
||
129 | |||
130 | if( *p == '\\' ) |
||
131 | { |
||
132 | if( p[1] == '\"' ) |
||
133 | { |
||
134 | ++p; |
||
135 | if( p[-2] == '\\' ) |
||
136 | { |
||
137 | continue; |
||
138 | } |
||
139 | } |
||
140 | } |
||
141 | if( argv ) |
||
142 | { |
||
143 | *(new_arg++) = *p; |
||
144 | } |
||
145 | ++p; |
||
146 | }; |
||
147 | |||
148 | if( argv ) |
||
149 | { |
||
150 | argv[ argc ] = start; |
||
151 | ++argc; |
||
152 | |||
153 | /* |
||
154 | The *new = '\0' is req'd in case there was a \" to " |
||
155 | translation. It must be after the *p check against |
||
156 | '\0' because new and p could point to the same char |
||
157 | in which case the scan would be terminated too soon. |
||
158 | */ |
||
159 | |||
160 | if( *p == '\0' ) |
||
161 | { |
||
162 | *new_arg = '\0'; |
||
163 | break; |
||
164 | } |
||
165 | *new_arg = '\0'; |
||
166 | ++p; |
||
167 | } |
||
168 | else |
||
169 | { |
||
170 | ++argc; |
||
171 | if( *p == '\0' ) |
||
172 | { |
||
173 | break; |
||
174 | } |
||
175 | ++p; |
||
176 | } |
||
177 | } |
||
178 | |||
179 | return argc; |
||
180 | }; |
||
181 | |||
6536 | serge | 182 | __attribute__((noreturn)) |
183 | void libc_crt_startup (void *libc_base) |
||
4349 | Serge | 184 | { |
6536 | serge | 185 | struct app_hdr *header = NULL; |
5190 | serge | 186 | int retval = 0; |
4349 | Serge | 187 | |
5190 | serge | 188 | char **argv; |
189 | int argc; |
||
4349 | Serge | 190 | |
191 | _pei386_runtime_relocator(); |
||
192 | |||
6536 | serge | 193 | tls_init(); |
6664 | serge | 194 | init_global_reent(); |
4921 | Serge | 195 | init_stdio(); |
6074 | serge | 196 | |
197 | if(header->__subsystem__ == 3) |
||
198 | __init_conio(); |
||
199 | |||
4349 | Serge | 200 | // __appenv = load_file("/sys/system.env", &__appenv_size); |
201 | |||
202 | init_loader(libc_base); |
||
203 | |||
204 | if( link_app() == 0) |
||
205 | goto done; |
||
206 | |||
207 | if( header->cmdline[0] != 0) |
||
208 | { |
||
5190 | serge | 209 | argc = split_cmdline(header->cmdline, NULL) + 1; |
210 | argv = alloca((argc+1)*sizeof(char*)); |
||
211 | argv[0] = header->path; |
||
212 | |||
213 | split_cmdline(header->cmdline, argv + 1); |
||
4349 | Serge | 214 | } |
5190 | serge | 215 | else |
216 | { |
||
217 | argc = 1; |
||
218 | argv = alloca((argc+1)*sizeof(char*)); |
||
219 | argv[0] = header->path; |
||
220 | } |
||
221 | argv[argc] = NULL; |
||
4349 | Serge | 222 | |
9959 | turbocat | 223 | init_environ(); |
224 | |||
225 | retval = header->main(argc, argv, environ); |
||
4349 | Serge | 226 | done: |
6074 | serge | 227 | if(header->__subsystem__ == 3) |
228 | __fini_conio(); |
||
229 | |||
4349 | Serge | 230 | exit (retval); |
231 | }> |
||
232 |