Merge pull request #2819 from BrzVlad/fix-major-log
[mono.git] / mono / mini / main.c
index 784179c64412c86fa7cdb933f081655e69ec94fc..de8ab61e3d5b64550e733981fcce690c013d7860 100644 (file)
@@ -1,9 +1,18 @@
 #include <config.h>
+#include <fcntl.h>
+#include <mono/metadata/assembly.h>
+#include <mono/utils/mono-mmap.h>
 #include "mini.h"
-#ifndef HOST_WIN32
-#ifndef BUILDVER_INCLUDED
-#include "buildver-boehm.h"
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
 #endif
+#ifdef HOST_WIN32
+#  include <io.h>
+#else
+#  ifndef BUILDVER_INCLUDED
+#    include "buildver-boehm.h"
+#  endif
 #endif
 
 /*
 static int
 mono_main_with_options (int argc, char *argv [])
 {
-       const char *env_options = g_getenv ("MONO_ENV_OPTIONS");
-       if (env_options != NULL){
-               GPtrArray *array = g_ptr_array_new ();
-               GString *buffer = g_string_new ("");
-               const char *p;
-               unsigned i;
-               gboolean in_quotes = FALSE;
-               char quote_char = '\0';
-
-               for (p = env_options; *p; p++){
-                       switch (*p){
-                       case ' ': case '\t':
-                               if (!in_quotes) {
-                                       if (buffer->len != 0){
-                                               g_ptr_array_add (array, g_strdup (buffer->str));
-                                               g_string_truncate (buffer, 0);
-                                       }
-                               } else {
-                                       g_string_append_c (buffer, *p);
-                               }
-                               break;
-                       case '\\':
-                               if (p [1]){
-                                       g_string_append_c (buffer, p [1]);
-                                       p++;
-                               }
-                               break;
-                       case '\'':
-                       case '"':
-                               if (in_quotes) {
-                                       if (quote_char == *p)
-                                               in_quotes = FALSE;
-                                       else
-                                               g_string_append_c (buffer, *p);
-                               } else {
-                                       in_quotes = TRUE;
-                                       quote_char = *p;
-                               }
-                               break;
-                       default:
-                               g_string_append_c (buffer, *p);
-                               break;
+       mono_parse_env_options (&argc, &argv);
+
+       return mono_main (argc, argv);
+}
+
+#define STREAM_INT(x) (*(uint32_t*)x)
+#define STREAM_LONG(x) (*(uint64_t*)x)
+
+static gboolean
+probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
+{
+       MonoBundledAssembly last = { NULL, 0, 0 };
+       char sigbuffer [16+sizeof (uint64_t)];
+       gboolean status = FALSE;
+       uint64_t directory_location;
+       off_t sigstart, baseline = 0;
+       uint64_t directory_size;
+       char *directory, *p;
+       int items, i;
+       unsigned char *mapaddress = NULL;
+       void *maphandle = NULL;
+       GArray *assemblies;
+       char *entry_point = NULL;
+       char **new_argv;
+       int j;
+
+       int fd = open (program, O_RDONLY);
+       if (fd == -1)
+               return FALSE;
+       if ((sigstart = lseek (fd, -(16+sizeof(uint64_t)), SEEK_END)) == -1)
+               goto doclose;
+       if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
+               goto doclose;
+       if (memcmp (sigbuffer+sizeof(uint64_t), "xmonkeysloveplay", 16) != 0)
+               goto doclose;
+       directory_location = GUINT64_FROM_LE ((*(uint64_t *) &sigbuffer [0]));
+       if (lseek (fd, directory_location, SEEK_SET) == -1)
+               goto doclose;
+       directory_size = sigstart-directory_location;
+       directory = g_malloc (directory_size);
+       if (directory == NULL)
+               goto doclose;
+       if (read (fd, directory, directory_size) == -1)
+               goto dofree;
+
+       items = STREAM_INT (directory);
+       p = directory+4;
+
+       assemblies = g_array_new (0, 0, sizeof (MonoBundledAssembly*));
+       for (i = 0; i < items; i++){
+               char *kind;
+               int strsize = STREAM_INT (p);
+               uint64_t offset, item_size;
+               kind = p+4;
+               p += 4 + strsize;
+               offset = STREAM_LONG(p);
+               p += 8;
+               item_size = STREAM_INT (p);
+               p += 4;
+               
+               if (mapaddress == NULL){
+                       mapaddress = mono_file_map (directory_location-offset, MONO_MMAP_READ | MONO_MMAP_PRIVATE, fd, offset, &maphandle);
+                       if (mapaddress == NULL){
+                               perror ("Error mapping file");
+                               exit (1);
                        }
+                       baseline = offset;
                }
-               if (in_quotes) {
-                       fprintf (stderr, "Unmatched quotes in value of MONO_ENV_OPTIONS: [%s]\n", env_options);
+               if (strncmp (kind, "assembly:", strlen ("assembly:")) == 0){
+                       char *aname = kind + strlen ("assembly:");
+                       MonoBundledAssembly mba = { aname, mapaddress + offset - baseline, item_size }, *ptr;
+                       ptr = g_new (MonoBundledAssembly, 1);
+                       memcpy (ptr, &mba, sizeof (MonoBundledAssembly));
+                       g_array_append_val  (assemblies, ptr);
+                       if (entry_point == NULL)
+                               entry_point = aname;
+               } else if (strncmp (kind, "config:", strlen ("config:")) == 0){
+                       printf ("c-Found: %s %llx\n", kind, offset);
+                       char *config = kind + strlen ("config:");
+                       char *aname = g_strdup (config);
+                       aname [strlen(aname)-strlen(".config")] = 0;
+                       mono_register_config_for_assembly (aname, config);
+               } else if (strncmp (kind, "system_config:", strlen ("system_config:")) == 0){
+                       printf ("TODO s-Found: %s %llx\n", kind, offset);
+               } else if (strncmp (kind, "options:", strlen ("options:")) == 0){
+                       mono_parse_options_from (kind + strlen("options:"), ref_argc, ref_argv);
+               } else if (strncmp (kind, "config_dir:", strlen ("config_dir:")) == 0){
+                       printf ("TODO Found: %s %llx\n", kind, offset);
+               } else {
+                       fprintf (stderr, "Unknown stream on embedded package: %s\n", kind);
                        exit (1);
                }
-                       
-               if (buffer->len != 0)
-                       g_ptr_array_add (array, g_strdup (buffer->str));
-               g_string_free (buffer, TRUE);
-
-               if (array->len > 0){
-                       int new_argc = array->len + argc;
-                       char **new_argv = g_new (char *, new_argc + 1);
-                       int j;
-
-                       new_argv [0] = argv [0];
-                       
-                       /* First the environment variable settings, to allow the command line options to override */
-                       for (i = 0; i < array->len; i++)
-                               new_argv [i+1] = g_ptr_array_index (array, i);
-                       i++;
-                       for (j = 1; j < argc; j++)
-                               new_argv [i++] = argv [j];
-                       new_argv [i] = NULL;
-
-                       argc = new_argc;
-                       argv = new_argv;
-               }
-               g_ptr_array_free (array, TRUE);
        }
-
-       return mono_main (argc, argv);
+       g_array_append_val (assemblies, last);
+       
+       mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data);
+       new_argv = g_new (char *, (*ref_argc)+1);
+       for (j = 0; j < *ref_argc; j++)
+               new_argv [j] = (*ref_argv)[j];
+       new_argv [j] = entry_point;
+       *ref_argv = new_argv;
+       (*ref_argc)++;
+       
+       return TRUE;
+       
+dofree:
+       g_free (directory);
+doclose:
+       if (!status)
+               close (fd);
+       return status;
 }
 
 #ifdef HOST_WIN32
 
+#include <shellapi.h>
+
 int
 main (void)
 {
+       TCHAR szFileName[MAX_PATH];
        int argc;
        gunichar2** argvw;
        gchar** argv;
        int i;
-
+       DWORD count;
+       
        argvw = CommandLineToArgvW (GetCommandLine (), &argc);
        argv = g_new0 (gchar*, argc + 1);
        for (i = 0; i < argc; i++)
@@ -109,6 +158,11 @@ main (void)
 
        LocalFree (argvw);
 
+       if ((count = GetModuleFileName (NULL, szFileName, MAX_PATH)) != 0){
+               char *entry = g_utf16_to_utf8 (szFileName, count, NULL, NULL, NULL);
+               probe_embedded (entry, &argc, &argv);
+       }
+
        return mono_main_with_options  (argc, argv);
 }
 
@@ -118,7 +172,8 @@ int
 main (int argc, char* argv[])
 {
        mono_build_date = build_date;
-       
+
+       probe_embedded (argv [0], &argc, &argv);
        return mono_main_with_options (argc, argv);
 }