VirtualBox

Changeset 3040 in kBuild for trunk/src/kmk/kmkbuiltin.c


Ignore:
Timestamp:
May 10, 2017 1:07:10 PM (8 years ago)
Author:
bird
Message:

kmk_builtin_command: do bourn style argument splitting, not stupid custom stuff.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin.c

    r3034 r3040  
    4343#endif
    4444
     45
    4546int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
    4647{
     
    4849    char      **argv;
    4950    int         rc;
     51    char       *pszzCmd;
     52    char       *pszDst;
     53    int         fOldStyle = 0;
    5054
    5155    /*
     
    5458    if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
    5559    {
    56         printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
     60        fprintf(stderr, "kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
    5761        return 1;
    5862    }
     
    6165     * Parse arguments.
    6266     */
    63     argc = 0;
    64     argv = NULL;
    65     while (*pszCmd)
    66     {
    67         const char *pszEnd;
    68         const char *pszNext;
    69         int         fEscaped = 0;
    70         size_t      cch;
     67    rc      = 0;
     68    argc    = 0;
     69    argv    = NULL;
     70    pszzCmd = pszDst = (char *)strdup(pszCmd);
     71    if (!pszDst)
     72    {
     73        fprintf(stderr, "kmk_builtin: out of memory. argc=%d\n", argc);
     74        return 1;
     75    }
     76    do
     77    {
     78        const char * const pszSrcStart = pszCmd;
     79        char ch;
     80        char chQuote;
    7181
    7282        /*
    73          * Find start and end of the current command.
    74          */
    75         if (*pszCmd == '"' || *pszCmd == '\'')
    76         {
    77             pszEnd = pszCmd;
    78             for (;;)
    79             {
    80                 pszEnd = strchr(pszEnd + 1, *pszCmd);
    81                 if (!pszEnd)
    82                 {
    83                     printf("kmk_builtin: Unbalanced quote in argument %d: %s\n", argc + 1, pszCmd);
    84                     while (argc--)
    85                         free(argv[argc]);
    86                     free(argv);
    87                     return 1;
    88                 }
    89                 /* two quotes -> escaped quote. */
    90                 if (pszEnd[0] != pszEnd[1])
    91                     break;
    92                 fEscaped = 1;
    93             }
    94             pszNext = pszEnd + 1;
    95             pszCmd++;
    96         }
    97         else
    98         {
    99             pszEnd = pszCmd;
    100             while (!isspace(*pszEnd) && *pszEnd)
    101                 pszEnd++;
    102             pszNext = pszEnd;
    103         }
    104 
    105         /*
    106          * Make argument.
     83         * Start new argument.
    10784         */
    10885        if (!(argc % 16))
     
    11188            if (!pv)
    11289            {
    113                 printf("kmk_builtin: out of memory. argc=%d\n", argc);
     90                fprintf(stderr, "kmk_builtin: out of memory. argc=%d\n", argc);
     91                rc = 1;
    11492                break;
    11593            }
    11694            argv = (char **)pv;
    11795        }
    118         cch = pszEnd - pszCmd;
    119         argv[argc] = malloc(cch + 1);
    120         if (!argv[argc])
     96        argv[argc++] = pszDst;
     97        argv[argc]   = NULL;
     98
     99        if (!fOldStyle)
    121100        {
    122             printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, (int)(pszEnd - pszCmd + 1));
     101            /*
     102             * Process the next argument, bourne style.
     103             */
     104            chQuote = 0;
     105            ch = *pszCmd++;
     106            do
     107            {
     108                /* Unquoted mode? */
     109                if (chQuote == 0)
     110                {
     111                    if (ch != '\'' && ch != '"')
     112                    {
     113                        if (!isspace(ch))
     114                        {
     115                            if (ch != '\\')
     116                                *pszDst++ = ch;
     117                            else
     118                            {
     119                                ch = *pszCmd++;
     120                                if (ch)
     121                                    *pszDst++ = ch;
     122                                else
     123                                {
     124                                    fprintf(stderr, "kmk_builtin: Incomplete escape sequence in argument %d: %s\n",
     125                                            argc, pszSrcStart);
     126                                    rc = 1;
     127                                    break;
     128                                }
     129                            }
     130                        }
     131                        else
     132                            break;
     133                    }
     134                    else
     135                        chQuote = ch;
     136                }
     137                /* Quoted mode */
     138                else if (ch != chQuote)
     139                {
     140                    if (   ch != '\\'
     141                        || chQuote == '\'')
     142                        *pszDst++ = ch;
     143                    else
     144                    {
     145                        ch = *pszCmd++;
     146                        if (ch)
     147                        {
     148                            if (   ch != '\\'
     149                                && ch != '"'
     150                                && ch != '`'
     151                                && ch != '$'
     152                                && ch != '\n')
     153                                *pszDst++ = '\\';
     154                            *pszDst++ = ch;
     155                        }
     156                        else
     157                        {
     158                            fprintf(stderr, "kmk_builtin: Unbalanced quote in argument %d: %s\n", argc, pszSrcStart);
     159                            rc = 1;
     160                            break;
     161                        }
     162                    }
     163                }
     164                else
     165                    chQuote = 0;
     166            } while ((ch = *pszCmd++) != '\0');
     167        }
     168        else
     169        {
     170            /*
     171             * Old style in case we ever need it.
     172             */
     173            ch = *pszCmd++;
     174            if (ch != '"' && ch != '\'')
     175            {
     176                do
     177                    *pszDst++ = ch;
     178                while ((ch = *pszCmd++) != '\0' && !isspace(ch));
     179            }
     180            else
     181            {
     182                chQuote = ch;
     183                for (;;)
     184                {
     185                    char *pszEnd = strchr(pszCmd, chQuote);
     186                    if (pszEnd)
     187                    {
     188                        fprintf(stderr, "kmk_builtin: Unbalanced quote in argument %d: %s\n", argc, pszSrcStart);
     189                        rc = 1;
     190                        break;
     191                    }
     192                    memcpy(pszDst, pszCmd, pszEnd - pszCmd);
     193                    pszDst += pszEnd - pszCmd;
     194                    if (pszEnd[1] != chQuote)
     195                        break;
     196                    *pszDst++ = chQuote;
     197                }
     198            }
     199        }
     200        *pszDst++ = '\0';
     201
     202        /*
     203         * Skip argument separators (IFS=space() for now).  Check for EOS.
     204         */
     205        if (ch != 0)
     206            while ((ch = *pszCmd) && isspace(ch))
     207                pszCmd++;
     208        if (ch == 0)
    123209            break;
    124         }
    125         memcpy(argv[argc], pszCmd, cch);
    126         argv[argc][cch] = '\0';
    127 
    128         /* unescape quotes? */
    129         if (fEscaped)
    130         {
    131             char ch = pszCmd[-1];
    132             char *pszW = argv[argc];
    133             char *pszR = argv[argc];
    134             while (*pszR)
    135             {
    136                 if (*pszR == ch)
    137                     pszR++;
    138                 *pszW++ = *pszR++;
    139             }
    140             *pszW = '\0';
    141         }
    142         /* commit it */
    143         argv[++argc] = NULL;
    144 
    145         /*
    146          * Next
    147          */
    148         pszCmd = pszNext;
    149         while (isspace(*pszCmd) && *pszCmd)
    150             pszCmd++;
    151     }
     210    } while (rc == 0);
    152211
    153212    /*
    154213     * Execute the command if parsing was successful.
    155214     */
    156     if (!*pszCmd)
     215    if (rc == 0)
    157216        rc = kmk_builtin_command_parsed(argc, argv, pChild, ppapszArgvToSpawn, pPidSpawned);
    158     else
    159         rc = 1;
    160217
    161218    /* clean up and return. */
    162     while (argc--)
    163         free(argv[argc]);
    164219    free(argv);
     220    free(pszzCmd);
    165221    return rc;
    166222}
     
    178234    if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
    179235    {
    180         printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
     236        fprintf(stderr, "kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
    181237        return 1;
    182238    }
     
    241297    else
    242298    {
    243         printf("kmk_builtin: Unknown command '%s'!\n", pszCmd);
     299        fprintf(stderr, "kmk_builtin: Unknown command '%s'!\n", pszCmd);
    244300        return 1;
    245301    }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette