Subversion Repositories Kolibri OS

Rev

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