Changeset 3168 for trunk/src


Ignore:
Timestamp:
Mar 21, 2018, 1:04:56 AM (7 years ago)
Author:
bird
Message:

kmkbuiltin.c: Prepping for async builtin command execution in threads on windows.

File:
1 edited

Legend:

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

    r3059 r3168  
    223223
    224224
     225/**
     226 * kmk built command.
     227 */
     228static struct KMKBUILTINENTRY
     229{
     230    const char *pszName;
     231    size_t      cchName;
     232    union
     233    {
     234        uintptr_t uPfn;
     235#define FN_SIG_MAIN             0
     236        int (* pfnMain)(int argc, char **argv, char **envp);
     237#define FN_SIG_MAIN_SPAWNS      1
     238        int (* pfnMainSpawns)(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPid);
     239#define FN_SIG_MAIN_TO_SPAWN    2
     240        int (* pfnMainToSpawn)(int argc, char **argv, char **envp, char ***ppapszArgvToSpawn);
     241    } u;
     242    size_t      uFnSignature : 8;
     243    size_t      fMpSafe : 1;
     244    size_t      fNeedEnv : 1;
     245} const g_aBuiltins[] =
     246{
     247#define BUILTIN_ENTRY(a_fn, a_uFnSignature, fMpSafe, fNeedEnv) \
     248    { &(#a_fn)[12], sizeof(#a_fn) - 12 - 1, \
     249       (uintptr_t)a_fn,                     a_uFnSignature,  fMpSafe, fNeedEnv }
     250
     251    /* More frequently used commands: */
     252    BUILTIN_ENTRY(kmk_builtin_append,       FN_SIG_MAIN,            0, 0),
     253    BUILTIN_ENTRY(kmk_builtin_printf,       FN_SIG_MAIN,            0, 0),
     254    BUILTIN_ENTRY(kmk_builtin_echo,         FN_SIG_MAIN,            0, 0),
     255    BUILTIN_ENTRY(kmk_builtin_install,      FN_SIG_MAIN,            0, 0),
     256    BUILTIN_ENTRY(kmk_builtin_kDepObj,      FN_SIG_MAIN,            0, 0),
     257#ifdef KBUILD_OS_WINDOWS
     258    BUILTIN_ENTRY(kmk_builtin_kSubmit,      FN_SIG_MAIN_SPAWNS,     0, 0),
     259#endif
     260    BUILTIN_ENTRY(kmk_builtin_mkdir,        FN_SIG_MAIN,            0, 0),
     261    BUILTIN_ENTRY(kmk_builtin_mv,           FN_SIG_MAIN,            0, 0),
     262    BUILTIN_ENTRY(kmk_builtin_redirect,     FN_SIG_MAIN_SPAWNS,     0, 0),
     263    BUILTIN_ENTRY(kmk_builtin_rm,           FN_SIG_MAIN,            0, 0),
     264    BUILTIN_ENTRY(kmk_builtin_rmdir,        FN_SIG_MAIN,            0, 0),
     265    BUILTIN_ENTRY(kmk_builtin_test,         FN_SIG_MAIN_TO_SPAWN,   0, 0),
     266    /* Less frequently used commands: */
     267    BUILTIN_ENTRY(kmk_builtin_kDepIDB,      FN_SIG_MAIN,            0, 0),
     268    BUILTIN_ENTRY(kmk_builtin_chmod,        FN_SIG_MAIN,            0, 0),
     269    BUILTIN_ENTRY(kmk_builtin_cp,           FN_SIG_MAIN,            0, 0),
     270    BUILTIN_ENTRY(kmk_builtin_expr,         FN_SIG_MAIN,            0, 0),
     271    BUILTIN_ENTRY(kmk_builtin_ln,           FN_SIG_MAIN,            0, 0),
     272    BUILTIN_ENTRY(kmk_builtin_md5sum,       FN_SIG_MAIN,            0, 0),
     273    BUILTIN_ENTRY(kmk_builtin_cmp,          FN_SIG_MAIN,            0, 0),
     274    BUILTIN_ENTRY(kmk_builtin_cat,          FN_SIG_MAIN,            0, 0),
     275    BUILTIN_ENTRY(kmk_builtin_touch,        FN_SIG_MAIN,            0, 0),
     276    BUILTIN_ENTRY(kmk_builtin_sleep,        FN_SIG_MAIN,            0, 0),
     277    BUILTIN_ENTRY(kmk_builtin_dircache,     FN_SIG_MAIN,            0, 0),
     278};
     279
     280
    225281int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
    226282{
    227     const char *pszCmd = argv[0];
    228     int         iUmask;
    229     int         rc;
    230 
    231283    /*
    232284     * Check and skip the prefix.
    233285     */
    234     if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
    235     {
     286    static const char s_szPrefix[] = "kmk_builtin_";
     287    const char *pszCmd = argv[0];
     288    if (strncmp(pszCmd, s_szPrefix, sizeof(s_szPrefix) - 1) == 0)
     289    {
     290        struct KMKBUILTINENTRY const *pEntry;
     291        size_t cchCmd;
     292        char ch0;
     293        int  cLeft;
     294
     295        pszCmd += sizeof(s_szPrefix) - 1;
     296
     297        /*
     298         * Look up the builtin command in the table.
     299         */
     300        cchCmd  = strlen(pszCmd);
     301        ch0     = *pszCmd;
     302        pEntry  = &g_aBuiltins[0];
     303        cLeft   = sizeof(g_aBuiltins) / sizeof(g_aBuiltins[0]);
     304        while (cLeft-- > 0)
     305            if (   *pEntry->pszName != ch0
     306                || pEntry->cchName != cchCmd
     307                || memcmp(pEntry->pszName, pszCmd, cchCmd) != 0)
     308                pEntry++;
     309            else
     310            {
     311                int rc;
     312#if defined(KBUILD_OS_WINDOWS) && CONFIG_NEW_WIN_CHILDREN
     313                if (pEntry->fMpSafe)
     314                {
     315                    rc = 98;
     316                }
     317                else
     318#endif
     319                {
     320                    char **envp = environ; /** @todo fixme? */
     321
     322                    /*
     323                     * Call the worker function, making sure to preserve umask.
     324                     */
     325                    int const iUmask = umask(0);        /* save umask */
     326                    umask(iUmask);
     327
     328                    if (pEntry->uFnSignature == FN_SIG_MAIN)
     329                        rc = pEntry->u.pfnMain(argc, argv, envp);
     330                    else if (pEntry->uFnSignature == FN_SIG_MAIN_SPAWNS)
     331                        rc = pEntry->u.pfnMainSpawns(argc, argv, envp, pChild, pPidSpawned);
     332                    else if (pEntry->uFnSignature == FN_SIG_MAIN_TO_SPAWN)
     333                    {
     334                        /*
     335                         * When we got something to execute, check if the child is a kmk_builtin thing.
     336                         * We recurse here, both because I'm lazy and because it's easier to debug a
     337                         * problem then (the call stack shows what's been going on).
     338                         */
     339                        rc = pEntry->u.pfnMainToSpawn(argc, argv, envp, ppapszArgvToSpawn);
     340                        if (   !rc
     341                            && *ppapszArgvToSpawn
     342                            && !strncmp(**ppapszArgvToSpawn, s_szPrefix, sizeof(s_szPrefix) - 1))
     343                        {
     344                            char **argv_new = *ppapszArgvToSpawn;
     345                            int argc_new = 1;
     346                            while (argv_new[argc_new])
     347                              argc_new++;
     348
     349                            assert(argv_new[0] != argv[0]);
     350                            assert(!*pPidSpawned);
     351
     352                            *ppapszArgvToSpawn = NULL;
     353                            rc = kmk_builtin_command_parsed(argc_new, argv_new, pChild, ppapszArgvToSpawn, pPidSpawned);
     354
     355                            free(argv_new[0]);
     356                            free(argv_new);
     357                        }
     358                    }
     359                    else
     360                        rc = 99;
     361                    g_progname = "kmk";                 /* paranoia, make sure it's not pointing at a freed argv[0]. */
     362                    umask(iUmask);                      /* restore it */
     363                }
     364                return rc;
     365            }
     366        fprintf(stderr, "kmk_builtin: Unknown command '%s%s'!\n", s_szPrefix, pszCmd);
     367    }
     368    else
    236369        fprintf(stderr, "kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
    237         return 1;
    238     }
    239     pszCmd += sizeof("kmk_builtin_") - 1;
    240 
    241     /*
    242      * String switch on the command (frequent stuff at the top).
    243      */
    244     iUmask = umask(0);
    245     umask(iUmask);
    246     if (!strcmp(pszCmd, "append"))
    247         rc = kmk_builtin_append(argc, argv, environ);
    248     else if (!strcmp(pszCmd, "printf"))
    249         rc = kmk_builtin_printf(argc, argv, environ);
    250     else if (!strcmp(pszCmd, "echo"))
    251         rc = kmk_builtin_echo(argc, argv, environ);
    252     else if (!strcmp(pszCmd, "install"))
    253         rc = kmk_builtin_install(argc, argv, environ);
    254     else if (!strcmp(pszCmd, "kDepIDB"))
    255         rc = kmk_builtin_kDepIDB(argc, argv, environ);
    256 #ifdef KBUILD_OS_WINDOWS
    257     else if (!strcmp(pszCmd, "kSubmit"))
    258         rc = kmk_builtin_kSubmit(argc, argv, environ, pChild, pPidSpawned);
    259 #endif
    260     else if (!strcmp(pszCmd, "mkdir"))
    261         rc = kmk_builtin_mkdir(argc, argv, environ);
    262     else if (!strcmp(pszCmd, "mv"))
    263         rc = kmk_builtin_mv(argc, argv, environ);
    264     else if (!strcmp(pszCmd, "redirect"))
    265         rc = kmk_builtin_redirect(argc, argv, environ, pChild, pPidSpawned);
    266     else if (!strcmp(pszCmd, "rm"))
    267         rc = kmk_builtin_rm(argc, argv, environ);
    268     else if (!strcmp(pszCmd, "rmdir"))
    269         rc = kmk_builtin_rmdir(argc, argv, environ);
    270     else if (!strcmp(pszCmd, "test"))
    271         rc = kmk_builtin_test(argc, argv, environ, ppapszArgvToSpawn);
    272     /* rarely used commands: */
    273     else if (!strcmp(pszCmd, "kDepObj"))
    274         rc = kmk_builtin_kDepObj(argc, argv, environ);
    275     else if (!strcmp(pszCmd, "chmod"))
    276         rc = kmk_builtin_chmod(argc, argv, environ);
    277     else if (!strcmp(pszCmd, "cp"))
    278         rc = kmk_builtin_cp(argc, argv, environ);
    279     else if (!strcmp(pszCmd, "expr"))
    280         rc = kmk_builtin_expr(argc, argv, environ);
    281     else if (!strcmp(pszCmd, "ln"))
    282         rc = kmk_builtin_ln(argc, argv, environ);
    283     else if (!strcmp(pszCmd, "md5sum"))
    284         rc = kmk_builtin_md5sum(argc, argv, environ);
    285     else if (!strcmp(pszCmd, "cmp"))
    286         rc = kmk_builtin_cmp(argc, argv, environ);
    287     else if (!strcmp(pszCmd, "cat"))
    288         rc = kmk_builtin_cat(argc, argv, environ);
    289     else if (!strcmp(pszCmd, "touch"))
    290         rc = kmk_builtin_touch(argc, argv, environ);
    291     else if (!strcmp(pszCmd, "sleep"))
    292         rc = kmk_builtin_sleep(argc, argv, environ);
    293     else if (!strcmp(pszCmd, "dircache"))
    294 #ifdef KBUILD_OS_WINDOWS
    295         rc = kmk_builtin_dircache(argc, argv, environ);
    296 #else
    297         rc = 0;
    298 #endif
    299     else
    300     {
    301         fprintf(stderr, "kmk_builtin: Unknown command '%s'!\n", pszCmd);
    302         return 1;
    303     }
    304 
    305     /*
    306      * Cleanup.
    307      */
    308     g_progname = "kmk";                 /* paranoia, make sure it's not pointing at a freed argv[0]. */
    309     umask(iUmask);
    310 
    311 
    312     /*
    313      * If we've executed a conditional test or something that wishes to execute
    314      * some child process, check if the child is a kmk_builtin thing. We recurse
    315      * here, both because I'm lazy and because it's easier to debug a problem then
    316      * (the call stack shows what's been going on).
    317      */
    318     if (    !rc
    319         &&  *ppapszArgvToSpawn
    320         &&  !strncmp(**ppapszArgvToSpawn, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
    321     {
    322         char **argv_new = *ppapszArgvToSpawn;
    323         int argc_new = 1;
    324         while (argv_new[argc_new])
    325           argc_new++;
    326 
    327         assert(argv_new[0] != argv[0]);
    328         assert(!*pPidSpawned);
    329 
    330         *ppapszArgvToSpawn = NULL;
    331         rc = kmk_builtin_command_parsed(argc_new, argv_new, pChild, ppapszArgvToSpawn, pPidSpawned);
    332 
    333         free(argv_new[0]);
    334         free(argv_new);
    335     }
    336 
    337     return rc;
     370    return 1;
    338371}
    339372
     373#ifndef KBUILD_OS_WINDOWS
     374/** Dummy. */
     375int kmk_builtin_dircache(int argc, char **argv, char **envp)
     376{
     377    (void)argc; (void)argv; (void)envp;
     378    return 0;
     379}
     380#endif
     381
Note: See TracChangeset for help on using the changeset viewer.