home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / crt0 / c1args.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-31  |  10.6 KB  |  457 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <libc/stubs.h>
  4. #include <io.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <crt0.h>
  8. #include <go32.h>
  9. #include <fcntl.h>
  10. #include <libc/farptrgs.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include <stubinfo.h>
  14.  
  15. #define ds _my_ds()
  16.  
  17. static void *
  18. c1xmalloc(size_t s)
  19. {
  20.   void *q = malloc(s);
  21.   if (q == 0)
  22.   {
  23. #define err(x) _write(STDERR_FILENO, x, sizeof(x)-1)
  24.     err("No memory to gather arguments\r\n");
  25.     _exit(1);
  26.   }
  27.   return q;
  28. }
  29.  
  30. static int
  31. far_strlen(int selector, int linear_addr)
  32. {
  33.   int save=linear_addr;
  34.   _farsetsel(selector);
  35.   while (_farnspeekb(linear_addr))
  36.     linear_addr++;
  37.   return linear_addr - save;
  38. }
  39.  
  40. static int
  41. atohex(char *s)
  42. {
  43.   int rv = 0;
  44.   while (*s)
  45.   {
  46.     int v = *s - '0';
  47.     if (v > 9)
  48.       v -= 7;
  49.     v &= 15; /* in case it's lower case */
  50.     rv = rv*16 + v;
  51.     s++;
  52.   }
  53.   return rv;
  54. }
  55.  
  56. typedef struct Arg {
  57.   char *arg;
  58.   char **arg_globbed;
  59.   struct ArgList *arg_file;
  60.   struct Arg *next;
  61.   int was_quoted;
  62. } Arg;
  63.  
  64. typedef struct ArgList {
  65.   int argc;
  66.   Arg **argv;
  67. } ArgList;
  68.  
  69. static Arg *new_arg(void)
  70. {
  71.   Arg *a = (Arg *)c1xmalloc(sizeof(Arg));
  72.   memset(a, 0, sizeof(Arg));
  73.   return a;
  74. }
  75.  
  76. static void delete_arglist(ArgList *al);
  77.  
  78. static void
  79. delete_arg(Arg *a)
  80. {
  81.   if (a->arg) free(a->arg);
  82.   if (a->arg_globbed)
  83.   {
  84.     int i;
  85.     for (i=0; a->arg_globbed[i]; i++)
  86.       free(a->arg_globbed[i]);
  87.     free(a->arg_globbed);
  88.   }
  89.   if (a->arg_file)
  90.     delete_arglist(a->arg_file);
  91.   free(a);
  92. }
  93.  
  94. static ArgList *
  95. new_arglist(int count)
  96. {
  97.   ArgList *al = (ArgList *)c1xmalloc(sizeof(ArgList));
  98.   al->argc = count;
  99.   al->argv = (Arg **)c1xmalloc((count+1)*sizeof(Arg *));
  100.   memset(al->argv, 0, (count+1)*sizeof(Arg *));
  101.   return al;
  102. }
  103.  
  104. static void
  105. delete_arglist(ArgList *al)
  106. {
  107.   int i;
  108.   for (i=0; i<al->argc; i++)
  109.     delete_arg(al->argv[i]);
  110.   free(al->argv);
  111.   free(al);
  112. }
  113.  
  114. static char *
  115. parse_arg(char *bp, char *last, size_t *len, int *was_quoted)
  116. {
  117.   char *ep = bp, *epp = bp;
  118.   int quote=0;
  119.  
  120.   while ((quote || !isspace(*ep)) && ep < last)
  121.   {
  122.     if (quote && *ep == quote)
  123.     {
  124.       quote = 0;
  125.       ep++;
  126.     }
  127.     else if (!quote && (*ep == '\'' || *ep == '"'))
  128.     {
  129.       quote = *ep;
  130.       ep++;
  131.     }
  132.     else if (*ep == '\\' && strchr("'\"", ep[1]) && ep < last-1)
  133.     {
  134.       ep++;
  135.       *epp++ = *ep++;
  136.       /* *was_quoted = 1;  - This makes no sense. */
  137.     }
  138.     else
  139.     {
  140.       if (quote && (strchr("[?*", *ep) || strncmp(ep, "...", 3) == 0))
  141.     *was_quoted = 1;
  142.       *epp++ = *ep++;
  143.     }
  144.   }
  145.  
  146.   *len = epp - bp;
  147.   return ep;
  148. }
  149.  
  150. static ArgList *
  151. parse_bytes(char *bytes, int length)
  152. {
  153.   int largc, i;
  154.   Arg *a, **anext, *afirst;
  155.   ArgList *al;
  156.   char *bp=bytes, *ep, *last=bytes+length;
  157.  
  158.   anext = &afirst;
  159.   largc = 0;
  160.   while (bp<last)
  161.   {
  162.     size_t arg_len;
  163.     while (isspace(*bp) && bp < last)
  164.       bp++;
  165.     if (bp == last)
  166.       break;
  167.     *anext = a = new_arg();
  168.     ep = parse_arg(bp, last, &arg_len, &(a->was_quoted));
  169.     anext = &(a->next);
  170.     largc++;
  171.     a->arg = (char *)c1xmalloc(arg_len+1);
  172.     memcpy(a->arg, bp, arg_len);
  173.     a->arg[arg_len] = 0;
  174.     bp = ep+1;
  175.   }
  176.   al = new_arglist(largc);
  177.   for (i=0, a=afirst; i<largc; i++, a=a->next)
  178.     al->argv[i] = a;
  179.   return al;
  180. }
  181.  
  182. static int
  183. count_args(ArgList *al)
  184. {
  185.   int i, r=0;
  186.   for (i=0; i<al->argc; i++)
  187.   {
  188.     int j;
  189.     if (al->argv[i]->arg_globbed)
  190.     {
  191.       for (j=0; al->argv[i]->arg_globbed[j]; j++);
  192.       r += j;
  193.     }
  194.     else if (al->argv[i]->arg_file)
  195.     {
  196.       r += count_args(al->argv[i]->arg_file);
  197.     }
  198.     else
  199.     {
  200.       r++;
  201.     }
  202.   }
  203.   return r;
  204. }
  205.  
  206. static char **
  207. fill_args(char **largv, ArgList *al)
  208. {
  209.   int i;
  210.   for (i=0; i<al->argc; i++)
  211.   {
  212.     int j;
  213.     if (al->argv[i]->arg_globbed)
  214.     {
  215.       for (j=0; al->argv[i]->arg_globbed[j]; j++)
  216.       {
  217.         *largv++ = al->argv[i]->arg_globbed[j];
  218.         al->argv[i]->arg_globbed[j] = 0;
  219.       }
  220.     }
  221.     else if (al->argv[i]->arg_file)
  222.     {
  223.       largv = fill_args(largv, al->argv[i]->arg_file);
  224.     }
  225.     else
  226.     {
  227.       *largv++ = al->argv[i]->arg;
  228.       al->argv[i]->arg = 0;
  229.     }
  230.   }
  231.   return largv;
  232. }
  233.  
  234. static void
  235. expand_response_files(ArgList *al)
  236. {
  237.   int i, f;
  238.   for (i=0; i<al->argc; i++)
  239.   {
  240.     if (! al->argv[i]->was_quoted && al->argv[i]->arg[0] == '@')
  241.       if ((f = _open(al->argv[i]->arg+1, O_RDONLY)) >= 0)
  242.       {
  243.     char *bytes;
  244.     int len, st_size;
  245.     st_size = lseek(f, 0L, SEEK_END);
  246.     lseek(f, 0L, SEEK_SET);
  247.         bytes = (char *)alloca(st_size);
  248.         len = _read(f, bytes, st_size);
  249.         _close(f);
  250.         al->argv[i]->arg_file = parse_bytes(bytes, len);
  251.         expand_response_files(al->argv[i]->arg_file);
  252.       }
  253.   }
  254. }
  255.  
  256. static void
  257. expand_wildcards(ArgList *al)
  258. {
  259.   int i;
  260.   for (i=0; i<al->argc; i++)
  261.   {
  262.     if (al->argv[i]->arg_file)
  263.       expand_wildcards(al->argv[i]->arg_file);
  264.     else if (!(al->argv[i]->was_quoted))
  265.     {
  266.       al->argv[i]->arg_globbed = __crt0_glob_function(al->argv[i]->arg);
  267.     }
  268.   }
  269. }
  270.  
  271. extern char __PROXY[]; /* defined on crt0/crt1.c */
  272. extern size_t __PROXY_LEN;
  273.  
  274. void
  275. __crt0_setup_arguments(void)
  276. {
  277.   ArgList *arglist;
  278.   char *argv0;
  279.   int prepend_argv0 = 1;
  280.   int should_expand_wildcards = 1;
  281.   char *proxy_v = 0;
  282.  
  283.   /*
  284.   ** first, figure out what to pass for argv[0]
  285.   */
  286.   {
  287.     int i;
  288.     char *ap, *ls, *fc;
  289. /*    char newbase[14]; */
  290.  
  291.     if (_crt0_startup_flags & _CRT0_FLAG_DROP_DRIVE_SPECIFIER)
  292.       if (__dos_argv0[1] == ':')
  293.         __dos_argv0 += 2;
  294.  
  295.     ls = __dos_argv0;
  296.     for (ap=__dos_argv0; *ap; ap++)
  297.       if (*ap == ':' || *ap == '\\' || *ap == '/')
  298.         ls = ap + 1;
  299.     fc = ls;
  300. #if 0
  301.     /* We never do this!  Only the stub uses this field */
  302.     if (_stubinfo->basename[0])
  303.     {
  304.       for (i=0; i<8 && _stubinfo->basename[i]; i++)
  305.     newbase[i] = _stubinfo->basename[i];
  306.       newbase[i++] = '.';
  307.       newbase[i++] = 'E';
  308.       newbase[i++] = 'X';
  309.       newbase[i++] = 'E';
  310.       newbase[i++] = 0;
  311.       fc = newbase;
  312.     }
  313. #endif
  314.     if (_stubinfo->argv0[0])
  315.     {
  316.       fc = _stubinfo->argv0;
  317.     }
  318.     argv0 = (char *)calloc(1, ls-__dos_argv0+strlen(fc)+1);
  319.     if (ls == __dos_argv0)
  320.       strncpy(argv0, fc, 16);
  321.     else
  322.     {
  323.       strncpy(argv0, __dos_argv0, ls-__dos_argv0);
  324.       strncat(argv0, fc, 16);
  325.     }
  326.     for (i=0; (fc == _stubinfo->argv0)?(i<ls-__dos_argv0):(argv0[i]); i++)
  327.     {
  328.       if (!(_crt0_startup_flags & _CRT0_FLAG_USE_DOS_SLASHES))
  329.         if (argv0[i] == '\\')
  330.           argv0[i] = '/';
  331.       if (!(_crt0_startup_flags & _CRT0_FLAG_PRESERVE_UPPER_CASE))
  332.         if (isupper(argv0[i]))
  333.           argv0[i] = tolower(argv0[i]);
  334.     }
  335.     if (_crt0_startup_flags & _CRT0_FLAG_DROP_EXE_SUFFIX)
  336.     {
  337.       char *sp = argv0 + strlen(argv0) - 4;
  338.       if (sp[0] == '.'
  339.       && (sp[1] == 'e' || sp[1] == 'E')
  340.       && (sp[2] == 'x' || sp[2] == 'X')
  341.       && (sp[3] == 'e' || sp[3] == 'E'))
  342.         *sp = 0;
  343.     }
  344.   }
  345.   
  346.   /*
  347.   ** Next, scan dos's command line.
  348.   */
  349.   {
  350.     char doscmd[128];
  351.     movedata(_stubinfo->psp_selector, 128, ds, (int)doscmd, 128);
  352.     arglist = parse_bytes(doscmd+1, doscmd[0] & 0x7f);
  353.   }
  354.   
  355.   /*
  356.   ** Check for !proxy.
  357.   **
  358.   ** If there is " !proxy" (note the leading blank!) in the environ,
  359.   ** use it instead of what DOS command line tells.  This is the method
  360.   ** v2.01 and later uses to pass long command lines from `system';
  361.   ** these should be passed through wildcard expansion unless quoted.
  362.   */
  363.   if ((proxy_v = getenv(__PROXY)))
  364.   {
  365.     char proxy_line[50];    /* need only 34 */
  366.     size_t plen = strlen(proxy_v);
  367.     strncpy(proxy_line, __PROXY, __PROXY_LEN + 1); /* copy " !proxy" */
  368.     proxy_line[__PROXY_LEN] = ' ';
  369.     strncpy(proxy_line + __PROXY_LEN+1, proxy_v, plen+1); /* copy value */
  370.     delete_arglist(arglist);
  371.     arglist = parse_bytes(proxy_line, plen+__PROXY_LEN+1);
  372.   }
  373.   if (arglist->argc > 3 && strcmp(arglist->argv[0]->arg, __PROXY+1) == 0)
  374.   {
  375.     int argv_seg, argv_ofs, i;
  376.     unsigned short *rm_argv;
  377.     __crt0_argc = atohex(arglist->argv[1]->arg);
  378.     argv_seg = atohex(arglist->argv[2]->arg);
  379.     argv_ofs = atohex(arglist->argv[3]->arg);
  380.     delete_arglist(arglist);
  381.  
  382.     rm_argv = (unsigned short *)alloca(__crt0_argc*sizeof(unsigned short));
  383.     movedata(_dos_ds, argv_seg*16+argv_ofs, ds, (int)rm_argv, __crt0_argc*sizeof(unsigned short));
  384.  
  385.     arglist = new_arglist(__crt0_argc);
  386.     if (proxy_v)
  387.       should_expand_wildcards = 1;
  388.     else
  389.       should_expand_wildcards = 0;
  390.  
  391.     
  392.     for (i=0; i<__crt0_argc; i++)
  393.     {
  394.       int al = far_strlen(_dos_ds, argv_seg*16 + rm_argv[i]);
  395.       arglist->argv[i] = new_arg();
  396.       arglist->argv[i]->arg = (char *)c1xmalloc(al+1);
  397.       movedata(_dos_ds, argv_seg*16 + rm_argv[i], ds, (int)(arglist->argv[i]->arg), al+1);
  398.       if (proxy_v)
  399.       {
  400.     size_t ln;
  401.     char *lastc = arglist->argv[i]->arg + al;
  402.     parse_arg(arglist->argv[i]->arg, lastc,
  403.           &ln, &(arglist->argv[i]->was_quoted));
  404.     arglist->argv[i]->arg[ln] = '\0';
  405.       }
  406.     }
  407.     prepend_argv0 = 0;
  408.   }
  409. #if 0
  410.   /* This method will break under DPMI 1.0, because descriptor
  411.      tables are private to a process there.  Disabled.  */
  412.   else if (arglist->argc > 3 && strcmp(arglist->argv[0]->arg, "!proxy2") == 0)
  413.   {
  414.     int argv_sel, argv_ofs, i;
  415.     unsigned long *pm_argv;
  416.     __crt0_argc = atohex(arglist->argv[1]->arg);
  417.     argv_sel = atohex(arglist->argv[2]->arg);
  418.     argv_ofs = atohex(arglist->argv[3]->arg);
  419.     delete_arglist(arglist);
  420.  
  421.     pm_argv = (unsigned long *)alloca(__crt0_argc*sizeof(unsigned long));
  422.     movedata(argv_sel, argv_ofs, ds, (int)pm_argv, __crt0_argc*sizeof(unsigned long));
  423.  
  424.     arglist = new_arglist(__crt0_argc);
  425.     
  426.     for (i=0; i<__crt0_argc; i++)
  427.     {
  428.       int al = far_strlen(argv_sel, pm_argv[i]);
  429.       arglist->argv[i] = new_arg();
  430.       arglist->argv[i]->arg = (char *)c1xmalloc(al+1);
  431.       movedata(argv_sel, pm_argv[i], ds, (int)(arglist->argv[i]->arg), al+1);
  432.     }
  433.     prepend_argv0 = 0;
  434.     should_expand_wildcards = 0;
  435.   }
  436. #endif
  437.  
  438.   /*
  439.   **  Now, expand response files
  440.   */
  441.   if (!(_crt0_startup_flags & _CRT0_FLAG_DISALLOW_RESPONSE_FILES))
  442.     expand_response_files(arglist);
  443.  
  444.   /*
  445.   **  Now, expand wildcards
  446.   */
  447.  
  448.   if (should_expand_wildcards)
  449.     expand_wildcards(arglist);
  450.  
  451.   __crt0_argc = prepend_argv0 + count_args(arglist);
  452.   __crt0_argv = (char **)c1xmalloc((__crt0_argc+1) * sizeof(char *));
  453.   if (prepend_argv0)
  454.     __crt0_argv[0] = argv0;
  455.   *fill_args(__crt0_argv+prepend_argv0, arglist) = 0;
  456. }
  457.