New run-jenkins tags to allow a checked build job and fix partial checked build suppo...
[mono.git] / mono / mini / main.c
1 #include <config.h>
2 #include <fcntl.h>
3 #include <mono/metadata/assembly.h>
4 #include <mono/metadata/mono-config.h>
5 #include <mono/utils/mono-mmap.h>
6 #include "mini.h"
7
8 #ifdef HAVE_UNISTD_H
9 #  include <unistd.h>
10 #endif
11 #ifdef HOST_WIN32
12 #  include <io.h>
13 #else
14 #  ifndef BUILDVER_INCLUDED
15 #    include "buildver-boehm.h"
16 #  endif
17 #endif
18
19 /*
20  * If the MONO_ENV_OPTIONS environment variable is set, it uses this as a
21  * source of command line arguments that are passed to Mono before the
22  * command line arguments specified in the command line.
23  */
24 static int
25 mono_main_with_options (int argc, char *argv [])
26 {
27         mono_parse_env_options (&argc, &argv);
28
29         return mono_main (argc, argv);
30 }
31
32 #define STREAM_INT(x) GUINT32_TO_LE((*(uint32_t*)x))
33 #define STREAM_LONG(x) GUINT64_TO_LE((*(uint64_t*)x))
34
35 /**
36  * Loads a chunk of data from the file pointed to by the
37  * @fd starting at the file offset @offset for @size bytes
38  * and returns an allocated version of that string, or NULL
39  * on error.
40  */
41 static char *
42 load_from_region (int fd, uint64_t offset, uint64_t size)
43 {
44         char *buffer;
45         off_t loc;
46         int status;
47         
48         do {
49                 loc = lseek (fd, offset, SEEK_SET);
50         } while (loc == -1 && errno == EINTR);
51         if (loc == -1)
52                 return NULL;
53         buffer = g_malloc (size + 1);
54         if (buffer == NULL)
55                 return NULL;
56         buffer [size] = 0;
57         do {
58                 status = read (fd, buffer, size);
59         } while (status == -1 && errno == EINTR);
60         if (status == -1){
61                 g_free (buffer);
62                 return NULL;
63         }
64         return buffer;
65 }
66
67 static gboolean
68 probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
69 {
70         MonoBundledAssembly last = { NULL, 0, 0 };
71         char sigbuffer [16+sizeof (uint64_t)];
72         gboolean status = FALSE;
73         uint64_t directory_location;
74         off_t sigstart, baseline = 0;
75         uint64_t directory_size;
76         char *directory, *p;
77         int items, i;
78         unsigned char *mapaddress = NULL;
79         void *maphandle = NULL;
80         GArray *assemblies;
81         char *entry_point = NULL;
82         char **new_argv;
83         int j;
84
85         int fd = open (program, O_RDONLY);
86         if (fd == -1)
87                 return FALSE;
88         if ((sigstart = lseek (fd, -24, SEEK_END)) == -1)
89                 goto doclose;
90         if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
91                 goto doclose;
92         if (memcmp (sigbuffer+sizeof(uint64_t), "xmonkeysloveplay", 16) != 0)
93                 goto doclose;
94         directory_location = GUINT64_FROM_LE ((*(uint64_t *) &sigbuffer [0]));
95         if (lseek (fd, directory_location, SEEK_SET) == -1)
96                 goto doclose;
97         directory_size = sigstart-directory_location;
98         directory = g_malloc (directory_size);
99         if (directory == NULL)
100                 goto doclose;
101         if (read (fd, directory, directory_size) == -1)
102                 goto dofree;
103
104         items = STREAM_INT (directory);
105         p = directory+4;
106
107         assemblies = g_array_new (0, 0, sizeof (MonoBundledAssembly*));
108         for (i = 0; i < items; i++){
109                 char *kind;
110                 int strsize = STREAM_INT (p);
111                 uint64_t offset, item_size;
112                 kind = p+4;
113                 p += 4 + strsize;
114                 offset = STREAM_LONG(p);
115                 p += 8;
116                 item_size = STREAM_INT (p);
117                 p += 4;
118                 
119                 if (mapaddress == NULL){
120                         mapaddress = mono_file_map (directory_location-offset, MONO_MMAP_READ | MONO_MMAP_PRIVATE, fd, offset, &maphandle);
121                         if (mapaddress == NULL){
122                                 perror ("Error mapping file");
123                                 exit (1);
124                         }
125                         baseline = offset;
126                 }
127                 if (strncmp (kind, "assembly:", strlen ("assembly:")) == 0){
128                         char *aname = kind + strlen ("assembly:");
129                         MonoBundledAssembly mba = { aname, mapaddress + offset - baseline, item_size }, *ptr;
130                         ptr = g_new (MonoBundledAssembly, 1);
131                         memcpy (ptr, &mba, sizeof (MonoBundledAssembly));
132                         g_array_append_val  (assemblies, ptr);
133                         if (entry_point == NULL)
134                                 entry_point = aname;
135                 } else if (strncmp (kind, "config:", strlen ("config:")) == 0){
136                         char *config = kind + strlen ("config:");
137                         char *aname = g_strdup (config);
138                         aname [strlen(aname)-strlen(".config")] = 0;
139                         mono_register_config_for_assembly (aname, load_from_region (fd, offset, item_size));
140                 } else if (strncmp (kind, "systemconfig:", strlen ("systemconfig:")) == 0){
141                         mono_config_parse_memory (load_from_region (fd, offset, item_size));
142                 } else if (strncmp (kind, "options:", strlen ("options:")) == 0){
143                         mono_parse_options_from (load_from_region (fd, offset, item_size), ref_argc, ref_argv);
144                 } else if (strncmp (kind, "config_dir:", strlen ("config_dir:")) == 0){
145                         mono_set_dirs (getenv ("MONO_PATH"), load_from_region (fd, offset, item_size));
146                 } else if (strncmp (kind, "machineconfig:", strlen ("machineconfig:")) == 0) {
147                         mono_register_machine_config (load_from_region (fd, offset, item_size));
148                 } else if (strncmp (kind, "env:", strlen ("env:")) == 0){
149                         char *data = load_from_region (fd, offset, item_size);
150                         uint8_t count = *data++;
151                         char *value = data + count + 1;
152                         g_setenv (data, value, FALSE);
153                 } else {
154                         fprintf (stderr, "Unknown stream on embedded package: %s\n", kind);
155                         exit (1);
156                 }
157         }
158         g_array_append_val (assemblies, last);
159         
160         mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data);
161         new_argv = g_new (char *, (*ref_argc)+1);
162         for (j = 0; j < *ref_argc; j++)
163                 new_argv [j] = (*ref_argv)[j];
164         new_argv [j] = entry_point;
165         *ref_argv = new_argv;
166         (*ref_argc)++;
167         
168         return TRUE;
169         
170 dofree:
171         g_free (directory);
172 doclose:
173         if (!status)
174                 close (fd);
175         return status;
176 }
177
178 #ifdef HOST_WIN32
179
180 #include <shellapi.h>
181
182 int
183 main (void)
184 {
185         TCHAR szFileName[MAX_PATH];
186         int argc;
187         gunichar2** argvw;
188         gchar** argv;
189         int i;
190         DWORD count;
191         
192         argvw = CommandLineToArgvW (GetCommandLine (), &argc);
193         argv = g_new0 (gchar*, argc + 1);
194         for (i = 0; i < argc; i++)
195                 argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
196         argv [argc] = NULL;
197
198         LocalFree (argvw);
199
200         if ((count = GetModuleFileName (NULL, szFileName, MAX_PATH)) != 0){
201                 char *entry = g_utf16_to_utf8 (szFileName, count, NULL, NULL, NULL);
202                 probe_embedded (entry, &argc, &argv);
203         }
204
205         return mono_main_with_options  (argc, argv);
206 }
207
208 #else
209
210 int
211 main (int argc, char* argv[])
212 {
213         mono_build_date = build_date;
214
215         probe_embedded (argv [0], &argc, &argv);
216         return mono_main_with_options (argc, argv);
217 }
218
219 #endif