Subversion Repositories Kolibri OS

Rev

Rev 9952 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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.  */
  11.  
  12. #include <_ansi.h>
  13. #include <reent.h>
  14. #include <stdint.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <setjmp.h>
  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;
  31.     int    __subsystem__;
  32.     void  *__idata_start;
  33.     void  *__idata_end;
  34.     int  (*main)(int argc, char **argv, char **envp);
  35. };
  36.  
  37. #define ENV_SIZE 16
  38. /* TODO: Make it dynamic?* */
  39. static char* __environ[ENV_SIZE] = {0};
  40. char **environ = &__environ[0];
  41.  
  42. extern void _pei386_runtime_relocator (void);
  43. extern void init_loader(void *libc_image);
  44. extern void init_global_reent(void);
  45. extern void init_stdio(void);
  46.  
  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.  
  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;
  59.  
  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.     }
  66. }
  67.  
  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.     };
  76.  
  77.     enum quote_state state;
  78.     unsigned int argc;
  79.     char *p = cmdline;
  80.     char *new_arg, *start;
  81.  
  82.     argc = 0;
  83.  
  84.     for(;;)
  85.     {
  86.         /* skip over spaces and tabs */
  87.         if ( *p )
  88.         {
  89.             while (*p == ' ' || *p == '\t')
  90.                 ++p;
  91.         }
  92.  
  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.  
  182. __attribute__((noreturn))
  183. void  libc_crt_startup (void *libc_base)
  184. {
  185.     struct app_hdr *header = NULL;
  186.     int retval = 0;
  187.  
  188.     char **argv;
  189.     int    argc;
  190.  
  191.     _pei386_runtime_relocator();
  192.  
  193.     tls_init();
  194.     init_global_reent();
  195.     init_stdio();
  196.  
  197.     if(header->__subsystem__ == 3)
  198.         __init_conio();
  199.  
  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.     {
  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);
  214.     }
  215.     else
  216.     {
  217.         argc = 1;
  218.         argv = alloca((argc+1)*sizeof(char*));
  219.         argv[0] = header->path;
  220.     }
  221.     argv[argc] = NULL;
  222.  
  223.     init_environ();
  224.  
  225.     retval = header->main(argc, argv, environ);
  226. done:
  227.     if(header->__subsystem__ == 3)
  228.         __fini_conio();
  229.  
  230.     exit (retval);
  231. }
  232.  
  233.