home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / ms_sh22b.zip / src / stdargv.c < prev    next >
C/C++ Source or Header  |  1993-12-01  |  17KB  |  808 lines

  1. /* MS-DOS stdargv Function
  2.  *
  3.  * MS-DOS stdargv - Copyright (c) 1990,1,2 Data Logic Limited.
  4.  *
  5.  * This code is subject to the following copyright restrictions:
  6.  *
  7.  * 1.  Redistribution and use in source and binary forms are permitted
  8.  *     provided that the above copyright notice is duplicated in the
  9.  *     source form.
  10.  *
  11.  *    $Header: /usr/users/istewart/src/shell/sh2.2/RCS/stdargv.c,v 2.5 1993/08/25 16:04:22 istewart Exp $
  12.  *
  13.  *    $Log: stdargv.c,v $
  14.  *    Revision 2.5  1993/08/25  16:04:22  istewart
  15.  *    Add support for MSC 6 which requires osmajor and osminor to be set up
  16.  *    for MSDOS.
  17.  *
  18.  *    Revision 2.4  1993/06/14  10:59:58  istewart
  19.  *    More changes for 223 beta
  20.  *
  21.  *    Revision 2.3  1993/06/02  09:54:21  istewart
  22.  *    Beta 223 Updates - see Notes file
  23.  *
  24.  *    Revision 2.2  1992/12/14  11:12:37  istewart
  25.  *    BETA 215 Fixes and 2.1 Release
  26.  *
  27.  *    Revision 2.1  1992/11/06  10:03:44  istewart
  28.  *    214 Beta test updates
  29.  *
  30.  *    Revision 2.0  1992/04/13  17:39:09  Ian_Stewartson
  31.  *    MS-Shell 2.0 Baseline release
  32.  *
  33.  *
  34.  *
  35.  * MODULE DEFINITION:
  36.  *
  37.  * This function expandes the command line parameters in a UNIX like manner.
  38.  * Wild character *?[] are allowed in file names. @filename causes command lines
  39.  * to be read from filename.  Strings between " or ' are not expanded.  All
  40.  * entries in the array are malloced.
  41.  *
  42.  * This function replaces the standard Microsoft C5.1 & C6.0 C Run-Time
  43.  * start up line processing function (_setargv in stdargv.obj).
  44.  *
  45.  * For OS/2 2.x, this function replaces the standard IBM C Set/2 C Run-Time
  46.  * start up line processing function (_setuparg in stdargv.obj).
  47.  *
  48.  * For Turbo C, this function replaces the standard Borland C Run-Time
  49.  * start up line processing function (_setargv).
  50.  *
  51.  * For WatCom C, this function replaces the standard WatCom C Run-Time
  52.  * start up line processing function (__Init_Argv).
  53.  *
  54.  * To get the OS2 16-bit version, compile with -DOS2
  55.  * To get the OS2 32-bit version, compile with -D__OS2__
  56.  *
  57.  * Author:
  58.  *    Ian Stewartson
  59.  *    Data Logic, Queens House, Greenhill Way
  60.  *    Harrow, Middlesex  HA1 1YR, UK.
  61.  *    istewart@datlog.co.uk or ukc!datlog!istewart
  62.  */
  63.  
  64. #include <sys/types.h>            /* MS-DOS type definitions      */
  65. #include <sys/stat.h>            /* File status definitions    */
  66. #include <stdio.h>            /* Standard I/O delarations     */
  67. #include <stdlib.h>            /* Standard library functions   */
  68. #include <errno.h>            /* Error number declarations    */
  69.  
  70. #if defined (OS2) || defined (__OS2__)
  71. #  define INCL_DOSSESMGR
  72. #  define INCL_DOSMEMMGR
  73. #  define INCL_DOSPROCESS
  74. #  define INCL_DOSMODULEMGR
  75. #  define INCL_WINSWITCHLIST
  76. #  include <os2.h>            /* OS2 functions declarations   */
  77. #else
  78. #  include <dos.h>            /* DOS functions declarations   */
  79. #  include <bios.h>            /* BIOS functions declarations  */
  80. #endif
  81.  
  82. #include <ctype.h>            /* Character type declarations  */
  83. #include <string.h>            /* String library functions     */
  84. #include <limits.h>            /* String library functions     */
  85. #include <fcntl.h>            /* File Control Declarations    */
  86. #include <dirent.h>            /* Direction I/O functions    */
  87. #include <unistd.h>
  88. #include <glob.h>            /* Globbing functions        */
  89.  
  90. /*
  91.  *  DATA DEFINITIONS:
  92.  */
  93.  
  94. #define MAX_LINE    160        /* Max line length        */
  95. #define S_ENTRY        sizeof (char *)
  96.  
  97. /*
  98.  *  DATA DECLARATIONS:
  99.  */
  100.  
  101. static void    _Ex_CommandLine (char *);    /* Expand file        */
  102. static void    _Ex_ExpandIndirectFile (char *);
  103. static char    *_Ex_GetSpace (int, char *);    /* Get space        */
  104. static void    _Ex_AddArgument (char *);    /* Add argument        */
  105. static char    *_Ex_SkipWhiteSpace (char *);    /* Skip spaces        */
  106. static char    *_Ex_ConvertToUnixFormat (char *);
  107. static void    _Ex_ExpandField (char *);    /* Split file name    */
  108. static void    _Ex_FatalError (int, char *, char *);
  109. static char    *_Ex_ConvertEnvVariables (char *);
  110. static char    *_EX_OutOfMemory = "%s: %s\n";
  111.  
  112. #if defined (OS2) || defined (__OS2__)
  113. static void    _Ex_ProcessEMXArguments (char *);
  114. static void    _Ex_SetUpWindowName (void);
  115. #endif
  116.  
  117. /*
  118.  * Command Line pointers
  119.  */
  120.  
  121. #if defined (__OS2__)
  122. #  define ARG_ARRAY    _argv
  123. #  define ARG_COUNT    _argc
  124. #  define ENTRY_POINT    _setuparg
  125. #elif defined (__TURBOC__)
  126. #  define ARG_ARRAY    _C0argv
  127. #  define ARG_COUNT    _C0argc
  128. #  define ENTRY_POINT    _setargv
  129. #elif defined (__WATCOMC__)
  130. #  define ARG_ARRAY    ___Argv
  131. #  define ARG_COUNT    ___Argc
  132. #  define ENTRY_POINT    __Init_Argv
  133. #else
  134. #  define ARG_ARRAY    __argv
  135. #  define ARG_COUNT    __argc
  136. #  define ENTRY_POINT    _setargv
  137. #endif
  138.  
  139. extern void    ENTRY_POINT (void);
  140. extern char    **ARG_ARRAY;         /* Current argument address    */
  141. extern int    ARG_COUNT;         /* Current argument count    */
  142.  
  143. /*
  144.  * General OS independent start of the command line and program name.
  145.  */
  146.  
  147. #if defined (__OS2__)
  148. char         *_ACmdLine;
  149. char         *_APgmName;         /* Program name            */
  150. #else
  151. #  if defined (OS2)
  152. extern ushort far _aenvseg;
  153. extern ushort far _acmdln;
  154. #  endif
  155. char far    *_ACmdLine;
  156. char far    *_APgmName;         /* Program name            */
  157. #endif
  158.  
  159. /*
  160.  *  MODULE ABSTRACT: _setargv
  161.  *
  162.  *  UNIX like command line expansion
  163.  */
  164.  
  165. /*
  166.  * OS/2 2.x (32-bit) version
  167.  */
  168.  
  169.  
  170. #if defined (__OS2__)
  171. void    ENTRY_POINT (void)
  172. {
  173.     char    *argvp;
  174.     APIRET    rc;
  175.     PTIB    ptib;
  176.     PPIB    ppib;
  177.     char    *MName;
  178.  
  179. /* Get the command line and program name */
  180.  
  181.     if (rc = DosGetInfoBlocks (&ptib, &ppib))
  182.     {
  183.         fprintf (stderr, "DosGetInfoBlocks: Cannot find command line (%d)\n",
  184.          rc);
  185.         exit (1);
  186.     }
  187.  
  188.     if ((MName = malloc (PATH_MAX + NAME_MAX + 3)) == (char *)NULL)
  189.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  190.  
  191.     if (rc = DosQueryModuleName (ppib->pib_hmte, NAME_MAX + PATH_MAX + 2,
  192.                      MName))
  193.     {
  194.         fprintf (stderr, "DosQueryModuleName: Cannot get program name (%d)\n",
  195.          rc);
  196.         exit (1);
  197.     }
  198.  
  199. /* Save the program name and process the command line */
  200.  
  201.     _APgmName = MName;
  202.     _Ex_ProcessEMXArguments (ppib->pib_pchcmd);
  203.  
  204. /* Set up the Window name.  Give up if it does not work.  */
  205.  
  206.     _Ex_SetUpWindowName ();
  207.     _Ex_AddArgument ((char *)NULL);
  208.     --ARG_COUNT;
  209. }
  210.  
  211. #elif defined (OS2)
  212.  
  213. /*
  214.  * OS/2 1.x (16-bit) version
  215.  */
  216.  
  217. void    ENTRY_POINT (void)
  218. {
  219. #  if !defined (M_I86LM) && !defined (__LARGE__)
  220.     char far        *s;         /* Temporary string pointer        */
  221.     char        buf[MAX_LINE];    /* Temporary space        */
  222.     char        *cp;
  223. #  endif
  224.     char far        *argvp = (char far *)((((long)_aenvseg) << 16));
  225.     ushort        off = _acmdln;
  226.  
  227.     while (--off)
  228.     {
  229.     if (argvp[off - 1] == 0)
  230.          break;
  231.     }
  232.  
  233. /* Add program name */
  234.  
  235.     _APgmName =  &argvp[off];
  236.  
  237.     if (argvp[_acmdln] == 0)
  238.     {
  239. #  if !defined (M_I86LM) && !defined (__LARGE__)
  240.     cp = buf;
  241.     s = _APgmName;
  242.     while (*(cp++) = *(s++))
  243.         continue;
  244.  
  245.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
  246. #  else
  247.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (_APgmName));
  248. #  endif
  249.     }
  250.  
  251.     else
  252.     {
  253.     argvp += _acmdln;
  254.  
  255. #  if !defined (M_I86LM) && !defined (__LARGE__)
  256.     cp = buf;
  257.     s = argvp;
  258.     while (*(cp++) = *(s++))
  259.         continue;
  260.  
  261.     off = strlen (buf);
  262.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
  263.     argvp += off + 1;
  264.  
  265.     cp = buf;
  266.     s = argvp;
  267.     while (*(cp++) = *(s++))
  268.         continue;
  269.  
  270.     _Ex_CommandLine (buf);
  271. #  else
  272.     _Ex_ProcessEMXArguments (argvp);
  273. #  endif
  274.     }
  275.  
  276. /* Set up the Window name.  Give up if it does not work.  */
  277.  
  278.     _Ex_SetUpWindowName ();
  279.     _Ex_AddArgument ((char *)NULL);
  280.     --ARG_COUNT;
  281. }
  282.  
  283. #else
  284.  
  285. /*
  286.  * MSDOS version
  287.  */
  288.  
  289. void    ENTRY_POINT (void)
  290. {
  291.     char far        *s;         /* Temporary string pointer        */
  292.     union REGS        r;
  293.  
  294. #  if !defined (M_I86LM) && !defined (__LARGE__)
  295.     char        buf[MAX_LINE];    /* Temporary space        */
  296. #  endif
  297.                     /* Set up pointer to command line */
  298.     unsigned int    envs = *(int far *)((((long)_psp) << 16) + 0x02cL);
  299.     unsigned int    Length;
  300.  
  301. /* For reasons that escape me, MSC 6.0 does sets up _osmajor and _osminor
  302.  * in the command line parser!
  303.  */
  304.  
  305.    r.h.ah = 0x30;
  306.    intdos (&r, &r);
  307.    _osminor = r.h.ah;
  308.    _osmajor = r.h.al;
  309.  
  310. /* Check the length */
  311.  
  312.     _ACmdLine = (char far *)((((long)_psp) << 16) + 0x080L);
  313.  
  314.     if ((Length = (unsigned int)*(_ACmdLine++)) > 127)
  315.     Length = 127;
  316.  
  317.     _ACmdLine[Length] = 0;
  318.  
  319. /* Command line can be null or 0x0d terminated - convert to null */
  320.  
  321.     if ((s = strchr (_ACmdLine, 0x0d)) != (char *)NULL)
  322.     *s = 0;
  323.  
  324. /* Set up global parameters and expand */
  325.  
  326.     ARG_COUNT = 0;
  327.  
  328. /* Get the program name */
  329.  
  330.     if ((_osmajor <= 2) || (envs == 0))
  331.     s = "unknown";
  332.  
  333. /* In the case of DOS 3+, we look in the environment space */
  334.  
  335.     else
  336.     {
  337.     s = (char far *)(((long)envs) << 16);
  338.  
  339.     while (*s)
  340.     {
  341.         while (*(s++) != 0)
  342.         continue;
  343.     }
  344.  
  345.     s += 3;
  346.     }
  347.  
  348. /* Add the program name        */
  349.  
  350.     _APgmName = s;
  351.  
  352. #  if !defined (M_I86LM) && !defined (__LARGE__)
  353.     cp = buf;
  354.     while (*(cp++) = *(s++))
  355.     continue;
  356.  
  357.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
  358.  
  359.     s  = _ACmdLine;
  360.     cp = buf;
  361.     while (*(cp++) = *(s++))
  362.     continue;
  363.  
  364.     _Ex_CommandLine (buf);
  365. #  else
  366.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (s));
  367.     _Ex_CommandLine (_ACmdLine);
  368. #  endif
  369.  
  370.     _Ex_AddArgument ((char *)NULL);
  371.     --ARG_COUNT;
  372. }
  373. #endif
  374.  
  375. /*
  376.  * Expand the DOS Command line
  377.  */
  378.  
  379. static void    _Ex_CommandLine (argvp)
  380. char        *argvp;            /* Line to expand            */
  381. {
  382.     char    *spos;            /* End of string pointer    */
  383.     char    *cpos;            /* Start of string pointer    */
  384.     char    *fn;            /* Extracted file name string    */
  385.  
  386. /* Search for next separator */
  387.  
  388.     spos = argvp;
  389.  
  390.     while (*(cpos = _Ex_SkipWhiteSpace (spos)))
  391.     {
  392.  
  393. /* Extract string argument */
  394.  
  395.     if ((*cpos == '"') || (*cpos == '\''))
  396.     {
  397.         spos = cpos + 1;
  398.  
  399.         do
  400.         {
  401.         if ((spos = strchr (spos, *cpos)) != NULL)
  402.         {
  403.             spos++;
  404.             if (spos[-2] != '\\')
  405.             break;
  406.         }
  407.  
  408.         else
  409.             spos = &spos[strlen (cpos)];
  410.  
  411.         } while (*spos);
  412.  
  413.         fn    = _Ex_GetSpace (spos - cpos - 2, cpos + 1);
  414.     }
  415.  
  416. /* Extract normal argument */
  417.  
  418.     else
  419.     {
  420.         spos = cpos;
  421.         while (!isspace (*spos) && *spos)
  422.         spos++;
  423.  
  424.         fn = _Ex_GetSpace (spos - cpos, cpos);
  425.     }
  426.  
  427. /* Process argument */
  428.  
  429.     if (*cpos != '\'')
  430.         fn = _Ex_ConvertEnvVariables (fn);
  431.  
  432.     switch (*cpos)
  433.     {
  434.         case '@':        /* Expand file                    */
  435.         _Ex_ExpandIndirectFile (fn);
  436.         break;
  437.  
  438.         case '"':        /* Expand string                */
  439.         case '\'':
  440.         _Ex_AddArgument (fn);
  441.         break;
  442.  
  443.         default:        /* Expand field                    */
  444.         _Ex_ExpandField (fn);
  445.     }
  446.  
  447.     free (fn);
  448.     }
  449. }
  450.  
  451. /* Expand an indirect file Argument */
  452.  
  453. static void    _Ex_ExpandIndirectFile (file)
  454. char        *file;        /* Expand file name                */
  455. {
  456.     FILE        *fp;        /* File descriptor                */
  457.     char    *EoLFound;    /* Pointer                */
  458.     int        c_maxlen = MAX_LINE;
  459.     char    *line;        /* Line buffer                    */
  460.     char    *eolp;
  461.  
  462. /* If file open fails, expand as a field */
  463.  
  464. #ifdef __OS2__
  465.     if ((fp = fopen (file + 1, "r")) == NULL)
  466. #else
  467.     if ((fp = fopen (file + 1, "rt")) == NULL)
  468. #endif
  469.     _Ex_FatalError (errno, "%s: Cannot open re-direct file - %s (%s)\n",
  470.             file + 1);
  471.  
  472. /* Grab some memory for the line */
  473.  
  474.     if ((line = malloc (c_maxlen)) == (char *)NULL)
  475.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  476.  
  477. /* For each line in the file, remove EOF characters and add argument */
  478.  
  479.     while (fgets (line, c_maxlen, fp) != (char *)NULL)
  480.     {
  481.     EoLFound = strchr (line, '\n');
  482.     eolp = line;
  483.  
  484. /* Handle continuation characters */
  485.  
  486.     while (TRUE)
  487.     {
  488.  
  489. /* Check for a continuation character */
  490.  
  491.         if (((EoLFound = strchr (eolp, '\n')) != (char *)NULL) &&
  492.         (*(EoLFound - 1) == '\\'))
  493.         {
  494.         *(EoLFound - 1) = '\n';
  495.         *EoLFound = 0;
  496.         EoLFound = (char *)NULL;
  497.         }
  498.  
  499.         else if (EoLFound == (char *)NULL)
  500.         EoLFound = strchr (line, 0x1a);
  501.  
  502.         if (EoLFound != (char *)NULL)
  503.         break;
  504.  
  505. /* Find the end of the line */
  506.  
  507.         c_maxlen = strlen (line);
  508.  
  509. /* Get some more space */
  510.  
  511.         if ((line = realloc (line, c_maxlen + MAX_LINE)) == (char *)NULL)
  512.         _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  513.  
  514.         eolp = &line[c_maxlen];
  515.  
  516.         if (fgets (eolp, MAX_LINE, fp) == (char *)NULL)
  517.         break;
  518.     }
  519.  
  520. /* Terminate the line and add it to the argument list */
  521.  
  522.     if (EoLFound != (char *)NULL)
  523.         *EoLFound = 0;
  524.  
  525.     _Ex_AddArgument (line);
  526.     }
  527.  
  528.     if (ferror(fp))
  529.     _Ex_FatalError (errno, "%s: %s (%s)\n", file + 1);
  530.  
  531.     free (line);
  532.     fclose (fp);
  533.  
  534. /* Delete tempoary files */
  535.  
  536.     if (((line = strrchr (file + 1, '.')) != (char *)NULL) &&
  537.     (stricmp (line, ".tmp") == 0))
  538.     unlink (file + 1);            /* Delete it        */
  539. }
  540.  
  541. /* Get space for an argument name */
  542.  
  543. static char    *_Ex_GetSpace (length, in_s)
  544. int        length;            /* String length                */
  545. char        *in_s;                  /* String address        */
  546. {
  547.     char    *out_s;            /* Malloced space address       */
  548.  
  549.     if ((out_s = malloc (length + 1)) == (char *)NULL)
  550.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  551.  
  552. /* Copy string for specified length */
  553.  
  554.     strncpy (out_s, in_s, length);
  555.     out_s[length] = 0;
  556.  
  557.     return (out_s);
  558. }
  559.  
  560. /* Append an argument to the array */
  561.  
  562. static void    _Ex_AddArgument (Argument)
  563. char        *Argument;            /* Argument to add        */
  564. {
  565.     if (ARG_COUNT == 0)
  566.     ARG_ARRAY = (char **)malloc (50 * S_ENTRY);
  567.  
  568.     else if ((ARG_COUNT % 50) == 0)
  569.     ARG_ARRAY = (char **)realloc (ARG_ARRAY, (ARG_COUNT + 50) * S_ENTRY);
  570.  
  571.     if (ARG_ARRAY == (char **)NULL)
  572.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  573.  
  574.     if (Argument == (char *)NULL)
  575.     ARG_ARRAY[ARG_COUNT++] = (char *)NULL;
  576.  
  577.     else
  578.     ARG_ARRAY[ARG_COUNT++] = _Ex_GetSpace (strlen (Argument), Argument);
  579. }
  580.  
  581. /*  Skip over spaces */
  582.  
  583. static char    *_Ex_SkipWhiteSpace (a)
  584. char        *a;            /* String start address        */
  585. {
  586.     while (isspace(*a))
  587.         a++;
  588.  
  589.     return (a);
  590. }
  591.  
  592. /* Convert name to Unix format */
  593.  
  594. static char    *_Ex_ConvertToUnixFormat (a)
  595. char        *a;
  596. {
  597.     char    *sp = a;
  598.  
  599.     while ((a = strchr (a, '\\')) != (char *)NULL)
  600.     *(a++) = '/';
  601.  
  602. #ifndef OS2
  603.     return strlwr (sp);
  604. #else
  605.     if (!IsHPFSFileSystem (sp))
  606.     strlwr (sp);
  607.  
  608.     return sp;
  609. #endif
  610.  
  611. }
  612.  
  613. /* Find the location of meta-characters.  If no meta, add the argument and
  614.  * return NULL.  If meta characters, return position of end of directory
  615.  * name.  If not multiple directories, return -1
  616.  */
  617.  
  618. static void    _Ex_ExpandField (file)
  619. char        *file;
  620. {
  621.     int        i = 0;
  622.     glob_t    gp;
  623.  
  624.     if (strpbrk (file, "?*[]\\") == (char *)NULL)
  625.     {
  626.     _Ex_AddArgument (file);
  627.     return;
  628.     }
  629.  
  630.     if (glob (file, GLOB_NOCHECK, (int (_CDECL *)(char *, int))NULL , &gp))
  631.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  632.  
  633.     i = 0;
  634.  
  635.     while (i < gp.gl_pathc)
  636.     _Ex_AddArgument (gp.gl_pathv[i++]);
  637.  
  638.     globfree (&gp);
  639. }
  640.  
  641. /* Fatal errors */
  642.  
  643. static void    _Ex_FatalError (ecode, format, para)
  644. int        ecode;
  645. char        *format;
  646. char        *para;
  647. {
  648.     fprintf (stderr, format, "stdargv", strerror (ecode), para);
  649.     exit (1);
  650. }
  651.  
  652. /* Process Environment - note that field is a malloc'ed field */
  653.  
  654. static char    *_Ex_ConvertEnvVariables (field)
  655. char        *field;
  656. {
  657.     char    *sp, *cp, *np, *ep;
  658.     char    save;
  659.     int        b_flag;
  660.  
  661.     sp = field;
  662.  
  663. /* Replace any $ strings */
  664.  
  665.     while ((sp = strchr (sp, '$')) != (char *)NULL)
  666.     {
  667.  
  668. /* If ${...}, find the terminating } */
  669.  
  670.     if (*(cp = ++sp) == '{')
  671.     {
  672.         b_flag = 1;
  673.         ++cp;
  674.  
  675.         while (*cp && (*cp != '}'))
  676.         cp++;
  677.     }
  678.  
  679. /* Else must be $..., find the terminating non-alphanumeric */
  680.  
  681.     else
  682.     {
  683.         b_flag = 0;
  684.  
  685.         while (isalnum (*cp))
  686.         cp++;
  687.     }
  688.  
  689. /* Grab the environment variable */
  690.  
  691.     if (cp == sp)
  692.         continue;
  693.  
  694. /* Get its value */
  695.  
  696.     save = *cp;
  697.     *cp = 0;
  698.     ep = getenv (sp + b_flag);
  699.     *cp = save;
  700.  
  701.     if (ep != (char *)NULL)
  702.     {
  703.         np = _Ex_GetSpace (strlen(field) - (cp - sp) + strlen (ep) - 1, field);
  704.         strcpy (&np[sp - field - 1], ep);
  705.         free (field);
  706.         strcpy ((sp = &np[strlen(np)]), cp + b_flag);
  707.         field = np;
  708.     }
  709.     }
  710.  
  711.     return field;
  712. }
  713.  
  714. /*
  715.  * Handle EMX style arguments
  716.  */
  717.  
  718. #if defined (OS2) || defined (__OS2__)
  719. static void    _Ex_ProcessEMXArguments (char *argvp)
  720. {
  721.     char    *cp;
  722.     char    *s = argvp;
  723.  
  724.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (argvp));
  725.     argvp += strlen (argvp) + 1;
  726.     _ACmdLine = argvp;
  727.  
  728. /*
  729.  * Add support in OS2 version for Eberhard Mattes EMX interface to commands.
  730.  */
  731.  
  732.     if ((*argvp) && (*(cp = argvp + strlen (argvp) + 1) == '~') &&
  733.     (strcmp (s, _Ex_ConvertToUnixFormat (cp + 1)) == 0))
  734.     {
  735.  
  736. /* Skip over the program name at string 2 to the start of the first
  737.  * argument at string 3
  738.  */
  739.  
  740.     argvp += strlen (argvp) + 1;
  741.     argvp += strlen (argvp) + 1;
  742.  
  743.     while (*argvp)
  744.     {
  745.         cp = (*argvp == '~') ? argvp + 1 : argvp;
  746.  
  747.         if (*cp == '@')
  748.         _Ex_ExpandIndirectFile (cp);
  749.  
  750.         else
  751.         _Ex_AddArgument (cp);
  752.  
  753.         argvp += strlen (argvp) + 1;
  754.     }
  755.     }
  756.  
  757.     else
  758.     _Ex_CommandLine (argvp);
  759. }
  760.  
  761. /*
  762.  * Set up the Window Name
  763.  */
  764.  
  765. static void    _Ex_SetUpWindowName (void)
  766. {
  767.     HSWITCH        hswitch;
  768.     SWCNTRL        swctl;
  769.     char        *cp;
  770.  
  771.     if (((hswitch = WinQuerySwitchHandle (0, getpid ()))) &&
  772.     (!WinQuerySwitchEntry (hswitch, &swctl)))
  773.     {
  774.     if ((cp = strrchr (ARG_ARRAY[0], '/')) == (char *)NULL)
  775.         cp = ARG_ARRAY[0];
  776.  
  777.     else
  778.         ++cp;
  779.  
  780.     strncpy (swctl.szSwtitle, cp, MAXNAMEL);
  781.     swctl.szSwtitle[MAXNAMEL] = 0;
  782.  
  783.     if ((cp = strrchr (swctl.szSwtitle, '.')) != (char *)NULL)
  784.         *cp = 0;
  785.  
  786.     WinChangeSwitchEntry (hswitch, &swctl);
  787.     }
  788. }
  789. #endif
  790.  
  791. /*
  792.  * Test main program
  793.  */
  794.  
  795. #ifdef TEST
  796. int    main (int argc, char **argv)
  797. {
  798.     int        i;
  799.  
  800.     printf ("_ACmdLine = <%s>\n", _ACmdLine);
  801.  
  802.     for (i = 0; i < argc; i++)
  803.     printf ("Arg %d = |%s|\n", i, argv[i]);
  804.  
  805.     return 0;
  806. }
  807. #endif
  808.