Changeset 3644 for trunk


Ignore:
Timestamp:
May 19, 2008, 1:41:35 AM (17 years ago)
Author:
bird
Message:

Proper argument passing - finally!

Location:
trunk/libc/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/libc/src/kNIX/b_initArgv.c

    r2989 r3644  
    3030*******************************************************************************/
    3131#include "kNIX.h"
     32#include <klibc/startup.h>
    3233#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_INITTERM
    3334#include <klibc/logstrict.h>
     
    7576static size_t parse_args(const char *pszSrc, char **papszArgs, char *pbPool)
    7677{
     78    char ch;
    7779    size_t cbArgs = 0;
    7880    __libc_Back_gcArgs = 0;
     
    8991    }
    9092    ++pszSrc;
    91     for (;;)
     93
     94    /* Check for the kLIBC signature used for unix arguments. */
     95    if (    pszSrc[0] != 0x7f
     96        ||  pszSrc[1] != 'k'
     97        ||  pszSrc[2] != 'L'
     98        ||  pszSrc[3] != 'I'
     99        ||  pszSrc[4] != 'B'
     100        ||  pszSrc[5] != 'C'
     101        ||  pszSrc[6] != 0x7f
     102        ||  pszSrc[7] != '\0')
    92103    {
    93         /* skip white spaces */
    94         while (IS_WHITE(*pszSrc))
    95             ++pszSrc;
    96         if (*pszSrc == 0)
    97             break;
    98 
    99         /*
    100          * Parse one argument.
    101          */
    102         char fFlags;
    103         char *pfFlags = pbPool ? pbPool++ : &fFlags;
    104         *pfFlags = (char)_ARG_NONZERO;
    105         cbArgs++;
    106         const size_t offArg = cbArgs;
    107         PUTV;
    108         char chQuote = 0;
     104        /* Convert from OS/2 command line convention to C/Unix. */
    109105        for (;;)
    110106        {
    111             /* End quote. */
    112             if (*pszSrc == chQuote && chQuote)
    113                 chQuote = 0;
    114             /* Start of double quote. */
    115             else if (!chQuote && *pszSrc == '"')
     107            /* skip white spaces */
     108            while (IS_WHITE(*pszSrc))
     109                ++pszSrc;
     110            if (*pszSrc == 0)
     111                break;
     112   
     113            /*
     114             * Parse one argument.
     115             */
     116            char fFlags;
     117            char *pfFlags = pbPool ? pbPool++ : &fFlags;
     118            *pfFlags = (char)_ARG_NONZERO;
     119            cbArgs++;
     120            const size_t offArg = cbArgs;
     121            PUTV;
     122            char chQuote = 0;
     123            for (;;)
    116124            {
    117                 chQuote = '"';
    118                 *pfFlags |= _ARG_DQUOTE;
     125                /* End quote. */
     126                if (*pszSrc == chQuote && chQuote)
     127                    chQuote = 0;
     128                /* Start of double quote. */
     129                else if (!chQuote && *pszSrc == '"')
     130                {
     131                    chQuote = '"';
     132                    *pfFlags |= _ARG_DQUOTE;
     133                }
     134                /*
     135                 * Only permit the single quote to be used at the start of an argument or
     136                 * within an already quoted one. This restriction is necessary to support
     137                 * unquoted filenames containing the single quote char.
     138                 */
     139                else if (   !chQuote
     140                         && *pszSrc == '\''
     141                         && (   offArg == cbArgs
     142                             || (*pfFlags & _ARG_DQUOTE)))
     143                {
     144                    chQuote = '\'';
     145                    *pfFlags |= _ARG_DQUOTE;
     146                }
     147                /*
     148                 * The escape character. This is truly magic/weird.
     149                 * It doesn't escape anything unless it's in front of a
     150                 * double quote character. EMX weirdness...
     151                 * (Ok, not escaping more than necessary is ok when using \ as path
     152                 * separator, but why weird interpretation of \\\\"asdf"?
     153                 */
     154                else if (*pszSrc == '\\' && chQuote != '\'')
     155                {
     156                    int cSlashes = 0;
     157                    do
     158                    {
     159                        cSlashes++;
     160                        pszSrc++;
     161                    } while (*pszSrc == '\\');
     162   
     163                    if (*pszSrc == '"')
     164                    {
     165                        /* Treat it as escapes. */
     166                        while (cSlashes >= 2)
     167                        {
     168                            PUTC('\\');
     169                            cSlashes -= 2;
     170                        }
     171                        if (cSlashes & 1)
     172                            PUTC(*pszSrc);
     173                        else
     174                            pszSrc--;
     175                    }
     176                    else
     177                    {
     178                        /* unmodified, no escaping. */
     179                        while (cSlashes-- > 0)
     180                            PUTC('\\');
     181                        pszSrc--;
     182                    }
     183                }
     184                /* Check for end of argument. */
     185                else if (   *pszSrc == '\0'
     186                         || (   IS_WHITE(*pszSrc)
     187                             && !chQuote))
     188                    break;
     189                /* Normal character. */
     190                else
     191                    PUTC(*pszSrc);
     192                ++pszSrc;
    119193            }
    120             /*
    121              * Only permit the single quote to be used at the start of an argument or
    122              * within an already quoted one. This restriction is necessary to support
    123              * unquoted filenames containing the single quote char.
    124              */
    125             else if (   !chQuote
    126                      && *pszSrc == '\''
    127                      && (   offArg == cbArgs
    128                          || (*pfFlags & _ARG_DQUOTE)))
     194            PUTC(0);
     195        }
     196    }
     197    else
     198    {
     199        /* The kLIBC spawn packs exactly what we want, including the flag at [-1]. */
     200        pszSrc += sizeof(__KLIBC_ARG_SIGNATURE);
     201        if (pbPool)
     202        {
     203            /* copying */
     204            while (*pszSrc)
    129205            {
    130                 chQuote = '\'';
    131                 *pfFlags |= _ARG_DQUOTE;
     206                LIBC_ASSERT((unsigned)*pszSrc & __KLIBC_ARG_NONZERO);
     207                __libc_Back_gcArgs++;
     208                *papszArgs++ = pbPool + 1;
     209                do
     210                {
     211                    *pbPool++ = ch = *pszSrc++;
     212                } while (ch);
    132213            }
    133             /*
    134              * The escape character. This is truly magic/weird.
    135              * It doesn't escape anything unless it's in front of a
    136              * double quote character. EMX weirdness...
    137              * (Ok, not escaping more than necessary is ok when using \ as path
    138              * separator, but why weird interpretation of \\\\"asdf"?
    139              */
    140             else if (*pszSrc == '\\' && chQuote != '\'')
     214        }
     215        else
     216        {
     217            /* counting */
     218            while (*pszSrc)
    141219            {
    142                 int cSlashes = 0;
     220                __libc_Back_gcArgs++;
     221                LIBC_ASSERT((unsigned)*pszSrc & __KLIBC_ARG_NONZERO);
    143222                do
    144223                {
    145                     cSlashes++;
    146                     pszSrc++;
    147                 } while (*pszSrc == '\\');
    148 
    149                 if (*pszSrc == '"')
    150                 {
    151                     /* Treat it as escapes. */
    152                     while (cSlashes >= 2)
    153                     {
    154                         PUTC('\\');
    155                         cSlashes -= 2;
    156                     }
    157                     if (cSlashes & 1)
    158                         PUTC(*pszSrc);
    159                     else
    160                         pszSrc--;
    161                 }
    162                 else
    163                 {
    164                     /* unmodified, no escaping. */
    165                     while (cSlashes-- > 0)
    166                         PUTC('\\');
    167                     pszSrc--;
    168                 }
     224                    cbArgs++;
     225                    ch = *pszSrc++;
     226                } while (ch);
    169227            }
    170             /* Check for end of argument. */
    171             else if (   *pszSrc == '\0'
    172                      || (   IS_WHITE(*pszSrc)
    173                          && !chQuote))
    174                 break;
    175             /* Normal character. */
    176             else
    177                 PUTC(*pszSrc);
    178             ++pszSrc;
    179228        }
    180         PUTC(0);
    181229    }
    182230    return cbArgs;
  • trunk/libc/src/kNIX/os2/__spawnve.c

    r3641 r3644  
    3333/** @todo Cleanup __spawnve.c properly! */
    3434#include <emx/syscalls.h>
     35#include <klibc/startup.h>
    3536#define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_PROCESS
    3637#include <klibc/logstrict.h>
     
    193194    LIBCLOG_ENTER("np=%p:{mode=%#x}\n", (void *)np, np->mode);
    194195    FS_VAR();
     196    char szLineBuf[512];
    195197
    196198    /*
     
    234236
    235237    /*
    236      * cmd.exe and 4os2.exe needs different argument handling.
     238     * cmd.exe and 4os2.exe needs different argument handling, and
     239     * starting with kLIBC 0.6.4 we can pass argv directly to LIBC
     240     * programs.
    237241     * (1 == cmd or 4os2 shell, 0 == anything else)
    238242     */
     243    enum { args_standard, args_cmd, args_unix } enmMethod = args_standard;
    239244    char *psz = _getname(pszPgmName);
    240     int method = stricmp(psz, "cmd.exe") == 0
    241               || stricmp(psz, "4os2.exe") == 0;
     245    if (   stricmp(psz, "cmd.exe") == 0
     246        || stricmp(psz, "4os2.exe") == 0)
     247        enmMethod = args_cmd;
     248    else
     249    {
     250        HFILE hFile = NULLHANDLE;
     251        ULONG ulAction = 0;
     252        rc = DosOpen((PCSZ)pszPgmName, &hFile, &ulAction, 0, FILE_NORMAL,
     253                     OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
     254                     OPEN_FLAGS_SEQUENTIAL | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
     255                     NULL);
     256        if (!rc)
     257        {
     258            ULONG cbRead = 0;
     259            rc = DosRead(hFile, szLineBuf, sizeof(szLineBuf), &cbRead);
     260            DosClose(hFile);
     261            if (rc)
     262                LIBCLOG_ERROR("DosRead - rc=%d (%s)\n", rc, pszPgmName);
     263            else if (   cbRead >= __KLIBC_STUB_MIN_SIZE
     264                     && szLineBuf[0] == 'M'
     265                     && szLineBuf[1] == 'Z'
     266                     && !memcmp(&szLineBuf[__KLIBC_STUB_SIGNATURE_OFF], __KLIBC_STUB_SIGNATURE_BASE, sizeof(__KLIBC_STUB_SIGNATURE_BASE) - 1)
     267                    )
     268            {
     269                char const *pchVer = &szLineBuf[__KLIBC_STUB_SIGNATURE_OFF + sizeof(__KLIBC_STUB_SIGNATURE_BASE) - 1];
     270                if (*pchVer >= '0' && *pchVer <= '9')
     271                    enmMethod = !(np->mode & P_NOUNIXARGV) ? args_unix : args_standard;
     272            }
     273            /** @todo move the hash bang handling up here. */
     274            /*else if (!rc && szLineBuf[0] == '#')
     275            {
     276            } */
     277        }
     278        /* Catch some plain failures here, leave the rest for later. */
     279        else if (   rc == ERROR_FILE_NOT_FOUND
     280                 || rc == ERROR_PATH_NOT_FOUND)
     281        {
     282            errno = __libc_back_native2errno(rc);
     283            LIBCLOG_RETURN_INT(-1);
     284        }
     285        else
     286            LIBCLOG_ERROR("rc=%d (%s)\n", rc, pszPgmName);
     287    }
    242288
    243289    /*
     
    249295    char       *pszArg = NULL;
    250296    size_t      cbArgs = 0;
     297    int         i;
     298
    251299    if (np->arg_count > 0)
    252300    {
     
    257305        pszArg += cch; pszSrc += cch;
    258306    }
    259     int i;
    260     for (i = 1; i < np->arg_count; ++i)
     307    if (enmMethod == args_unix)
    261308    {
    262         if (i > 1)
     309        /* first arg is the signature. */
     310        ADD(sizeof(__KLIBC_ARG_SIGNATURE));
     311        memcpy(pszArg, __KLIBC_ARG_SIGNATURE, sizeof(__KLIBC_ARG_SIGNATURE));
     312        pszArg += sizeof(__KLIBC_ARG_SIGNATURE);
     313
     314        /* then comes the argument vector. */
     315        for (i = 1; i < np->arg_count; ++i)
    263316        {
    264             ADD(1);
    265             *pszArg++ = ' ';
     317            unsigned char chFlags = *pszSrc++;
     318            chFlags &= __KLIBC_ARG_MASK;
     319            chFlags |= __KLIBC_ARG_ARGV;
     320            cch = strlen(pszSrc) + 1;
     321            ADD(cch + 1);
     322            *pszArg++ = chFlags;
     323            memcpy(pszArg, pszSrc, cch);
     324            pszArg += cch;
     325            pszSrc += cch;
    266326        }
    267         ++pszSrc;                    /* skip flags byte */
    268         BOOL fQuote = FALSE;
    269         if (*pszSrc == 0)
    270             fQuote = TRUE;
    271         else if (ulMode & P_QUOTE)
     327
     328        /* the double termination. */
     329        ADD(1);
     330        *pszArg = '\0';
     331    }
     332    else
     333    {
     334        /* quote the arguments in emx / cmd.exe fashion. */
     335        for (i = 1; i < np->arg_count; ++i)
    272336        {
    273             if (pszSrc[0] == '@' && pszSrc[1] != 0)
     337            if (i > 1)
     338            {
     339                ADD(1);
     340                *pszArg++ = ' ';
     341            }
     342            ++pszSrc;                    /* skip flags byte */
     343            BOOL fQuote = FALSE;
     344            if (*pszSrc == 0)
    274345                fQuote = TRUE;
    275             else
     346            else if (ulMode & P_QUOTE)
     347            {
     348                if (pszSrc[0] == '@' && pszSrc[1] != 0)
     349                    fQuote = TRUE;
     350                else
     351                    for (psz = (char *)pszSrc; *psz != 0; ++psz)
     352                        if (*psz == '?' || *psz == '*')
     353                        {
     354                            fQuote = TRUE;
     355                            break;
     356                        }
     357            }
     358            if (!fQuote)
     359            {
    276360                for (psz = (char *)pszSrc; *psz != 0; ++psz)
    277                     if (*psz == '?' || *psz == '*')
     361                    if (*psz == ' ' || *psz == '\t' || (*psz == '"' && enmMethod == args_cmd))
    278362                    {
    279363                        fQuote = TRUE;
    280364                        break;
    281365                    }
    282         }
    283         if (!fQuote)
    284         {
    285             for (psz = (char *)pszSrc; *psz != 0; ++psz)
    286                 if (*psz == ' ' || *psz == '\t' || (*psz == '"' && method == 1))
     366            }
     367            if (fQuote)
     368            {
     369                ADD(1);
     370                *pszArg++ = '"';
     371            }
     372            size_t bs = 0;
     373            while (*pszSrc != 0)
     374            {
     375                if (*pszSrc == '"' && enmMethod == args_standard)
    287376                {
    288                     fQuote = TRUE;
    289                     break;
     377                    ++bs;
     378                    ADD(bs);
     379                    memset(pszArg, '\\', bs); pszArg += bs;
     380                    bs = 0;
    290381                }
    291         }
    292         if (fQuote)
    293         {
    294             ADD(1);
    295             *pszArg++ = '"';
    296         }
    297         size_t bs = 0;
    298         while (*pszSrc != 0)
    299         {
    300             if (*pszSrc == '"' && method == 0)
    301             {
    302                 ++bs;
    303                 ADD(bs);
     382                else if (*pszSrc == '\\' && enmMethod == args_standard)
     383                    ++bs;
     384                else
     385                    bs = 0;
     386                ADD(1);
     387                *pszArg++ = *pszSrc;
     388                ++pszSrc;
     389            }
     390            if (fQuote)
     391            {
     392                ADD(1+bs);
    304393                memset(pszArg, '\\', bs); pszArg += bs;
    305                 bs = 0;
    306             }
    307             else if (*pszSrc == '\\' && method == 0)
    308                 ++bs;
    309             else
    310                 bs = 0;
    311             ADD(1);
    312             *pszArg++ = *pszSrc;
     394                *pszArg++ = '"';
     395            }
    313396            ++pszSrc;
    314397        }
    315         if (fQuote)
    316         {
    317             ADD(1+bs);
    318             memset(pszArg, '\\', bs); pszArg += bs;
    319             *pszArg++ = '"';
    320         }
    321         ++pszSrc;
     398        /* The arguments are an array of zero terminated strings, ending with an empty string. */
     399        ADD(2);
     400        *pszArg++ = '\0';
     401        *pszArg++ = '\0';
    322402    }
    323     /* The arguments are an array of zero terminated strings, ending with an empty string. */
    324     ADD(2);
    325     *pszArg++ = '\0';
    326     *pszArg++ = '\0';
    327403
    328404
     
    359435                 * requires inspection of the first line of the file.
    360436                 */
    361                 char szLineBuf[256];
    362437                const char *pszInterpreter = NULL;
    363438                const char *pszInterpreterArgs = NULL;
     
    528603
    529604                /*
    530                  * Delay a tiny bit while the child is starting up and doing the inheriting.
    531                  * If we figure that it's a libc child, we can wait a good deal longer.
     605                 * Wait for the child to become active and complete the inhertining.
    532606                 */
    533607                int fDoneInherit = __libc_spmWaitForChildToBecomeAlive(pEmbryo);
     
    701775            }
    702776            else if (rc > 0)
    703                 errno = rc;
     777                errno = __libc_back_native2errno(rc);
    704778            else
    705779                errno = -rc;
  • trunk/libc/src/libc/misc/response.c

    r2433 r3644  
    55#include <stdlib.h>
    66#include <string.h>
    7 #include <emx/startup.h>
     7#include <klibc/startup.h>
    88
    99#define RPUT(x) do \
     
    3030  for (i = 1; i < old_argc; ++i)
    3131    if (old_argv[i] != NULL
    32         && !(old_argv[i][-1] & (_ARG_DQUOTE|_ARG_WILDCARD))
     32        && !(old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL))
    3333        && old_argv[i][0] == '@')
    3434      break;
     
    3939    {
    4040      if (i == 0 || old_argv[i] == NULL
    41           || (old_argv[i][-1] & (_ARG_DQUOTE|_ARG_WILDCARD))
     41          || (old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL))
    4242          || old_argv[i][0] != '@'
    4343          || (f = fopen (old_argv[i]+1, "rt")) == NULL)
     
    4545      else
    4646        {
    47           line[0] = _ARG_NONZERO|_ARG_RESPONSE;
     47          line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_RESPONSE;
    4848          while (fgets (line+1, sizeof (line)-1, f) != NULL)
    4949            {
  • trunk/libc/src/libc/misc/wildcard.c

    r732 r3644  
    55#include <stdlib.h>
    66#include <string.h>
    7 #include <emx/startup.h>
    87#include <emx/syscalls.h>
     8#include <klibc/startup.h>
    99
    1010#define WPUT(x) do { \
     
    3232  for (i = 1; i < old_argc; ++i)
    3333    if (old_argv[i] != NULL &&
    34         !(old_argv[i][-1] & (_ARG_DQUOTE|_ARG_RESPONSE)) &&
     34        !(old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_RESPONSE | __KLIBC_ARG_ARGV | __KLIBC_ARG_SHELL)) &&
    3535        strpbrk (old_argv[i], "?*") != NULL)
    3636      break;
     
    4141    {
    4242      if (i == 0 || old_argv[i] == NULL
    43           || (old_argv[i][-1] & (_ARG_DQUOTE|_ARG_RESPONSE))
     43          || (old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_RESPONSE | __KLIBC_ARG_ARGV | __KLIBC_ARG_SHELL))
    4444          || strpbrk (old_argv[i], "?*") == NULL
    4545          || __findfirst (old_argv[i], 0x10, &find) != 0)
     
    4747      else
    4848        {
    49           line[0] = _ARG_NONZERO|_ARG_WILDCARD;
     49          line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_WILDCARD;
    5050          strcpy (line+1, old_argv[i]);
    5151          p = _getname (line + 1);
Note: See TracChangeset for help on using the changeset viewer.