Changeset 3168 for trunk/src/kmk/kmkbuiltin.c
- Timestamp:
- Mar 21, 2018, 1:04:56 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin.c
r3059 r3168 223 223 224 224 225 /** 226 * kmk built command. 227 */ 228 static 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 225 281 int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned) 226 282 { 227 const char *pszCmd = argv[0];228 int iUmask;229 int rc;230 231 283 /* 232 284 * Check and skip the prefix. 233 285 */ 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 236 369 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; 338 371 } 339 372 373 #ifndef KBUILD_OS_WINDOWS 374 /** Dummy. */ 375 int 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.