home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 January / PCWorld_2000-01_cd.bin / Software / Servis / Devc / _SETUP.5 / Group13 / fixargv.c next >
C/C++ Source or Header  |  1997-12-05  |  6KB  |  291 lines

  1. /*
  2.  * fixargv.c
  3.  *
  4.  * A special function which "fixes" an argv array by replacing arguments
  5.  * that need quoting with quoted versions.
  6.  *
  7.  * NOTE: In order to be reasonably consistent there is some misuse of the
  8.  *       const keyword here-- which leads to compilation warnings. These
  9.  *       should be ok to ignore.
  10.  *
  11.  * This is a sample distributed as part of the Mingw32 package.
  12.  *
  13.  * Contributors:
  14.  *  Created by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
  15.  *
  16.  *  THIS SOFTWARE IS NOT COPYRIGHTED
  17.  *
  18.  *  This source code is offered for use in the public domain. You may
  19.  *  use, modify or distribute it freely.
  20.  *
  21.  *  This code is distributed in the hope that it will be useful but
  22.  *  WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
  23.  *  DISCLAMED. This includes but is not limited to warrenties of
  24.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  25.  *
  26.  * $Revision: 1.1 $
  27.  * $Author: colin $
  28.  * $Date: 1997/12/05 00:31:14 $
  29.  *
  30.  */
  31.  
  32. #include <string.h>
  33. #include "fixargv.h"
  34.  
  35. /*
  36.  * This takes a single string and fixes it, enclosing it in quotes if it
  37.  * contains any spaces and/or escaping the quotes it contains.
  38.  */
  39. char*
  40. fix_arg (const char* szArg)
  41. {
  42.     int    nQuoteAll;    /* Does the whole arg need quoting? */
  43.     int    nBkSlRun;    /* How may backslashes in a row? */
  44.     char*    sz;
  45.     char*    szNew;
  46.     size_t    sizeLen;
  47.  
  48.     nQuoteAll = 0;
  49.     nBkSlRun = 0;
  50.     sz = szArg;
  51.     sizeLen = 1;
  52.  
  53.     /* First we figure out how much bigger the new string has to be
  54.      * than the old one. */
  55.     while (*sz != '\0')
  56.     {
  57.         /*
  58.          * Arguments containing whitespace of wildcards will be
  59.          * quoted to preserve tokenization and/or those special
  60.          * characters (i.e. wildcarding will NOT be done at the
  61.          * other end-- they will get the * and ? characters as is).
  62.          * TODO: Is this the best way? Do we want to enable wildcards?
  63.          *       If so, when?
  64.          */
  65.         if (!nQuoteAll &&
  66.             (*sz == ' ' || *sz == '\t' || *sz == '*' || *sz == '?'))
  67.         {
  68.             nQuoteAll = 1;
  69.         }
  70.         else if (*sz == '\\')
  71.         {
  72.             nBkSlRun++;
  73.         }
  74.         else
  75.         {
  76.             if (*sz == '\"')
  77.             {
  78.                 sizeLen += nBkSlRun + 1;
  79.             }
  80.             nBkSlRun = 0;
  81.         }
  82.  
  83.         sizeLen++;
  84.         sz++;
  85.     }
  86.  
  87.     if (nQuoteAll)
  88.     {
  89.         sizeLen += 2;
  90.     }
  91.  
  92.     /*
  93.      * Make a new string big enough.
  94.      */
  95.     szNew = (char*) malloc (sizeLen);
  96.     if (!szNew)
  97.     {
  98.         return NULL;
  99.     }
  100.     sz = szNew;
  101.  
  102.     /* First enclosing quote for fully quoted args. */
  103.     if (nQuoteAll)
  104.     {
  105.         *sz = '\"';
  106.         sz++;
  107.     }
  108.  
  109.     /*
  110.      * Go through the string putting backslashes in front of quotes,
  111.      * and doubling all backslashes immediately in front of quotes.
  112.      */
  113.     nBkSlRun = 0;
  114.     while (*szArg != '\0')
  115.     {
  116.         if (*szArg == '\\')
  117.         {
  118.             nBkSlRun++;
  119.         }
  120.         else
  121.         {
  122.             if (*szArg == '\"')
  123.             {
  124.                 while (nBkSlRun > 0)
  125.                 {
  126.                     *sz = '\\';
  127.                     sz++;
  128.                     nBkSlRun--;
  129.                 }
  130.                 *sz = '\\';
  131.                 sz++;
  132.             }
  133.             nBkSlRun = 0;
  134.         }
  135.  
  136.         *sz = *szArg;
  137.         sz++;
  138.         szArg++;
  139.     }
  140.  
  141.     /* Closing quote for fully quoted args. */
  142.     if (nQuoteAll)
  143.     {
  144.         *sz = '\"';
  145.         sz++;
  146.     }
  147.  
  148.     *sz = '\0';
  149.     return szNew;
  150. }
  151.  
  152. /*
  153.  * Takes argc and argv and returns a new argv with escaped members. Pass
  154.  * this fixed argv (along with the old one) to free_fixed_argv after
  155.  * you finish with it. Pass in an argc of -1 and make sure the argv vector
  156.  * ends with a null pointer to have fix_argv count the arguments for you.
  157.  */
  158. char* const*
  159. fix_argv (int argc, char* const* szaArgv)
  160. {
  161.     char**    szaNew;
  162.     char*    sz;
  163.     int    i;
  164.  
  165.     if (!szaArgv)
  166.     {
  167.         return NULL;
  168.     }
  169.  
  170.     /*
  171.      * Count the arguments if asked.
  172.      */
  173.     if (argc == -1)
  174.     {
  175.         for (i = 0; szaArgv[i]; i++)
  176.             ;
  177.  
  178.         argc = i;
  179.     }
  180.  
  181.     /*
  182.      * If there are no args or only one arg then do no escaping.
  183.      */
  184.     if (argc < 2)
  185.     {
  186.         return szaArgv;
  187.     }
  188.  
  189.     for (i = 1, szaNew = NULL; i < argc; i++)
  190.     {
  191.         sz = szaArgv[i];
  192.  
  193.         /*
  194.          * If an argument needs fixing, then fix it.
  195.          */
  196.         if (strpbrk (sz, "\" \t*?"))
  197.         {
  198.             /*
  199.              * If we haven't created a new argv list already
  200.              * then make one.
  201.              */
  202.             if (!szaNew)
  203.             {
  204.                 szaNew = (char**) malloc ((argc + 1) *
  205.                     sizeof (char*));
  206.                 if (!szaNew)
  207.                 {
  208.                     return NULL;
  209.                 }
  210.  
  211.                 /*
  212.                  * Copy previous args from old to new.
  213.                  */
  214.                 memcpy (szaNew, szaArgv, sizeof(char*) * i);
  215.             }
  216.  
  217.             /*
  218.              * Now do the fixing.
  219.              */
  220.             szaNew[i] = fix_arg (sz);
  221.             if (!szaNew[i])
  222.             {
  223.                 /* Fixing failed, free up and return error. */
  224.                 free_fixed_argv (szaNew, szaArgv);
  225.                 return NULL;
  226.             }
  227.         }
  228.         else if (szaNew)
  229.         {
  230.             szaNew[i] = sz;
  231.         }
  232.     }
  233.  
  234.     if (szaNew)
  235.     {
  236.         /* If we have created a new argv list then we might as well
  237.          * terminate it nicely. (And we depend on it in
  238.          * free_fixed_argv.) */
  239.         szaNew[argc] = NULL;
  240.     }
  241.     else
  242.     {
  243.         /* If we didn't create a new argv list then return the
  244.          * original. */
  245.         return szaArgv;
  246.     }
  247.  
  248.     return szaNew;
  249. }
  250.  
  251. void
  252. free_fixed_argv (char* const* szaFixed, char* const* szaOld)
  253. {
  254.     char* const*    sza;
  255.  
  256.     /*
  257.      * Check for error conditions. Also note that if no corrections
  258.      * were required the fixed argv will actually be the same as
  259.      * the old one, and we don't need to do anything.
  260.      */
  261.     if (!szaFixed || !szaOld || szaFixed == szaOld)
  262.     {
  263.         return;
  264.     }
  265.  
  266.     /*
  267.      * Go through all members of the argv list. If any of the
  268.      * members in the fixed list are different from the old
  269.      * list we free those members.
  270.      * NOTE: The first member is never modified, so we don't need to
  271.      * check.
  272.      */
  273.     sza = szaFixed + 1;
  274.     szaOld++;
  275.     while (*sza)
  276.     {
  277.         if (*sza != *szaOld)
  278.         {
  279.             free (*sza);
  280.         }
  281.         sza++;
  282.         szaOld++;
  283.     }
  284.  
  285.     /*
  286.      * Now we can free the array of char pointers itself.
  287.      */
  288.     free (szaFixed);
  289. }
  290.  
  291.