Merge pull request #3355 from ludovic-henry/process-fix-exited
[mono.git] / mono / mini / main.c
1 #include <config.h>
2 #include <fcntl.h>
3 #include <mono/metadata/assembly.h>
4 #include <mono/utils/mono-mmap.h>
5 #include "mini.h"
6
7 #ifdef HAVE_UNISTD_H
8 #  include <unistd.h>
9 #endif
10 #ifdef HOST_WIN32
11 #  include <io.h>
12 #else
13 #  ifndef BUILDVER_INCLUDED
14 #    include "buildver-boehm.h"
15 #  endif
16 #endif
17
18 /*
19  * If the MONO_ENV_OPTIONS environment variable is set, it uses this as a
20  * source of command line arguments that are passed to Mono before the
21  * command line arguments specified in the command line.
22  */
23 static int
24 mono_main_with_options (int argc, char *argv [])
25 {
26         mono_parse_env_options (&argc, &argv);
27
28         return mono_main (argc, argv);
29 }
30
31 #define STREAM_INT(x) (*(uint32_t*)x)
32 #define STREAM_LONG(x) (*(uint64_t*)x)
33
34 static gboolean
35 probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
36 {
37         MonoBundledAssembly last = { NULL, 0, 0 };
38         char sigbuffer [16+sizeof (uint64_t)];
39         gboolean status = FALSE;
40         uint64_t directory_location;
41         off_t sigstart, baseline = 0;
42         uint64_t directory_size;
43         char *directory, *p;
44         int items, i;
45         unsigned char *mapaddress = NULL;
46         void *maphandle = NULL;
47         GArray *assemblies;
48         char *entry_point = NULL;
49         char **new_argv;
50         int j;
51
52         int fd = open (program, O_RDONLY);
53         if (fd == -1)
54                 return FALSE;
55         if ((sigstart = lseek (fd, -24, SEEK_END)) == -1)
56                 goto doclose;
57         if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
58                 goto doclose;
59         if (memcmp (sigbuffer+sizeof(uint64_t), "xmonkeysloveplay", 16) != 0)
60                 goto doclose;
61         directory_location = GUINT64_FROM_LE ((*(uint64_t *) &sigbuffer [0]));
62         if (lseek (fd, directory_location, SEEK_SET) == -1)
63                 goto doclose;
64         directory_size = sigstart-directory_location;
65         directory = g_malloc (directory_size);
66         if (directory == NULL)
67                 goto doclose;
68         if (read (fd, directory, directory_size) == -1)
69                 goto dofree;
70
71         items = STREAM_INT (directory);
72         p = directory+4;
73
74         assemblies = g_array_new (0, 0, sizeof (MonoBundledAssembly*));
75         for (i = 0; i < items; i++){
76                 char *kind;
77                 int strsize = STREAM_INT (p);
78                 uint64_t offset, item_size;
79                 kind = p+4;
80                 p += 4 + strsize;
81                 offset = STREAM_LONG(p);
82                 p += 8;
83                 item_size = STREAM_INT (p);
84                 p += 4;
85                 
86                 if (mapaddress == NULL){
87                         mapaddress = mono_file_map (directory_location-offset, MONO_MMAP_READ | MONO_MMAP_PRIVATE, fd, offset, &maphandle);
88                         if (mapaddress == NULL){
89                                 perror ("Error mapping file");
90                                 exit (1);
91                         }
92                         baseline = offset;
93                 }
94                 if (strncmp (kind, "assembly:", strlen ("assembly:")) == 0){
95                         char *aname = kind + strlen ("assembly:");
96                         MonoBundledAssembly mba = { aname, mapaddress + offset - baseline, item_size }, *ptr;
97                         ptr = g_new (MonoBundledAssembly, 1);
98                         memcpy (ptr, &mba, sizeof (MonoBundledAssembly));
99                         g_array_append_val  (assemblies, ptr);
100                         if (entry_point == NULL)
101                                 entry_point = aname;
102                 } else if (strncmp (kind, "config:", strlen ("config:")) == 0){
103                         char *config = kind + strlen ("config:");
104                         char *aname = g_strdup (config);
105                         aname [strlen(aname)-strlen(".config")] = 0;
106                         mono_register_config_for_assembly (aname, config);
107                 } else if (strncmp (kind, "system_config:", strlen ("system_config:")) == 0){
108                         printf ("TODO s-Found: %s %llx\n", kind, (long long)offset);
109                 } else if (strncmp (kind, "options:", strlen ("options:")) == 0){
110                         mono_parse_options_from (kind + strlen("options:"), ref_argc, ref_argv);
111                 } else if (strncmp (kind, "config_dir:", strlen ("config_dir:")) == 0){
112                         printf ("TODO Found: %s %llx\n", kind, (long long)offset);
113                 } else {
114                         fprintf (stderr, "Unknown stream on embedded package: %s\n", kind);
115                         exit (1);
116                 }
117         }
118         g_array_append_val (assemblies, last);
119         
120         mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data);
121         new_argv = g_new (char *, (*ref_argc)+1);
122         for (j = 0; j < *ref_argc; j++)
123                 new_argv [j] = (*ref_argv)[j];
124         new_argv [j] = entry_point;
125         *ref_argv = new_argv;
126         (*ref_argc)++;
127         
128         return TRUE;
129         
130 dofree:
131         g_free (directory);
132 doclose:
133         if (!status)
134                 close (fd);
135         return status;
136 }
137
138 #ifdef HOST_WIN32
139
140 #include <shellapi.h>
141
142 int
143 main (void)
144 {
145         TCHAR szFileName[MAX_PATH];
146         int argc;
147         gunichar2** argvw;
148         gchar** argv;
149         int i;
150         DWORD count;
151         
152         argvw = CommandLineToArgvW (GetCommandLine (), &argc);
153         argv = g_new0 (gchar*, argc + 1);
154         for (i = 0; i < argc; i++)
155                 argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
156         argv [argc] = NULL;
157
158         LocalFree (argvw);
159
160         if ((count = GetModuleFileName (NULL, szFileName, MAX_PATH)) != 0){
161                 char *entry = g_utf16_to_utf8 (szFileName, count, NULL, NULL, NULL);
162                 probe_embedded (entry, &argc, &argv);
163         }
164
165         return mono_main_with_options  (argc, argv);
166 }
167
168 #else
169
170 int
171 main (int argc, char* argv[])
172 {
173         mono_build_date = build_date;
174
175         probe_embedded (argv [0], &argc, &argv);
176         return mono_main_with_options (argc, argv);
177 }
178
179 #endif