VirtualBox

Changeset 3039 in kBuild


Ignore:
Timestamp:
May 10, 2017 10:55:51 AM (8 years ago)
Author:
bird
Message:

kmk_redirect,kmk_kSubmit: Added --append <var=value> and --prepend <var=value> options for modifying the environment (e.g. PATH).

Location:
trunk/src/kmk
Files:
4 edited

Legend:

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

    r2912 r3039  
    7878extern int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
    7979                             int cVerbosity, const char *pszValue);
     80extern int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     81                                int cVerbosity, const char *pszValue);
     82extern int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     83                                 int cVerbosity, const char *pszValue);
    8084extern int kBuiltinOptEnvUnset(char **papszEnv, unsigned *pcEnvVars, int cVerbosity, const char *pszVarToRemove);
    8185extern int kBuiltinOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue);
  • trunk/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c

    r2912 r3039  
    4646
    4747/**
     48 * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that adds
     49 * a new variable to the environment.
     50 *
     51 * @returns 0 on success, non-zero exit code on error.
     52 * @param   papszEnv            The environment vector.
     53 * @param   pcEnvVars           Pointer to the variable holding the number of
     54 *                              environment variables held by @a papszEnv.
     55 * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
     56 *                              environment vector.
     57 * @param   cVerbosity          The verbosity level.
     58 * @param   pszValue            The var=value string to apply.
     59 */
     60static int kBuiltinOptEnvAddVar(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     61                                int cVerbosity, const char *pszValue)
     62{
     63    /* Append new variable. We probably need to resize the vector. */
     64    char   **papszEnv = *ppapszEnv;
     65    unsigned cEnvVars = *pcEnvVars;
     66    if ((cEnvVars + 2) > *pcAllocatedEnvVars)
     67    {
     68        *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
     69        papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
     70        if (!papszEnv)
     71            return errx(1, "out of memory!");
     72        *ppapszEnv = papszEnv;
     73    }
     74    papszEnv[cEnvVars] = strdup(pszValue);
     75    if (!papszEnv[cEnvVars])
     76        return errx(1, "out of memory!");
     77    papszEnv[++cEnvVars]   = NULL;
     78    *pcEnvVars = cEnvVars;
     79    if (cVerbosity > 0)
     80        warnx("added '%s'", papszEnv[cEnvVars - 1]);
     81    return 0;
     82}
     83
     84
     85/**
     86 * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that
     87 * remove duplicates.
     88 *
     89 * @returns 0 on success, non-zero exit code on error.
     90 * @param   papszEnv            The environment vector.
     91 * @param   cEnvVars            Number of environment variables.
     92 * @param   cVerbosity          The verbosity level.
     93 * @param   pszValue            The var=value string to apply.
     94 * @param   cchVar              The length of the variable part of @a pszValue.
     95 * @param   iEnvVar             Where to start searching after.
     96 */
     97static int kBuiltinOptEnvRemoveDuplicates(char **papszEnv, unsigned cEnvVars, int cVerbosity,
     98                                          const char *pszValue, size_t cchVar, unsigned iEnvVar)
     99{
     100    for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
     101        if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
     102            && papszEnv[iEnvVar][cchVar] == '=')
     103        {
     104            if (cVerbosity > 0)
     105                warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
     106            free(papszEnv[iEnvVar]);
     107            cEnvVars--;
     108            if (iEnvVar != cEnvVars)
     109                papszEnv[iEnvVar] = papszEnv[cEnvVars];
     110            papszEnv[cEnvVars] = NULL;
     111            iEnvVar--;
     112        }
     113    return 0;
     114}
     115
     116
     117/**
    48118 * Handles the --set var=value option.
    49119 *
    50120 * @returns 0 on success, non-zero exit code on error.
    51  * @param   papszEnv            The environment vector.
     121 * @param   ppapszEnv           The environment vector pointer.
    52122 * @param   pcEnvVars           Pointer to the variable holding the number of
    53123 *                              environment variables held by @a papszEnv.
     
    78148                if (!papszEnv[iEnvVar])
    79149                    return errx(1, "out of memory!");
    80                 break;
    81             }
    82         }
    83         if (iEnvVar == cEnvVars)
    84         {
    85             /* Append new variable. We probably need to resize the vector. */
    86             if ((cEnvVars + 2) > *pcAllocatedEnvVars)
    87             {
    88                 *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
    89                 papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
    90                 if (!papszEnv)
     150
     151                return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
     152            }
     153        }
     154        return kBuiltinOptEnvAddVar(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);
     155    }
     156    return errx(1, "Missing '=': -E %s", pszValue);
     157}
     158
     159
     160/**
     161 * Common worker for kBuiltinOptEnvAppend and kBuiltinOptEnvPrepend.
     162 *
     163 * @returns 0 on success, non-zero exit code on error.
     164 * @param   ppapszEnv           The environment vector pointer.
     165 * @param   pcEnvVars           Pointer to the variable holding the number of
     166 *                              environment variables held by @a papszEnv.
     167 * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
     168 *                              environment vector.
     169 * @param   cVerbosity          The verbosity level.
     170 * @param   pszValue            The var=value string to apply.
     171 */
     172static int kBuiltinOptEnvAppendPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     173                                       int cVerbosity, const char *pszValue, int fAppend)
     174{
     175    const char *pszEqual = strchr(pszValue, '=');
     176    if (pszEqual)
     177    {
     178        char   **papszEnv = *ppapszEnv;
     179        unsigned iEnvVar;
     180        unsigned cEnvVars = *pcEnvVars;
     181        size_t const cchVar = pszEqual - pszValue;
     182        for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
     183        {
     184            char *pszCur = papszEnv[iEnvVar];
     185            if (   KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 0
     186                && pszCur[cchVar] == '=')
     187            {
     188                size_t cchOldValue = strlen(papszEnv[iEnvVar]) - cchVar - 1;
     189                size_t cchNewValue = strlen(pszValue)          - cchVar - 1;
     190                char *pszNew = malloc(cchVar + 1 + cchOldValue + cchNewValue);
     191                if (!papszEnv[iEnvVar])
    91192                    return errx(1, "out of memory!");
    92                 *ppapszEnv = papszEnv;
    93             }
    94             papszEnv[cEnvVars] = strdup(pszValue);
    95             if (!papszEnv[cEnvVars])
    96                 return errx(1, "out of memory!");
    97             papszEnv[++cEnvVars]   = NULL;
    98             *pcEnvVars = cEnvVars;
    99             if (cVerbosity > 0)
    100                 warnx("added '%s'", papszEnv[iEnvVar]);
    101         }
    102         else
    103         {
    104             /* Check for duplicates. */
    105             for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
    106                 if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
    107                     && papszEnv[iEnvVar][cchVar] == '=')
     193                if (fAppend)
    108194                {
    109                     if (cVerbosity > 0)
    110                         warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
    111                     free(papszEnv[iEnvVar]);
    112                     cEnvVars--;
    113                     if (iEnvVar != cEnvVars)
    114                         papszEnv[iEnvVar] = papszEnv[cEnvVars];
    115                     papszEnv[cEnvVars] = NULL;
    116                     iEnvVar--;
     195                    memcpy(pszNew, papszEnv[iEnvVar], cchVar + 1 + cchOldValue);
     196                    memcpy(&pszNew[cchVar + 1 + cchOldValue], &pszValue[cchVar + 1], cchNewValue + 1);
    117197                }
    118         }
    119     }
    120     else
    121         return errx(1, "Missing '=': -E %s", pszValue);
    122 
    123     return 0;
     198                else
     199                {
     200                    memcpy(pszNew, papszEnv[iEnvVar], cchVar + 1); /* preserve variable name case  */
     201                    memcpy(&pszNew[cchVar + 1], &pszValue[cchVar + 1], cchNewValue);
     202                    memcpy(&pszNew[cchVar + 1 + cchNewValue], &papszEnv[iEnvVar][cchVar + 1], cchOldValue + 1);
     203                }
     204
     205                if (cVerbosity > 0)
     206                    warnx("replacing '%s' with '%s'", papszEnv[iEnvVar], pszNew);
     207                free(papszEnv[iEnvVar]);
     208                papszEnv[iEnvVar] = pszNew;
     209
     210                return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
     211            }
     212        }
     213        return kBuiltinOptEnvAddVar(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);
     214    }
     215    return errx(1, "Missing '=': -E %s", pszValue);
     216}
     217
     218
     219/**
     220 * Handles the --append var=value option.
     221 *
     222 * @returns 0 on success, non-zero exit code on error.
     223 * @param   ppapszEnv           The environment vector pointer.
     224 * @param   pcEnvVars           Pointer to the variable holding the number of
     225 *                              environment variables held by @a papszEnv.
     226 * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
     227 *                              environment vector.
     228 * @param   cVerbosity          The verbosity level.
     229 * @param   pszValue            The var=value string to apply.
     230 */
     231int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
     232{
     233    return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 1 /*fAppend*/);
     234}
     235
     236
     237/**
     238 * Handles the --prepend var=value option.
     239 *
     240 * @returns 0 on success, non-zero exit code on error.
     241 * @param   ppapszEnv           The environment vector pointer.
     242 * @param   pcEnvVars           Pointer to the variable holding the number of
     243 *                              environment variables held by @a papszEnv.
     244 * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
     245 *                              environment vector.
     246 * @param   cVerbosity          The verbosity level.
     247 * @param   pszValue            The var=value string to apply.
     248 */
     249int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
     250{
     251    return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 0 /*fAppend*/);
    124252}
    125253
  • trunk/src/kmk/kmkbuiltin/kSubmit.c

    r2959 r3039  
    11691169    fprintf(pOut,
    11701170            "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"
     1171            "           [-A|--append <var=val>] [-D|--prepend <var=val>]\n"
    11711172            "           [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n"
    11721173            "           [-3|--32-bit] [-6|--64-bit] [-v]\n"
     
    11821183            "  -U, --unset <var>\n"
    11831184            "    Removes an environment variable. Position dependent.\n"
     1185            "  -A, --append <var>=<value>\n"
     1186            "    Appends the given value to the environment variable.\n"
     1187            "  -D,--prepend <var>=<value>\n"
     1188            "    Prepends the given value to the environment variable.\n"
    11841189            "  -C, --chdir <dir>\n"
    11851190            "    Specifies the current directory for the program.  Relative paths\n"
     
    12961301                else if (strcmp(pszArg, "set") == 0)
    12971302                    chOpt = 'E';
     1303                else if (strcmp(pszArg, "append") == 0)
     1304                    chOpt = 'A';
     1305                else if (strcmp(pszArg, "prepend") == 0)
     1306                    chOpt = 'D';
    12981307                else if (strcmp(pszArg, "unset") == 0)
    12991308                    chOpt = 'U';
     
    13271336                switch (chOpt)
    13281337                {
     1338                    case 'A':
     1339                    case 'C':
    13291340                    case 'E':
    13301341                    case 'U':
    1331                     case 'C':
     1342                    case 'D':
    13321343                    case 'e':
    13331344                        if (*pszArg != '\0')
     
    13551366                    case 'E':
    13561367                        rcExit = kBuiltinOptEnvSet(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1368                        pChild->environment = papszEnv;
     1369                        if (rcExit == 0)
     1370                            break;
     1371                        return rcExit;
     1372
     1373                    case 'A':
     1374                        rcExit = kBuiltinOptEnvAppend(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1375                        pChild->environment = papszEnv;
     1376                        if (rcExit == 0)
     1377                            break;
     1378                        return rcExit;
     1379
     1380                    case 'D':
     1381                        rcExit = kBuiltinOptEnvPrepend(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    13571382                        pChild->environment = papszEnv;
    13581383                        if (rcExit == 0)
  • trunk/src/kmk/kmkbuiltin/redirect.c

    r3032 r3039  
    11391139                         || strcmp(pszArg, "env") == 0)
    11401140                    chOpt = 'E';
     1141                else if (strcmp(pszArg, "append") == 0)
     1142                    chOpt = 'A';
     1143                else if (strcmp(pszArg, "prepend") == 0)
     1144                    chOpt = 'D';
    11411145                else if (strcmp(pszArg, "unset") == 0)
    11421146                    chOpt = 'U';
     
    11791183             */
    11801184            if (   chOpt == 'E'
     1185                || chOpt == 'A'
     1186                || chOpt == 'D'
    11811187                || chOpt == 'U'
    11821188                || chOpt == 'C'
     
    12711277
    12721278            /*
     1279             * Append or prepend value to and environment variable.
     1280             */
     1281            if (chOpt == 'A' || chOpt == 'D')
     1282            {
     1283#ifdef KBUILD_OS_OS2
     1284                if (   strcmp(pszValue, "BEGINLIBPATH") == 0
     1285                    || strcmp(pszValue, "ENDLIBPATH") == 0
     1286                    || strcmp(pszValue, "LIBPATHSTRICT") == 0)
     1287                    rcExit = errx(2, "error: '%s' cannot currently be appended or prepended to. Please use -E/--set for now.", pszValue);
     1288                else
     1289#endif
     1290                if (chOpt == 'A')
     1291                    rcExit = kBuiltinOptEnvAppend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1292                else
     1293                    rcExit = kBuiltinOptEnvPrepend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1294                continue;
     1295            }
     1296
     1297            /*
    12731298             * Unset environment variable.
    12741299             */
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