Changeset 3192 in kBuild
- Timestamp:
- Mar 26, 2018 8:25:56 PM (7 years ago)
- Location:
- trunk/src
- Files:
-
- 42 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kWorker/Makefile.kmk
r3188 r3192 36 36 kWorker_SOURCES = \ 37 37 kWorker.c \ 38 ../kmk/kmkbuiltin/kDepObj.c 38 ../kmk/kmkbuiltin/kDepObj.c \ 39 ../kmk/kmkbuiltin/err.c 39 40 kWorker_INCS = \ 40 41 ../kmk/ \ -
trunk/src/kWorker/kWorker.c
r3188 r3192 10290 10290 /* Command switch. */ 10291 10291 if (kHlpStrComp(pszCmd, "kDepObj") == 0) 10292 return kmk_builtin_kDepObj(cPostCmdArgs, (char **)papszPostCmdArgs, NULL); 10292 { 10293 KMKBUILTINCTX Ctx = { papszPostCmdArgs[0], NULL }; 10294 return kmk_builtin_kDepObj(cPostCmdArgs, (char **)papszPostCmdArgs, NULL, &Ctx); 10295 } 10293 10296 10294 10297 return kwErrPrintfRc(42 + 5 , "Unknown post command: '%s'\n", pszCmd); -
trunk/src/kmk/Makefile.kmk
r3189 r3192 83 83 endif 84 84 85 # 86 # Template for building standalone built-in utilities. 87 # 88 TEMPLATE_BIN-KMK-BUILTIN = Template for standalone built-in utilies. 89 TEMPLATE_BIN-KMK-BUILTIN_EXTENDS = BIN-KMK 90 TEMPLATE_BIN-KMK-BUILTIN_EXTENDS_BY = appending 91 TEMPLATE_BIN-KMK-BUILTIN_DEFS += KMK_BUILTIN_STANDALONE 92 TEMPLATE_BIN-KMK-BUILTIN_SOURCES += kmkbuiltin/err.c 85 93 86 94 # … … 93 101 kmkmissing_NOINST = 1 94 102 kmkmissing_SOURCES = \ 95 kmkbuiltin/err.c \96 103 kmkbuiltin/fts.c \ 97 104 kmkbuiltin/setmode.c \ … … 328 335 kmkbuiltin/sleep.c \ 329 336 kmkbuiltin/test.c \ 330 kmkbuiltin/touch.c 337 kmkbuiltin/touch.c \ 338 \ 339 kmkbuiltin/err.c 340 331 341 332 342 ## @todo kmkbuiltin/redirect.c … … 364 374 kDepObj \ 365 375 366 kmk_append_TEMPLATE = BIN-KMK 367 kmk_append_DEFS = kmk_builtin_append=main 376 kmk_append_TEMPLATE = BIN-KMK-BUILTIN 368 377 kmk_append_INCS = . 369 378 kmk_append_SOURCES = \ 370 379 kmkbuiltin/append.c 371 380 372 kmk_cat_TEMPLATE = BIN-KMK 373 kmk_cat_DEFS = kmk_builtin_cat=main 381 kmk_cat_TEMPLATE = BIN-KMK-BUILTIN 374 382 kmk_cat_SOURCES = \ 375 383 kmkbuiltin/cat.c 376 384 377 kmk_chmod_TEMPLATE = BIN-KMK 378 kmk_chmod_DEFS = kmk_builtin_chmod=main 385 kmk_chmod_TEMPLATE = BIN-KMK-BUILTIN 379 386 kmk_chmod_SOURCES = \ 380 387 kmkbuiltin/chmod.c 381 388 382 kmk_cmp_TEMPLATE = BIN-KMK 383 kmk_cmp_DEFS = kmk_builtin_cmp=main 389 kmk_cmp_TEMPLATE = BIN-KMK-BUILTIN 384 390 kmk_cmp_SOURCES = \ 385 391 kmkbuiltin/cmp.c \ 386 392 kmkbuiltin/cmp_util.c 387 393 388 kmk_cp_TEMPLATE = BIN-KMK 389 kmk_cp_DEFS = kmk_builtin_cp=main 394 kmk_cp_TEMPLATE = BIN-KMK-BUILTIN 390 395 kmk_cp_SOURCES = \ 391 396 kmkbuiltin/cp.c \ … … 393 398 kmkbuiltin/cmp_util.c 394 399 395 kmk_echo_TEMPLATE = BIN-KMK 396 kmk_echo_DEFS = kmk_builtin_echo=main 400 kmk_echo_TEMPLATE = BIN-KMK-BUILTIN 397 401 kmk_echo_SOURCES = \ 398 402 kmkbuiltin/echo.c 399 403 400 kmk_expr_TEMPLATE = BIN-KMK 401 kmk_expr_DEFS = kmk_builtin_expr=main 404 kmk_expr_TEMPLATE = BIN-KMK-BUILTIN 402 405 kmk_expr_SOURCES = \ 403 406 kmkbuiltin/expr.c 404 407 405 kmk_install_TEMPLATE = BIN-KMK 406 kmk_install_DEFS = kmk_builtin_install=main 408 kmk_install_TEMPLATE = BIN-KMK-BUILTIN 407 409 kmk_install_SOURCES = \ 408 410 kmkbuiltin/install.c 409 411 410 kmk_ln_TEMPLATE = BIN-KMK 411 kmk_ln_DEFS = kmk_builtin_ln=main 412 kmk_ln_TEMPLATE = BIN-KMK-BUILTIN 412 413 kmk_ln_SOURCES = \ 413 414 kmkbuiltin/ln.c 414 415 415 kmk_mkdir_TEMPLATE = BIN-KMK 416 kmk_mkdir_DEFS = kmk_builtin_mkdir=main 416 kmk_mkdir_TEMPLATE = BIN-KMK-BUILTIN 417 417 kmk_mkdir_SOURCES = \ 418 418 kmkbuiltin/mkdir.c 419 419 420 kmk_md5sum_TEMPLATE = BIN-KMK 421 kmk_md5sum_DEFS = kmk_builtin_md5sum=main 420 kmk_md5sum_TEMPLATE = BIN-KMK-BUILTIN 422 421 kmk_md5sum_SOURCES = \ 423 422 kmkbuiltin/md5sum.c 424 423 kmk_md5sum_LIBS = $(LIB_KUTIL) 425 424 426 kmk_mv_TEMPLATE = BIN-KMK 427 kmk_mv_DEFS = kmk_builtin_mv=main 425 kmk_mv_TEMPLATE = BIN-KMK-BUILTIN 428 426 kmk_mv_SOURCES = \ 429 427 kmkbuiltin/mv.c 430 428 431 kmk_printf_TEMPLATE = BIN-KMK 432 kmk_printf_DEFS = kmk_builtin_printf=main 429 kmk_printf_TEMPLATE = BIN-KMK-BUILTIN 433 430 kmk_printf_SOURCES = \ 434 431 kmkbuiltin/printf.c 435 432 436 kmk_rm_TEMPLATE = BIN-KMK 437 kmk_rm_DEFS = kmk_builtin_rm=main 433 kmk_rm_TEMPLATE = BIN-KMK-BUILTIN 438 434 kmk_rm_SOURCES = \ 439 435 kmkbuiltin/rm.c 440 436 441 kmk_redirect_TEMPLATE = BIN-KMK 437 kmk_redirect_TEMPLATE = BIN-KMK-BUILTIN 442 438 kmk_redirect_SOURCES = \ 443 439 kmkbuiltin/redirect.c … … 445 441 ../lib/startuphacks-win.c 446 442 447 kmk_rmdir_TEMPLATE = BIN-KMK 448 kmk_rmdir_DEFS = kmk_builtin_rmdir=main 443 kmk_rmdir_TEMPLATE = BIN-KMK-BUILTIN 449 444 kmk_rmdir_SOURCES = \ 450 445 kmkbuiltin/rmdir.c 451 446 452 kmk_sleep_TEMPLATE = BIN-KMK 453 kmk_sleep_DEFS = kmk_builtin_sleep=main 447 kmk_sleep_TEMPLATE = BIN-KMK-BUILTIN 454 448 kmk_sleep_SOURCES = \ 455 449 kmkbuiltin/sleep.c 456 450 457 kmk_test_TEMPLATE = BIN-KMK 458 kmk_test_DEFS = kmk_builtin_test=main 451 kmk_test_TEMPLATE = BIN-KMK-BUILTIN 459 452 kmk_test_SOURCES = \ 460 453 kmkbuiltin/test.c 461 454 462 kmk_touch_TEMPLATE = BIN-KMK 463 kmk_touch_DEFS = kmk_builtin_touch=main 455 kmk_touch_TEMPLATE = BIN-KMK-BUILTIN 464 456 kmk_touch_SOURCES = \ 465 457 kmkbuiltin/touch.c 466 458 467 kDepIDB_TEMPLATE = BIN-KMK 468 kDepIDB_DEFS = kmk_builtin_kDepIDB=main 459 kDepIDB_TEMPLATE = BIN-KMK-BUILTIN 469 460 kDepIDB_INCS = . 470 461 kDepIDB_LIBS = $(LIB_KDEP) $(LIB_KUTIL) … … 472 463 kmkbuiltin/kDepIDB.c 473 464 474 kDepObj_TEMPLATE = BIN-KMK 475 kDepObj_DEFS = kmk_builtin_kDepObj=main 465 kDepObj_TEMPLATE = BIN-KMK-BUILTIN 476 466 kDepObj_INCS = . 477 467 kDepObj_LIBS = $(LIB_KDEP) $(LIB_KUTIL) -
trunk/src/kmk/dir-nt-bird.c
r3184 r3192 40 40 #endif 41 41 #include <assert.h> 42 #include "kmkbuiltin.h" 43 #include "kmkbuiltin/err.h" 42 44 43 45 #include "nt_fullpath.h" /* for the time being - will be implemented here later on. */ … … 730 732 731 733 732 int kmk_builtin_dircache(int argc, char **argv, char **envp )734 int kmk_builtin_dircache(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 733 735 { 734 736 assert(GetCurrentThreadId() == g_idMainThread); … … 743 745 return 0; 744 746 } 745 fprintf(stderr, "kmk_builtin_dircache:the 'invalidate' command takes no arguments!\n");747 errx(pCtx, 2, "the 'invalidate' command takes no arguments!\n"); 746 748 } 747 749 else if (strcmp(pszCmd, "invalidate-missing") == 0) … … 752 754 return 0; 753 755 } 754 fprintf(stderr, "kmk_builtin_dircache:the 'invalidate-missing' command takes no arguments!\n");756 errx(pCtx, 2, "the 'invalidate-missing' command takes no arguments!\n"); 755 757 } 756 758 else if (strcmp(pszCmd, "volatile") == 0) … … 769 771 } 770 772 else 771 fprintf(stderr, "kmk_builtin_dircache:Invalid command '%s'!\n", pszCmd);772 } 773 else 774 fprintf(stderr, "kmk_builtin_dircache:No command given!\n");773 errx(pCtx, 2, "Invalid command '%s'!\n", pszCmd); 774 } 775 else 776 errx(pCtx, 2, "No command given!\n"); 775 777 776 778 K_NOREF(envp); -
trunk/src/kmk/job.c
r3186 r3192 1481 1481 } 1482 1482 1483 /* We're sure we're going to invoke a command: set up the output. */ 1484 output_start (); 1485 1486 /* Flush the output streams so they won't have things written twice. */ 1487 1488 fflush (stdout); 1489 fflush (stderr); 1490 1483 1491 #ifdef CONFIG_WITH_KMK_BUILTIN 1484 1492 /* If builtin command then pass it on to the builtin shell interpreter. */ … … 1538 1546 } 1539 1547 #endif /* CONFIG_WITH_KMK_BUILTIN */ 1540 1541 /* We're sure we're going to invoke a command: set up the output. */1542 output_start ();1543 1544 /* Flush the output streams so they won't have things written twice. */1545 1546 fflush (stdout);1547 fflush (stderr);1548 1548 1549 1549 /* Decide whether to give this child the 'good' standard input -
trunk/src/kmk/kmkbuiltin.c
r3173 r3192 392 392 big_int nsStart = print_stats_flag ? nano_timestamp() : 0; 393 393 #endif 394 KMKBUILTINCTX Ctx; 394 395 int const iUmask = umask(0); /* save umask */ 395 396 umask(iUmask); 396 397 398 Ctx.pszProgName = pEntry->uName.s.sz; 399 Ctx.pOut = pChild ? &pChild->output : NULL; 400 397 401 if (pEntry->uFnSignature == FN_SIG_MAIN) 398 rc = pEntry->u.pfnMain(argc, argv, papszEnvVars );402 rc = pEntry->u.pfnMain(argc, argv, papszEnvVars, &Ctx); 399 403 else if (pEntry->uFnSignature == FN_SIG_MAIN_SPAWNS) 400 rc = pEntry->u.pfnMainSpawns(argc, argv, papszEnvVars, pChild, pPidSpawned);404 rc = pEntry->u.pfnMainSpawns(argc, argv, papszEnvVars, &Ctx, pChild, pPidSpawned); 401 405 else if (pEntry->uFnSignature == FN_SIG_MAIN_TO_SPAWN) 402 406 { … … 406 410 * problem then (the call stack shows what's been going on). 407 411 */ 408 rc = pEntry->u.pfnMainToSpawn(argc, argv, papszEnvVars, ppapszArgvToSpawn);412 rc = pEntry->u.pfnMainToSpawn(argc, argv, papszEnvVars, &Ctx, ppapszArgvToSpawn); 409 413 if ( !rc 410 414 && *ppapszArgvToSpawn … … 429 433 rc = 99; 430 434 431 g_progname = "kmk"; /* paranoia, make sure it's not pointing at a freed argv[0]. */432 435 umask(iUmask); /* restore it */ 433 436 -
trunk/src/kmk/kmkbuiltin.h
r3173 r3192 34 34 # include <sys/types.h> 35 35 #endif 36 #include <fcntl.h> 36 37 37 38 /* For the GNU/hurd weirdo. */ … … 57 58 #endif 58 59 60 /** This is for telling open() to open to return a close-on-exec descriptor. */ 61 #ifdef _O_NOINHERIT 62 # define KMK_OPEN_NO_INHERIT _O_NOINHERIT 63 #elif defined(O_NOINHERIT) 64 # define KMK_OPEN_NO_INHERIT O_NOINHERIT 65 #elif defined(O_CLOEXEC) 66 # define KMK_OPEN_NO_INHERIT O_CLOEXEC 67 #else 68 # define KMK_OPEN_NO_INHERIT 0 69 #endif 70 71 59 72 #include "kbuild_version.h" 73 #ifndef KMK_BUILTIN_STANDALONE 74 # include "../output.h" 75 #endif 60 76 61 77 struct child; 62 78 int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned); 63 79 int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned); 80 81 82 /** 83 * KMK built-in command execution context. 84 */ 85 typedef struct KMKBUILTINCTX 86 { 87 /** The program name to use in error messages. */ 88 const char *pszProgName; 89 /** The KMK output synchronizer. */ 90 struct output *pOut; 91 } KMKBUILTINCTX; 92 /** Pointer to kmk built-in command execution context. */ 93 typedef KMKBUILTINCTX *PKMKBUILTINCTX; 64 94 65 95 /** … … 81 111 uintptr_t uPfn; 82 112 #define FN_SIG_MAIN 0 83 int (* pfnMain)(int argc, char **argv, char **envp );113 int (* pfnMain)(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 84 114 #define FN_SIG_MAIN_SPAWNS 1 85 int (* pfnMainSpawns)(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPid);115 int (* pfnMainSpawns)(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPid); 86 116 #define FN_SIG_MAIN_TO_SPAWN 2 87 int (* pfnMainToSpawn)(int argc, char **argv, char **envp, char ***ppapszArgvToSpawn);117 int (* pfnMainToSpawn)(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvToSpawn); 88 118 } u; 89 119 size_t uFnSignature : 8; … … 94 124 typedef KMKBUILTINENTRY const *PCKMKBUILTINENTRY; 95 125 96 #ifndef kmk_builtin_append 97 extern int kmk_builtin_append(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned); 98 #endif 99 extern int kmk_builtin_cp(int argc, char **argv, char **envp); 100 extern int kmk_builtin_cat(int argc, char **argv, char **envp); 101 extern int kmk_builtin_chmod(int argc, char **argv, char **envp); 102 extern int kmk_builtin_cmp(int argc, char **argv, char **envp); 103 extern int kmk_builtin_dircache(int argc, char **argv, char **envp); 104 extern int kmk_builtin_echo(int argc, char **argv, char **envp); 105 extern int kmk_builtin_expr(int argc, char **argv, char **envp); 106 extern int kmk_builtin_install(int argc, char **argv, char **envp); 107 extern int kmk_builtin_ln(int argc, char **argv, char **envp); 108 extern int kmk_builtin_md5sum(int argc, char **argv, char **envp); 109 extern int kmk_builtin_mkdir(int argc, char **argv, char **envp); 110 extern int kmk_builtin_mv(int argc, char **argv, char **envp); 111 extern int kmk_builtin_printf(int argc, char **argv, char **envp); 112 extern int kmk_builtin_redirect(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned); 113 extern int kmk_builtin_rm(int argc, char **argv, char **envp); 114 extern int kmk_builtin_rmdir(int argc, char **argv, char **envp); 115 extern int kmk_builtin_sleep(int argc, char **argv, char **envp); 116 extern int kmk_builtin_test(int argc, char **argv, char **envp 117 #ifndef kmk_builtin_test 118 , char ***ppapszArgvSpawn 119 #endif 120 ); 121 extern int kmk_builtin_touch(int argc, char **argv, char **envp); 126 extern int kmk_builtin_append(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned); 127 extern int kmk_builtin_cp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 128 extern int kmk_builtin_cat(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 129 extern int kmk_builtin_chmod(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 130 extern int kmk_builtin_cmp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 131 extern int kmk_builtin_dircache(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 132 extern int kmk_builtin_echo(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 133 extern int kmk_builtin_expr(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 134 extern int kmk_builtin_install(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 135 extern int kmk_builtin_ln(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 136 extern int kmk_builtin_md5sum(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 137 extern int kmk_builtin_mkdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 138 extern int kmk_builtin_mv(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 139 extern int kmk_builtin_printf(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 140 extern int kmk_builtin_redirect(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned); 141 extern int kmk_builtin_rm(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 142 extern int kmk_builtin_rmdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 143 extern int kmk_builtin_sleep(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 144 extern int kmk_builtin_test(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvSpawn); 145 extern int kmk_builtin_touch(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 122 146 #ifdef KBUILD_OS_WINDOWS 123 extern int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned);147 extern int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned); 124 148 extern int kSubmitSubProcGetResult(intptr_t pvUser, int *prcExit, int *piSigNo); 125 149 extern int kSubmitSubProcKill(intptr_t pvUser, int iSignal); 126 150 extern void kSubmitSubProcCleanup(intptr_t pvUser); 127 151 #endif 128 extern int kmk_builtin_kDepIDB(int argc, char **argv, char **envp );129 extern int kmk_builtin_kDepObj(int argc, char **argv, char **envp );152 extern int kmk_builtin_kDepIDB(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 153 extern int kmk_builtin_kDepObj(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx); 130 154 131 155 extern char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname); 132 156 133 157 /* common-env-and-cwd-opt.c: */ 134 extern int kBuiltinOptEnvSet( char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,158 extern int kBuiltinOptEnvSet(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 135 159 int cVerbosity, const char *pszValue); 136 extern int kBuiltinOptEnvAppend( char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,160 extern int kBuiltinOptEnvAppend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 137 161 int cVerbosity, const char *pszValue); 138 extern int kBuiltinOptEnvPrepend( char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,162 extern int kBuiltinOptEnvPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 139 163 int cVerbosity, const char *pszValue); 140 extern int kBuiltinOptEnvUnset(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszVarToRemove); 141 extern int kBuiltinOptEnvZap(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity); 164 extern int kBuiltinOptEnvUnset(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 165 int cVerbosity, const char *pszVarToRemove); 166 extern int kBuiltinOptEnvZap(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 167 int cVerbosity); 142 168 extern void kBuiltinOptEnvCleanup(char ***ppapszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars); 143 extern int kBuiltinOptChDir( char *pszCwd, size_t cbCwdBuf, const char *pszValue);169 extern int kBuiltinOptChDir(PKMKBUILTINCTX pCtx, char *pszCwd, size_t cbCwdBuf, const char *pszValue); 144 170 145 171 #ifdef CONFIG_WITH_KMK_BUILTIN_STATS -
trunk/src/kmk/kmkbuiltin/append.c
r3177 r3192 24 24 */ 25 25 26 /******************************************************************************* 27 * Header Files *28 ******************************************************************************* /29 #ifndef kmk_builtin_append26 /********************************************************************************************************************************* 27 * Header Files * 28 *********************************************************************************************************************************/ 29 #ifndef KMK_BUILTIN_STANDALONE 30 30 # include "makeint.h" 31 31 # include "filedef.h" … … 46 46 # include <alloca.h> 47 47 #endif 48 #if !defined( kmk_builtin_append) && defined(KBUILD_OS_WINDOWS) && defined(CONFIG_NEW_WIN_CHILDREN)48 #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) && defined(CONFIG_NEW_WIN_CHILDREN) 49 49 # include "../w32/winchildren.h" 50 50 #endif … … 173 173 * Appends text to a textfile, creating the textfile if necessary. 174 174 */ 175 #ifndef kmk_builtin_append 176 int kmk_builtin_append(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned) 177 #else 178 int main(int argc, char **argv, char **envp) 179 #endif 175 int kmk_builtin_append(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) 180 176 { 181 177 #if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) … … 195 191 int fVariables = 0; 196 192 int fCommands = 0; 197 #ifndef kmk_builtin_append193 #ifndef KMK_BUILTIN_STANDALONE 198 194 int fLookForInserts = 0; 199 #e ndif200 201 g_progname = argv[0]; 195 #else 196 (void)pChild; (void)pPidSpawned; 197 #endif 202 198 203 199 /* … … 221 217 if (fVariables) 222 218 { 223 errx( 1, "Option '-c' clashes with '-v'.");219 errx(pCtx, 1, "Option '-c' clashes with '-v'."); 224 220 return kmk_builtin_append_usage(argv[0], stderr); 225 221 } 226 #ifndef kmk_builtin_append222 #ifndef KMK_BUILTIN_STANDALONE 227 223 fCommands = 1; 228 224 break; 229 225 #else 230 errx( 1, "Option '-c' isn't supported in external mode.");226 errx(pCtx, 1, "Option '-c' isn't supported in external mode."); 231 227 return kmk_builtin_append_usage(argv[0], stderr); 232 228 #endif … … 234 230 if (fVariables) 235 231 { 236 errx( 1, "Option '-d' must come before '-v'!");232 errx(pCtx, 1, "Option '-d' must come before '-v'!"); 237 233 return kmk_builtin_append_usage(argv[0], stderr); 238 234 } … … 242 238 if (fVariables || fCommands) 243 239 { 244 errx( 1, fVariables ? "Option '-i' clashes with '-v'." : "Option '-i' clashes with '-c'.");240 errx(pCtx, 1, fVariables ? "Option '-i' clashes with '-v'." : "Option '-i' clashes with '-c'."); 245 241 return kmk_builtin_append_usage(argv[0], stderr); 246 242 } 247 #ifndef kmk_builtin_append243 #ifndef KMK_BUILTIN_STANDALONE 248 244 fLookForInserts = 1; 249 245 break; 250 246 #else 251 errx( 1, "Option '-C' isn't supported in external mode.");247 errx(pCtx, 1, "Option '-C' isn't supported in external mode."); 252 248 return kmk_builtin_append_usage(argv[0], stderr); 253 249 #endif … … 264 260 if (fCommands) 265 261 { 266 errx( 1, "Option '-v' clashes with '-c'.");262 errx(pCtx, 1, "Option '-v' clashes with '-c'."); 267 263 return kmk_builtin_append_usage(argv[0], stderr); 268 264 } 269 #ifndef kmk_builtin_append265 #ifndef KMK_BUILTIN_STANDALONE 270 266 fVariables = 1; 271 267 break; 272 268 #else 273 errx( 1, "Option '-v' isn't supported in external mode.");269 errx(pCtx, 1, "Option '-v' isn't supported in external mode."); 274 270 return kmk_builtin_append_usage(argv[0], stderr); 275 271 #endif 276 272 default: 277 errx( 1, "Invalid option '%c'! (%s)", *psz, argv[i]);273 errx(pCtx, 1, "Invalid option '%c'! (%s)", *psz, argv[i]); 278 274 return kmk_builtin_append_usage(argv[0], stderr); 279 275 } … … 300 296 { 301 297 if (i <= argc) 302 errx( 1, "missing filename!");298 errx(pCtx, 1, "missing filename!"); 303 299 else 304 errx( 1, "missing define name!");300 errx(pCtx, 1, "missing define name!"); 305 301 return kmk_builtin_append_usage(argv[0], stderr); 306 302 } … … 334 330 write_to_buf(&OutBuf, STR_TUPLE(" ")); 335 331 } 336 #ifndef kmk_builtin_append332 #ifndef KMK_BUILTIN_STANDALONE 337 333 if (fCommands) 338 334 { … … 417 413 * Write the buffer (unless we ran out of heap already). 418 414 */ 419 #if !defined( kmk_builtin_append) && defined(KBUILD_OS_WINDOWS) && defined(CONFIG_NEW_WIN_CHILDREN)415 #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) && defined(CONFIG_NEW_WIN_CHILDREN) 420 416 if (!OutBuf.fOutOfMemory) 421 417 { 422 418 rc = MkWinChildCreateAppend(pszFilename, &OutBuf.pszBuf, OutBuf.offBuf, fTruncate, pChild, pPidSpawned); 423 419 if (rc != 0) 424 rc = errx( rc, "MkWinChildCreateAppend failed: %u", rc);420 rc = errx(pCtx, rc, "MkWinChildCreateAppend failed: %u", rc); 425 421 if (OutBuf.pszBuf) 426 422 free(OutBuf.pszBuf); … … 440 436 rc = 0; 441 437 else 442 rc = err( 1, "error writing %lu bytes to '%s'", (unsigned long)OutBuf.offBuf, pszFilename);438 rc = err(pCtx, 1, "error writing %lu bytes to '%s'", (unsigned long)OutBuf.offBuf, pszFilename); 443 439 if (close(fd) < 0) 444 rc = err( 1, "error closing '%s'", pszFilename);440 rc = err(pCtx, 1, "error closing '%s'", pszFilename); 445 441 } 446 442 else 447 rc = err( 1, "failed to open '%s'", pszFilename);443 rc = err(pCtx, 1, "failed to open '%s'", pszFilename); 448 444 free(OutBuf.pszBuf); 449 445 } 450 446 else 451 rc = errx( 1, "out of memory for output buffer! (%u needed)", OutBuf.offBuf + 1);447 rc = errx(pCtx, 1, "out of memory for output buffer! (%u needed)", OutBuf.offBuf + 1); 452 448 return rc; 453 449 } 454 450 451 #ifdef KMK_BUILTIN_STANDALONE 452 int main(int argc, char **argv, char **envp) 453 { 454 KMKBUILTINCTX Ctx = { "kmk_append", NULL }; 455 return kmk_builtin_append(argc, argv, envp, &Ctx, NULL, NULL); 456 } 457 #endif 458 -
trunk/src/kmk/kmkbuiltin/cat.c
r3117 r3192 93 93 94 94 95 static int usage( FILE *);96 static int scanfiles( char *argv[], int cooked);97 static int cook_cat( FILE *);98 static int raw_cat( int);95 static int usage(PKMKBUILTINCTX pCtx, int fIsErr); 96 static int scanfiles(PKMKBUILTINCTX pCtx, char *argv[], int cooked); 97 static int cook_cat(PKMKBUILTINCTX pCtx, FILE *); 98 static int raw_cat(PKMKBUILTINCTX pCtx, int); 99 99 100 100 #ifndef NO_UDOM_SUPPORT 101 static int udom_open( const char *path, int flags);101 static int udom_open(PKMKBUILTINCTX pCtx, const char *path, int flags); 102 102 #endif 103 103 104 104 int 105 kmk_builtin_cat(int argc, char * argv[], char **envp)105 kmk_builtin_cat(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 106 106 { 107 107 int ch, rc; … … 112 112 113 113 /* kmk: reset getopt and set progname */ 114 g_progname = argv[0];115 114 opterr = 1; 116 115 optarg = NULL; … … 118 117 optind = 0; /* init */ 119 118 120 #ifdef kmk_builtin_cat/* kmk did this already. */119 #ifdef KMK_BUILTIN_STANDALONE /* kmk did this already. */ 121 120 setlocale(LC_CTYPE, ""); 122 #else123 fflush(stdout);124 121 #endif 125 122 … … 142 139 break; 143 140 case 'u': 141 #ifdef KMK_BUILTIN_STANDALONE /* don't allow messing with stdout */ 144 142 setbuf(stdout, NULL); 143 #endif 145 144 break; 146 145 case 'v': … … 148 147 break; 149 148 case 261: 150 usage( stdout);149 usage(pCtx, 0); 151 150 return 0; 152 151 case 262: 153 152 return kbuild_version(argv[0]); 154 153 default: 155 return usage( stderr);154 return usage(pCtx, 1); 156 155 } 157 156 argv += optind; 158 157 159 158 if (bflag || eflag || nflag || sflag || tflag || vflag) 160 rc = scanfiles( argv, 1);159 rc = scanfiles(pCtx, argv, 1); 161 160 else 162 rc = scanfiles( argv, 0);163 #ifdef kmk_builtin_cat /* only in the external program.*/161 rc = scanfiles(pCtx, argv, 0); 162 #ifdef KMK_BUILTIN_STANDALONE /* don't allow messing with stdout */ 164 163 if (fclose(stdout)) 165 return err( 1, "stdout");164 return err(pCtx, 1, "stdout"); 166 165 #endif 167 166 return rc; 168 167 } 169 168 170 static int 171 usage(FILE *fp) 172 { 173 fprintf(fp, "usage: %s [-benstuv] [file ...]\n" 174 " or: %s --help\n" 175 " or: %s --version\n", 176 g_progname, g_progname, g_progname); 169 #ifdef KMK_BUILTIN_STANDALONE 170 int main(int argc, char **argv, char **envp) 171 { 172 KMKBUILTINCTX Ctx = { "kmk_cat", NULL }; 173 return kmk_builtin_cat(argc, argv, envp, &Ctx); 174 } 175 #endif 176 177 static int 178 usage(PKMKBUILTINCTX pCtx, int fIsErr) 179 { 180 kmk_builtin_ctx_printf(pCtx, fIsErr, 181 "usage: %s [-benstuv] [file ...]\n" 182 " or: %s --help\n" 183 " or: %s --version\n", 184 pCtx->pszProgName, pCtx->pszProgName, 185 pCtx->pszProgName); 177 186 return 1; 178 187 } 179 188 180 189 static int 181 scanfiles( char *argv[], int cooked)190 scanfiles(PKMKBUILTINCTX pCtx, char *argv[], int cooked) 182 191 { 183 192 int i = 0; … … 198 207 #ifndef NO_UDOM_SUPPORT 199 208 if (fd < 0 && errno == EOPNOTSUPP) 200 fd = udom_open(p ath, O_RDONLY);209 fd = udom_open(pCtx, path, O_RDONLY); 201 210 #endif 202 211 } 203 212 if (fd < 0) { 204 warn( "%s", path);213 warn(pCtx, "%s", path); 205 214 rc2 = 1; /* non fatal */ 206 215 } else if (cooked) { 207 216 if (fd == STDIN_FILENO) 208 rc = cook_cat( stdin);217 rc = cook_cat(pCtx, stdin); 209 218 else { 210 219 fp = fdopen(fd, "r"); 211 rc = cook_cat( fp);220 rc = cook_cat(pCtx, fp); 212 221 fclose(fp); 213 222 } 214 223 } else { 215 rc = raw_cat( fd);224 rc = raw_cat(pCtx, fd); 216 225 if (fd != STDIN_FILENO) 217 226 close(fd); … … 224 233 } 225 234 226 static int 227 cook_cat(FILE *fp) 235 static int cat_putchar(PKMKBUILTINCTX pCtx, char ch) 236 { 237 #ifndef KMK_BUILTIN_STANDALONE 238 if (pCtx->pOut) { 239 output_write_text(pCtx->pOut, 0, &ch, 1); 240 return 0; 241 } 242 #endif 243 return putchar(ch); 244 } 245 246 static int 247 cook_cat(PKMKBUILTINCTX pCtx, FILE *fp) 228 248 { 229 249 int ch, gobble, line, prev; … … 246 266 } 247 267 if (nflag && (!bflag || ch != '\n')) { 248 (void)fprintf(stdout, "%6d\t", ++line);268 kmk_builtin_ctx_printf(pCtx, 0, "%6d\t", ++line); 249 269 if (ferror(stdout)) 250 270 break; … … 252 272 } 253 273 if (ch == '\n') { 254 if (eflag && putchar('$') == EOF)274 if (eflag && cat_putchar(pCtx, '$') == EOF) 255 275 break; 256 276 } else if (ch == '\t') { 257 277 if (tflag) { 258 if ( putchar('^') == EOF || putchar('I') == EOF)278 if (cat_putchar(pCtx, '^') == EOF || cat_putchar(pCtx, 'I') == EOF) 259 279 break; 260 280 continue; … … 262 282 } else if (vflag) { 263 283 if (!isascii(ch) && !isprint(ch)) { 264 if ( putchar('M') == EOF || putchar('-') == EOF)284 if (cat_putchar(pCtx, 'M') == EOF || cat_putchar(pCtx, '-') == EOF) 265 285 break; 266 286 ch = toascii(ch); 267 287 } 268 288 if (iscntrl(ch)) { 269 if ( putchar('^') == EOF ||270 putchar(ch == '\177' ? '?' :289 if (cat_putchar(pCtx, '^') == EOF || 290 cat_putchar(pCtx, ch == '\177' ? '?' : 271 291 ch | 0100) == EOF) 272 292 break; … … 274 294 } 275 295 } 276 if ( putchar(ch) == EOF)296 if (cat_putchar(pCtx, ch) == EOF) 277 297 break; 278 298 } 279 299 if (ferror(fp)) { 280 warn( "%s", filename);300 warn(pCtx, "%s", filename); 281 301 rc = 1; 282 302 clearerr(fp); 283 303 } 284 304 if (ferror(stdout)) 285 return err( 1, "stdout");305 return err(pCtx, 1, "stdout"); 286 306 return rc; 287 307 } 288 308 289 309 static int 290 raw_cat( int rfd)310 raw_cat(PKMKBUILTINCTX pCtx, int rfd) 291 311 { 292 312 int off, wfd = fileno(stdout); … … 299 319 if (buf == NULL) { 300 320 if (fstat(wfd, &sbuf)) 301 return err( 1, "%s", filename);321 return err(pCtx, 1, "%s", filename); 302 322 #ifdef KBUILD_OS_WINDOWS 303 323 bsize = 16384; … … 306 326 #endif 307 327 if ((buf = malloc(bsize)) == NULL) 308 return err( 1, "buffer");328 return err(pCtx, 1, "buffer"); 309 329 } 310 330 while ((nr = read(rfd, buf, bsize)) > 0) 311 for (off = 0; nr; nr -= nw, off += nw) 312 if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 313 return err(1, "stdout"); 331 for (off = 0; nr; nr -= nw, off += nw) { 332 #ifndef KMK_BUILTIN_STANDALONE 333 if (pCtx->pOut) 334 nw = output_write_text(pCtx->pOut, 0, buf, nr); 335 else 336 #endif 337 nw = write(wfd, buf + off, (size_t)nr); 338 if (nw < 0) 339 return err(pCtx, 1, "stdout"); 340 } 314 341 if (nr < 0) { 315 warn( "%s", filename);342 warn(pCtx, "%s", filename); 316 343 return 1; 317 344 } … … 322 349 323 350 static int 324 udom_open( const char *path, int flags)351 udom_open(PKMKBUILTINCTX pCtx, const char *path, int flags) 325 352 { 326 353 struct sockaddr_un sou; … … 356 383 case O_RDONLY: 357 384 if (shutdown(fd, SHUT_WR) == -1) 358 warn( NULL);385 warn(pCtx, NULL); 359 386 break; 360 387 case O_WRONLY: 361 388 if (shutdown(fd, SHUT_RD) == -1) 362 warn( NULL);389 warn(pCtx, NULL); 363 390 break; 364 391 default: … … 370 397 371 398 #endif 399 -
trunk/src/kmk/kmkbuiltin/chmod.c
r3148 r3192 75 75 #endif 76 76 77 static int usage( FILE *);77 static int usage(PKMKBUILTINCTX pCtx, int is_err); 78 78 79 79 static struct option long_options[] = … … 86 86 87 87 int 88 kmk_builtin_chmod(int argc, char *argv[], char **envp )88 kmk_builtin_chmod(int argc, char *argv[], char **envp, PKMKBUILTINCTX pCtx) 89 89 { 90 90 FTS *ftsp; … … 98 98 99 99 /* kmk: reset getopt and set progname */ 100 g_progname = argv[0];101 100 opterr = 1; 102 101 optarg = NULL; … … 153 152 break; 154 153 case 261: 155 usage( stdout);154 usage(pCtx, 0); 156 155 return 0; 157 156 case 262: … … 159 158 case '?': 160 159 default: 161 return usage( stderr);160 return usage(pCtx, 1); 162 161 } 163 162 done: argv += optind; … … 165 164 166 165 if (argc < 2) 167 return usage( stderr);166 return usage(pCtx, 1); 168 167 169 168 if (Rflag) { 170 169 fts_options = FTS_PHYSICAL; 171 170 if (hflag) 172 return errx( 1,171 return errx(pCtx, 1, 173 172 "the -R and -h options may not be specified together."); 174 173 if (Hflag) … … 188 187 mode = *argv; 189 188 if ((set = bsd_setmode(mode)) == NULL) 190 return errx( 1, "invalid file mode: %s", mode);189 return errx(pCtx, 1, "invalid file mode: %s", mode); 191 190 192 191 if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) 193 return err( 1, "fts_open");192 return err(pCtx, 1, "fts_open"); 194 193 for (rval = 0; (p = fts_read(ftsp)) != NULL;) { 195 194 switch (p->fts_info) { … … 199 198 continue; 200 199 case FTS_DNR: /* Warn, chmod, continue. */ 201 warnx( "fts: %s: %s", p->fts_path, strerror(p->fts_errno));200 warnx(pCtx, "fts: %s: %s", p->fts_path, strerror(p->fts_errno)); 202 201 rval = 1; 203 202 break; 204 203 case FTS_ERR: /* Warn, continue. */ 205 204 case FTS_NS: 206 warnx( "fts: %s: %s", p->fts_path, strerror(p->fts_errno));205 warnx(pCtx, "fts: %s: %s", p->fts_path, strerror(p->fts_errno)); 207 206 rval = 1; 208 207 continue; … … 225 224 continue; 226 225 if ((*change_mode)(p->fts_accpath, newmode) && !fflag) { 227 warn( "%schmod: %s", hflag ? "l" : "", p->fts_path);226 warn(pCtx, "%schmod: %s", hflag ? "l" : "", p->fts_path); 228 227 rval = 1; 229 228 } else { 230 229 if (vflag) { 231 (void)printf("%s", p->fts_path);230 kmk_builtin_ctx_printf(pCtx, 0, "%s", p->fts_path); 232 231 233 232 if (vflag > 1) { … … 238 237 S_IFMT) | newmode, m2); 239 238 240 (void)printf(": 0%o [%s] -> 0%o [%s]",239 kmk_builtin_ctx_printf(pCtx, 0, ": 0%o [%s] -> 0%o [%s]", 241 240 (unsigned int)p->fts_statp->st_mode, m1, 242 241 (unsigned int)((p->fts_statp->st_mode & S_IFMT) | newmode), m2); 243 242 } 244 (void)printf("\n");243 kmk_builtin_ctx_printf(pCtx, 0, "\n"); 245 244 } 246 245 … … 248 247 } 249 248 if (errno) 250 rval = err( 1, "fts_read");249 rval = err(pCtx, 1, "fts_read"); 251 250 free(set); 252 251 fts_close(ftsp); … … 255 254 256 255 int 257 usage( FILE *out)258 { 259 (void)fprintf(out,256 usage(PKMKBUILTINCTX pCtx, int is_err) 257 { 258 kmk_builtin_ctx_printf(pCtx, is_err, 260 259 "usage: %s [-fhv] [-R [-H | -L | -P]] mode file ...\n" 261 260 " or: %s --version\n" 262 261 " or: %s --help\n", 263 g_progname, g_progname, g_progname);262 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 264 263 265 264 return 1; 266 265 } 266 267 #ifdef KMK_BUILTIN_STANDALONE 268 int main(int argc, char **argv, char **envp) 269 { 270 KMKBUILTINCTX Ctx = { "kmk_chmod", NULL }; 271 return kmk_builtin_chmod(argc, argv, envp, &Ctx); 272 } 273 #endif 274 -
trunk/src/kmk/kmkbuiltin/cmp.c
r3092 r3192 64 64 65 65 66 static int usage( FILE *);66 static int usage(PKMKBUILTINCTX pCtx, int is_err); 67 67 68 68 int 69 kmk_builtin_cmp(int argc, char * argv[], char **envp)69 kmk_builtin_cmp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 70 70 { 71 71 off_t skip1 = 0, skip2 = 0; … … 74 74 char *file1, *file2; 75 75 76 #ifdef kmk_builtin_cmp76 #ifdef KMK_BUILTIN_STANDALONE 77 77 setlocale(LC_ALL, ""); 78 78 #endif 79 79 80 80 /* reset getopt and set progname. */ 81 g_progname = argv[0];82 81 opterr = 1; 83 82 optarg = NULL; … … 96 95 break; 97 96 case 261: 98 usage( stdout);97 usage(pCtx, 0); 99 98 return 0; 100 99 case 262: … … 102 101 case '?': 103 102 default: 104 return usage( stderr);103 return usage(pCtx, 1); 105 104 } 106 105 } … … 109 108 110 109 if (argc < 2 || argc > 4) 111 return usage( stderr);110 return usage(pCtx, 1); 112 111 113 112 file1 = argv[0]; … … 121 120 skip1 = strtoll(argv[2], &ep, 0); 122 121 if (errno || ep == argv[2]) 123 return errx( ERR_EXIT, "strtoll(%s,,) failed", argv[2]);122 return errx(pCtx, ERR_EXIT, "strtoll(%s,,) failed", argv[2]); 124 123 125 124 if (argc == 4) … … 127 126 skip2 = strtoll(argv[3], &ep, 0); 128 127 if (errno || ep == argv[3]) 129 return errx( ERR_EXIT, "strtoll(%s,,) failed", argv[3]);128 return errx(pCtx, ERR_EXIT, "strtoll(%s,,) failed", argv[3]); 130 129 } 131 130 } 132 131 133 return cmp_file_and_file_ex( file1, skip1, file2, skip2, sflag, lflag, 0);132 return cmp_file_and_file_ex(pCtx, file1, skip1, file2, skip2, sflag, lflag, 0); 134 133 } 135 134 136 135 static int 137 usage( FILE *fp)136 usage(PKMKBUILTINCTX pCtx, int is_err) 138 137 { 139 fprintf(fp, "usage: %s [-l | -s] file1 file2 [skip1 [skip2]]\n" 140 " or: %s --help\n" 141 " or: %s --version\n", 142 g_progname, g_progname, g_progname); 138 kmk_builtin_ctx_printf(pCtx, is_err, 139 "usage: %s [-l | -s] file1 file2 [skip1 [skip2]]\n" 140 " or: %s --help\n" 141 " or: %s --version\n", 142 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 143 143 return ERR_EXIT; 144 144 } 145 146 #ifdef KMK_BUILTIN_STANDALONE 147 int main(int argc, char **argv, char **envp) 148 { 149 KMKBUILTINCTX Ctx = { "kmk_cmp", NULL }; 150 return kmk_builtin_cmp(argc, argv, envp, &Ctx); 151 } 152 #endif 153 -
trunk/src/kmk/kmkbuiltin/cmp_extern.h
r1309 r3192 36 36 #define ERR_EXIT 2 /* error exit code */ 37 37 38 int cmp_file_and_file( const char *file1, const char *file2, int sflag, int lflag, int special);39 int cmp_file_and_file_ex( const char *file1, off_t skip1,38 int cmp_file_and_file(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, int sflag, int lflag, int special); 39 int cmp_file_and_file_ex(PKMKBUILTINCTX pCtx, const char *file1, off_t skip1, 40 40 const char *file2, off_t skip2, int sflag, int lflag, int special); 41 int cmp_fd_and_file( int fd1, const char *file1,41 int cmp_fd_and_file(PKMKBUILTINCTX pCtx, int fd1, const char *file1, 42 42 const char *file2, int sflag, int lflag, int special); 43 int cmp_fd_and_file_ex( int fd1, const char *file1, off_t skip1,43 int cmp_fd_and_file_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, 44 44 const char *file2, off_t skip2, int sflag, int lflag, int special); 45 int cmp_fd_and_fd( int fd1, const char *file1,45 int cmp_fd_and_fd(PKMKBUILTINCTX pCtx, int fd1, const char *file1, 46 46 int fd2, const char *file2, int sflag, int lflag, int special); 47 int cmp_fd_and_fd_ex( int fd1, const char *file1, off_t skip1,47 int cmp_fd_and_fd_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, 48 48 int fd2, const char *file2, off_t skip2, int sflag, int lflag, int special); 49 49 -
trunk/src/kmk/kmkbuiltin/cmp_util.c
r3095 r3192 66 66 67 67 static int 68 errmsg( const char *file, off_t byte, off_t line, int lflag)68 errmsg(PKMKBUILTINCTX pCtx, const char *file, off_t byte, off_t line, int lflag) 69 69 { 70 70 if (lflag) 71 71 #ifdef _MSC_VER 72 return err( ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line);73 #else 74 return err( ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line);75 #endif 76 return err( ERR_EXIT, "%s", file);72 return err(pCtx, ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line); 73 #else 74 return err(pCtx, ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line); 75 #endif 76 return err(pCtx, ERR_EXIT, "%s", file); 77 77 } 78 78 79 79 80 80 static int 81 eofmsg( const char *file, off_t byte, off_t line, int sflag, int lflag)81 eofmsg(PKMKBUILTINCTX pCtx, const char *file, off_t byte, off_t line, int sflag, int lflag) 82 82 { 83 83 if (!sflag) 84 84 { 85 85 if (!lflag) 86 warnx( "EOF on %s", file);86 warnx(pCtx, "EOF on %s", file); 87 87 else 88 88 { 89 89 #ifdef _MSC_VER 90 90 if (line > 0) 91 warnx( "EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line);91 warnx(pCtx, "EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line); 92 92 else 93 warnx( "EOF on %s: char %I64d", file, (__int64)byte);93 warnx(pCtx, "EOF on %s: char %I64d", file, (__int64)byte); 94 94 #else 95 95 if (line > 0) 96 warnx( "EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line);96 warnx(pCtx, "EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line); 97 97 else 98 warnx( "EOF on %s: char %lld", file, (long long)byte);98 warnx(pCtx, "EOF on %s: char %lld", file, (long long)byte); 99 99 #endif 100 100 } … … 105 105 106 106 static int 107 diffmsg( const char *file1, const char *file2, off_t byte, off_t line, int sflag)107 diffmsg(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, off_t byte, off_t line, int sflag) 108 108 { 109 109 if (!sflag) 110 110 #ifdef _MSC_VER 111 printf("%s %s differ: char %I64d, line %I64d\n",111 kmk_builtin_ctx_printf(pCtx, 0, "%s %s differ: char %I64d, line %I64d\n", 112 112 file1, file2, (__int64)byte, (__int64)line); 113 113 #else 114 printf("%s %s differ: char %lld, line %lld\n",114 kmk_builtin_ctx_printf(pCtx, 0, "%s %s differ: char %lld, line %lld\n", 115 115 file1, file2, (long long)byte, (long long)line); 116 116 #endif … … 123 123 */ 124 124 static int 125 c_special( int fd1, const char *file1, off_t skip1,125 c_special(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, 126 126 int fd2, const char *file2, off_t skip2, 127 127 int lflag, int sflag) … … 134 134 fd1dup = dup(fd1); 135 135 if (fd1 < 0) 136 return err( ERR_EXIT, "%s", file1);136 return err(pCtx, ERR_EXIT, "%s", file1); 137 137 fp1 = fdopen(fd1dup, "rb"); 138 138 if (!fp1) … … 140 140 if (!fp1) 141 141 { 142 err( ERR_EXIT, "%s", file1);142 err(pCtx, ERR_EXIT, "%s", file1); 143 143 close(fd1dup); 144 144 return ERR_EXIT; … … 189 189 if (!lflag) 190 190 { 191 rc = diffmsg( file1, file2, byte, line, sflag);191 rc = diffmsg(pCtx, file1, file2, byte, line, sflag); 192 192 break; 193 193 } 194 194 rc = DIFF_EXIT; 195 195 #ifdef _MSC_VER 196 printf("%6i64d %3o %3o\n", (__int64)byte, ch1, ch2);197 #else 198 printf("%6lld %3o %3o\n", (long long)byte, ch1, ch2);196 kmk_builtin_ctx_printf(pCtx, 0, "%6i64d %3o %3o\n", (__int64)byte, ch1, ch2); 197 #else 198 kmk_builtin_ctx_printf(pCtx, 0, "%6lld %3o %3o\n", (long long)byte, ch1, ch2); 199 199 #endif 200 200 } … … 206 206 /* Check for errors and length differences (EOF). */ 207 207 if (ferror(fp1) && rc != ERR_EXIT) 208 rc = errmsg( file1, byte, line, lflag);208 rc = errmsg(pCtx, file1, byte, line, lflag); 209 209 if (ferror(fp2) && rc != ERR_EXIT) 210 rc = errmsg( file2, byte, line, lflag);210 rc = errmsg(pCtx, file2, byte, line, lflag); 211 211 if (rc == OK_EXIT) 212 212 { … … 214 214 { 215 215 if (!feof(fp2)) 216 rc = eofmsg( file1, byte, line, sflag, lflag);216 rc = eofmsg(pCtx, file1, byte, line, sflag, lflag); 217 217 } 218 218 else if (feof(fp2)) 219 rc = eofmsg( file2, byte, line, sflag, lflag);219 rc = eofmsg(pCtx, file2, byte, line, sflag, lflag); 220 220 } 221 221 … … 224 224 else 225 225 { 226 rc = err( ERR_EXIT, "%s", file2);226 rc = err(pCtx, ERR_EXIT, "%s", file2); 227 227 close(fd2dup); 228 228 } 229 229 } 230 230 else 231 rc = err( ERR_EXIT, "%s", file2);231 rc = err(pCtx, ERR_EXIT, "%s", file2); 232 232 233 233 fclose(fp1); … … 241 241 */ 242 242 static int 243 c_regular( int fd1, const char *file1, off_t skip1, off_t len1,243 c_regular(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, off_t len1, 244 244 int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag) 245 245 { … … 253 253 254 254 if (skip1 > len1) 255 return eofmsg( file1, len1 + 1, 0, sflag, lflag);255 return eofmsg(pCtx, file1, len1 + 1, 0, sflag, lflag); 256 256 len1 -= skip1; 257 257 if (skip2 > len2) 258 return eofmsg( file2, len2 + 1, 0, sflag, lflag);258 return eofmsg(pCtx, file2, len2 + 1, 0, sflag, lflag); 259 259 len2 -= skip2; 260 260 … … 290 290 dfound = 1; 291 291 #ifdef _MSC_VER 292 printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);293 #else 294 printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);292 kmk_builtin_ctx_printf(pCtx, 0, "%6I64d %3o %3o\n", (__int64)byte, ch, *p2); 293 #else 294 kmk_builtin_ctx_printf(pCtx, 0, "%6lld %3o %3o\n", (long long)byte, ch, *p2); 295 295 #endif 296 296 } … … 305 305 306 306 if (len1 != len2) 307 return eofmsg( len1 > len2 ? file2 : file1, byte, line, sflag, lflag);307 return eofmsg(pCtx, len1 > len2 ? file2 : file1, byte, line, sflag, lflag); 308 308 if (dfound) 309 309 return DIFF_EXIT; … … 311 311 312 312 l_mmap_failed: 313 return c_special( fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);313 return c_special(pCtx, fd1, file1, skip1, fd2, file2, skip2, lflag, sflag); 314 314 } 315 315 … … 320 320 */ 321 321 static int 322 c_regular( int fd1, const char *file1, off_t skip1, off_t len1,322 c_regular(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, off_t len1, 323 323 int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag) 324 324 { … … 332 332 333 333 if (skip1 > len1) 334 return eofmsg( file1, len1 + 1, 0, sflag, lflag);334 return eofmsg(pCtx, file1, len1 + 1, 0, sflag, lflag); 335 335 len1 -= skip1; 336 336 if (skip2 > len2) 337 return eofmsg( file2, len2 + 1, 0, sflag, lflag);337 return eofmsg(pCtx, file2, len2 + 1, 0, sflag, lflag); 338 338 len2 -= skip2; 339 339 … … 343 343 { 344 344 if (skip1 && lseek(fd1, 0, SEEK_SET) < 0) 345 return err( 1, "seek failed");345 return err(pCtx, 1, "seek failed"); 346 346 goto l_special; 347 347 } … … 383 383 free(b1); 384 384 free(b2); 385 return diffmsg( file1, file2, byte, line, sflag);385 return diffmsg(pCtx, file1, file2, byte, line, sflag); 386 386 } 387 387 dfound = 1; 388 388 #ifdef _MSC_VER 389 printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2);390 #else 391 printf("%6lld %3o %3o\n", (long long)byte, ch, *p2);389 kmk_builtin_ctx_printf(pCtx, 0, "%6I64d %3o %3o\n", (__int64)byte, ch, *p2); 390 #else 391 kmk_builtin_ctx_printf(pCtx, 0, "%6lld %3o %3o\n", (long long)byte, ch, *p2); 392 392 #endif 393 393 } … … 400 400 401 401 if (len1 != len2) 402 return eofmsg( len1 > len2 ? file2 : file1, byte, line, sflag, lflag);402 return eofmsg(pCtx, len1 > len2 ? file2 : file1, byte, line, sflag, lflag); 403 403 if (dfound) 404 404 return DIFF_EXIT; … … 409 409 || lseek(fd2, 0, SEEK_SET) < 0) 410 410 { 411 err( 1, "seek failed");411 err(pCtx, 1, "seek failed"); 412 412 free(b1); 413 413 free(b2); … … 418 418 free(b2); 419 419 l_special: 420 return c_special( fd1, file1, skip1, fd2, file2, skip2, lflag, sflag);420 return c_special(pCtx, fd1, file1, skip1, fd2, file2, skip2, lflag, sflag); 421 421 } 422 422 #endif /* non-mmap c_regular */ … … 427 427 */ 428 428 int 429 cmp_fd_and_fd_ex( int fd1, const char *file1, off_t skip1,429 cmp_fd_and_fd_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, 430 430 int fd2, const char *file2, off_t skip2, 431 431 int sflag, int lflag, int special) … … 435 435 436 436 if (fstat(fd1, &st1)) 437 return err( ERR_EXIT, "%s", file1);437 return err(pCtx, ERR_EXIT, "%s", file1); 438 438 if (fstat(fd2, &st2)) 439 return err( ERR_EXIT, "%s", file2);439 return err(pCtx, ERR_EXIT, "%s", file2); 440 440 441 441 if ( !S_ISREG(st1.st_mode) 442 442 || !S_ISREG(st2.st_mode) 443 443 || special) 444 rc = c_special( fd1, file1, skip1,444 rc = c_special(pCtx, fd1, file1, skip1, 445 445 fd2, file2, skip2, sflag, lflag); 446 446 else 447 rc = c_regular( fd1, file1, skip1, st1.st_size,447 rc = c_regular(pCtx, fd1, file1, skip1, st1.st_size, 448 448 fd2, file2, skip2, st2.st_size, sflag, lflag); 449 449 return rc; … … 455 455 */ 456 456 int 457 cmp_fd_and_fd( int fd1, const char *file1,457 cmp_fd_and_fd(PKMKBUILTINCTX pCtx, int fd1, const char *file1, 458 458 int fd2, const char *file2, 459 459 int sflag, int lflag, int special) 460 460 { 461 return cmp_fd_and_fd_ex( fd1, file1, 0, fd2, file2, 0, sflag, lflag, special);461 return cmp_fd_and_fd_ex(pCtx, fd1, file1, 0, fd2, file2, 0, sflag, lflag, special); 462 462 } 463 463 … … 467 467 */ 468 468 int 469 cmp_fd_and_file_ex( int fd1, const char *file1, off_t skip1,469 cmp_fd_and_file_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, 470 470 const char *file2, off_t skip2, 471 471 int sflag, int lflag, int special) … … 484 484 if (fd2 >= 0) 485 485 { 486 rc = cmp_fd_and_fd_ex( fd1, file1, skip1,486 rc = cmp_fd_and_fd_ex(pCtx, fd1, file1, skip1, 487 487 fd2, file2, skip2, sflag, lflag, special); 488 488 close(fd2); … … 491 491 { 492 492 if (!sflag) 493 warn( "%s", file2);493 warn(pCtx, "%s", file2); 494 494 rc = ERR_EXIT; 495 495 } … … 502 502 */ 503 503 int 504 cmp_fd_and_file( int fd1, const char *file1,504 cmp_fd_and_file(PKMKBUILTINCTX pCtx, int fd1, const char *file1, 505 505 const char *file2, 506 506 int sflag, int lflag, int special) 507 507 { 508 return cmp_fd_and_file_ex( fd1, file1, 0,508 return cmp_fd_and_file_ex(pCtx, fd1, file1, 0, 509 509 file2, 0, sflag, lflag, special); 510 510 } … … 515 515 */ 516 516 int 517 cmp_file_and_file_ex( const char *file1, off_t skip1,517 cmp_file_and_file_ex(PKMKBUILTINCTX pCtx, const char *file1, off_t skip1, 518 518 const char *file2, off_t skip2, 519 519 int sflag, int lflag, int special) … … 523 523 524 524 if (lflag && sflag) 525 return errx( ERR_EXIT, "only one of -l and -s may be specified");525 return errx(pCtx, ERR_EXIT, "only one of -l and -s may be specified"); 526 526 527 527 if (!strcmp(file1, "-")) 528 528 { 529 529 if (!strcmp(file2, "-")) 530 return errx( ERR_EXIT, "standard input may only be specified once");530 return errx(pCtx, ERR_EXIT, "standard input may only be specified once"); 531 531 file1 = "stdin"; 532 532 fd1 = 1; … … 537 537 if (fd1 >= 0) 538 538 { 539 rc = cmp_fd_and_file_ex( fd1, file1, skip1,539 rc = cmp_fd_and_file_ex(pCtx, fd1, file1, skip1, 540 540 file2, skip2, sflag, lflag, special); 541 541 close(fd1); … … 544 544 { 545 545 if (!sflag) 546 warn( "%s", file1);546 warn(pCtx, "%s", file1); 547 547 rc = ERR_EXIT; 548 548 } … … 556 556 */ 557 557 int 558 cmp_file_and_file( const char *file1, const char *file2, int sflag, int lflag, int special)559 { 560 return cmp_file_and_file_ex( file1, 0, file2, 0, sflag, lflag, special);561 } 562 558 cmp_file_and_file(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, int sflag, int lflag, int special) 559 { 560 return cmp_file_and_file_ex(pCtx, file1, 0, file2, 0, sflag, lflag, special); 561 } 562 -
trunk/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c
r3177 r3192 50 50 * 51 51 * @returns The duplicate enviornment. 52 * @param pCtx The built-in command context. 52 53 * @param papszEnv The read-only vector. 53 54 * @param cEnvVars The number of variables. … … 56 57 * @param cVerbosity The verbosity level. 57 58 */ 58 static char **kBuiltinOptEnvDuplicate(char **papszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity) 59 static char **kBuiltinOptEnvDuplicate(PKMKBUILTINCTX pCtx, char **papszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars, 60 int cVerbosity) 59 61 { 60 62 unsigned cAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf; … … 72 74 free(papszEnvNew[i]); 73 75 free(papszEnvNew); 74 errx( 1, "out of memory for duplicating environment variables!", i);76 errx(pCtx, 1, "out of memory for duplicating environment variables!", i); 75 77 return NULL; 76 78 } … … 80 82 } 81 83 else 82 errx( 1, "out of memory for duplicating environment vector!");84 errx(pCtx, 1, "out of memory for duplicating environment vector!"); 83 85 return papszEnvNew; 84 86 } … … 90 92 * 91 93 * @returns 0 on success, non-zero exit code on error. 94 * @param pCtx The built-in command context. 92 95 * @param papszEnv The environment vector. 93 96 * @param pcEnvVars Pointer to the variable holding the number of … … 98 101 * @param pszValue The var=value string to apply. 99 102 */ 100 static int kBuiltinOptEnvAddVar( char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,103 static int kBuiltinOptEnvAddVar(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 101 104 int cVerbosity, const char *pszValue) 102 105 { … … 109 112 papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0])); 110 113 if (!papszEnv) 111 return errx( 1, "out of memory growing environment vector!");114 return errx(pCtx, 1, "out of memory growing environment vector!"); 112 115 *ppapszEnv = papszEnv; 113 116 } 114 117 papszEnv[cEnvVars] = strdup(pszValue); 115 118 if (!papszEnv[cEnvVars]) 116 return errx( 1, "out of memory adding environment variable!");119 return errx(pCtx, 1, "out of memory adding environment variable!"); 117 120 papszEnv[++cEnvVars] = NULL; 118 121 *pcEnvVars = cEnvVars; 119 122 if (cVerbosity > 0) 120 warnx( "added '%s'", papszEnv[cEnvVars - 1]);123 warnx(pCtx, "added '%s'", papszEnv[cEnvVars - 1]); 121 124 return 0; 122 125 } … … 128 131 * 129 132 * @returns 0 on success, non-zero exit code on error. 133 * @param pCtx The built-in command context. 130 134 * @param papszEnv The environment vector. 131 135 * @param cEnvVars Number of environment variables. … … 135 139 * @param iEnvVar Where to start searching after. 136 140 */ 137 static int kBuiltinOptEnvRemoveDuplicates( char **papszEnv, unsigned cEnvVars, int cVerbosity,141 static int kBuiltinOptEnvRemoveDuplicates(PKMKBUILTINCTX pCtx, char **papszEnv, unsigned cEnvVars, int cVerbosity, 138 142 const char *pszValue, size_t cchVar, unsigned iEnvVar) 139 143 { … … 143 147 { 144 148 if (cVerbosity > 0) 145 warnx( "removing duplicate '%s'", papszEnv[iEnvVar]);149 warnx(pCtx, "removing duplicate '%s'", papszEnv[iEnvVar]); 146 150 free(papszEnv[iEnvVar]); 147 151 cEnvVars--; … … 159 163 * 160 164 * @returns 0 on success, non-zero exit code on error. 165 * @param pCtx The built-in command context. 161 166 * @param ppapszEnv The environment vector pointer. 162 167 * @param pcEnvVars Pointer to the variable holding the number of … … 167 172 * @param pszValue The var=value string to apply. 168 173 */ 169 int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) 174 int kBuiltinOptEnvSet(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 175 int cVerbosity, const char *pszValue) 170 176 { 171 177 const char *pszEqual = strchr(pszValue, '='); … … 179 185 if (!*pcAllocatedEnvVars) 180 186 { 181 papszEnv = kBuiltinOptEnvDuplicate(p apszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);187 papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity); 182 188 if (!papszEnv) 183 return errx( 1, "out of memory duplicating enviornment (setenv)!");189 return errx(pCtx, 1, "out of memory duplicating enviornment (setenv)!"); 184 190 *ppapszEnv = papszEnv; 185 191 } … … 192 198 { 193 199 if (cVerbosity > 0) 194 warnx( "replacing '%s' with '%s'", papszEnv[iEnvVar], pszValue);200 warnx(pCtx, "replacing '%s' with '%s'", papszEnv[iEnvVar], pszValue); 195 201 free(papszEnv[iEnvVar]); 196 202 papszEnv[iEnvVar] = strdup(pszValue); 197 203 if (!papszEnv[iEnvVar]) 198 return errx( 1, "out of memory for modified environment variable!");199 200 return kBuiltinOptEnvRemoveDuplicates(p apszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);204 return errx(pCtx, 1, "out of memory for modified environment variable!"); 205 206 return kBuiltinOptEnvRemoveDuplicates(pCtx, papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar); 201 207 } 202 208 } 203 return kBuiltinOptEnvAddVar(p papszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);204 } 205 return errx( 1, "Missing '=': -E %s", pszValue);209 return kBuiltinOptEnvAddVar(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue); 210 } 211 return errx(pCtx, 1, "Missing '=': -E %s", pszValue); 206 212 } 207 213 … … 211 217 * 212 218 * @returns 0 on success, non-zero exit code on error. 219 * @param pCtx The built-in command context. 213 220 * @param ppapszEnv The environment vector pointer. 214 221 * @param pcEnvVars Pointer to the variable holding the number of … … 219 226 * @param pszValue The var=value string to apply. 220 227 */ 221 static int kBuiltinOptEnvAppendPrepend( char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,228 static int kBuiltinOptEnvAppendPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 222 229 int cVerbosity, const char *pszValue, int fAppend) 223 230 { … … 232 239 if (!*pcAllocatedEnvVars) 233 240 { 234 papszEnv = kBuiltinOptEnvDuplicate(p apszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);241 papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity); 235 242 if (!papszEnv) 236 return errx( 1, "out of memory duplicating environment (append)!");243 return errx(pCtx, 1, "out of memory duplicating environment (append)!"); 237 244 *ppapszEnv = papszEnv; 238 245 } … … 248 255 char *pszNew = malloc(cchVar + 1 + cchOldValue + cchNewValue + 1); 249 256 if (!pszNew) 250 return errx( 1, "out of memory appending to environment variable!");257 return errx(pCtx, 1, "out of memory appending to environment variable!"); 251 258 if (fAppend) 252 259 { … … 262 269 263 270 if (cVerbosity > 0) 264 warnx( "replacing '%s' with '%s'", pszCur, pszNew);271 warnx(pCtx, "replacing '%s' with '%s'", pszCur, pszNew); 265 272 free(pszCur); 266 273 papszEnv[iEnvVar] = pszNew; 267 274 268 return kBuiltinOptEnvRemoveDuplicates(p apszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);275 return kBuiltinOptEnvRemoveDuplicates(pCtx, papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar); 269 276 } 270 277 } 271 return kBuiltinOptEnvAddVar(p papszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);272 } 273 return errx( 1, "Missing '=': -E %s", pszValue);278 return kBuiltinOptEnvAddVar(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue); 279 } 280 return errx(pCtx, 1, "Missing '=': -E %s", pszValue); 274 281 } 275 282 … … 279 286 * 280 287 * @returns 0 on success, non-zero exit code on error. 288 * @param pCtx The built-in command context. 281 289 * @param ppapszEnv The environment vector pointer. 282 290 * @param pcEnvVars Pointer to the variable holding the number of … … 287 295 * @param pszValue The var=value string to apply. 288 296 */ 289 int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) 290 { 291 return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 1 /*fAppend*/); 297 int kBuiltinOptEnvAppend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 298 int cVerbosity, const char *pszValue) 299 { 300 return kBuiltinOptEnvAppendPrepend(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 1 /*fAppend*/); 292 301 } 293 302 … … 297 306 * 298 307 * @returns 0 on success, non-zero exit code on error. 308 * @param pCtx The built-in command context. 299 309 * @param ppapszEnv The environment vector pointer. 300 310 * @param pcEnvVars Pointer to the variable holding the number of … … 305 315 * @param pszValue The var=value string to apply. 306 316 */ 307 int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue) 308 { 309 return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 0 /*fAppend*/); 317 int kBuiltinOptEnvPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 318 int cVerbosity, const char *pszValue) 319 { 320 return kBuiltinOptEnvAppendPrepend(pCtx, ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 0 /*fAppend*/); 310 321 } 311 322 … … 315 326 * 316 327 * @returns 0 on success, non-zero exit code on error. 328 * @param pCtx The built-in command context. 317 329 * @param ppapszEnv The environment vector pointer. 318 330 * @param pcEnvVars Pointer to the variable holding the number of … … 324 336 * @param pszVarToRemove The name of the variable to remove. 325 337 */ 326 int kBuiltinOptEnvUnset(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszVarToRemove) 338 int kBuiltinOptEnvUnset(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, 339 int cVerbosity, const char *pszVarToRemove) 327 340 { 328 341 if (strchr(pszVarToRemove, '=') == NULL) … … 339 352 { 340 353 if (cVerbosity > 0) 341 warnx( !cRemoved ? "removing '%s'" : "removing duplicate '%s'", papszEnv[iEnvVar]);354 warnx(pCtx, !cRemoved ? "removing '%s'" : "removing duplicate '%s'", papszEnv[iEnvVar]); 342 355 343 356 if (!*pcAllocatedEnvVars) 344 357 { 345 papszEnv = kBuiltinOptEnvDuplicate(p apszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);358 papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity); 346 359 if (!papszEnv) 347 return errx( 1, "out of memory duplicating environment (unset)!");360 return errx(pCtx, 1, "out of memory duplicating environment (unset)!"); 348 361 *ppapszEnv = papszEnv; 349 362 } … … 360 373 361 374 if (cVerbosity > 0 && !cRemoved) 362 warnx( "not found '%s'", pszVarToRemove);375 warnx(pCtx, "not found '%s'", pszVarToRemove); 363 376 } 364 377 else 365 return errx( 1, "Found invalid variable name character '=' in: -U %s", pszVarToRemove);378 return errx(pCtx, 1, "Found invalid variable name character '=' in: -U %s", pszVarToRemove); 366 379 return 0; 367 380 } … … 372 385 * 373 386 * @returns 0 on success, non-zero exit code on error. 387 * @param pCtx The built-in command context. 374 388 * @param ppapszEnv The environment vector pointer. 375 389 * @param pcEnvVars Pointer to the variable holding the number of … … 380 394 * @param cVerbosity The verbosity level. 381 395 */ 382 int kBuiltinOptEnvZap( char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity)396 int kBuiltinOptEnvZap(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity) 383 397 { 384 398 if (*pcAllocatedEnvVars > 0) … … 396 410 char **papszEnv = calloc(4, sizeof(char *)); 397 411 if (!papszEnv) 398 return err( 1, "out of memory!");412 return err(pCtx, 1, "out of memory!"); 399 413 *ppapszEnv = papszEnv; 400 414 *pcAllocatedEnvVars = 4; … … 435 449 * 436 450 * @returns 0 on success, non-zero exit code on error. 451 * @param pCtx The built-in command context. 437 452 * @param pszCwd The CWD buffer. Contains current CWD on input, 438 453 * modified by @a pszValue on output. … … 440 455 * @param pszValue The --chdir value to apply. 441 456 */ 442 int kBuiltinOptChDir( char *pszCwd, size_t cbCwdBuf, const char *pszValue)457 int kBuiltinOptChDir(PKMKBUILTINCTX pCtx, char *pszCwd, size_t cbCwdBuf, const char *pszValue) 443 458 { 444 459 size_t cchNewCwd = strlen(pszValue); … … 454 469 offDst = 2; /* Take drive letter from CWD. */ 455 470 else 456 return errx( 1, "UNC relative CWD not implemented: cur='%s' new='%s'", pszCwd, pszValue);471 return errx(pCtx, 1, "UNC relative CWD not implemented: cur='%s' new='%s'", pszCwd, pszValue); 457 472 } 458 473 else if ( pszValue[1] == ':' … … 473 488 int iDrive = tolower(pszValue[0]) - 'a' + 1; 474 489 if (!_getdcwd(iDrive, pszCwd, cbCwdBuf)) 475 return err( 1, "_getdcwd(%d,,) failed", iDrive);490 return err(pCtx, 1, "_getdcwd(%d,,) failed", iDrive); 476 491 pszValue += 2; 477 492 cchNewCwd -= 2; … … 493 508 pszCwd[offDst++] = '/'; 494 509 if (offDst + cchNewCwd >= cbCwdBuf) 495 return errx( 1, "Too long CWD: %*.*s%s", offDst, offDst, pszCwd, pszValue);510 return errx(pCtx, 1, "Too long CWD: %*.*s%s", offDst, offDst, pszCwd, pszValue); 496 511 memcpy(&pszCwd[offDst], pszValue, cchNewCwd + 1); 497 512 } -
trunk/src/kmk/kmkbuiltin/cp.c
r3148 r3192 157 157 158 158 159 static int copy( char *[], enum op, int);159 static int copy(PKMKBUILTINCTX pCtx, char *[], enum op, int); 160 160 static int mastercmp(const FTSENT **, const FTSENT **); 161 161 #ifdef SIGINFO 162 162 static void siginfo(int __unused); 163 163 #endif 164 static int usage( FILE *);164 static int usage(PKMKBUILTINCTX, int); 165 165 166 166 int 167 kmk_builtin_cp(int argc, char * argv[], char **envp)167 kmk_builtin_cp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 168 168 { 169 169 struct stat to_stat, tmp_stat; … … 180 180 info = 0; 181 181 cp_ignore_non_existing = cp_changed_only = 0; 182 kBuildProtectionInit(&g_ProtData );182 kBuildProtectionInit(&g_ProtData, pCtx); 183 183 184 184 /* reset getopt and set progname. */ 185 g_progname = argv[0];186 185 opterr = 1; 187 186 optarg = NULL; … … 229 228 break; 230 229 case CP_OPT_HELP: 231 usage( stdout);230 usage(pCtx, 0); 232 231 kBuildProtectionTerm(&g_ProtData); 233 232 return 0; … … 261 260 default: 262 261 kBuildProtectionTerm(&g_ProtData); 263 return usage( stderr);262 return usage(pCtx, 1); 264 263 } 265 264 argc -= optind; … … 268 267 if (argc < 2) { 269 268 kBuildProtectionTerm(&g_ProtData); 270 return usage( stderr);269 return usage(pCtx, 1); 271 270 } 272 271 … … 275 274 if (Rflag) { 276 275 kBuildProtectionTerm(&g_ProtData); 277 return errx( 1,276 return errx(pCtx, 1, 278 277 "the -R and -r options may not be specified together."); 279 278 } 280 279 if (Hflag || Lflag || Pflag) 281 errx( 1,280 errx(pCtx, 1, 282 281 "the -H, -L, and -P options may not be specified with the -r option."); 283 282 fts_options &= ~FTS_PHYSICAL; … … 303 302 if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) { 304 303 kBuildProtectionTerm(&g_ProtData); 305 return errx( 1, "%s: name too long", target);304 return errx(pCtx, 1, "%s: name too long", target); 306 305 } 307 306 to.p_end = to.p_path + strlen(to.p_path); … … 335 334 if (r == -1 && errno != ENOENT) { 336 335 kBuildProtectionTerm(&g_ProtData); 337 return err( 1, "stat: %s", to.p_path);336 return err(pCtx, 1, "stat: %s", to.p_path); 338 337 } 339 338 if (r == -1 || !S_ISDIR(to_stat.st_mode)) { … … 343 342 if (argc > 1) { 344 343 kBuildProtectionTerm(&g_ProtData); 345 return usage( stderr);344 return usage(pCtx, 1); 346 345 } 347 346 /* … … 368 367 kBuildProtectionTerm(&g_ProtData); 369 368 if (r == -1) 370 return errx( 1, "directory %s does not exist",369 return errx(pCtx, 1, "directory %s does not exist", 371 370 to.p_path); 372 371 else 373 return errx( 1, "%s is not a directory", to.p_path);372 return errx(pCtx, 1, "%s is not a directory", to.p_path); 374 373 } 375 374 } else … … 387 386 : KBUILDPROTECTIONTYPE_FULL, 388 387 to.p_path)) { 389 rc = copy( argv, type, fts_options);388 rc = copy(pCtx, argv, type, fts_options); 390 389 } 391 390 … … 394 393 } 395 394 395 #ifdef KMK_BUILTIN_STANDALONE 396 int main(int argc, char **argv, char **envp) 397 { 398 KMKBUILTINCTX Ctx = { "kmk_cp", NULL }; 399 return kmk_builtin_cp(argc, argv, envp, &Ctx); 400 } 401 #endif 402 396 403 static int 397 copy( char *argv[], enum op type, int fts_options)404 copy(PKMKBUILTINCTX pCtx, char *argv[], enum op type, int fts_options) 398 405 { 399 406 struct stat to_stat; … … 413 420 414 421 if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL) 415 return err( 1, "fts_open");422 return err(pCtx, 1, "fts_open"); 416 423 for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) { 417 424 int copied = 0; … … 422 429 && curr->fts_errno == ENOENT) { 423 430 if (vflag) { 424 warnx( "fts: %s: %s", curr->fts_path,431 warnx(pCtx, "fts: %s: %s", curr->fts_path, 425 432 strerror(curr->fts_errno)); 426 433 } … … 430 437 case FTS_DNR: 431 438 case FTS_ERR: 432 warnx( "fts: %s: %s",439 warnx(pCtx, "fts: %s: %s", 433 440 curr->fts_path, strerror(curr->fts_errno)); 434 441 badcp = rval = 1; 435 442 continue; 436 443 case FTS_DC: /* Warn, continue. */ 437 warnx( "%s: directory causes a cycle", curr->fts_path);444 warnx(pCtx, "%s: directory causes a cycle", curr->fts_path); 438 445 badcp = rval = 1; 439 446 continue; … … 490 497 *target_mid = 0; 491 498 if (target_mid - to.p_path + nlen >= PATH_MAX) { 492 warnx( "%s%s: name too long (not copied)",499 warnx(pCtx, "%s%s: name too long (not copied)", 493 500 to.p_path, p); 494 501 badcp = rval = 1; … … 519 526 */ 520 527 if (pflag) { 521 if (setfile( curr->fts_statp, -1))528 if (setfile(pCtx, curr->fts_statp, -1)) 522 529 rval = 1; 523 530 } else { … … 526 533 ((mode | S_IRWXU) & mask) != (mode & mask)) 527 534 if (chmod(to.p_path, mode & mask) != 0){ 528 warn( "chmod: %s", to.p_path);535 warn(pCtx, "chmod: %s", to.p_path); 529 536 rval = 1; 530 537 } … … 541 548 to_stat.st_ino == curr->fts_statp->st_ino && 542 549 to_stat.st_ino != 0) { 543 warnx( "%s and %s are identical (not copied).",550 warnx(pCtx, "%s and %s are identical (not copied).", 544 551 to.p_path, curr->fts_path); 545 552 badcp = rval = 1; … … 550 557 if (!S_ISDIR(curr->fts_statp->st_mode) && 551 558 S_ISDIR(to_stat.st_mode)) { 552 warnx( "cannot overwrite directory %s with "559 warnx(pCtx, "cannot overwrite directory %s with " 553 560 "non-directory %s", 554 561 to.p_path, curr->fts_path); … … 566 573 ((fts_options & FTS_COMFOLLOW) && 567 574 curr->fts_level == 0)) { 568 if (copy_file( curr, dne, cp_changed_only, &copied))575 if (copy_file(pCtx, curr, dne, cp_changed_only, &copied)) 569 576 badcp = rval = 1; 570 577 } else { 571 if (copy_link( curr, !dne))578 if (copy_link(pCtx, curr, !dne)) 572 579 badcp = rval = 1; 573 580 } … … 576 583 case S_IFDIR: 577 584 if (!Rflag && !rflag) { 578 warnx( "%s is a directory (not copied).",585 warnx(pCtx, "%s is a directory (not copied).", 579 586 curr->fts_path); 580 587 (void)fts_set(ftsp, curr, FTS_SKIP); … … 593 600 if (mkdir(to.p_path, 594 601 curr->fts_statp->st_mode | S_IRWXU) < 0) 595 return err( 1, "mkdir: %s", to.p_path);602 return err(pCtx, 1, "mkdir: %s", to.p_path); 596 603 } else if (!S_ISDIR(to_stat.st_mode)) { 597 604 errno = ENOTDIR; 598 return err( 1, "to-mode: %s", to.p_path);605 return err(pCtx, 1, "to-mode: %s", to.p_path); 599 606 } 600 607 /* … … 610 617 case S_IFCHR: 611 618 if (Rflag) { 612 if (copy_special( curr->fts_statp, !dne))619 if (copy_special(pCtx, curr->fts_statp, !dne)) 613 620 badcp = rval = 1; 614 621 } else { 615 if (copy_file( curr, dne, cp_changed_only, &copied))622 if (copy_file(pCtx, curr, dne, cp_changed_only, &copied)) 616 623 badcp = rval = 1; 617 624 } … … 621 628 #endif 622 629 if (Rflag) { 623 if (copy_fifo( curr->fts_statp, !dne))630 if (copy_fifo(pCtx, curr->fts_statp, !dne)) 624 631 badcp = rval = 1; 625 632 } else { 626 if (copy_file( curr, dne, cp_changed_only, &copied))633 if (copy_file(pCtx, curr, dne, cp_changed_only, &copied)) 627 634 badcp = rval = 1; 628 635 } 629 636 break; 630 637 default: 631 if (copy_file( curr, dne, cp_changed_only, &copied))638 if (copy_file(pCtx, curr, dne, cp_changed_only, &copied)) 632 639 badcp = rval = 1; 633 640 break; 634 641 } 635 642 if (vflag && !badcp) 636 (void)printf(copied ? "%s -> %s\n" : "%s matches %s - not copied\n",637 curr->fts_path, to.p_path);643 kmk_builtin_ctx_printf(pCtx, 0, copied ? "%s -> %s\n" : "%s matches %s - not copied\n", 644 curr->fts_path, to.p_path); 638 645 } 639 646 if (errno) 640 return err( 1, "fts_read");647 return err(pCtx, 1, "fts_read"); 641 648 return (rval); 642 649 } … … 679 686 680 687 static int 681 usage( FILE *fp)688 usage(PKMKBUILTINCTX pCtx, int fIsErr) 682 689 { 683 fprintf(fp,690 kmk_builtin_ctx_printf(pCtx, fIsErr, 684 691 "usage: %s [options] src target\n" 685 692 " or: %s [options] src1 ... srcN directory\n" … … 728 735 "yourself in the foot.\n" 729 736 , 730 g_progname, g_progname, g_progname, g_progname, 737 pCtx->pszProgName, pCtx->pszProgName, 738 pCtx->pszProgName, pCtx->pszProgName, 731 739 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); 732 740 return 1; -
trunk/src/kmk/kmkbuiltin/cp_extern.h
r3107 r3192 55 55 extern volatile sig_atomic_t info; 56 56 57 int copy_fifo( struct stat *, int);58 int copy_file( const FTSENT *, int, int, int *);59 int copy_link( const FTSENT *, int);60 int copy_special( struct stat *, int);61 int setfile( struct stat *, int);57 int copy_fifo(PKMKBUILTINCTX pCtx, struct stat *, int); 58 int copy_file(PKMKBUILTINCTX pCtx, const FTSENT *, int, int, int *); 59 int copy_link(PKMKBUILTINCTX pCtx, const FTSENT *, int); 60 int copy_special(PKMKBUILTINCTX pCtx, struct stat *, int); 61 int setfile(PKMKBUILTINCTX pCtx, struct stat *, int); -
trunk/src/kmk/kmkbuiltin/cp_utils.c
r3148 r3192 87 87 88 88 int 89 copy_file( const FTSENT *entp, int dne, int changed_only, int *pcopied)89 copy_file(PKMKBUILTINCTX pCtx, const FTSENT *entp, int dne, int changed_only, int *pcopied) 90 90 { 91 91 static char buf[MAXBSIZE]; … … 103 103 104 104 if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) { 105 warn( "open: %s", entp->fts_path);105 warn(pCtx, "open: %s", entp->fts_path); 106 106 return (1); 107 107 } … … 120 120 /* compare the files first if requested */ 121 121 if (changed_only) { 122 if (cmp_fd_and_file( from_fd, entp->fts_path, to.p_path,122 if (cmp_fd_and_file(pCtx, from_fd, entp->fts_path, to.p_path, 123 123 1 /* silent */, 0 /* lflag */, 124 124 0 /* special */) == OK_EXIT) { … … 129 129 close(from_fd); 130 130 if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) { 131 warn( "open: %s", entp->fts_path);131 warn(pCtx, "open: %s", entp->fts_path); 132 132 return (1); 133 133 } … … 138 138 if (nflag) { 139 139 if (vflag) 140 printf("%s not overwritten\n", to.p_path);140 kmk_builtin_ctx_printf(pCtx, 0, "%s not overwritten\n", to.p_path); 141 141 return (0); 142 142 } else if (iflag) { … … 148 148 if (checkch != 'y' && checkch != 'Y') { 149 149 (void)close(from_fd); 150 (void)fprintf(stderr, "not overwritten\n");150 kmk_builtin_ctx_printf(pCtx, 1, "not overwritten\n"); 151 151 return (1); 152 152 } … … 167 167 168 168 if (to_fd == -1) { 169 warn( "open: %s", to.p_path);169 warn(pCtx, "open: %s", to.p_path); 170 170 (void)close(from_fd); 171 171 return (1); … … 185 185 if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, 186 186 MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { 187 warn( "mmap: %s", entp->fts_path);187 warn(pCtx, "mmap: %s", entp->fts_path); 188 188 rval = 1; 189 189 } else { … … 195 195 if (info) { 196 196 info = 0; 197 (void)fprintf(stderr,197 kmk_builtin_ctx_printf(pCtx, 1, 198 198 "%s -> %s %3d%%\n", 199 199 entp->fts_path, to.p_path, … … 205 205 } 206 206 if (wcount != (ssize_t)wresid) { 207 warn( "write[%zd != %zu]: %s", wcount, wresid, to.p_path);207 warn(pCtx, "write[%zd != %zu]: %s", wcount, wresid, to.p_path); 208 208 rval = 1; 209 209 } 210 210 /* Some systems don't unmap on close(2). */ 211 211 if (munmap(p, fs->st_size) < 0) { 212 warn( "munmap: %s", entp->fts_path);212 warn(pCtx, "munmap: %s", entp->fts_path); 213 213 rval = 1; 214 214 } … … 225 225 if (info) { 226 226 info = 0; 227 (void)fprintf(stderr,227 kmk_builtin_ctx_printf(pCtx, 1, 228 228 "%s -> %s %3d%%\n", 229 229 entp->fts_path, to.p_path, … … 235 235 } 236 236 if (wcount != (ssize_t)wresid) { 237 warn( "write[%zd != %zu]: %s", wcount, wresid, to.p_path);237 warn(pCtx, "write[%zd != %zu]: %s", wcount, wresid, to.p_path); 238 238 rval = 1; 239 239 break; … … 241 241 } 242 242 if (rcount < 0) { 243 warn( "read: %s", entp->fts_path);243 warn(pCtx, "read: %s", entp->fts_path); 244 244 rval = 1; 245 245 } … … 253 253 */ 254 254 255 if (pflag && setfile( fs, to_fd))255 if (pflag && setfile(pCtx, fs, to_fd)) 256 256 rval = 1; 257 257 (void)close(from_fd); 258 258 if (close(to_fd)) { 259 warn( "close: %s", to.p_path);259 warn(pCtx, "close: %s", to.p_path); 260 260 rval = 1; 261 261 } … … 264 264 265 265 int 266 copy_link( const FTSENT *p, int exists)266 copy_link(PKMKBUILTINCTX pCtx, const FTSENT *p, int exists) 267 267 { 268 268 int len; … … 270 270 271 271 if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) { 272 warn( "readlink: %s", p->fts_path);272 warn(pCtx, "readlink: %s", p->fts_path); 273 273 return (1); 274 274 } 275 275 llink[len] = '\0'; 276 276 if (exists && unlink(to.p_path)) { 277 warn( "unlink: %s", to.p_path);277 warn(pCtx, "unlink: %s", to.p_path); 278 278 return (1); 279 279 } 280 280 if (symlink(llink, to.p_path)) { 281 warn( "symlink: %s", llink);282 return (1); 283 } 284 return (pflag ? setfile(p ->fts_statp, -1) : 0);285 } 286 287 int 288 copy_fifo( struct stat *from_stat, int exists)281 warn(pCtx, "symlink: %s", llink); 282 return (1); 283 } 284 return (pflag ? setfile(pCtx, p->fts_statp, -1) : 0); 285 } 286 287 int 288 copy_fifo(PKMKBUILTINCTX pCtx, struct stat *from_stat, int exists) 289 289 { 290 290 if (exists && unlink(to.p_path)) { 291 warn( "unlink: %s", to.p_path);291 warn(pCtx, "unlink: %s", to.p_path); 292 292 return (1); 293 293 } 294 294 if (mkfifo(to.p_path, from_stat->st_mode)) { 295 warn( "mkfifo: %s", to.p_path);296 return (1); 297 } 298 return (pflag ? setfile( from_stat, -1) : 0);299 } 300 301 int 302 copy_special( struct stat *from_stat, int exists)295 warn(pCtx, "mkfifo: %s", to.p_path); 296 return (1); 297 } 298 return (pflag ? setfile(pCtx, from_stat, -1) : 0); 299 } 300 301 int 302 copy_special(PKMKBUILTINCTX pCtx, struct stat *from_stat, int exists) 303 303 { 304 304 if (exists && unlink(to.p_path)) { 305 warn( "unlink: %s", to.p_path);305 warn(pCtx, "unlink: %s", to.p_path); 306 306 return (1); 307 307 } 308 308 if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) { 309 warn( "mknod: %s", to.p_path);310 return (1); 311 } 312 return (pflag ? setfile( from_stat, -1) : 0);313 } 314 315 int 316 setfile( struct stat *fs, int fd)309 warn(pCtx, "mknod: %s", to.p_path); 310 return (1); 311 } 312 return (pflag ? setfile(pCtx, from_stat, -1) : 0); 313 } 314 315 int 316 setfile(PKMKBUILTINCTX pCtx, struct stat *fs, int fd) 317 317 { 318 318 static struct timeval tv[2]; … … 335 335 #endif 336 336 if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) { 337 warn( "%sutimes: %s", islink ? "l" : "", to.p_path);337 warn(pCtx, "%sutimes: %s", islink ? "l" : "", to.p_path); 338 338 rval = 1; 339 339 } … … 357 357 chown(to.p_path, fs->st_uid, fs->st_gid))) { 358 358 if (errno != EPERM) { 359 warn( "chown: %s", to.p_path);359 warn(pCtx, "chown: %s", to.p_path); 360 360 rval = 1; 361 361 } … … 367 367 (islink ? lchmod(to.p_path, fs->st_mode) : 368 368 chmod(to.p_path, fs->st_mode))) { 369 warn( "chmod: %s", to.p_path);369 warn(pCtx, "chmod: %s", to.p_path); 370 370 rval = 1; 371 371 } … … 377 377 (islink ? (errno = ENOSYS) : 378 378 chflags(to.p_path, fs->st_flags))) { 379 warn( "chflags: %s", to.p_path);379 warn(pCtx, "chflags: %s", to.p_path); 380 380 rval = 1; 381 381 } -
trunk/src/kmk/kmkbuiltin/echo.c
r3065 r3192 1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 1 /* $Id$ */ 2 /** @file 3 * kMk Builtin command - echo 28 4 */ 29 5 30 #if 0 31 #ifndef lint 32 static char const copyright[] = 33 "@(#) Copyright (c) 1989, 1993\n\ 34 The Regents of the University of California. All rights reserved.\n"; 35 #endif /* not lint */ 6 /* 7 * Copyright (c) 2018 knut st. osmundsen <[email protected]> 8 * 9 * This file is part of kBuild. 10 * 11 * kBuild is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 3 of the License, or 14 * (at your option) any later version. 15 * 16 * kBuild is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with kBuild. If not, see <http://www.gnu.org/licenses/> 23 * 24 */ 36 25 37 #ifndef lint 38 static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; 39 #endif /* not lint */ 40 #include <sys/cdefs.h> 41 /*__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $");*/ 26 27 /********************************************************************************************************************************* 28 * Header Files * 29 *********************************************************************************************************************************/ 30 #include "config.h" 31 32 #include <string.h> 33 #include <stdlib.h> 34 #include <stdio.h> 35 #ifdef HAVE_UNISTD_H 36 # include <unistd.h> 37 #endif 38 #ifdef _MSC_VER 39 # include <io.h> 42 40 #endif 43 41 44 #include "config.h" 45 #include <sys/types.h> 46 #ifndef _MSC_VER 47 #include <sys/uio.h> 42 #include "kmkbuiltin.h" 43 #include "err.h" 44 45 46 int kmk_builtin_echo(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 47 { 48 int rcExit = 0; 49 int iFirst = 1; 50 int i; 51 char *pszBuf; 52 size_t cbBuf; 53 54 /* 55 * Check for the -n option. 56 */ 57 int fNoNewLine = 0; 58 if ( argc > iFirst 59 && strcmp(argv[iFirst], "-n") == 0) 60 { 61 iFirst++; 62 fNoNewLine = 1; 63 } 64 65 /* 66 * Calc buffer size and allocate it. 67 */ 68 cbBuf = 1 + 1; 69 for (i = 1; i < argc; i++) 70 cbBuf += (i > iFirst) + strlen(argv[i]); 71 pszBuf = (char *)malloc(cbBuf); 72 if (pszBuf) 73 { 74 /* 75 * Assembler the output into the buffer. 76 */ 77 char *pszDst = pszBuf; 78 for (i = iFirst; i < argc; i++) 79 { 80 const char *pszArg = argv[i]; 81 size_t cchArg = strlen(pszArg); 82 83 /* Check for "\c" in final argument (same as -n). */ 84 if (i + 1 >= argc 85 && cchArg >= 2 86 && pszArg[cchArg - 2] == '\\' 87 && pszArg[cchArg - 1] == 'c') 88 { 89 fNoNewLine = 1; 90 cchArg -= 2; 91 } 92 if (i > iFirst) 93 *pszDst++ = ' '; 94 memcpy(pszDst, pszArg, cchArg); 95 pszDst += cchArg; 96 } 97 if (!fNoNewLine) 98 *pszDst++ = '\n'; 99 *pszDst = '\0'; 100 101 /* 102 * Push it out. 103 */ 104 #ifndef KMK_BUILTIN_STANDALONE 105 if (output_write_text(pCtx->pOut, 0, pszBuf, pszDst - pszBuf) == -1) 106 rcExit = err(pCtx, 1, "output_write_text"); 107 #else 108 if (write(STDOUT_FILENO, pszBuf, pszDst - pszBuf) == -1) 109 rcExit = err(pCtx, 1, "write"); 110 #endif 111 free(pszBuf); 112 } 113 else 114 rcExit = err(pCtx, 1, "malloc(%lu)", (unsigned long)cbBuf); 115 return rcExit; 116 } 117 118 #ifdef KMK_BUILTIN_STANDALONE 119 int main(int argc, char **argv, char **envp) 120 { 121 KMKBUILTINCTX Ctx = { "kmk_echo", NULL }; 122 return kmk_builtin_echo(argc, argv, envp, &Ctx); 123 } 48 124 #endif 49 125 50 #include <stdio.h>51 #include <assert.h>52 #include <errno.h>53 #include <limits.h>54 #include <stdlib.h>55 #include <string.h>56 #ifndef _MSC_VER57 #include <unistd.h>58 #else59 #include "mscfakes.h"60 #endif61 62 #ifndef IOV_MAX63 #define IOV_MAX 102464 #endif65 66 67 /*68 * Report an error and exit.69 * Use it instead of err(3) to avoid linking-in stdio.70 */71 static void72 errexit(const char *prog, const char *reason)73 {74 char *errstr = strerror(errno);75 ssize_t cchIgn = 0; /* this is to shut up irrelevant warnings on linux. */76 #ifdef _MSC_VER77 int doserrno = _doserrno;78 char szDosErr[48];79 sprintf(szDosErr, " (doserrno=%d)", doserrno);80 #endif81 cchIgn += write(STDERR_FILENO, prog, strlen(prog));82 cchIgn += write(STDERR_FILENO, ": ", 2);83 cchIgn += write(STDERR_FILENO, reason, strlen(reason));84 cchIgn += write(STDERR_FILENO, ": ", 2);85 cchIgn += write(STDERR_FILENO, errstr, strlen(errstr));86 #ifdef _MSC_VER87 cchIgn += write(STDERR_FILENO, szDosErr, strlen(szDosErr));88 #endif89 cchIgn += write(STDERR_FILENO, "\n", 1);90 (void)cchIgn;91 }92 93 int94 kmk_builtin_echo(int argc, char *argv[])95 {96 int nflag; /* if not set, output a trailing newline. */97 int veclen; /* number of writev arguments. */98 struct iovec *iov, *vp, *iovfree; /* Elements to write, current element. */99 char space[] = " ";100 char newline[] = "\n";101 char *progname = argv[0];102 103 /* This utility may NOT do getopt(3) option parsing. */104 if (*++argv && !strcmp(*argv, "-n")) {105 ++argv;106 --argc;107 nflag = 1;108 } else109 nflag = 0;110 111 veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;112 113 if ((iovfree = vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) {114 errexit(progname, "malloc");115 exit(1);116 }117 118 while (argv[0] != NULL) {119 size_t len;120 121 len = strlen(argv[0]);122 123 /*124 * If the next argument is NULL then this is this125 * the last argument, therefore we need to check126 * for a trailing \c.127 */128 if (argv[1] == NULL) {129 /* is there room for a '\c' and is there one? */130 if (len >= 2 &&131 argv[0][len - 2] == '\\' &&132 argv[0][len - 1] == 'c') {133 /* chop it and set the no-newline flag. */134 len -= 2;135 nflag = 1;136 }137 }138 vp->iov_base = *argv;139 vp++->iov_len = len;140 if (*++argv) {141 vp->iov_base = space;142 vp++->iov_len = 1;143 }144 }145 if (!nflag) {146 veclen++;147 vp->iov_base = newline;148 vp++->iov_len = 1;149 }150 /* assert(veclen == (vp - iov)); */151 while (veclen) {152 int nwrite;153 154 nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;155 if (writev(STDOUT_FILENO, iov, nwrite) == -1) {156 errexit(progname, "write");157 free(iovfree);158 return 1;159 }160 iov += nwrite;161 veclen -= nwrite;162 }163 free(iovfree);164 return 0;165 } -
trunk/src/kmk/kmkbuiltin/err.c
r3188 r3192 27 27 * Header Files * 28 28 *******************************************************************************/ 29 #include "config.h" 29 #ifdef HAVE_CONFIG_H 30 # include "config.h" 31 #else 32 # include <stdlib.h> 33 # define snprintf _snprintf 34 #endif 30 35 #include <stdio.h> 31 36 #include <stdarg.h> … … 33 38 #include <errno.h> 34 39 #include "err.h" 40 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) 41 # include "../output.h" 42 #endif 35 43 36 44 #ifdef KBUILD_OS_WINDOWS … … 41 49 #endif 42 50 43 44 /** The current program name. */ 45 const char *g_progname = "kmk"; 46 47 48 int err(int eval, const char *fmt, ...) 49 { 50 va_list args; 51 int error = errno; 52 53 /* stderr is unbuffered, so try format the whole message and print it in 54 one go so it won't be split by other output. */ 55 char szMsg[4096]; 56 int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname); 57 if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0) 58 { 59 int cchMsg2; 60 va_start(args, fmt); 61 cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args); 62 va_end(args); 63 64 if ( cchMsg < (int)sizeof(szMsg) - 1 65 && cchMsg2 >= 0) 66 { 67 cchMsg += cchMsg2 = snprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, ": %s\n", strerror(error)); 68 if ( cchMsg < (int)sizeof(szMsg) - 1 51 int err(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...) 52 { 53 /* 54 * We format into a buffer and pass that onto output.c or fwrite. 55 */ 56 int error = errno; 57 char *pszToFree = NULL; 58 char szMsgStack[4096]; 59 char *pszMsg = szMsgStack; 60 size_t cbMsg = sizeof(szMsgStack); 61 for (;;) 62 { 63 int cchMsg = snprintf(pszMsg, cbMsg, "%s: error: ", pCtx->pszProgName); 64 if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) 65 { 66 int cchMsg2; 67 va_list va; 68 va_start(va, fmt); 69 cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); 70 va_end(va); 71 72 if ( cchMsg < (int)cbMsg - 1 69 73 && cchMsg2 >= 0) 70 74 { 71 fwrite(szMsg, cchMsg, 1, stderr); 75 cchMsg += cchMsg2 = snprintf(&pszMsg[cchMsg], cbMsg - cchMsg, ": %s\n", strerror(error)); 76 if ( cchMsg < (int)cbMsg - 1 77 && cchMsg2 >= 0) 78 { 79 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) 80 if (pCtx->pOut) 81 output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); 82 else 83 #endif 84 { 85 fflush(stdout); 86 fwrite(pszMsg, cchMsg, 1, stderr); 87 fflush(stderr); /* paranoia */ 88 } 89 if (pszToFree) 90 free(pszToFree); 91 errno = error; 92 return eval; 93 } 94 } 95 } 96 97 /* double the buffer size and retry */ 98 if (pszToFree) 99 free(pszToFree); 100 cbMsg *= 2; 101 pszToFree = malloc(cbMsg); 102 if (!pszToFree) 103 { 104 fprintf(stderr, "out of memory!\n"); 105 errno = error; 106 return eval; 107 } 108 } 109 } 110 111 112 int errx(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...) 113 { 114 /* 115 * We format into a buffer and pass that onto output.c or fwrite. 116 */ 117 char *pszToFree = NULL; 118 char szMsgStack[4096]; 119 char *pszMsg = szMsgStack; 120 size_t cbMsg = sizeof(szMsgStack); 121 for (;;) 122 { 123 int cchMsg = snprintf(pszMsg, cbMsg, "%s: error: ", pCtx->pszProgName); 124 if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) 125 { 126 int cchMsg2; 127 va_list va; 128 va_start(va, fmt); 129 cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); 130 va_end(va); 131 132 if ( cchMsg < (int)cbMsg - 2 133 && cchMsg2 >= 0) 134 { 135 /* ensure newline */ 136 if (pszMsg[cchMsg - 1] != '\n') 137 { 138 pszMsg[cchMsg++] = '\n'; 139 pszMsg[cchMsg] = '\0'; 140 } 141 142 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) 143 if (pCtx->pOut) 144 output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); 145 else 146 #endif 147 { 148 fflush(stdout); 149 fwrite(pszMsg, cchMsg, 1, stderr); 150 fflush(stderr); /* paranoia */ 151 } 152 if (pszToFree) 153 free(pszToFree); 72 154 return eval; 73 155 } 74 75 } 76 77 } 78 79 /* fallback */ 80 fprintf(stderr, "%s: ", g_progname); 81 va_start(args, fmt); 82 vfprintf(stderr, fmt, args); 83 va_end(args); 84 fprintf(stderr, ": %s\n", strerror(error)); 85 86 return eval; 87 } 88 89 90 int errx(int eval, const char *fmt, ...) 91 { 92 va_list args; 93 94 /* stderr is unbuffered, so try format the whole message and print it in 95 one go so it won't be split by other output. */ 96 char szMsg[4096]; 97 int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname); 98 if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0) 99 { 100 int cchMsg2; 101 va_start(args, fmt); 102 cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args); 103 va_end(args); 104 105 if ( cchMsg < (int)sizeof(szMsg) - 1 106 && cchMsg2 >= 0) 107 { 108 szMsg[cchMsg++] = '\n'; 109 fwrite(szMsg, cchMsg, 1, stderr); 156 } 157 158 /* double the buffer size and retry */ 159 if (pszToFree) 160 free(pszToFree); 161 cbMsg *= 2; 162 pszToFree = malloc(cbMsg); 163 if (!pszToFree) 164 { 165 fprintf(stderr, "out of memory!\n"); 110 166 return eval; 111 167 } 112 113 } 114 115 /* fallback */ 116 fprintf(stderr, "%s: ", g_progname); 117 va_start(args, fmt); 118 vfprintf(stderr, fmt, args); 119 va_end(args); 120 fprintf(stderr, "\n"); 121 122 return eval; 123 } 124 125 void warn(const char *fmt, ...) 126 { 127 int error = errno; 128 va_list args; 129 130 /* stderr is unbuffered, so try format the whole message and print it in 131 one go so it won't be split by other output. */ 132 char szMsg[4096]; 133 int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname); 134 if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0) 135 { 136 int cchMsg2; 137 va_start(args, fmt); 138 cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args); 139 va_end(args); 140 141 if ( cchMsg < (int)sizeof(szMsg) - 1 142 && cchMsg2 >= 0) 143 { 144 cchMsg += cchMsg2 = snprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, ": %s\n", strerror(error)); 145 if ( cchMsg < (int)sizeof(szMsg) - 1 168 } 169 } 170 171 void warn(PKMKBUILTINCTX pCtx, const char *fmt, ...) 172 { 173 /* 174 * We format into a buffer and pass that onto output.c or fwrite. 175 */ 176 int error = errno; 177 char *pszToFree = NULL; 178 char szMsgStack[4096]; 179 char *pszMsg = szMsgStack; 180 size_t cbMsg = sizeof(szMsgStack); 181 for (;;) 182 { 183 int cchMsg = snprintf(pszMsg, cbMsg, "%s: ", pCtx->pszProgName); 184 if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) 185 { 186 int cchMsg2; 187 va_list va; 188 va_start(va, fmt); 189 cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); 190 va_end(va); 191 192 if ( cchMsg < (int)cbMsg - 1 146 193 && cchMsg2 >= 0) 147 194 { 148 fwrite(szMsg, cchMsg, 1, stderr); 195 cchMsg += cchMsg2 = snprintf(&pszMsg[cchMsg], cbMsg - cchMsg, ": %s\n", strerror(error)); 196 if ( cchMsg < (int)cbMsg - 1 197 && cchMsg2 >= 0) 198 { 199 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) 200 if (pCtx->pOut) 201 output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); 202 else 203 #endif 204 { 205 fflush(stdout); 206 fwrite(pszMsg, cchMsg, 1, stderr); 207 fflush(stderr); /* paranoia */ 208 } 209 if (pszToFree) 210 free(pszToFree); 211 errno = error; 212 return; 213 } 214 } 215 } 216 217 /* double the buffer size and retry */ 218 if (pszToFree) 219 free(pszToFree); 220 cbMsg *= 2; 221 pszToFree = malloc(cbMsg); 222 if (!pszToFree) 223 { 224 fprintf(stderr, "out of memory!\n"); 225 errno = error; 226 return; 227 } 228 } 229 } 230 231 void warnx(PKMKBUILTINCTX pCtx, const char *fmt, ...) 232 { 233 /* 234 * We format into a buffer and pass that onto output.c or fwrite. 235 */ 236 char *pszToFree = NULL; 237 char szMsgStack[4096]; 238 char *pszMsg = szMsgStack; 239 size_t cbMsg = sizeof(szMsgStack); 240 for (;;) 241 { 242 int cchMsg = snprintf(pszMsg, cbMsg, "%s: ", pCtx->pszProgName); 243 if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) 244 { 245 int cchMsg2; 246 va_list va; 247 va_start(va, fmt); 248 cchMsg += cchMsg2 = vsnprintf(&pszMsg[cchMsg], cbMsg - cchMsg, fmt, va); 249 va_end(va); 250 251 if ( cchMsg < (int)cbMsg - 2 252 && cchMsg2 >= 0) 253 { 254 /* ensure newline */ 255 if (pszMsg[cchMsg - 1] != '\n') 256 { 257 pszMsg[cchMsg++] = '\n'; 258 pszMsg[cchMsg] = '\0'; 259 } 260 261 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) 262 if (pCtx->pOut) 263 output_write_text(pCtx->pOut, 1 /*is_err*/, pszMsg, cchMsg); 264 else 265 #endif 266 { 267 fflush(stdout); 268 fwrite(pszMsg, cchMsg, 1, stderr); 269 fflush(stderr); /* paranoia */ 270 } 271 if (pszToFree) 272 free(pszToFree); 149 273 return; 150 274 } 151 152 } 153 } 154 155 /* fallback */ 156 fprintf(stderr, "%s: ", g_progname); 157 va_start(args, fmt); 158 vfprintf(stderr, fmt, args); 159 va_end(args); 160 fprintf(stderr, ": %s\n", strerror(error)); 161 } 162 163 void warnx(const char *fmt, ...) 164 { 165 va_list args; 166 167 /* stderr is unbuffered, so try format the whole message and print it in 168 one go so it won't be split by other output. */ 169 char szMsg[4096]; 170 int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname); 171 if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0) 172 { 173 int cchMsg2; 174 va_start(args, fmt); 175 cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args); 176 va_end(args); 177 178 if ( cchMsg < (int)sizeof(szMsg) - 1 179 && cchMsg2 >= 0) 180 { 181 szMsg[cchMsg++] = '\n'; 182 fwrite(szMsg, cchMsg, 1, stderr); 275 } 276 277 /* double the buffer size and retry */ 278 if (pszToFree) 279 free(pszToFree); 280 cbMsg *= 2; 281 pszToFree = malloc(cbMsg); 282 if (!pszToFree) 283 { 284 fprintf(stderr, "out of memory!\n"); 183 285 return; 184 286 } 185 186 } 187 188 /* fallback */ 189 fprintf(stderr, "%s: ", g_progname); 190 va_start(args, fmt); 191 vfprintf(stderr, fmt, args); 192 va_end(args); 193 fprintf(stderr, "\n"); 194 } 195 287 } 288 } 289 290 void kmk_builtin_ctx_printf(PKMKBUILTINCTX pCtx, int fIsErr, const char *pszFormat, ...) 291 { 292 /* 293 * We format into a buffer and pass that onto output.c or fwrite. 294 */ 295 char *pszToFree = NULL; 296 char szMsgStack[4096]; 297 char *pszMsg = szMsgStack; 298 size_t cbMsg = sizeof(szMsgStack); 299 for (;;) 300 { 301 int cchMsg; 302 va_list va; 303 va_start(va, pszFormat); 304 cchMsg = vsnprintf(pszMsg, cbMsg, pszFormat, va); 305 va_end(va); 306 if (cchMsg < (int)cbMsg - 1 && cchMsg > 0) 307 { 308 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER) 309 if (pCtx->pOut) 310 output_write_text(pCtx->pOut, fIsErr, pszMsg, cchMsg); 311 else 312 #endif 313 { 314 fwrite(pszMsg, cchMsg, 1, fIsErr ? stderr : stdout); 315 fflush(fIsErr ? stderr : stdout); 316 } 317 if (pszToFree) 318 free(pszToFree); 319 return; 320 } 321 322 /* double the buffer size and retry */ 323 if (pszToFree) 324 free(pszToFree); 325 cbMsg *= 2; 326 pszToFree = malloc(cbMsg); 327 if (!pszToFree) 328 { 329 fprintf(stderr, "out of memory!\n"); 330 return; 331 } 332 } 333 } 334 -
trunk/src/kmk/kmkbuiltin/err.h
r2413 r3192 27 27 #define ___err_h 28 28 29 extern const char *g_progname; 30 int err(int eval, const char *fmt, ...); 31 int errx(int eval, const char *fmt, ...); 32 void warn(const char *fmt, ...); 33 void warnx(const char *fmt, ...); 29 #include "../kmkbuiltin.h" 30 31 int err(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...); 32 int errx(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...); 33 void warn(PKMKBUILTINCTX pCtx, const char *fmt, ...); 34 void warnx(PKMKBUILTINCTX pCtx, const char *fmt, ...); 35 void kmk_builtin_ctx_printf(PKMKBUILTINCTX pCtx, int fIsErr, const char *pszFormat, ...); 34 36 35 37 #endif -
trunk/src/kmk/kmkbuiltin/expr.c
r3140 r3192 22 22 #endif 23 23 #include "err.h" 24 #include "getopt.h"25 24 #include "kmkbuiltin.h" 26 25 27 static struct val *make_int(int); 28 static struct val *make_str(char *); 29 static void free_value(struct val *); 26 typedef struct EXPRINSTANCE *PEXPRINSTANCE; 27 28 static struct val *make_int(PEXPRINSTANCE, int); 29 static struct val *make_str(PEXPRINSTANCE, char *); 30 static void free_value(PEXPRINSTANCE, struct val *); 30 31 static int is_integer(struct val *, int *); 31 static int to_integer( struct val *);32 static void to_string( struct val *);33 static int is_zero_or_null( struct val *);34 static void nexttoken( int);35 static struct val *eval6( void);36 static struct val *eval5( void);37 static struct val *eval4( void);38 static struct val *eval3( void);39 static struct val *eval2( void);40 static struct val *eval1( void);41 static struct val *eval0( void);32 static int to_integer(PEXPRINSTANCE, struct val *); 33 static void to_string(PEXPRINSTANCE, struct val *); 34 static int is_zero_or_null(PEXPRINSTANCE, struct val *); 35 static void nexttoken(PEXPRINSTANCE, int); 36 static struct val *eval6(PEXPRINSTANCE); 37 static struct val *eval5(PEXPRINSTANCE); 38 static struct val *eval4(PEXPRINSTANCE); 39 static struct val *eval3(PEXPRINSTANCE); 40 static struct val *eval2(PEXPRINSTANCE); 41 static struct val *eval1(PEXPRINSTANCE); 42 static struct val *eval0(PEXPRINSTANCE); 42 43 43 44 enum token { … … 58 59 }; 59 60 60 static enum token token; 61 static struct val *tokval; 62 static char **av; 63 static jmp_buf g_expr_jmp; 64 static void **recorded_allocations; 65 static int num_recorded_allocations; 66 67 68 static void expr_mem_record_alloc(void *ptr) 69 { 70 if (!(num_recorded_allocations & 31)) { 71 void *newtab = realloc(recorded_allocations, (num_recorded_allocations + 33) * sizeof(void *)); 61 typedef struct EXPRINSTANCE { 62 PKMKBUILTINCTX pCtx; 63 enum token token; 64 struct val *tokval; 65 char **av; 66 jmp_buf g_expr_jmp; 67 void **recorded_allocations; 68 int num_recorded_allocations; 69 } EXPRINSTANCE; 70 71 72 static void expr_mem_record_alloc(PEXPRINSTANCE pThis, void *ptr) 73 { 74 if (!(pThis->num_recorded_allocations & 31)) { 75 void *newtab = realloc(pThis->recorded_allocations, (pThis->num_recorded_allocations + 33) * sizeof(void *)); 72 76 if (!newtab) 73 longjmp( g_expr_jmp, err(3, NULL));74 recorded_allocations = (void **)newtab;75 } 76 recorded_allocations[num_recorded_allocations++] = ptr;77 } 78 79 80 static void expr_mem_record_free( void *ptr)81 { 82 int i = num_recorded_allocations;77 longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); 78 pThis->recorded_allocations = (void **)newtab; 79 } 80 pThis->recorded_allocations[pThis->num_recorded_allocations++] = ptr; 81 } 82 83 84 static void expr_mem_record_free(PEXPRINSTANCE pThis, void *ptr) 85 { 86 int i = pThis->num_recorded_allocations; 83 87 while (i-- > 0) 84 if ( recorded_allocations[i] == ptr) {85 num_recorded_allocations--;86 recorded_allocations[i] = recorded_allocations[num_recorded_allocations];88 if (pThis->recorded_allocations[i] == ptr) { 89 pThis->num_recorded_allocations--; 90 pThis->recorded_allocations[i] = pThis->recorded_allocations[pThis->num_recorded_allocations]; 87 91 return; 88 92 } … … 90 94 } 91 95 92 static void expr_mem_init( void)93 { 94 num_recorded_allocations = 0;95 recorded_allocations = NULL;96 } 97 98 static void expr_mem_cleanup( void)99 { 100 if ( recorded_allocations) {101 while ( num_recorded_allocations-- > 0)102 free( recorded_allocations[num_recorded_allocations]);103 free( recorded_allocations);104 recorded_allocations = NULL;105 } 106 } 107 108 109 static struct val * 110 make_int( int i)96 static void expr_mem_init(PEXPRINSTANCE pThis) 97 { 98 pThis->num_recorded_allocations = 0; 99 pThis->recorded_allocations = NULL; 100 } 101 102 static void expr_mem_cleanup(PEXPRINSTANCE pThis) 103 { 104 if (pThis->recorded_allocations) { 105 while (pThis->num_recorded_allocations-- > 0) 106 free(pThis->recorded_allocations[pThis->num_recorded_allocations]); 107 free(pThis->recorded_allocations); 108 pThis->recorded_allocations = NULL; 109 } 110 } 111 112 113 static struct val * 114 make_int(PEXPRINSTANCE pThis, int i) 111 115 { 112 116 struct val *vp; … … 114 118 vp = (struct val *) malloc(sizeof(*vp)); 115 119 if (vp == NULL) 116 longjmp( g_expr_jmp, err(3, NULL));117 expr_mem_record_alloc( vp);120 longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); 121 expr_mem_record_alloc(pThis, vp); 118 122 vp->type = integer; 119 123 vp->u.i = i; … … 123 127 124 128 static struct val * 125 make_str( char *s)129 make_str(PEXPRINSTANCE pThis, char *s) 126 130 { 127 131 struct val *vp; … … 129 133 vp = (struct val *) malloc(sizeof(*vp)); 130 134 if (vp == NULL || ((vp->u.s = strdup(s)) == NULL)) 131 longjmp( g_expr_jmp, err(3, NULL));132 expr_mem_record_alloc( vp->u.s);133 expr_mem_record_alloc( vp);135 longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); 136 expr_mem_record_alloc(pThis, vp->u.s); 137 expr_mem_record_alloc(pThis, vp); 134 138 vp->type = string; 135 139 return vp; … … 138 142 139 143 static void 140 free_value( struct val *vp)144 free_value(PEXPRINSTANCE pThis, struct val *vp) 141 145 { 142 146 if (vp->type == string) { 143 expr_mem_record_free( vp->u.s);147 expr_mem_record_free(pThis, vp->u.s); 144 148 free(vp->u.s); 145 149 } 146 150 free(vp); 147 expr_mem_record_free( vp);151 expr_mem_record_free(pThis, vp); 148 152 } 149 153 … … 193 197 /* coerce to vp to an integer */ 194 198 static int 195 to_integer( struct val *vp)199 to_integer(PEXPRINSTANCE pThis, struct val *vp) 196 200 { 197 201 int r; … … 201 205 202 206 if (is_integer(vp, &r)) { 203 expr_mem_record_free( vp->u.s);207 expr_mem_record_free(pThis, vp->u.s); 204 208 free(vp->u.s); 205 209 vp->u.i = r; … … 214 218 /* coerce to vp to an string */ 215 219 static void 216 to_string( struct val *vp)220 to_string(PEXPRINSTANCE pThis, struct val *vp) 217 221 { 218 222 char *tmp; … … 222 226 223 227 if (asprintf(&tmp, "%d", vp->u.i) == -1) 224 longjmp( g_expr_jmp, err(3, NULL));225 expr_mem_record_alloc( tmp);228 longjmp(pThis->g_expr_jmp, err(pThis->pCtx, 3, NULL)); 229 expr_mem_record_alloc(pThis, tmp); 226 230 227 231 vp->type = string; … … 230 234 231 235 static int 232 is_zero_or_null( struct val *vp)236 is_zero_or_null(PEXPRINSTANCE pThis, struct val *vp) 233 237 { 234 238 if (vp->type == integer) { 235 239 return (vp->u.i == 0); 236 240 } else { 237 return (*vp->u.s == 0 || (to_integer( vp) && vp->u.i == 0));241 return (*vp->u.s == 0 || (to_integer(pThis, vp) && vp->u.i == 0)); 238 242 } 239 243 /* NOTREACHED */ … … 241 245 242 246 static void 243 nexttoken( int pat)247 nexttoken(PEXPRINSTANCE pThis, int pat) 244 248 { 245 249 char *p; 246 250 247 if ((p = * av) == NULL) {248 token = EOI;251 if ((p = *pThis->av) == NULL) { 252 pThis->token = EOI; 249 253 return; 250 254 } 251 av++;255 pThis->av++; 252 256 253 257 … … 258 262 259 263 if ((i = strchr(x, *p)) != NULL) { 260 token = i - x;264 pThis->token = i - x; 261 265 return; 262 266 } … … 264 268 switch (*p) { 265 269 case '<': 266 token = LE;270 pThis->token = LE; 267 271 return; 268 272 case '>': 269 token = GE;273 pThis->token = GE; 270 274 return; 271 275 case '!': 272 token = NE;276 pThis->token = NE; 273 277 return; 274 278 } 275 279 } 276 280 } 277 tokval = make_str(p);278 token = OPERAND;281 pThis->tokval = make_str(pThis, p); 282 pThis->token = OPERAND; 279 283 return; 280 284 } … … 287 291 #endif 288 292 static void 289 error( void)290 { 291 longjmp( g_expr_jmp, errx(2, "syntax error"));293 error(PEXPRINSTANCE pThis) 294 { 295 longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "syntax error")); 292 296 /* NOTREACHED */ 293 297 } 294 298 295 299 static struct val * 296 eval6( void)300 eval6(PEXPRINSTANCE pThis) 297 301 { 298 302 struct val *v; 299 303 300 if ( token == OPERAND) {301 nexttoken( 0);302 return tokval;303 304 } else if ( token == RP) {305 nexttoken( 0);306 v = eval0( );307 308 if ( token != LP) {309 error( );304 if (pThis->token == OPERAND) { 305 nexttoken(pThis, 0); 306 return pThis->tokval; 307 308 } else if (pThis->token == RP) { 309 nexttoken(pThis, 0); 310 v = eval0(pThis); 311 312 if (pThis->token != LP) { 313 error(pThis); 310 314 /* NOTREACHED */ 311 315 } 312 nexttoken( 0);316 nexttoken(pThis, 0); 313 317 return v; 314 318 } else { 315 error( );319 error(pThis); 316 320 } 317 321 /* NOTREACHED */ … … 320 324 /* Parse and evaluate match (regex) expressions */ 321 325 static struct val * 322 eval5( void)326 eval5(PEXPRINSTANCE pThis) 323 327 { 324 328 #ifdef KMK_WITH_REGEX … … 332 336 struct val *l; 333 337 334 l = eval6( );335 while ( token == MATCH) {338 l = eval6(pThis); 339 while (pThis->token == MATCH) { 336 340 #ifdef KMK_WITH_REGEX 337 nexttoken( 1);338 r = eval6( );341 nexttoken(pThis, 1); 342 r = eval6(pThis); 339 343 340 344 /* coerce to both arguments to strings */ 341 to_string( l);342 to_string( r);345 to_string(pThis, l); 346 to_string(pThis, r); 343 347 344 348 /* compile regular expression */ 345 349 if ((eval = regcomp(&rp, r->u.s, 0)) != 0) { 346 350 regerror(eval, &rp, errbuf, sizeof(errbuf)); 347 longjmp( g_expr_jmp, errx(2, "%s", errbuf));351 longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "%s", errbuf)); 348 352 } 349 353 … … 353 357 if (rm[1].rm_so >= 0) { 354 358 *(l->u.s + rm[1].rm_eo) = '\0'; 355 v = make_str( l->u.s + rm[1].rm_so);359 v = make_str(pThis, l->u.s + rm[1].rm_so); 356 360 357 361 } else { 358 v = make_int( (int)(rm[0].rm_eo - rm[0].rm_so));362 v = make_int(pThis, (int)(rm[0].rm_eo - rm[0].rm_so)); 359 363 } 360 364 } else { 361 365 if (rp.re_nsub == 0) { 362 v = make_int( 0);366 v = make_int(pThis, 0); 363 367 } else { 364 v = make_str( "");368 v = make_str(pThis, ""); 365 369 } 366 370 } 367 371 368 372 /* free arguments and pattern buffer */ 369 free_value( l);370 free_value( r);373 free_value(pThis, l); 374 free_value(pThis, r); 371 375 regfree(&rp); 372 376 373 377 l = v; 374 378 #else 375 longjmp( g_expr_jmp, errx(2, "regex not supported, sorry."));379 longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "regex not supported, sorry.")); 376 380 #endif 377 381 } … … 382 386 /* Parse and evaluate multiplication and division expressions */ 383 387 static struct val * 384 eval4( void)388 eval4(PEXPRINSTANCE pThis) 385 389 { 386 390 struct val *l, *r; 387 391 enum token op; 388 392 389 l = eval5( );390 while ((op = token) == MUL || op == DIV || op == MOD) {391 nexttoken( 0);392 r = eval5( );393 394 if (!to_integer( l) || !to_integer(r)) {395 longjmp( g_expr_jmp, errx(2, "non-numeric argument"));393 l = eval5(pThis); 394 while ((op = pThis->token) == MUL || op == DIV || op == MOD) { 395 nexttoken(pThis, 0); 396 r = eval5(pThis); 397 398 if (!to_integer(pThis, l) || !to_integer(pThis, r)) { 399 longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "non-numeric argument")); 396 400 } 397 401 … … 400 404 } else { 401 405 if (r->u.i == 0) { 402 longjmp( g_expr_jmp, errx(2, "division by zero"));406 longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "division by zero")); 403 407 } 404 408 if (op == DIV) { … … 409 413 } 410 414 411 free_value( r);415 free_value(pThis, r); 412 416 } 413 417 … … 417 421 /* Parse and evaluate addition and subtraction expressions */ 418 422 static struct val * 419 eval3( void)423 eval3(PEXPRINSTANCE pThis) 420 424 { 421 425 struct val *l, *r; 422 426 enum token op; 423 427 424 l = eval4( );425 while ((op = token) == ADD || op == SUB) {426 nexttoken( 0);427 r = eval4( );428 429 if (!to_integer( l) || !to_integer(r)) {430 longjmp( g_expr_jmp, errx(2, "non-numeric argument"));428 l = eval4(pThis); 429 while ((op = pThis->token) == ADD || op == SUB) { 430 nexttoken(pThis, 0); 431 r = eval4(pThis); 432 433 if (!to_integer(pThis, l) || !to_integer(pThis, r)) { 434 longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "non-numeric argument")); 431 435 } 432 436 … … 437 441 } 438 442 439 free_value( r);443 free_value(pThis, r); 440 444 } 441 445 … … 445 449 /* Parse and evaluate comparison expressions */ 446 450 static struct val * 447 eval2( void)451 eval2(PEXPRINSTANCE pThis) 448 452 { 449 453 struct val *l, *r; … … 451 455 int v = 0, li, ri; 452 456 453 l = eval3( );454 while ((op = token) == EQ || op == NE || op == LT || op == GT ||457 l = eval3(pThis); 458 while ((op = pThis->token) == EQ || op == NE || op == LT || op == GT || 455 459 op == LE || op == GE) { 456 nexttoken( 0);457 r = eval3( );460 nexttoken(pThis, 0); 461 r = eval3(pThis); 458 462 459 463 if (is_integer(l, &li) && is_integer(r, &ri)) { … … 481 485 } 482 486 } else { 483 to_string( l);484 to_string( r);487 to_string(pThis, l); 488 to_string(pThis, r); 485 489 486 490 switch (op) { … … 508 512 } 509 513 510 free_value( l);511 free_value( r);512 l = make_int( v);514 free_value(pThis, l); 515 free_value(pThis, r); 516 l = make_int(pThis, v); 513 517 } 514 518 … … 518 522 /* Parse and evaluate & expressions */ 519 523 static struct val * 520 eval1( void)524 eval1(PEXPRINSTANCE pThis) 521 525 { 522 526 struct val *l, *r; 523 527 524 l = eval2( );525 while ( token == AND) {526 nexttoken( 0);527 r = eval2( );528 529 if (is_zero_or_null( l) || is_zero_or_null(r)) {530 free_value( l);531 free_value( r);532 l = make_int( 0);528 l = eval2(pThis); 529 while (pThis->token == AND) { 530 nexttoken(pThis, 0); 531 r = eval2(pThis); 532 533 if (is_zero_or_null(pThis, l) || is_zero_or_null(pThis, r)) { 534 free_value(pThis, l); 535 free_value(pThis, r); 536 l = make_int(pThis, 0); 533 537 } else { 534 free_value( r);538 free_value(pThis, r); 535 539 } 536 540 } … … 541 545 /* Parse and evaluate | expressions */ 542 546 static struct val * 543 eval0( void)547 eval0(PEXPRINSTANCE pThis) 544 548 { 545 549 struct val *l, *r; 546 550 547 l = eval1( );548 while ( token == OR) {549 nexttoken( 0);550 r = eval1( );551 552 if (is_zero_or_null( l)) {553 free_value( l);551 l = eval1(pThis); 552 while (pThis->token == OR) { 553 nexttoken(pThis, 0); 554 r = eval1(pThis); 555 556 if (is_zero_or_null(pThis, l)) { 557 free_value(pThis, l); 554 558 l = r; 555 559 } else { 556 free_value( r);560 free_value(pThis, r); 557 561 } 558 562 } … … 563 567 564 568 int 565 kmk_builtin_expr(int argc, char *argv[], char **envp) 566 { 567 struct val *vp; 569 kmk_builtin_expr(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 570 { 571 EXPRINSTANCE This; 572 struct val *vp; 568 573 int rval; 569 570 /* re-init globals */571 token = 0;572 tokval = 0;573 av = 0;574 expr_mem_init();575 576 #ifdef kmk_builtin_expr /* kmk already does this. */577 (void) setlocale(LC_ALL, "");578 #endif579 574 580 575 if (argc > 1 && !strcmp(argv[1], "--")) 581 576 argv++; 582 577 583 av = argv + 1; 584 585 rval = setjmp(g_expr_jmp); 578 /* Init globals */ 579 This.pCtx = pCtx; 580 This.token = 0; 581 This.tokval = 0; 582 This.av = argv + 1; 583 expr_mem_init(&This); 584 585 rval = setjmp(This.g_expr_jmp); 586 586 if (!rval) { 587 nexttoken( 0);588 vp = eval0( );589 590 if ( token != EOI) {591 error( );587 nexttoken(&This, 0); 588 vp = eval0(&This); 589 590 if (This.token != EOI) { 591 error(&This); 592 592 /* NOTREACHED */ 593 593 } 594 594 595 595 if (vp->type == integer) 596 printf("%d\n", vp->u.i);596 kmk_builtin_ctx_printf(pCtx, 0, "%d\n", vp->u.i); 597 597 else 598 printf("%s\n", vp->u.s);599 600 rval = is_zero_or_null( vp);598 kmk_builtin_ctx_printf(pCtx, 0, "%s\n", vp->u.s); 599 600 rval = is_zero_or_null(&This, vp); 601 601 } 602 602 /* else: longjmp */ 603 603 604 604 /* cleanup */ 605 expr_mem_cleanup( );605 expr_mem_cleanup(&This); 606 606 return rval; 607 607 } 608 609 #ifdef KMK_BUILTIN_STANDALONE 610 int main(int argc, char **argv, char **envp) 611 { 612 KMKBUILTINCTX Ctx = { "kmk_expr", NULL }; 613 (void) setlocale(LC_ALL, ""); 614 return kmk_builtin_expr(argc, argv, envp, &Ctx); 615 } 616 #endif 617 -
trunk/src/kmk/kmkbuiltin/install.c
r3145 r3192 122 122 #endif 123 123 124 static gid_t gid; 125 static uid_t uid; 126 static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given; 127 static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 128 static const char *suffix = BACKUP_SUFFIX; 129 static int ignore_perm_errors; 130 static int hard_link_files_when_possible; 131 static int dos2unix; 132 124 /********************************************************************************************************************************* 125 * Structures and Typedefs * 126 *********************************************************************************************************************************/ 127 typedef struct INSTALLINSTANCE 128 { 129 PKMKBUILTINCTX pCtx; 130 131 gid_t gid; 132 uid_t uid; 133 int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given; 134 mode_t mode; 135 const char *suffix; 136 int ignore_perm_errors; 137 int hard_link_files_when_possible; 138 int dos2unix; 139 } INSTALLINSTANCE; 140 typedef INSTALLINSTANCE *PINSTALLINSTANCE; 141 142 143 /********************************************************************************************************************************* 144 * Global Variables * 145 *********************************************************************************************************************************/ 133 146 static struct option long_options[] = 134 147 { … … 145 158 146 159 147 static int copy( int, const char *, int *, const char *);160 static int copy(PINSTALLINSTANCE, int, const char *, int *, const char *); 148 161 static int compare(int, size_t, int, size_t); 149 static int create_newfile( const char *, int, struct stat *);162 static int create_newfile(PINSTALLINSTANCE, const char *, int, struct stat *); 150 163 static int create_tempfile(const char *, char *, size_t); 151 static int install( const char *, const char *, u_long, u_int);152 static int install_dir( char *);153 static u_long numeric_id( const char *, const char *);154 static int strip( const char *);155 static int usage( FILE *);164 static int install(PINSTALLINSTANCE, const char *, const char *, u_long, u_int); 165 static int install_dir(PINSTALLINSTANCE, char *); 166 static u_long numeric_id(PINSTALLINSTANCE, const char *, const char *); 167 static int strip(PINSTALLINSTANCE, const char *); 168 static int usage(PKMKBUILTINCTX, int); 156 169 static char *last_slash(const char *); 157 170 static KBOOL needs_dos2unix_conversion(const char *pszFilename); … … 159 172 160 173 int 161 kmk_builtin_install(int argc, char *argv[], char ** envp) 162 { 174 kmk_builtin_install(int argc, char *argv[], char ** envp, PKMKBUILTINCTX pCtx) 175 { 176 INSTALLINSTANCE This; 163 177 struct stat from_sb, to_sb; 164 178 mode_t *set; … … 170 184 (void)envp; 171 185 172 /* reinitialize globals */ 173 mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 174 suffix = BACKUP_SUFFIX; 175 gid = 0; 176 uid = 0; 177 dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = mode_given = 0; 178 ignore_perm_errors = geteuid() != 0; 179 hard_link_files_when_possible = 0; 180 dos2unix = 0; 186 /* Initialize global instance data. */ 187 This.pCtx = pCtx; 188 This.mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 189 This.suffix = BACKUP_SUFFIX; 190 This.gid = 0; 191 This.uid = 0; 192 This.dobackup = 0; 193 This.docompare = 0; 194 This.dodir = 0; 195 This.dopreserve = 0; 196 This.dostrip = 0; 197 This.nommap = 0; 198 This.safecopy = 0; 199 This.verbose = 0; 200 This.mode_given = 0; 201 This.ignore_perm_errors = geteuid() != 0; 202 This.hard_link_files_when_possible = 0; 203 This.dos2unix = 0; 181 204 182 205 /* reset getopt and set progname. */ 183 g_progname = argv[0];184 206 opterr = 1; 185 207 optarg = NULL; … … 192 214 switch(ch) { 193 215 case 'B': 194 suffix = optarg;216 This.suffix = optarg; 195 217 /* FALLTHROUGH */ 196 218 case 'b': 197 dobackup = 1;219 This.dobackup = 1; 198 220 break; 199 221 case 'C': 200 docompare = 1;222 This.docompare = 1; 201 223 break; 202 224 case 'c': … … 204 226 break; 205 227 case 'd': 206 dodir = 1;228 This.dodir = 1; 207 229 break; 208 230 case 'f': … … 210 232 flags = optarg; 211 233 if (strtofflags(&flags, &fset, NULL)) 212 return errx( EX_USAGE, "%s: invalid flag", flags);234 return errx(pCtx, EX_USAGE, "%s: invalid flag", flags); 213 235 iflags |= SETFLAGS; 214 236 #else … … 220 242 break; 221 243 case 'M': 222 nommap = 1;244 This.nommap = 1; 223 245 break; 224 246 case 'm': 225 247 if (!(set = bsd_setmode(optarg))) 226 return errx(EX_USAGE, "invalid file mode: %s", 227 optarg); 228 mode = bsd_getmode(set, 0); 248 return errx(pCtx, EX_USAGE, "invalid file mode: %s", optarg); 249 This.mode = bsd_getmode(set, 0); 229 250 free(set); 230 mode_given = 1;251 This.mode_given = 1; 231 252 break; 232 253 case 'o': … … 234 255 break; 235 256 case 'p': 236 docompare =dopreserve = 1;257 This.docompare = This.dopreserve = 1; 237 258 break; 238 259 case 'S': 239 safecopy = 1;260 This.safecopy = 1; 240 261 break; 241 262 case 's': 242 dostrip = 1;263 This.dostrip = 1; 243 264 break; 244 265 case 'v': 245 verbose = 1;266 This.verbose = 1; 246 267 break; 247 268 case 261: 248 usage( stdout);269 usage(pCtx, 0); 249 270 return 0; 250 271 case 262: 251 272 return kbuild_version(argv[0]); 252 273 case 263: 253 ignore_perm_errors = 1;274 This.ignore_perm_errors = 1; 254 275 break; 255 276 case 264: 256 ignore_perm_errors = 0;277 This.ignore_perm_errors = 0; 257 278 break; 258 279 case 265: 259 hard_link_files_when_possible = 1;280 This.hard_link_files_when_possible = 1; 260 281 break; 261 282 case 266: 262 hard_link_files_when_possible = 0;283 This.hard_link_files_when_possible = 0; 263 284 break; 264 285 case 267: 265 dos2unix = 1;286 This.dos2unix = 1; 266 287 break; 267 288 case 268: 268 dos2unix = -1;289 This.dos2unix = -1; 269 290 break; 270 291 case '?': 271 292 default: 272 return usage( stderr);293 return usage(pCtx, 1); 273 294 } 274 295 argc -= optind; … … 276 297 277 298 /* some options make no sense when creating directories */ 278 if ( dostrip &&dodir) {279 warnx( "-d and -s may not be specified together");280 return usage( stderr);299 if (This.dostrip && This.dodir) { 300 warnx(pCtx, "-d and -s may not be specified together"); 301 return usage(pCtx, 1); 281 302 } 282 303 283 304 /* must have at least two arguments, except when creating directories */ 284 if (argc == 0 || (argc == 1 && ! dodir))285 return usage( stderr);305 if (argc == 0 || (argc == 1 && !This.dodir)) 306 return usage(pCtx, 1); 286 307 287 308 /* and unix2dos doesn't combine well with a couple of other options. */ 288 if ( dos2unix != 0) {289 if ( docompare) {290 warnx( "-C/-p and --dos2unix/unix2dos may not be specified together");291 return usage( stderr);292 } 293 if ( dostrip) {294 warnx( "-s and --dos2unix/unix2dos may not be specified together");295 return usage( stderr);309 if (This.dos2unix != 0) { 310 if (This.docompare) { 311 warnx(pCtx, "-C/-p and --dos2unix/unix2dos may not be specified together"); 312 return usage(pCtx, 1); 313 } 314 if (This.dostrip) { 315 warnx(pCtx, "-s and --dos2unix/unix2dos may not be specified together"); 316 return usage(pCtx, 1); 296 317 } 297 318 } 298 319 299 320 /* need to make a temp copy so we can compare stripped version */ 300 if ( docompare &&dostrip)301 safecopy = 1;321 if (This.docompare && This.dostrip) 322 This.safecopy = 1; 302 323 303 324 /* get group and owner id's */ … … 310 331 #endif 311 332 { 312 gid = (gid_t)numeric_id(group, "group");313 if ( gid == (gid_t)-1)333 This.gid = (gid_t)numeric_id(&This, group, "group"); 334 if (This.gid == (gid_t)-1) 314 335 return 1; 315 336 } 316 337 } else 317 gid = (gid_t)-1;338 This.gid = (gid_t)-1; 318 339 319 340 if (owner != NULL) { … … 325 346 #endif 326 347 { 327 uid = (uid_t)numeric_id(owner, "user");328 if ( uid == (uid_t)-1)348 This.uid = (uid_t)numeric_id(&This, owner, "user"); 349 if (This.uid == (uid_t)-1) 329 350 return 1; 330 351 } 331 352 } else 332 uid = (uid_t)-1;333 334 if ( dodir) {353 This.uid = (uid_t)-1; 354 355 if (This.dodir) { 335 356 for (; *argv != NULL; ++argv) { 336 int rc = install_dir( *argv);357 int rc = install_dir(&This, *argv); 337 358 if (rc) 338 359 return rc; … … 345 366 if (!no_target && S_ISDIR(to_sb.st_mode)) { 346 367 for (; *argv != to_name; ++argv) { 347 int rc = install( *argv, to_name, fset, iflags | DIRECTORY);368 int rc = install(&This, *argv, to_name, fset, iflags | DIRECTORY); 348 369 if (rc) 349 370 return rc; … … 354 375 /* can't do file1 file2 directory/file */ 355 376 if (argc != 2) { 356 warnx( "wrong number or types of arguments");357 return usage( stderr);377 warnx(pCtx, "wrong number or types of arguments"); 378 return usage(pCtx, 1); 358 379 } 359 380 360 381 if (!no_target) { 361 382 if (stat(*argv, &from_sb)) 362 return err( EX_OSERR, "%s", *argv);383 return err(pCtx, EX_OSERR, "%s", *argv); 363 384 if (!S_ISREG(to_sb.st_mode)) { 364 385 errno = EFTYPE; 365 return err( EX_OSERR, "%s", to_name);386 return err(pCtx, EX_OSERR, "%s", to_name); 366 387 } 367 388 if (to_sb.st_dev == from_sb.st_dev && … … 369 390 to_sb.st_ino == from_sb.st_ino && 370 391 to_sb.st_ino != 0 && 371 ! hard_link_files_when_possible)372 return errx( EX_USAGE,392 !This.hard_link_files_when_possible) 393 return errx(pCtx, EX_USAGE, 373 394 "%s and %s are the same file", *argv, to_name); 374 395 } 375 return install(*argv, to_name, fset, iflags); 376 } 396 return install(&This, *argv, to_name, fset, iflags); 397 } 398 399 #ifdef KMK_BUILTIN_STANDALONE 400 int main(int argc, char **argv, char **envp) 401 { 402 KMKBUILTINCTX Ctx = { "kmk_install", NULL }; 403 return kmk_builtin_install(argc, argv, envp, &Ctx); 404 } 405 #endif 377 406 378 407 static u_long 379 numeric_id( const char *name, const char *type)408 numeric_id(PINSTALLINSTANCE pThis, const char *name, const char *type) 380 409 { 381 410 u_long val; … … 389 418 val = strtoul(name, &ep, 10); 390 419 if (errno) 391 return err( -1, "%s", name);420 return err(pThis->pCtx, -1, "%s", name); 392 421 if (*ep != '\0') 393 return errx( -1, "unknown %s %s", type, name);422 return errx(pThis->pCtx, -1, "unknown %s %s", type, name); 394 423 return (val); 395 424 } … … 400 429 */ 401 430 static int 402 install( const char *from_name, const char *to_name, u_long fset, u_int flags)431 install(PINSTALLINSTANCE pThis, const char *from_name, const char *to_name, u_long fset, u_int flags) 403 432 { 404 433 struct stat from_sb, temp_sb, to_sb; … … 428 457 ) { 429 458 if (stat(from_name, &from_sb)) 430 return err( EX_OSERR, "%s", from_name);459 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 431 460 if (!S_ISREG(from_sb.st_mode)) { 432 461 errno = EFTYPE; 433 return err( EX_OSERR, "%s", from_name);462 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 434 463 } 435 464 /* Build the target path. */ … … 450 479 if (target && !S_ISREG(to_sb.st_mode)) { 451 480 errno = EFTYPE; 452 warn( "%s", to_name);481 warn(pThis->pCtx, "%s", to_name); 453 482 return EX_OK; 454 483 } 455 484 456 485 /* Only copy safe if the target exists. */ 457 tempcopy = safecopy && target;486 tempcopy = pThis->safecopy && target; 458 487 459 488 /* Try hard linking if wanted and possible. */ 460 if ( hard_link_files_when_possible)489 if (pThis->hard_link_files_when_possible) 461 490 { 462 491 #ifdef KBUILD_OS_OS2 … … 466 495 if (devnull) { 467 496 why_not = "/dev/null"; 468 } else if ( dostrip) {497 } else if (pThis->dostrip) { 469 498 why_not = "strip (-s)"; 470 } else if ( docompare) {499 } else if (pThis->docompare) { 471 500 why_not = "compare (-C)"; 472 } else if ( dobackup) {501 } else if (pThis->dobackup) { 473 502 why_not = "backup (-b/-B)"; 474 } else if ( safecopy) {503 } else if (pThis->safecopy) { 475 504 why_not = "safe copy (-S)"; 476 505 } else if (lstat(from_name, &temp_sb)) { … … 481 510 why_not = "not regular file"; 482 511 # if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) 483 } else if (( mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) {512 } else if ((pThis->mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) { 484 513 # else 485 } else if ( mode != (from_sb.st_mode & ALLPERMS)) {514 } else if (pThis->mode != (from_sb.st_mode & ALLPERMS)) { 486 515 # endif 487 printf("install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n" 488 "install: src path '%s'\n" 489 "install: dst path '%s'\n", 490 (from_sb.st_mode & ALLPERMS), mode, from_name, to_name); 516 kmk_builtin_ctx_printf(pThis->pCtx, 0, 517 "install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n" 518 "install: src path '%s'\n" 519 "install: dst path '%s'\n", 520 (from_sb.st_mode & ALLPERMS), pThis->mode, from_name, to_name); 491 521 why_not = NULL; 492 } else if ( uid != (uid_t)-1 && gid != from_sb.st_uid) {522 } else if (pThis->uid != (uid_t)-1 && pThis->uid != from_sb.st_uid) { 493 523 why_not = "uid mismatch"; 494 } else if ( gid != (gid_t)-1 &&gid != from_sb.st_gid) {524 } else if (pThis->gid != (gid_t)-1 && pThis->gid != from_sb.st_gid) { 495 525 why_not = "gid mismatch"; 496 } else if ( dos2unix > 0 && needs_dos2unix_conversion(from_name)) {526 } else if (pThis->dos2unix > 0 && needs_dos2unix_conversion(from_name)) { 497 527 why_not = "dos2unix"; 498 } else if ( dos2unix < 0 && needs_unix2dos_conversion(from_name)) {528 } else if (pThis->dos2unix < 0 && needs_unix2dos_conversion(from_name)) { 499 529 why_not = "unix2dos"; 500 530 } else { … … 505 535 } 506 536 if (rcLink == 0) { 507 if (verbose) 508 printf("install: %s -> %s (hardlinked)\n", from_name, to_name); 537 if (pThis->verbose) 538 kmk_builtin_ctx_printf(pThis->pCtx, 0, 539 "install: %s -> %s (hardlinked)\n", from_name, to_name); 509 540 goto l_done; 510 541 } 511 if ( verbose)512 printf("install: hard linking '%s' to '%s' failed: %s\n",542 if (pThis->verbose) 543 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: hard linking '%s' to '%s' failed: %s\n", 513 544 to_name, from_name, strerror(errno)); 514 545 why_not = NULL; 515 546 } 516 547 #endif 517 if ( verbose && why_not)518 printf("install: not hard linking '%s' to '%s' because: %s\n",519 to_name, from_name, why_not);548 if (pThis->verbose && why_not) 549 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: not hard linking '%s' to '%s' because: %s\n", 550 to_name, from_name, why_not); 520 551 521 552 /* Can't hard link or we failed, continue as nothing happend. */ … … 523 554 524 555 if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0) 525 return err( EX_OSERR, "%s", from_name);556 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 526 557 527 558 /* If we don't strip, we can compare first. */ 528 if ( docompare && !dostrip && target) {559 if (pThis->docompare && !pThis->dostrip && target) { 529 560 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 530 rc = err( EX_OSERR, "%s", to_name);561 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 531 562 goto l_done; 532 563 } … … 549 580 sizeof(tempfile)); 550 581 if (to_fd < 0) { 551 rc = err( EX_OSERR, "%s", tempfile);582 rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile); 552 583 goto l_done; 553 584 } 554 585 } else { 555 if ((to_fd = create_newfile(to_name, target, 556 &to_sb)) < 0) { 557 rc = err(EX_OSERR, "%s", to_name); 586 if ((to_fd = create_newfile(pThis, to_name, target, &to_sb)) < 0) { 587 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 558 588 goto l_done; 559 589 } 560 if (verbose) 561 (void)printf("install: %s -> %s\n", 562 from_name, to_name); 590 if (pThis->verbose) 591 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", from_name, to_name); 563 592 } 564 593 if (!devnull) { 565 rc = copy( from_fd, from_name, &to_fd, tempcopy ? tempfile : to_name);594 rc = copy(pThis, from_fd, from_name, &to_fd, tempcopy ? tempfile : to_name); 566 595 if (rc) 567 596 goto l_done; … … 569 598 } 570 599 571 if ( dostrip) {600 if (pThis->dostrip) { 572 601 #if defined(__EMX__) || defined(_MSC_VER) 573 602 /* close before we strip. */ … … 575 604 to_fd = -1; 576 605 #endif 577 rc = strip( tempcopy ? tempfile : to_name);606 rc = strip(pThis, tempcopy ? tempfile : to_name); 578 607 if (rc) 579 608 goto l_done; … … 588 617 to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0); 589 618 if (to_fd < 0) { 590 rc = err( EX_OSERR, "stripping %s", to_name);619 rc = err(pThis->pCtx, EX_OSERR, "stripping %s", to_name); 591 620 goto l_done; 592 621 } … … 596 625 * Compare the stripped temp file with the target. 597 626 */ 598 if ( docompare &&dostrip && target) {627 if (pThis->docompare && pThis->dostrip && target) { 599 628 temp_fd = to_fd; 600 629 601 630 /* Re-open to_fd using the real target name. */ 602 631 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 603 rc = err( EX_OSERR, "%s", to_name);632 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 604 633 goto l_done; 605 634 } … … 609 638 (void)unlink(tempfile); 610 639 errno = serrno; 611 rc = err( EX_OSERR, "%s", tempfile);640 rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile); 612 641 goto l_done; 613 642 } … … 649 678 (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS); 650 679 #endif 651 if ( dobackup) {652 if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,653 suffix) != strlen(to_name) + strlen(suffix)) {680 if (pThis->dobackup) { 681 if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name, pThis->suffix) 682 != strlen(to_name) + strlen(pThis->suffix)) { 654 683 unlink(tempfile); 655 rc = errx( EX_OSERR, "%s: backup filename too long",684 rc = errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long", 656 685 to_name); 657 686 goto l_done; 658 687 } 659 if ( verbose)660 (void)printf("install: %s -> %s\n", to_name, backup);688 if (pThis->verbose) 689 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", to_name, backup); 661 690 if (rename(to_name, backup) < 0) { 662 691 serrno = errno; 663 692 unlink(tempfile); 664 693 errno = serrno; 665 rc = err( EX_OSERR, "rename: %s to %s", to_name,694 rc = err(pThis->pCtx, EX_OSERR, "rename: %s to %s", to_name, 666 695 backup); 667 696 goto l_done; 668 697 } 669 698 } 670 if ( verbose)671 (void)printf("install: %s -> %s\n", from_name, to_name);699 if (pThis->verbose) 700 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", from_name, to_name); 672 701 if (rename(tempfile, to_name) < 0) { 673 702 serrno = errno; 674 703 unlink(tempfile); 675 704 errno = serrno; 676 rc = err(EX_OSERR, "rename: %s to %s", 677 tempfile, to_name); 705 rc = err(pThis->pCtx, EX_OSERR, "rename: %s to %s", tempfile, to_name); 678 706 goto l_done; 679 707 } … … 682 710 (void) close(to_fd); 683 711 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 684 rc = err( EX_OSERR, "%s", to_name);712 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 685 713 goto l_done; 686 714 } … … 690 718 * Preserve the timestamp of the source file if necessary. 691 719 */ 692 if ( dopreserve && !files_match && !devnull) {720 if (pThis->dopreserve && !files_match && !devnull) { 693 721 tvb[0].tv_sec = from_sb.st_atime; 694 722 tvb[0].tv_usec = 0; … … 702 730 (void)unlink(to_name); 703 731 errno = serrno; 704 rc = err( EX_OSERR, "%s", to_name);732 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 705 733 goto l_done; 706 734 } … … 720 748 #endif 721 749 722 if ((gid != (gid_t)-1 && gid != to_sb.st_gid) || 723 (uid != (uid_t)-1 && uid != to_sb.st_uid)) 724 if (fchown(to_fd, uid, gid) == -1) { 725 if (errno == EPERM && ignore_perm_errors) { 726 warn("%s: ignoring chown uid=%d gid=%d failure", to_name, (int)uid, (int)gid); 750 if ((pThis->gid != (gid_t)-1 && pThis->gid != to_sb.st_gid) || 751 (pThis->uid != (uid_t)-1 && pThis->uid != to_sb.st_uid)) 752 if (fchown(to_fd, pThis->uid, pThis->gid) == -1) { 753 if (errno == EPERM && pThis->ignore_perm_errors) { 754 warn(pThis->pCtx, "%s: ignoring chown uid=%d gid=%d failure", 755 to_name, (int)pThis->uid, (int)pThis->gid); 727 756 } else { 728 757 serrno = errno; 729 758 (void)unlink(to_name); 730 759 errno = serrno; 731 rc = err( EX_OSERR,"%s: chown/chgrp", to_name);760 rc = err(pThis->pCtx, EX_OSERR,"%s: chown/chgrp", to_name); 732 761 goto l_done; 733 762 } 734 763 } 735 764 736 if ( mode != (to_sb.st_mode & ALLPERMS))737 if (fchmod(to_fd, mode)) {765 if (pThis->mode != (to_sb.st_mode & ALLPERMS)) 766 if (fchmod(to_fd, pThis->mode)) { 738 767 serrno = errno; 739 if (serrno == EPERM && ignore_perm_errors) {740 fchmod(to_fd, mode & (ALLPERMS & ~0007000));768 if (serrno == EPERM && pThis->ignore_perm_errors) { 769 fchmod(to_fd, pThis->mode & (ALLPERMS & ~0007000)); 741 770 errno = errno; 742 warn( "%s: ignoring chmod 0%o failure", to_name, (int)(mode & ALLPERMS));771 warn(pThis->pCtx, "%s: ignoring chmod 0%o failure", to_name, (int)(pThis->mode & ALLPERMS)); 743 772 } else { 744 773 serrno = errno; 745 774 (void)unlink(to_name); 746 775 errno = serrno; 747 rc = err( EX_OSERR, "%s: chmod", to_name);776 rc = err(pThis->pCtx, EX_OSERR, "%s: chmod", to_name); 748 777 goto l_done; 749 778 } … … 758 787 */ 759 788 #ifdef UF_IMMUTABLE 760 if (!devnull && (flags & SETFLAGS || 761 (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) && 762 fchflags(to_fd, 763 flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { 789 if ( !devnull 790 && (flags & SETFLAGS || (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) 791 && fchflags(to_fd, flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { 764 792 if (flags & SETFLAGS) { 765 793 if (errno == EOPNOTSUPP) 766 warn( "%s: chflags", to_name);794 warn(pThis->pCtx, "%s: chflags", to_name); 767 795 else { 768 796 serrno = errno; 769 797 (void)unlink(to_name); 770 798 errno = serrno; 771 rc = err( EX_OSERR, "%s: chflags", to_name);799 rc = err(pThis->pCtx, EX_OSERR, "%s: chflags", to_name); 772 800 goto l_done; 773 801 } … … 851 879 */ 852 880 int 853 create_newfile( const char *path, int target, struct stat *sbp)881 create_newfile(PINSTALLINSTANCE pThis, const char *path, int target, struct stat *sbp) 854 882 { 855 883 char backup[MAXPATHLEN]; … … 868 896 #endif 869 897 870 if (dobackup) { 871 if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", 872 path, suffix) != strlen(path) + strlen(suffix)) { 873 errx(EX_OSERR, "%s: backup filename too long", 874 path); 898 if (pThis->dobackup) { 899 if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", path, pThis->suffix) 900 != strlen(path) + strlen(pThis->suffix)) { 901 errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long", path); 875 902 errno = ENAMETOOLONG; 876 903 return -1; 877 904 } 878 (void)snprintf(backup, MAXPATHLEN, "%s%s", 879 path, suffix); 880 if (verbose) 881 (void)printf("install: %s -> %s\n", 882 path, backup); 905 (void)snprintf(backup, MAXPATHLEN, "%s%s", path, pThis->suffix); 906 if (pThis->verbose) 907 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", path, backup); 883 908 if (rename(path, backup) < 0) { 884 err( EX_OSERR, "rename: %s to %s", path, backup);909 err(pThis->pCtx, EX_OSERR, "rename: %s to %s", path, backup); 885 910 return -1; 886 911 } … … 899 924 * Write error handler. 900 925 */ 901 static int write_error( int *ptr_to_fd, const char *to_name, int nw)926 static int write_error(PINSTALLINSTANCE pThis, int *ptr_to_fd, const char *to_name, int nw) 902 927 { 903 928 int serrno = errno; … … 906 931 (void)unlink(to_name); 907 932 errno = nw > 0 ? EIO : serrno; 908 return err( EX_OSERR, "%s", to_name);933 return err(pThis->pCtx, EX_OSERR, "%s", to_name); 909 934 } 910 935 … … 912 937 * Read error handler. 913 938 */ 914 static int read_error( const char *from_name, int *ptr_to_fd, const char *to_name)939 static int read_error(PINSTALLINSTANCE pThis, const char *from_name, int *ptr_to_fd, const char *to_name) 915 940 { 916 941 int serrno = errno; … … 919 944 (void)unlink(to_name); 920 945 errno = serrno; 921 return err( EX_OSERR, "%s", from_name);946 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 922 947 } 923 948 … … 927 952 */ 928 953 static int 929 copy( int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name)954 copy(PINSTALLINSTANCE pThis, int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name) 930 955 { 931 956 KBOOL fPendingCr = K_FALSE; … … 937 962 /* Rewind file descriptors. */ 938 963 if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1) 939 return err( EX_OSERR, "lseek: %s", from_name);964 return err(pThis->pCtx, EX_OSERR, "lseek: %s", from_name); 940 965 if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1) 941 return err( EX_OSERR, "lseek: %s", to_name);942 943 if ( dos2unix == 0) {966 return err(pThis->pCtx, EX_OSERR, "lseek: %s", to_name); 967 968 if (pThis->dos2unix == 0) { 944 969 /* 945 970 * Copy bytes, no conversion. … … 947 972 while ((nr = read(from_fd, buf, sizeof(buf))) > 0) 948 973 if ((nw = write(to_fd, buf, nr)) != nr) 949 return write_error(p tr_to_fd, to_name, nw);950 } else if ( dos2unix > 0) {974 return write_error(pThis, ptr_to_fd, to_name, nw); 975 } else if (pThis->dos2unix > 0) { 951 976 /* 952 977 * CRLF -> LF is a reduction, so we can work with full buffers. … … 956 981 && buf[0] != '\n' 957 982 && (nw = write(to_fd, "\r", 1)) != 1) 958 return write_error(p tr_to_fd, to_name, nw);983 return write_error(pThis, ptr_to_fd, to_name, nw); 959 984 960 985 fPendingCr = dos2unix_convert_to_unix(buf, nr, buf, &cchDst); … … 962 987 nw = write(to_fd, buf, cchDst); 963 988 if (nw != (int)cchDst) 964 return write_error(p tr_to_fd, to_name, nw);989 return write_error(pThis, ptr_to_fd, to_name, nw); 965 990 } 966 991 } else { … … 978 1003 && pchSrc[0] != '\n' 979 1004 && (nw = write(to_fd, "\r", 1))!= 1) 980 return write_error(p tr_to_fd, to_name, nw);1005 return write_error(pThis, ptr_to_fd, to_name, nw); 981 1006 982 1007 fPendingCr = dos2unix_convert_to_dos(pchSrc, nr, buf, &cchDst); … … 984 1009 nw = write(to_fd, buf, cchDst); 985 1010 if (nw != (int)cchDst) 986 return write_error(p tr_to_fd, to_name, nw);1011 return write_error(pThis, ptr_to_fd, to_name, nw); 987 1012 } 988 1013 } … … 990 1015 /* Check for read error. */ 991 1016 if (nr != 0) 992 return read_error( from_name, ptr_to_fd, to_name);1017 return read_error(pThis, from_name, ptr_to_fd, to_name); 993 1018 994 1019 /* When converting, we might have a pending final CR to write. */ 995 996 997 return write_error(p tr_to_fd, to_name, nw);1020 if ( fPendingCr 1021 && (nw = write(to_fd, "\r", 1))!= 1) 1022 return write_error(pThis, ptr_to_fd, to_name, nw); 998 1023 999 1024 return EX_OK; … … 1005 1030 */ 1006 1031 static int 1007 strip( const char *to_name)1032 strip(PINSTALLINSTANCE pThis, const char *to_name) 1008 1033 { 1009 1034 #if defined(__EMX__) || defined(_MSC_VER) … … 1011 1036 if (stripbin == NULL) 1012 1037 stripbin = "strip"; 1038 (void)pThis; 1013 1039 return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL); 1014 1040 #else … … 1023 1049 (void)unlink(to_name); 1024 1050 errno = serrno; 1025 return err( EX_TEMPFAIL, "fork");1051 return err(pThis->pCtx, EX_TEMPFAIL, "fork"); 1026 1052 case 0: 1027 1053 stripbin = getenv("STRIPBIN"); … … 1029 1055 stripbin = "strip"; 1030 1056 execlp(stripbin, stripbin, to_name, (char *)NULL); 1031 err( EX_OSERR, "exec(%s)", stripbin);1057 err(pThis->pCtx, EX_OSERR, "exec(%s)", stripbin); 1032 1058 exit(EX_OSERR); 1033 1059 default: … … 1036 1062 (void)unlink(to_name); 1037 1063 errno = serrno; 1038 return err( EX_SOFTWARE, "waitpid");1064 return err(pThis->pCtx, EX_SOFTWARE, "waitpid"); 1039 1065 /* NOTREACHED */ 1040 1066 } … … 1049 1075 */ 1050 1076 static int 1051 install_dir( char *path)1077 install_dir(PINSTALLINSTANCE pThis, char *path) 1052 1078 { 1053 1079 char *p; … … 1067 1093 if (stat(path, &sb)) { 1068 1094 if (errno != ENOENT || mkdir(path, 0755) < 0) { 1069 return err( EX_OSERR, "mkdir %s", path);1095 return err(pThis->pCtx, EX_OSERR, "mkdir %s", path); 1070 1096 /* NOTREACHED */ 1071 } else if (verbose) 1072 (void)printf("install: mkdir %s\n", 1073 path); 1097 } else if (pThis->verbose) 1098 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: mkdir %s\n", path); 1074 1099 } else if (!S_ISDIR(sb.st_mode)) 1075 return errx( EX_OSERR, "%s exists but is not a directory", path);1100 return errx(pThis->pCtx, EX_OSERR, "%s exists but is not a directory", path); 1076 1101 if (!(*p = ch)) 1077 1102 break; 1078 1103 } 1079 1104 1080 if (( gid != (gid_t)-1 || uid != (uid_t)-1) && chown(path, uid,gid))1081 warn( "chown %u:%u %s", uid,gid, path);1082 if (chmod(path, mode))1083 warn( "chmod %o %s",mode, path);1105 if ((pThis->gid != (gid_t)-1 || pThis->uid != (uid_t)-1) && chown(path, pThis->uid, pThis->gid)) 1106 warn(pThis->pCtx, "chown %u:%u %s", pThis->uid, pThis->gid, path); 1107 if (chmod(path, pThis->mode)) 1108 warn(pThis->pCtx, "chmod %o %s", pThis->mode, path); 1084 1109 return EX_OK; 1085 1110 } … … 1090 1115 */ 1091 1116 static int 1092 usage( FILE *pf)1093 { 1094 fprintf(pf,1117 usage(PKMKBUILTINCTX pCtx, int fIsErr) 1118 { 1119 kmk_builtin_ctx_printf(pCtx, fIsErr, 1095 1120 "usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n" 1096 1121 " [--[no-]ignore-perm-errors] [-B suffix] [-f flags] [-g group]\n" … … 1101 1126 " or: %s --help\n" 1102 1127 " or: %s --version\n", 1103 g_progname, g_progname, g_progname, g_progname, g_progname); 1128 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, 1129 pCtx->pszProgName, pCtx->pszProgName); 1104 1130 return EX_USAGE; 1105 1131 } -
trunk/src/kmk/kmkbuiltin/kDepIDB.c
r3167 r3192 46 46 #include "k/kTypes.h" 47 47 #include "kDep.h" 48 #include "err.h" 48 49 #include "kmkbuiltin.h" 49 50 … … 66 67 typedef struct KDEPIDBGLOBALS 67 68 { 69 PKMKBUILTINCTX pCtx; 68 70 DEPGLOBALS Core; 69 const char *argv0;70 71 } KDEPIDBGLOBALS; 71 72 typedef KDEPIDBGLOBALS *PKDEPIDBGLOBALS; … … 197 198 { 198 199 if (pHdr->cbPage * pHdr->cPages != cbFile) 199 { 200 fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", pThis->argv0); 201 return 1; 202 } 200 return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - cbPage * cPages != cbFile."); 203 201 if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0) 204 { 205 fprintf(stderr, "%s: error: Bad PDB 2.0 header - iStartPage=%u cPages=%u.\n", pThis->argv0, 206 pHdr->iStartPage, pHdr->cPages); 207 return 1; 208 } 202 return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - iStartPage=%u cPages=%u.", 203 pHdr->iStartPage, pHdr->cPages); 209 204 if (pHdr->iRootPages >= pHdr->cPages && pHdr->iRootPages <= 0) 210 { 211 fprintf(stderr, "%s: error: Bad PDB 2.0 header - iRootPages=%u cPage=%u.\n", pThis->argv0, 212 pHdr->iStartPage, pHdr->cPages); 213 return 1; 214 } 205 return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - iRootPages=%u cPage=%u.", 206 pHdr->iStartPage, pHdr->cPages); 215 207 return 0; 216 208 } … … 251 243 else 252 244 { 253 fprintf(stderr, "%s: warning: Invalid page index %u (max %u)!\n", pThis->argv0, 254 (unsigned)off, pHdr->cPages); 245 warnx(pThis->pCtx, "warning: Invalid page index %u (max %u)!\n", (unsigned)off, pHdr->cPages); 255 246 memset(pbBuf + iPage * cbPage, 0, cbPage); 256 247 } … … 261 252 } 262 253 else 263 fprintf(stderr, "%s: error: failed to allocate %lu bytes\n", pThis->argv0, (unsigned long)(cPages * cbPage + 1)); 254 { 255 errx(pThis->pCtx, 1, "failed to allocate %lu bytes", (unsigned long)(cPages * cbPage + 1)); 256 return NULL; 257 } 264 258 return pbBuf; 265 259 } … … 311 305 || cbStream == ~(KU32)0) 312 306 { 313 fprintf(stderr, "%s: error: Invalid stream %d\n", pThis->argv0, iStream);307 errx(pThis->pCtx, 1, "Invalid stream %d", iStream); 314 308 return NULL; 315 309 } … … 493 487 { 494 488 if (pHdr->cbPage * pHdr->cPages != cbFile) 495 { 496 fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", pThis->argv0); 497 return 1; 498 } 489 return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - cbPage * cPages != cbFile."); 499 490 if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0) 500 { 501 fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", pThis->argv0); 502 return 1; 503 } 491 return errx(pThis->pCtx, 1, "Bad PDB 2.0 header - cbPage * cPages != cbFile."); 504 492 return 0; 505 493 } … … 529 517 } 530 518 else 531 fprintf(stderr, "%s: error: failed to allocate %lu bytes\n", pThis->argv0, (unsigned long)(cPages * pHdr->cbPage + 1));519 errx(pThis->pCtx, 1, "failed to allocate %lu bytes", (unsigned long)(cPages * pHdr->cbPage + 1)); 532 520 return pbBuf; 533 521 } … … 573 561 || cbStream == ~(KU32)0) 574 562 { 575 fprintf(stderr, "%s: error: Invalid stream %d\n", pThis->argv0, iStream);563 errx(pThis->pCtx, 1, "Invalid stream %d", iStream); 576 564 return NULL; 577 565 } … … 653 641 rc = Pdb20Process(pThis, pbFile, cbFile); 654 642 else 655 { 656 fprintf(stderr, "%s: error: Doesn't recognize the header of the Visual C++ IDB file.\n", pThis->argv0); 657 rc = 1; 658 } 643 rc = errx(pThis->pCtx, 1, "Doesn't recognize the header of the Visual C++ IDB file."); 659 644 660 645 depFreeFileMemory(pbFile, pvOpaque); … … 663 648 664 649 665 static void kDepIDBUsage(const char *a_argv0) 666 { 667 printf("usage: %s -o <output> -t <target> [-fqs] <vc idb-file>\n" 668 " or: %s --help\n" 669 " or: %s --version\n", 670 a_argv0, a_argv0, a_argv0); 671 } 672 673 674 int kmk_builtin_kDepIDB(int argc, char *argv[], char **envp) 650 static void kDepIDBUsage(PKMKBUILTINCTX pCtx, int fIsErr) 651 { 652 kmk_builtin_ctx_printf(pCtx, fIsErr, 653 "usage: %s -o <output> -t <target> [-fqs] <vc idb-file>\n" 654 " or: %s --help\n" 655 " or: %s --version\n", 656 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 657 } 658 659 660 int kmk_builtin_kDepIDB(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 675 661 { 676 662 int i; … … 689 675 690 676 /* Init the instance data. */ 691 This. argv0 = argv[0];677 This.pCtx = pCtx; 692 678 693 679 /* … … 696 682 if (argc <= 1) 697 683 { 698 kDepIDBUsage( This.argv0);684 kDepIDBUsage(pCtx, 0); 699 685 return 1; 700 686 } … … 723 709 pszOutput = &argv[i][2]; 724 710 if (pOutput) 725 { 726 fprintf(stderr, "%s: syntax error: only one output file!\n", This.argv0); 727 return 1; 728 } 711 return errx(pCtx, 2, "only one output file!"); 729 712 if (!*pszOutput) 730 713 { 731 714 if (++i >= argc) 732 { 733 fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", This.argv0); 734 return 1; 735 } 715 return errx(pCtx, 2, "The '-o' argument is missing the filename."); 736 716 pszOutput = argv[i]; 737 717 } … … 741 721 pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE); 742 722 if (!pOutput) 743 { 744 fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", This.argv0, pszOutput); 745 return 1; 746 } 723 return err(pCtx, 1, "Failed to create output file '%s'", pszOutput); 747 724 break; 748 725 } … … 754 731 { 755 732 if (pszTarget) 756 { 757 fprintf(stderr, "%s: syntax error: only one target!\n", This.argv0); 758 return 1; 759 } 733 return errx(pCtx, 2, "only one target!"); 760 734 pszTarget = &argv[i][2]; 761 735 if (!*pszTarget) 762 736 { 763 737 if (++i >= argc) 764 { 765 fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", This.argv0); 766 return 1; 767 } 738 return errx(pCtx, 2, "The '-t' argument is missing the target name."); 768 739 pszTarget = argv[i]; 769 740 } … … 802 773 */ 803 774 case '?': 804 kDepIDBUsage( This.argv0);775 kDepIDBUsage(pCtx, 0); 805 776 return 0; 806 777 case 'V': 807 778 case 'v': 808 return kbuild_version( This.argv0);779 return kbuild_version(pCtx->pszProgName); 809 780 810 781 /* … … 812 783 */ 813 784 default: 814 fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", This.argv0, argv[i]);815 kDepIDBUsage( This.argv0);816 return 1;785 errx(pCtx, 2, "Invalid argument '%s.'", argv[i]); 786 kDepIDBUsage(pCtx, 1); 787 return 2; 817 788 } 818 789 } … … 821 792 pInput = fopen(argv[i], "rb" KMK_FOPEN_NO_INHERIT_MODE); 822 793 if (!pInput) 823 { 824 fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", This.argv0, argv[i]); 825 return 1; 826 } 794 return err(pCtx, 1, "Failed to open input file '%s'", argv[i]); 827 795 fInput = 1; 828 796 } … … 834 802 { 835 803 if (++i < argc) 836 { 837 fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", This.argv0); 838 return 1; 839 } 804 return errx(pCtx, 2, "No arguments shall follow the input spec."); 840 805 break; 841 806 } … … 846 811 */ 847 812 if (!pInput) 848 { 849 fprintf(stderr, "%s: syntax error: No input!\n", This.argv0); 850 return 1; 851 } 813 return errx(pCtx, 2, "No input!"); 852 814 if (!pOutput) 853 { 854 fprintf(stderr, "%s: syntax error: No output!\n", This.argv0); 855 return 1; 856 } 815 return errx(pCtx, 2, "No output!"); 857 816 if (!pszTarget) 858 { 859 fprintf(stderr, "%s: syntax error: No target!\n", This.argv0); 860 return 1; 861 } 817 return errx(pCtx, 2, "No target!"); 862 818 863 819 /* … … 884 840 */ 885 841 if (!i && ferror(pOutput)) 886 { 887 i = 1; 888 fprintf(stderr, "%s: error: Error writing to '%s'.\n", This.argv0, pszOutput); 889 } 842 i = errx(pCtx, 1, "Error writing to '%s'.", pszOutput); 890 843 fclose(pOutput); 891 844 if (i) 892 845 { 893 846 if (unlink(pszOutput)) 894 fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", This.argv0, pszOutput);847 warnx(pCtx, "warning: failed to remove output file '%s' on failure.", pszOutput); 895 848 } 896 849 … … 899 852 } 900 853 854 #ifdef KMK_BUILTIN_STANDALONE 855 int main(int argc, char **argv, char **envp) 856 { 857 KMKBUILTINCTX Ctx = { "kmk_kDepIDB", NULL }; 858 return kmk_builtin_kDepIDB(argc, argv, envp, &Ctx); 859 } 860 #endif 861 -
trunk/src/kmk/kmkbuiltin/kDepObj.c
r3167 r3192 39 39 #else 40 40 # include <io.h> 41 typedef intptr_t ssize_t; 41 42 #endif 42 43 #include "k/kDefs.h" … … 44 45 #include "k/kLdrFmts/pe.h" 45 46 #include "kDep.h" 47 #include "err.h" 46 48 #include "kmkbuiltin.h" 47 49 … … 170 172 typedef struct KDEPOBJGLOBALS 171 173 { 174 /** The command execution context. */ 175 PKMKBUILTINCTX pCtx; 172 176 /** Core instance. */ 173 177 DEPGLOBALS Core; 174 /** the executable name. */175 const char *argv0;176 178 /** The file. */ 177 179 const char *pszFile; … … 194 196 static int kDepErr(PKDEPOBJGLOBALS pThis, int rc, const char *pszFormat, ...) 195 197 { 198 char szMsg[2048]; 196 199 va_list va; 197 const char *psz; 198 const char *pszName = pThis->argv0; 199 200 fflush(stdout); 201 202 /* The message prefix. */ 203 while ((psz = strpbrk(pszName, "/\\:")) != NULL) 204 pszName = psz + 1; 200 va_start(va, pszFormat); 201 vsnprintf(szMsg, sizeof(szMsg) - 1, pszFormat, va); 202 va_end(va); 203 szMsg[sizeof(szMsg) - 1] = '\0'; 205 204 206 205 if (pThis->pszFile) 207 fprintf(stderr, "%s: %s: error: ", pszName, pThis->pszFile);206 warnx(pThis->pCtx, "%s: error: %s", pThis->pszFile, szMsg); 208 207 else 209 fprintf(stderr, "%s: error: ", pszName); 210 211 /* The message. */ 212 va_start(va, pszFormat); 213 vfprintf(stderr, pszFormat, va); 214 va_end(va); 215 208 errx(pThis->pCtx, rc, "%s", szMsg); 216 209 return rc; 217 210 } … … 294 287 PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr; 295 288 if (1 + pTHeadr->Name.cch + 1 != pHdr->cbRec) 296 return kDepErr(pThis, 1, "%#07x - Bad %cHEADR record, length mismatch. \n",289 return kDepErr(pThis, 1, "%#07x - Bad %cHEADR record, length mismatch.", 297 290 (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L'); 298 291 if ( ( pTHeadr->Name.cch > 2 … … 325 318 326 319 if (pHdr->cbRec < 2 + 1) 327 return kDepErr(pThis, 1, "%#07x - Bad COMMENT record, too small. \n", (const KU8*)pHdr - pbFile);320 return kDepErr(pThis, 1, "%#07x - Bad COMMENT record, too small.", (const KU8*)pHdr - pbFile); 328 321 if (uData.pb[0] & 0x3f) 329 return kDepErr(pThis, 1, "%#07x - Bad COMMENT record, reserved flags set. \n", (const KU8*)pHdr - pbFile);322 return kDepErr(pThis, 1, "%#07x - Bad COMMENT record, reserved flags set.", (const KU8*)pHdr - pbFile); 330 323 uClass = uData.pb[1]; 331 324 uData.pb += 2; … … 344 337 if (pHdr->cbRec == 2 + 1) 345 338 return 0; 346 return kDepErr(pThis, 1, "%#07lx - Bad DEPENDENCY FILE record, length mismatch. (%u/%u) \n",339 return kDepErr(pThis, 1, "%#07lx - Bad DEPENDENCY FILE record, length mismatch. (%u/%u)", 347 340 (long)((const KU8 *)pHdr - pbFile), 348 341 K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1, … … 398 391 KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft); 399 392 if (uSeg == KU16_MAX) 400 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record \n", (long)((const KU8 *)pHdr - pbFile));393 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record", (long)((const KU8 *)pHdr - pbFile)); 401 394 K_NOREF(uGrp); 402 395 … … 415 408 416 409 if (cbRecLeft < 2+1+1+2+2+4) 417 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, too short \n", (long)((const KU8 *)pHdr - pbFile));410 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, too short", (long)((const KU8 *)pHdr - pbFile)); 418 411 cbRecLeft -= 2+1+1+2+2+4; 419 412 uLine = *uData.pu16++; … … 431 424 432 425 if (uLine != 0) 433 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ) \n", (long)((const KU8 *)pHdr - pbFile), uLine);426 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ)", (long)((const KU8 *)pHdr - pbFile), uLine); 434 427 cLinFiles = iLinFile = KU32_MAX; 435 428 if ( uLinNumType == 3 /* file names table */ … … 437 430 cLinNums = 0; /* no line numbers */ 438 431 else if (uLinNumType > 4) 439 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, type %#x unknown \n", (long)((const KU8 *)pHdr - pbFile), uLinNumType);432 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, type %#x unknown", (long)((const KU8 *)pHdr - pbFile), uLinNumType); 440 433 } 441 434 else … … 452 445 { 453 446 if (cbRecLeft < cbEntry) 454 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, incomplete line entry \n", (long)((const KU8 *)pHdr - pbFile));447 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, incomplete line entry", (long)((const KU8 *)pHdr - pbFile)); 455 448 456 449 switch (uLinNumType) … … 492 485 493 486 if (cbRecLeft < 4+4+4) 494 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header \n", (long)((const KU8 *)pHdr - pbFile));487 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header", (long)((const KU8 *)pHdr - pbFile)); 495 488 cbRecLeft -= 4+4+4; 496 489 … … 501 494 uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols)); 502 495 if (cLinFiles == KU32_MAX) 503 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, too many file/path table entries. \n", (long)((const KU8 *)pHdr - pbFile));496 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, too many file/path table entries.", (long)((const KU8 *)pHdr - pbFile)); 504 497 iLinFile = 0; 505 498 } … … 510 503 int cbName = *uData.pb++; 511 504 if (cbRecLeft < 1 + cbName) 512 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, file/path table entry too long. \n", (long)((const KU8 *)pHdr - pbFile));505 return kDepErr(pThis, 1, "%#07lx - Bad LINNUM32 record, file/path table entry too long.", (long)((const KU8 *)pHdr - pbFile)); 513 506 iLinFile++; 514 507 dprintf(("#%" KU32_PRI": %.*s\n", iLinFile, cbName, uData.pch)); … … 542 535 543 536 if (cbLeft) 544 return kDepErr(pThis, 1, "%#07x - Unexpected EOF. cbLeft=%#x \n", (const KU8*)pHdr - pbFile, cbLeft);537 return kDepErr(pThis, 1, "%#07x - Unexpected EOF. cbLeft=%#x", (const KU8*)pHdr - pbFile, cbLeft); 545 538 546 539 if (iSrc == 0 && iMaybeSrc <= 1) … … 612 605 if (off + sizeof(*pHdr) >= cbSyms) 613 606 { 614 fprintf(stderr, "%s: CV symbol table entry at %08" KX32_PRI " is too long; cbSyms=%#" KX32_PRI "\n",615 pThis->argv0,off, cbSyms);607 kDepErr(pThis, 1, "CV symbol table entry at %08" KX32_PRI " is too long; cbSyms=%#" KX32_PRI "", 608 off, cbSyms); 616 609 return 1; /* FIXME */ 617 610 } … … 620 613 if (off + cbData + sizeof(*pHdr) > cbSyms) 621 614 { 622 fprintf(stderr, "%s: CV symbol table entry at %08" KX32_PRI " is too long; cbData=%#" KX32_PRI " cbSyms=%#" KX32_PRI "\n",623 pThis->argv0,off, cbData, cbSyms);615 kDepErr(pThis, 1, "CV symbol table entry at %08" KX32_PRI " is too long; cbData=%#" KX32_PRI " cbSyms=%#" KX32_PRI, 616 off, cbData, cbSyms); 624 617 return 1; /* FIXME */ 625 618 } … … 645 638 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData)); 646 639 if (pchStrTab) 647 fprintf(stderr, "%s: warning: Found yet another string table!\n", pThis->argv0);640 warnx(pThis->pCtx, "%s: warning: Found yet another string table!", pThis->pszFile); 648 641 pchStrTab = uData.pch; 649 642 cbStrTab = cbData; … … 654 647 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData)); 655 648 if (uSrcFiles.pb) 656 fprintf(stderr, "%s: warning: Found yet another source files table!\n", pThis->argv0);649 warnx(pThis->pCtx, "%s: warning: Found yet another source files table!", pThis->pszFile); 657 650 uSrcFiles = uData; 658 651 cbSrcFiles = cbData; … … 703 696 */ 704 697 if (off + 8 > cbSrcFiles) 705 { 706 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KX32_PRI "\n", 707 pThis->argv0, off, cbSrcFiles); 708 return 1; 709 } 698 return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KX32_PRI, 699 off, cbSrcFiles); 710 700 uSrc.pb = uSrcFiles.pb + off; 711 701 u16Type = uSrc.pu16[2]; 712 702 cbSrc = u16Type == 0x0110 ? 6 + 16 + 2 : 6 + 2; 713 703 if (off + cbSrc > cbSrcFiles) 714 { 715 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KX32_PRI "\n", 716 pThis->argv0, off, cbSrc, cbSrcFiles); 717 return 1; 718 } 704 return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KX32_PRI, 705 off, cbSrc, cbSrcFiles); 719 706 720 707 offFile = *uSrc.pu32; 721 708 if (offFile > cbStrTab) 722 { 723 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is out side the string table; offFile=%#" KX32_PRI " cbStrTab=%#" KX32_PRI "\n", 724 pThis->argv0, off, offFile, cbStrTab); 725 return 1; 726 } 709 return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " is out side the string table; offFile=%#" KX32_PRI " cbStrTab=%#" KX32_PRI, 710 off, offFile, cbStrTab); 727 711 pszFile = pchStrTab + offFile; 728 712 cchFile = strlen(pszFile); 729 713 if (cchFile == 0) 730 { 731 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " has an empty file name; offFile=%#x" KX32_PRI "\n", 732 pThis->argv0, off, offFile); 733 return 1; 734 } 714 return kDepErr(pThis, 1, "CV source file entry at %08" KX32_PRI " has an empty file name; offFile=%#x" KX32_PRI, 715 off, offFile); 735 716 736 717 /* … … 822 803 * @returns K_TRUE if it's COFF, K_FALSE otherwise. 823 804 * 805 * @param pThis The kDepObj instance data. 824 806 * @param pb The start of the file. 825 807 * @param cb The file size. 826 808 */ 827 KBOOL kDepObjCOFFTest( const KU8 *pbFile, KSIZE cbFile)809 KBOOL kDepObjCOFFTest(PKDEPOBJGLOBALS pThis, const KU8 *pbFile, KSIZE cbFile) 828 810 { 829 811 IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; … … 864 846 && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_EBC) 865 847 { 866 fprintf(stderr, "kDepObj: error: bigobj Machine not supported: %#x\n", pBigObjHdr->Machine);848 kDepErr(pThis, 1, "bigobj Machine not supported: %#x", pBigObjHdr->Machine); 867 849 return K_FALSE; 868 850 } 869 851 if (pBigObjHdr->Flags != 0) 870 852 { 871 fprintf(stderr, "kDepObj: error: bigobj Flags field is non-zero: %#x\n", pBigObjHdr->Flags);853 kDepErr(pThis, 1, "bigobj Flags field is non-zero: %#x", pBigObjHdr->Flags); 872 854 return K_FALSE; 873 855 } 874 856 if (pBigObjHdr->SizeOfData != 0) 875 857 { 876 fprintf(stderr, "kDepObj: error: bigobj SizeOfData field is non-zero: %#x\n", pBigObjHdr->SizeOfData);858 kDepErr(pThis, 1, "bigobj SizeOfData field is non-zero: %#x", pBigObjHdr->SizeOfData); 877 859 return K_FALSE; 878 860 } … … 977 959 if (kDepObjOMFTest(pbFile, cbFile)) 978 960 rc = kDepObjOMFParse(pThis, pbFile, cbFile); 979 else if (kDepObjCOFFTest(p bFile, cbFile))961 else if (kDepObjCOFFTest(pThis, pbFile, cbFile)) 980 962 rc = kDepObjCOFFParse(pThis, pbFile, cbFile); 981 963 else 982 { 983 fprintf(stderr, "%s: error: Doesn't recognize the header of the OMF/COFF file.\n", pThis->argv0); 984 rc = 1; 985 } 964 rc = kDepErr(pThis, 1, "Doesn't recognize the header of the OMF/COFF file."); 986 965 987 966 depFreeFileMemory(pbFile, pvOpaque); … … 990 969 991 970 992 static void kDebObjUsage(const char *a_argv0) 993 { 994 printf("usage: %s -o <output> -t <target> [-fqs] [-e <ignore-ext>] <OMF or COFF file>\n" 995 " or: %s --help\n" 996 " or: %s --version\n", 997 a_argv0, a_argv0, a_argv0); 971 static void kDebObjUsage(PKMKBUILTINCTX pCtx, int fIsErr) 972 { 973 kmk_builtin_ctx_printf(pCtx, fIsErr, 974 "usage: %s -o <output> -t <target> [-fqs] [-e <ignore-ext>] <OMF or COFF file>\n" 975 " or: %s --help\n" 976 " or: %s --version\n", 977 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 998 978 } 999 979 1000 980 1001 int kmk_builtin_kDepObj(int argc, char * argv[], char **envp)981 int kmk_builtin_kDepObj(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 1002 982 { 1003 983 int i; … … 1017 997 1018 998 /* Init instance data. */ 1019 This. argv0 = argv[0];999 This.pCtx = pCtx; 1020 1000 This.pszFile = NULL; 1021 1001 … … 1025 1005 if (argc <= 1) 1026 1006 { 1027 kDebObjUsage( argv[0]);1007 kDebObjUsage(pCtx, 0); 1028 1008 return 1; 1029 1009 } … … 1047 1027 else 1048 1028 { 1049 fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]);1050 kDebObjUsage( argv[0]);1029 errx(pCtx, 2, "Invalid argument '%s'.", argv[i]); 1030 kDebObjUsage(pCtx, 1); 1051 1031 return 2; 1052 1032 } … … 1067 1047 pszValue = argv[i]; 1068 1048 else 1069 { 1070 fprintf(stderr, "%s: syntax error: The '-%c' option takes a value.\n", argv[0], chOpt); 1071 return 2; 1072 } 1049 return errx(pCtx, 2, "The '-%c' option takes a value.", chOpt); 1073 1050 break; 1074 1051 … … 1087 1064 { 1088 1065 if (pOutput) 1089 { 1090 fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]); 1091 return 2; 1092 } 1066 return errx(pCtx, 2, "only one output file!"); 1093 1067 pszOutput = pszValue; 1094 1068 if (pszOutput[0] == '-' && !pszOutput[1]) … … 1097 1071 pOutput = fopen(pszOutput, "w"); 1098 1072 if (!pOutput) 1099 { 1100 fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput); 1101 return 1; 1102 } 1073 return err(pCtx, 1, "Failed to create output file '%s'", pszOutput); 1103 1074 break; 1104 1075 } … … 1110 1081 { 1111 1082 if (pszTarget) 1112 { 1113 fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]); 1114 return 1; 1115 } 1083 return errx(pCtx, 2, "only one target!"); 1116 1084 pszTarget = pszValue; 1117 1085 break; … … 1151 1119 { 1152 1120 if (pszIgnoreExt) 1153 { 1154 fprintf(stderr, "%s: syntax error: The '-e' option can only be used once!\n", argv[0]); 1155 return 2; 1156 } 1121 return errx(pCtx, 2, "The '-e' option can only be used once!"); 1157 1122 pszIgnoreExt = pszValue; 1158 1123 break; … … 1163 1128 */ 1164 1129 case '?': 1165 kDebObjUsage( argv[0]);1130 kDebObjUsage(pCtx, 0); 1166 1131 return 0; 1167 1132 case 'V': … … 1173 1138 */ 1174 1139 default: 1175 fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]);1176 kDebObjUsage( argv[0]);1140 errx(pCtx, 2, "Invalid argument '%s'.", argv[i]); 1141 kDebObjUsage(pCtx, 1); 1177 1142 return 2; 1178 1143 } … … 1182 1147 pInput = fopen(argv[i], "rb"); 1183 1148 if (!pInput) 1184 { 1185 fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]); 1186 return 1; 1187 } 1149 return err(pCtx, 1, "Failed to open input file '%s'", argv[i]); 1188 1150 fInput = 1; 1189 1151 } … … 1195 1157 { 1196 1158 if (++i < argc) 1197 { 1198 fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]); 1199 return 1; 1200 } 1159 return errx(pCtx, 2, "No arguments shall follow the input spec."); 1201 1160 break; 1202 1161 } … … 1207 1166 */ 1208 1167 if (!pInput) 1209 { 1210 fprintf(stderr, "%s: syntax error: No input!\n", argv[0]); 1211 return 1; 1212 } 1168 return errx(pCtx, 2, "No input!"); 1213 1169 if (!pOutput) 1214 { 1215 fprintf(stderr, "%s: syntax error: No output!\n", argv[0]); 1216 return 1; 1217 } 1170 return errx(pCtx, 2, "No output!"); 1218 1171 if (!pszTarget) 1219 { 1220 fprintf(stderr, "%s: syntax error: No target!\n", argv[0]); 1221 return 1; 1222 } 1172 return errx(pCtx, 2, "No target!"); 1223 1173 1224 1174 /* … … 1245 1195 */ 1246 1196 if (!i && ferror(pOutput)) 1247 { 1248 i = 1; 1249 fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput); 1250 } 1197 i = errx(pCtx, 1, "Error writing to '%s'", pszOutput); 1251 1198 fclose(pOutput); 1252 1199 if (i) 1253 1200 { 1254 1201 if (unlink(pszOutput)) 1255 fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput);1202 warn(pCtx, "warning: failed to remove output file '%s' on failure.", pszOutput); 1256 1203 } 1257 1204 … … 1260 1207 } 1261 1208 1209 #ifdef KMK_BUILTIN_STANDALONE 1210 int main(int argc, char **argv, char **envp) 1211 { 1212 KMKBUILTINCTX Ctx = { "kDepObj", NULL }; 1213 return kmk_builtin_kDepObj(argc, argv, envp, &Ctx); 1214 } 1215 #endif 1216 -
trunk/src/kmk/kmkbuiltin/kSubmit.c
r3173 r3192 293 293 * 294 294 * @returns 0 on success, non-zero value on failure. 295 * @param pCtx The command execution context. 295 296 * @param pWorker The worker structure. Caller does the linking 296 297 * (as we might be reusing an existing worker … … 299 300 * @param cVerbosity The verbosity level. 300 301 */ 301 static int kSubmitSpawnWorker(P WORKERINSTANCE pWorker, int cVerbosity)302 static int kSubmitSpawnWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity) 302 303 { 303 304 #if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) … … 319 320 pVarVolatile = lookup_variable(TUPLE("PATH_OUT_BASE")); 320 321 if (!pVarVolatile) 321 warn( "Neither PATH_OUT_BASE nor PATH_OUT was found.");322 warn(pCtx, "Neither PATH_OUT_BASE nor PATH_OUT was found."); 322 323 } 323 324 … … 346 347 if ( cchBinPath < sizeof(g_szArch) 347 348 || memcmp(&szExecutable[cchBinPath - sizeof(g_szArch) + 1], g_szArch, sizeof(g_szArch) - 1) != 0) 348 return errx(1, "KBUILD_BIN_PATH does not end with main architecture (%s) as expected: %s", pszBinPath, g_szArch); 349 return errx(pCtx, 1, "KBUILD_BIN_PATH does not end with main architecture (%s) as expected: %s", 350 pszBinPath, g_szArch); 349 351 cchExectuable -= sizeof(g_szArch) - 1; 350 352 memcpy(&szExecutable[cchExectuable], g_szAltArch, sizeof(g_szAltArch) - 1); … … 417 419 pWorker->pid = GetProcessId(pWorker->hProcess); 418 420 if (cVerbosity > 0) 419 fprintf(stderr, "kSubmit:created %d bit worker %d\n", pWorker->cBits, pWorker->pid);421 warnx(pCtx, "created %d bit worker %d\n", pWorker->cBits, pWorker->pid); 420 422 return 0; 421 423 } 422 err( 1, "_spawnve(,%s,,)", szExecutable);424 err(pCtx, 1, "_spawnve(,%s,,)", szExecutable); 423 425 CloseHandle(pWorker->OverlappedRead.hEvent); 424 426 pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE; 425 427 } 426 428 else 427 errx( 1, "CreateEventW failed: %u", GetLastError());429 errx(pCtx, 1, "CreateEventW failed: %u", GetLastError()); 428 430 CloseHandle(pWorker->hPipe); 429 431 pWorker->hPipe = INVALID_HANDLE_VALUE; 430 432 } 431 433 else 432 errx( 1, "Opening named pipe failed: %u", GetLastError());434 errx(pCtx, 1, "Opening named pipe failed: %u", GetLastError()); 433 435 CloseHandle(hWorkerPipe); 434 436 } 435 437 else 436 errx( 1, "CreateNamedPipeW failed: %u", GetLastError());438 errx(pCtx, 1, "CreateNamedPipeW failed: %u", GetLastError()); 437 439 438 440 #else … … 441 443 */ 442 444 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, aiPair) == 0) 443 {444 445 pWorker->fdSocket = aiPair[1]; 445 }446 446 else 447 err( 1, "socketpair");447 err(pCtx, 1, "socketpair"); 448 448 #endif 449 449 } 450 450 else 451 errx( 1, "KBUILD_BIN_PATH is too long");451 errx(pCtx, 1, "KBUILD_BIN_PATH is too long"); 452 452 return -1; 453 453 } … … 458 458 * 459 459 * @returns Pointer to the selected worker instance. NULL on error. 460 * @param pCtx The command execution context. 460 461 * @param pWorker The idle worker instance to respawn. 461 462 * On failure this will be freed! 462 463 * @param cBitsWorker The worker bitness - 64 or 32. 463 464 */ 464 static int kSubmitRespawnWorker(P WORKERINSTANCE pWorker, int cVerbosity)465 static int kSubmitRespawnWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity) 465 466 { 466 467 /* … … 475 476 { 476 477 if (!CloseHandle(pWorker->hPipe)) 477 warnx( "CloseHandle(pWorker->hPipe): %u", GetLastError());478 warnx(pCtx, "CloseHandle(pWorker->hPipe): %u", GetLastError()); 478 479 pWorker->hPipe = INVALID_HANDLE_VALUE; 479 480 } 480 481 481 482 if (!CloseHandle(pWorker->OverlappedRead.hEvent)) 482 warnx( "CloseHandle(pWorker->OverlappedRead.hEvent): %u", GetLastError());483 warnx(pCtx, "CloseHandle(pWorker->OverlappedRead.hEvent): %u", GetLastError()); 483 484 pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE; 484 485 … … 491 492 rcWait = WaitForSingleObject(pWorker->hProcess, 100); 492 493 if (rcWait != WAIT_OBJECT_0) 493 warnx( "WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc);494 warnx(pCtx, "WaitForSingleObject returns %u (and TerminateProcess %d)", rcWait, fRc); 494 495 } 495 496 496 497 if (!CloseHandle(pWorker->hProcess)) 497 warnx( "CloseHandle(pWorker->hProcess): %u", GetLastError());498 warnx(pCtx, "CloseHandle(pWorker->hProcess): %u", GetLastError()); 498 499 pWorker->hProcess = INVALID_HANDLE_VALUE; 499 500 … … 505 506 { 506 507 if (close(pWorker->fdSocket) != 0) 507 warn( "close(pWorker->fdSocket)");508 warn(pCtx, "close(pWorker->fdSocket)"); 508 509 pWorker->fdSocket = -1; 509 510 } … … 512 513 pidWait = waitpid(pWorker->pid, &rc, 0); 513 514 if (pidWait != pWorker->pid) 514 warn( "waitpid(pWorker->pid,,0)");515 warn(pCtx, "waitpid(pWorker->pid,,0)"); 515 516 #endif 516 517 … … 523 524 * Respawn it. 524 525 */ 525 if (kSubmitSpawnWorker(p Worker, cVerbosity) == 0)526 if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0) 526 527 { 527 528 /* … … 546 547 * @param cBitsWorker The worker bitness - 64 or 32. 547 548 */ 548 static PWORKERINSTANCE kSubmitSelectWorkSpawnNewIfNecessary( unsigned cBitsWorker, int cVerbosity)549 static PWORKERINSTANCE kSubmitSelectWorkSpawnNewIfNecessary(PKMKBUILTINCTX pCtx, unsigned cBitsWorker, int cVerbosity) 549 550 { 550 551 /* … … 564 565 pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker)); 565 566 pWorker->cBits = cBitsWorker; 566 if (kSubmitSpawnWorker(p Worker, cVerbosity) == 0)567 if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0) 567 568 { 568 569 /* … … 715 716 * @returns 0 on success, non-zero on failure. 716 717 * 718 * @param pCtx The command execution context. 717 719 * @param pWorker The work to send the request to. The worker is 718 720 * on the idle list. … … 722 724 * @param cVerbosity The verbosity level. 723 725 */ 724 static int kSubmitSendJobMessage(PWORKERINSTANCE pWorker, void const *pvMsg, uint32_t cbMsg, int fNoRespawning, int cVerbosity) 726 static int kSubmitSendJobMessage(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, void const *pvMsg, uint32_t cbMsg, 727 int fNoRespawning, int cVerbosity) 725 728 { 726 729 int cRetries; … … 738 741 { 739 742 if (cVerbosity > 0) 740 fprintf(stderr, "kSubmit:Respawning worker (#1)...\n");741 if (kSubmitRespawnWorker(p Worker, cVerbosity) != 0)743 warnx(pCtx, "Respawning worker (#1)...\n"); 744 if (kSubmitRespawnWorker(pCtx, pWorker, cVerbosity) != 0) 742 745 return 2; 743 746 } … … 772 775 && dwErr != ERROR_NO_DATA) 773 776 || cRetries <= 0) 774 return errx( 1, "Error writing to worker: %u", dwErr);777 return errx(pCtx, 1, "Error writing to worker: %u", dwErr); 775 778 #else 776 779 ssize_t cbWritten … … 788 791 && errno != ECONNRESET)) 789 792 || cRetries <= 0) 790 return err( 1, "Error writing to worker");793 return err(pCtx, 1, "Error writing to worker"); 791 794 # error "later" 792 795 #endif … … 796 799 */ 797 800 if (cVerbosity > 0) 798 fprintf(stderr, "kSubmit:Respawning worker (#2)...\n");799 if (kSubmitRespawnWorker(p Worker, cVerbosity) != 0)801 warnx(pCtx, "Respawning worker (#2)...\n"); 802 if (kSubmitRespawnWorker(pCtx, pWorker, cVerbosity) != 0) 800 803 return 2; 801 804 } … … 814 817 * which the process can terminate without us having to actively wait for it. 815 818 * 819 * @param pCtx The command execution context. 816 820 * @param pWorker The worker instance. 817 821 */ 818 static void kSubmitCloseConnectOnExitingWorker(P WORKERINSTANCE pWorker)822 static void kSubmitCloseConnectOnExitingWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker) 819 823 { 820 824 #ifdef KBUILD_OS_WINDOWS 821 825 if (!CloseHandle(pWorker->hPipe)) 822 warnx( "CloseHandle(pWorker->hPipe): %u", GetLastError());826 warnx(pCtx, "CloseHandle(pWorker->hPipe): %u", GetLastError()); 823 827 pWorker->hPipe = INVALID_HANDLE_VALUE; 824 828 #else 825 829 if (close(pWorker->fdSocket) != 0) 826 warn( "close(pWorker->fdSocket)");830 warn(pCtx, "close(pWorker->fdSocket)"); 827 831 pWorker->fdSocket = -1; 828 832 #endif … … 836 840 * 837 841 * @returns Exit code. 842 * @param pCtx The command execution context. 838 843 * @param pWorker The worker instance. 839 844 * @param dwErr The error code. 840 845 * @param pszWhere Where it failed. 841 846 */ 842 static int kSubmitWinReadFailed(P WORKERINSTANCE pWorker, DWORD dwErr, const char *pszWhere)847 static int kSubmitWinReadFailed(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, DWORD dwErr, const char *pszWhere) 843 848 { 844 849 DWORD dwExitCode; 845 850 846 851 if (pWorker->cbResultRead == 0) 847 errx( 1, "%s/ReadFile failed: %u", pszWhere, dwErr);852 errx(pCtx, 1, "%s/ReadFile failed: %u", pszWhere, dwErr); 848 853 else 849 errx( 1, "%s/ReadFile failed: %u (read %u bytes)", pszWhere, dwErr, pWorker->cbResultRead);854 errx(pCtx, 1, "%s/ReadFile failed: %u (read %u bytes)", pszWhere, dwErr, pWorker->cbResultRead); 850 855 assert(dwErr != 0); 851 856 … … 870 875 * @returns 0 if we got the whole result, -1 if I/O is pending, and windows last 871 876 * error on ReadFile failure. 877 * @param pCtx The command execution context. 872 878 * @param pWorker The worker instance. 873 879 */ 874 static int kSubmitReadMoreResultWin(P WORKERINSTANCE pWorker, const char *pszWhere)880 static int kSubmitReadMoreResultWin(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, const char *pszWhere) 875 881 { 876 882 /* … … 895 901 if (dwErr == ERROR_IO_PENDING) 896 902 return -1; 897 return kSubmitWinReadFailed(p Worker, dwErr, pszWhere);903 return kSubmitWinReadFailed(pCtx, pWorker, dwErr, pszWhere); 898 904 } 899 905 … … 913 919 * 914 920 * @returns Exit code. 921 * @param pCtx The command execution context. 915 922 * @param pWorker The worker instance to mark as active. 916 923 * @param cVerbosity The verbosity level. … … 920 927 * and we've returned the exit code of the job. 921 928 */ 922 static int kSubmitMarkActive(P WORKERINSTANCE pWorker, int cVerbosity, struct child *pChild, pid_t *pPidSpawned)929 static int kSubmitMarkActive(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity, struct child *pChild, pid_t *pPidSpawned) 923 930 { 924 931 #ifdef KBUILD_OS_WINDOWS … … 934 941 */ 935 942 l_again: 936 rc = kSubmitReadMoreResultWin(p Worker, "kSubmitMarkActive");943 rc = kSubmitReadMoreResultWin(pCtx, pWorker, "kSubmitMarkActive"); 937 944 if (rc == -1) 938 945 { … … 943 950 { 944 951 /* We need to do the waiting here because sub_proc.c has too much to do. */ 945 warnx( "Too many processes for sub_proc.c to handle!");952 warnx(pCtx, "Too many processes for sub_proc.c to handle!"); 946 953 WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE); 947 954 goto l_again; … … 953 960 { 954 961 /* We need to do the waiting here because sub_proc.c has too much to do. */ 955 warnx( "MkWinChildCreateSubmit failed!");962 warnx(pCtx, "MkWinChildCreateSubmit failed!"); 956 963 WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE); 957 964 goto l_again; … … 963 970 assert(rc == 0 || pWorker->Result.s.rcExit != 0); 964 971 if (pWorker->Result.s.bWorkerExiting) 965 kSubmitCloseConnectOnExitingWorker(p Worker);972 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 966 973 *pPidSpawned = 0; 967 974 return pWorker->Result.s.rcExit; … … 998 1005 { 999 1006 PWORKERINSTANCE pWorker = (PWORKERINSTANCE)pvUser; 1007 KMKBUILTINCTX FakeCtx = { "kSubmit/GetResult", NULL }; 1008 PKMKBUILTINCTX pCtx = &FakeCtx; 1000 1009 1001 1010 /* … … 1012 1021 while (pWorker->cbResultRead < sizeof(pWorker->Result)) 1013 1022 { 1014 int rc = kSubmitReadMoreResultWin(p Worker, "kSubmitSubProcGetResult/more");1023 int rc = kSubmitReadMoreResultWin(pCtx, pWorker, "kSubmitSubProcGetResult/more"); 1015 1024 if (rc == -1) 1016 1025 return -1; … … 1022 1031 { 1023 1032 DWORD dwErr = GetLastError(); 1024 kSubmitWinReadFailed(p Worker, dwErr, "kSubmitSubProcGetResult/result");1033 kSubmitWinReadFailed(pCtx, pWorker, dwErr, "kSubmitSubProcGetResult/result"); 1025 1034 } 1026 1035 … … 1039 1048 } 1040 1049 if (pWorker->Result.s.bWorkerExiting) 1041 kSubmitCloseConnectOnExitingWorker(p Worker);1050 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 1042 1051 1043 1052 return 0; … … 1074 1083 DWORD msStartTick; 1075 1084 DWORD cKillRaids = 0; 1085 KMKBUILTINCTX FakeCtx = { "kSubmit/atexit", NULL }; 1086 PKMKBUILTINCTX pCtx = &FakeCtx; 1076 1087 1077 1088 /* … … 1079 1090 */ 1080 1091 for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext) 1081 kSubmitCloseConnectOnExitingWorker(p Worker);1092 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 1082 1093 for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext) 1083 kSubmitCloseConnectOnExitingWorker(p Worker);1094 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 1084 1095 1085 1096 /* … … 1157 1168 if (cKillRaids == 1 && getenv("KMK_KSUBMIT_NO_KILL") == NULL) 1158 1169 { 1159 fprintf(stderr, "kmk/kSubmit:Killing %u lingering worker processe(s)!\n", cHandles);1170 warnx(pCtx, "Killing %u lingering worker processe(s)!\n", cHandles); 1160 1171 for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext) 1161 1172 if (pWorker->hProcess != INVALID_HANDLE_VALUE) … … 1167 1178 else 1168 1179 { 1169 fprintf(stderr, "kmk/kSubmit:Giving up on the last %u worker processe(s). :-(\n", cHandles);1180 warnx(pCtx, "Giving up on the last %u worker processe(s). :-(\n", cHandles); 1170 1181 return; 1171 1182 } … … 1176 1187 bad ones as well as completed ones. */ 1177 1188 size_t idx; 1178 fprintf(stderr, "kmk/kSubmit:WaitForMultipleObjects unexpectedly returned %#u (err=%u)\n",1179 1189 warnx(pCtx, "WaitForMultipleObjects unexpectedly returned %#u (err=%u)\n", 1190 dwWait, GetLastError()); 1180 1191 for (idx = 0; idx < cHandles; idx++) 1181 1192 { … … 1194 1205 1195 1206 1196 static int usage(FILE *pOut, const char *argv0)1197 { 1198 fprintf(pOut,1199 "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"1200 " [-A|--append <var=val>] [-D|--prepend <var=val>]\n"1201 " [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n"1202 " [-3|--32-bit] [-6|--64-bit] [-v]\n"1203 " [-P|--post-cmd <cmd> [args]] -- <program> [args]\n"1204 " or: %s --help\n"1205 " or: %s --version\n"1206 "\n"1207 "Options:\n"1208 " -Z, --zap-env, -i, --ignore-environment\n"1209 " Zaps the environment. Position dependent.\n"1210 " -E, --set <var>=[value]\n"1211 " Sets an enviornment variable putenv fashion. Position dependent.\n"1212 " -U, --unset <var>\n"1213 " Removes an environment variable. Position dependent.\n"1214 " -A, --append <var>=<value>\n"1215 " Appends the given value to the environment variable.\n"1216 " -D,--prepend <var>=<value>\n"1217 " Prepends the given value to the environment variable.\n"1218 " -C, --chdir <dir>\n"1219 " Specifies the current directory for the program. Relative paths\n"1220 " are relative to the previous -C option. Default is getcwd value.\n"1221 " -3, --32-bit\n"1222 " Selects a 32-bit kWorker process. Default: kmk bit count\n"1223 " -6, --64-bit\n"1224 " Selects a 64-bit kWorker process. Default: kmk bit count\n"1225 " --wcc-brain-damage\n"1226 " Works around wcc and wcc386 (Open Watcom) not following normal\n"1227 " quoting conventions on Windows, OS/2, and DOS.\n"1228 " --no-pch-caching\n"1229 " Do not cache precompiled header files because they're being created.\n"1230 " -v,--verbose\n"1231 " More verbose execution.\n"1232 " -P|--post-cmd <cmd> ...\n"1233 " For running a built-in command on the output, specifying the command\n"1234 " and all it's parameters. Currently supported commands:\n"1235 " kDepObj\n"1236 " -V,--version\n"1237 " Show the version number.\n"1238 " -h,--help\n"1239 " Show this usage information.\n"1240 "\n"1241 ,1242 argv0, argv0, argv0);1207 static int kmk_builtin_kSubmit_usage(PKMKBUILTINCTX pCtx, int fIsErr) 1208 { 1209 kmk_builtin_ctx_printf(pCtx, fIsErr, 1210 "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n" 1211 " [-A|--append <var=val>] [-D|--prepend <var=val>]\n" 1212 " [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n" 1213 " [-3|--32-bit] [-6|--64-bit] [-v]\n" 1214 " [-P|--post-cmd <cmd> [args]] -- <program> [args]\n" 1215 " or: %s --help\n" 1216 " or: %s --version\n" 1217 "\n" 1218 "Options:\n" 1219 " -Z, --zap-env, -i, --ignore-environment\n" 1220 " Zaps the environment. Position dependent.\n" 1221 " -E, --set <var>=[value]\n" 1222 " Sets an enviornment variable putenv fashion. Position dependent.\n" 1223 " -U, --unset <var>\n" 1224 " Removes an environment variable. Position dependent.\n" 1225 " -A, --append <var>=<value>\n" 1226 " Appends the given value to the environment variable.\n" 1227 " -D,--prepend <var>=<value>\n" 1228 " Prepends the given value to the environment variable.\n" 1229 " -C, --chdir <dir>\n" 1230 " Specifies the current directory for the program. Relative paths\n" 1231 " are relative to the previous -C option. Default is getcwd value.\n" 1232 " -3, --32-bit\n" 1233 " Selects a 32-bit kWorker process. Default: kmk bit count\n" 1234 " -6, --64-bit\n" 1235 " Selects a 64-bit kWorker process. Default: kmk bit count\n" 1236 " --wcc-brain-damage\n" 1237 " Works around wcc and wcc386 (Open Watcom) not following normal\n" 1238 " quoting conventions on Windows, OS/2, and DOS.\n" 1239 " --no-pch-caching\n" 1240 " Do not cache precompiled header files because they're being created.\n" 1241 " -v,--verbose\n" 1242 " More verbose execution.\n" 1243 " -P|--post-cmd <cmd> ...\n" 1244 " For running a built-in command on the output, specifying the command\n" 1245 " and all it's parameters. Currently supported commands:\n" 1246 " kDepObj\n" 1247 " -V,--version\n" 1248 " Show the version number.\n" 1249 " -h,--help\n" 1250 " Show this usage information.\n" 1251 "\n" 1252 , 1253 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 1243 1254 return 2; 1244 1255 } 1245 1256 1246 1257 1247 int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned)1258 int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) 1248 1259 { 1249 1260 int rcExit = 0; … … 1262 1273 PATH_VAR(szCwd); 1263 1274 1264 g_progname = argv[0];1265 1266 1275 /* 1267 1276 * Create default program environment. … … 1273 1282 { /* likely */ } 1274 1283 else 1275 return err( 1, "getcwd_fs failed\n");1284 return err(pCtx, 1, "getcwd_fs failed\n"); 1276 1285 1277 1286 /* The environment starts out in read-only mode and will be duplicated if modified. */ … … 1298 1307 else 1299 1308 { 1300 errx( 1, "Incomplete option: '-'");1301 return usage(stderr, argv[0]);1309 errx(pCtx, 1, "Incomplete option: '-'"); 1310 return kmk_builtin_kSubmit_usage(pCtx, 1); 1302 1311 } 1303 1312 } … … 1354 1363 else 1355 1364 { 1356 errx( 2, "Unknown option: '%s'", pszArg - 2);1357 return usage(stderr, argv[0]);1365 errx(pCtx, 2, "Unknown option: '%s'", pszArg - 2); 1366 return kmk_builtin_kSubmit_usage(pCtx, 1); 1358 1367 } 1359 1368 pszArg = ""; … … 1378 1387 else 1379 1388 { 1380 errx( 1, "Option -%c requires a value!", chOpt);1381 return usage(stderr, argv[0]);1389 errx(pCtx, 1, "Option -%c requires a value!", chOpt); 1390 return kmk_builtin_kSubmit_usage(pCtx, 1); 1382 1391 } 1383 1392 break; … … 1388 1397 case 'Z': 1389 1398 case 'i': /* GNU env compatibility. */ 1390 rcExit = kBuiltinOptEnvZap( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity);1399 rcExit = kBuiltinOptEnvZap(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity); 1391 1400 if (rcExit == 0) 1392 1401 break; … … 1394 1403 1395 1404 case 'E': 1396 rcExit = kBuiltinOptEnvSet( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1405 rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1397 1406 if (rcExit == 0) 1398 1407 break; … … 1400 1409 1401 1410 case 'A': 1402 rcExit = kBuiltinOptEnvAppend( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1411 rcExit = kBuiltinOptEnvAppend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1403 1412 if (rcExit == 0) 1404 1413 break; … … 1406 1415 1407 1416 case 'D': 1408 rcExit = kBuiltinOptEnvPrepend( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1417 rcExit = kBuiltinOptEnvPrepend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1409 1418 if (rcExit == 0) 1410 1419 break; … … 1412 1421 1413 1422 case 'U': 1414 rcExit = kBuiltinOptEnvUnset( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1423 rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1415 1424 if (rcExit == 0) 1416 1425 break; … … 1418 1427 1419 1428 case 'C': 1420 rcExit = kBuiltinOptChDir( szCwd, cbCwdBuf, pszValue);1429 rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue); 1421 1430 if (rcExit == 0) 1422 1431 break; … … 1425 1434 case 'P': 1426 1435 if (cPostCmdArgs > 0) 1427 return errx( 1, "The -P option can only be used once!");1436 return errx(pCtx, 1, "The -P option can only be used once!"); 1428 1437 if (*pszArg != '\0') 1429 return errx( 1, "The cmd part of the -P needs to be a separate argument!");1438 return errx(pCtx, 1, "The cmd part of the -P needs to be a separate argument!"); 1430 1439 iPostCmd = ++iArg; 1431 1440 if (iArg >= argc) 1432 return errx( 1, "The -P option requires a command following it!");1441 return errx(pCtx, 1, "The -P option requires a command following it!"); 1433 1442 while (iArg < argc && strcmp(argv[iArg], "--") != 0) 1434 1443 iArg++; … … 1454 1463 1455 1464 case 'h': 1456 usage(stdout, argv[0]);1465 kmk_builtin_kSubmit_usage(pCtx, 0); 1457 1466 kBuiltinOptEnvCleanup(&papszEnvVars, cEnvVars, &cAllocatedEnvVars); 1458 1467 return 0; … … 1466 1475 else 1467 1476 { 1468 errx( 1, "Unknown argument: '%s'", pszArg);1469 return usage(stderr, argv[0]);1477 errx(pCtx, 1, "Unknown argument: '%s'", pszArg); 1478 return kmk_builtin_kSubmit_usage(pCtx, 1); 1470 1479 } 1471 1480 } … … 1480 1489 fWatcomBrainDamage, fNoPchCaching, 1481 1490 &argv[iPostCmd], cPostCmdArgs, &cbMsg); 1482 PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary( cBitsWorker, cVerbosity);1491 PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity); 1483 1492 if (pWorker) 1484 1493 { … … 1486 1495 pszExecutable = argv[iArg]; 1487 1496 1488 rcExit = kSubmitSendJobMessage(p Worker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);1497 rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity); 1489 1498 if (rcExit == 0) 1490 rcExit = kSubmitMarkActive(p Worker, cVerbosity, pChild, pPidSpawned);1499 rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned); 1491 1500 1492 1501 if (!g_fAtExitRegistered) … … 1500 1509 else 1501 1510 { 1502 errx( 1, "Nothing to executed!");1503 rcExit = usage(stderr, argv[0]);1511 errx(pCtx, 1, "Nothing to executed!"); 1512 rcExit = kmk_builtin_kSubmit_usage(pCtx, 1); 1504 1513 } 1505 1514 -
trunk/src/kmk/kmkbuiltin/kbuild_protection.c
r2413 r3192 116 116 * On failure an error is printed, eval is set and -1 is returned. 117 117 */ 118 static int countPathComponents( const char *pszPath)118 static int countPathComponents(PCKBUILDPROTECTION pThis, const char *pszPath) 119 119 { 120 120 int cComponents = 0; … … 158 158 if (!pszTmp) 159 159 { 160 err( 1, "_getdcwd");160 err(pThis->pCtx, 1, "_getdcwd"); 161 161 return -1; 162 162 } … … 196 196 if (!getcwd(szCwd, sizeof(szCwd))) 197 197 { 198 err( 1, "getcwd");198 err(pThis->pCtx, 1, "getcwd"); 199 199 return -1; 200 200 } … … 217 217 * @param pThis Pointer to the instance data. 218 218 */ 219 void kBuildProtectionInit(PKBUILDPROTECTION pThis )219 void kBuildProtectionInit(PKBUILDPROTECTION pThis, PKMKBUILTINCTX pCtx) 220 220 { 221 221 pThis->uMagic = KBUILD_PROTECTION_MAGIC; 222 pThis->pCtx = pCtx; 222 223 pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] = 0; 223 224 pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] = 1; … … 268 269 /* number or path? */ 269 270 if (!isdigit(*pszValue) || strpbrk(pszValue, ":/\\")) 270 pThis->cProtectionDepth = countPathComponents(p szValue);271 pThis->cProtectionDepth = countPathComponents(pThis, pszValue); 271 272 else 272 273 { … … 280 281 } 281 282 if (!pThis->cProtectionDepth || pszValue == pszMore || *pszMore) 282 return errx( 1, "bogus protection depth: %s", pszValue);283 return errx(pThis->pCtx, 1, "bogus protection depth: %s", pszValue); 283 284 } 284 285 285 286 if (pThis->cProtectionDepth < 1) 286 return errx( 1, "bogus protection depth: %s", pszValue);287 return errx(pThis->pCtx, 1, "bogus protection depth: %s", pszValue); 287 288 return 0; 288 289 } … … 351 352 * Count the path and compare it with the required depth. 352 353 */ 353 int cComponents = countPathComponents(p szPath);354 int cComponents = countPathComponents(pThis, pszPath); 354 355 if (cComponents < 0) 355 356 return -1; 356 357 if ((unsigned int)cComponents <= pThis->cProtectionDepth) 357 358 { 358 errx( 1, "%s: protected", pszPath);359 errx(pThis->pCtx, 1, "%s: protected", pszPath); 359 360 return -1; 360 361 } -
trunk/src/kmk/kmkbuiltin/kbuild_protection.h
r2413 r3192 27 27 #define ___kbuild_protection_h 28 28 29 29 30 /** 30 31 * The different protection types. … … 47 48 unsigned int uMagic; 48 49 unsigned int cProtectionDepth; 50 struct KMKBUILTINCTX *pCtx; 49 51 unsigned char afTypes[KBUILDPROTECTIONTYPE_MAX]; 50 52 } KBUILDPROTECTION; … … 53 55 54 56 55 void kBuildProtectionInit(PKBUILDPROTECTION pThis );57 void kBuildProtectionInit(PKBUILDPROTECTION pThis, struct KMKBUILTINCTX *pCtx); 56 58 void kBuildProtectionTerm(PKBUILDPROTECTION pThis); 57 59 int kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix); -
trunk/src/kmk/kmkbuiltin/ln.c
r2466 r3192 61 61 #include "kmkbuiltin.h" 62 62 63 static int fflag; /* Unlink existing files. */ 64 static int hflag; /* Check new name for symlink first. */ 65 static int iflag; /* Interactive mode. */ 66 static int sflag; /* Symbolic, not hard, link. */ 67 static int vflag; /* Verbose output. */ 68 /* System link call. */ 69 static int (*linkf)(const char *, const char *); 70 static char linkch; 63 /********************************************************************************************************************************* 64 * Structures and Typedefs * 65 *********************************************************************************************************************************/ 66 typedef struct LNINSTANCE 67 { 68 PKMKBUILTINCTX pCtx; 69 int fflag; /* Unlink existing files. */ 70 int hflag; /* Check new name for symlink first. */ 71 int iflag; /* Interactive mode. */ 72 int sflag; /* Symbolic, not hard, link. */ 73 int vflag; /* Verbose output. */ 74 int (*linkf)(const char *, const char *); /* System link call. */ 75 char linkch; 76 } LNINSTANCE; 77 typedef LNINSTANCE *PLNINSTANCE; 78 71 79 static struct option long_options[] = 72 80 { … … 77 85 78 86 79 static int linkit( const char *, const char *, int);80 static int usage( FILE *);87 static int linkit(PLNINSTANCE,const char *, const char *, int); 88 static int usage(PKMKBUILTINCTX, int); 81 89 82 90 83 91 int 84 kmk_builtin_ln(int argc, char *argv[], char **envp) 85 { 92 kmk_builtin_ln(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 93 { 94 LNINSTANCE This; 86 95 struct stat sb; 87 96 char *sourcedir; … … 89 98 90 99 /* initialize globals. */ 91 fflag = hflag = iflag = sflag = vflag = 0; 92 linkch = 0; 93 linkf = NULL; 100 This.pCtx = pCtx; 101 This.fflag = 0; 102 This.hflag = 0; 103 This.iflag = 0; 104 This.sflag = 0; 105 This.vflag = 0; 106 This.linkch = 0; 107 This.linkf = NULL; 94 108 95 109 /* kmk: reset getopt() and set program name. */ 96 g_progname = argv[0];97 110 opterr = 1; 98 111 optarg = NULL; … … 103 116 switch (ch) { 104 117 case 'f': 105 fflag = 1;106 iflag = 0;118 This.fflag = 1; 119 This.iflag = 0; 107 120 break; 108 121 case 'h': 109 122 case 'n': 110 hflag = 1;123 This.hflag = 1; 111 124 break; 112 125 case 'i': 113 iflag = 1;114 fflag = 0;126 This.iflag = 1; 127 This.fflag = 0; 115 128 break; 116 129 case 's': 117 sflag = 1;130 This.sflag = 1; 118 131 break; 119 132 case 'v': 120 vflag = 1;133 This.vflag = 1; 121 134 break; 122 135 case 261: 123 usage( stdout);136 usage(pCtx, 0); 124 137 return 0; 125 138 case 262: … … 127 140 case '?': 128 141 default: 129 return usage( stderr);142 return usage(pCtx, 1); 130 143 } 131 144 … … 133 146 argc -= optind; 134 147 135 linkf =sflag ? symlink : link;136 linkch =sflag ? '-' : '=';148 This.linkf = This.sflag ? symlink : link; 149 This.linkch = This.sflag ? '-' : '='; 137 150 138 151 switch(argc) { 139 152 case 0: 140 return usage( stderr);153 return usage(pCtx, 1); 141 154 /* NOTREACHED */ 142 155 case 1: /* ln target */ 143 return linkit( argv[0], ".", 1);156 return linkit(&This, argv[0], ".", 1); 144 157 case 2: /* ln target source */ 145 return linkit( argv[0], argv[1], 0);158 return linkit(&This, argv[0], argv[1], 0); 146 159 default: 147 160 ; … … 149 162 /* ln target1 target2 directory */ 150 163 sourcedir = argv[argc - 1]; 151 if ( hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {164 if (This.hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) { 152 165 /* 153 166 * We were asked not to follow symlinks, but found one at … … 155 168 */ 156 169 errno = ENOTDIR; 157 return err( 1, "st_mode: %s", sourcedir);170 return err(pCtx, 1, "st_mode: %s", sourcedir); 158 171 } 159 172 if (stat(sourcedir, &sb)) 160 return err( 1, "stat: %s", sourcedir);173 return err(pCtx, 1, "stat: %s", sourcedir); 161 174 if (!S_ISDIR(sb.st_mode)) 162 return usage( stderr);175 return usage(pCtx, 1); 163 176 for (exitval = 0; *argv != sourcedir; ++argv) 164 exitval |= linkit( *argv, sourcedir, 1);177 exitval |= linkit(&This, *argv, sourcedir, 1); 165 178 return exitval; 166 179 } 167 180 168 181 static int 169 linkit( const char *target, const char *source, int isdir)182 linkit(PLNINSTANCE pThis, const char *target, const char *source, int isdir) 170 183 { 171 184 struct stat sb; … … 174 187 char path[PATH_MAX]; 175 188 176 if (! sflag) {189 if (!pThis->sflag) { 177 190 /* If target doesn't exist, quit now. */ 178 191 if (stat(target, &sb)) { 179 warn( "stat: %s", target);192 warn(pThis->pCtx, "stat: %s", target); 180 193 return (1); 181 194 } … … 183 196 if (S_ISDIR(sb.st_mode)) { 184 197 errno = EISDIR; 185 warn( "st_mode: %s", target);198 warn(pThis->pCtx, "st_mode: %s", target); 186 199 return (1); 187 200 } … … 194 207 if (isdir || 195 208 (lstat(source, &sb) == 0 && S_ISDIR(sb.st_mode)) || 196 (! hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) {209 (!pThis->hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) { 197 210 #if defined(_MSC_VER) || defined(__OS2__) 198 211 char *p2 = strrchr(target, '\\'); … … 210 223 (ssize_t)sizeof(path)) { 211 224 errno = ENAMETOOLONG; 212 warn( "snprintf: %s", target);225 warn(pThis->pCtx, "snprintf: %s", target); 213 226 return (1); 214 227 } … … 221 234 * and interactively if -i was specified. 222 235 */ 223 if ( fflag && exists) {236 if (pThis->fflag && exists) { 224 237 if (unlink(source)) { 225 warn( "unlink: %s", source);226 return (1); 227 } 228 } else if ( iflag && exists) {238 warn(pThis->pCtx, "unlink: %s", source); 239 return (1); 240 } 241 } else if (pThis->iflag && exists) { 229 242 fflush(stdout); 230 243 fprintf(stderr, "replace %s? ", source); … … 234 247 ch = getchar(); 235 248 if (first != 'y' && first != 'Y') { 236 fprintf(stderr, "not replaced\n");249 kmk_builtin_ctx_printf(pThis->pCtx, 1, "not replaced\n"); 237 250 return (1); 238 251 } 239 252 240 253 if (unlink(source)) { 241 warn( "unlink: %s", source);254 warn(pThis->pCtx, "unlink: %s", source); 242 255 return (1); 243 256 } … … 245 258 246 259 /* Attempt the link. */ 247 if ((* linkf)(target, source)) {248 warn( "%s: %s",linkf == link ? "link" : "symlink", source);260 if ((*pThis->linkf)(target, source)) { 261 warn(pThis->pCtx, "%s: %s", pThis->linkf == link ? "link" : "symlink", source); 249 262 return (1); 250 263 } 251 if ( vflag)252 (void)printf("%s %c> %s\n", source,linkch, target);264 if (pThis->vflag) 265 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s %c> %s\n", source, pThis->linkch, target); 253 266 return (0); 254 267 } 255 268 256 269 static int 257 usage(FILE *pf) 258 { 259 fprintf(pf, "usage: %s [-fhinsv] source_file [target_file]\n" 260 " or: %s [-fhinsv] source_file ... target_dir\n" 261 " or: %s source_file target_file\n" 262 " or: %s --help\n" 263 " or: %s --version\n", 264 g_progname, g_progname, g_progname, g_progname, g_progname); 270 usage(PKMKBUILTINCTX pCtx, int fIsErr) 271 { 272 kmk_builtin_ctx_printf(pCtx,fIsErr, 273 "usage: %s [-fhinsv] source_file [target_file]\n" 274 " or: %s [-fhinsv] source_file ... target_dir\n" 275 " or: %s source_file target_file\n" 276 " or: %s --help\n" 277 " or: %s --version\n", 278 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, 279 pCtx->pszProgName, pCtx->pszProgName); 265 280 return 1; 266 281 } 282 283 #ifdef KMK_BUILTIN_STANDALONE 284 int main(int argc, char **argv, char **envp) 285 { 286 KMKBUILTINCTX Ctx = { "kmk_ln", NULL }; 287 return kmk_builtin_ln(argc, argv, envp, &Ctx); 288 } 289 #endif 290 -
trunk/src/kmk/kmkbuiltin/md5sum.c
r3159 r3192 49 49 * Prints the usage and return 1. 50 50 */ 51 static int usage( FILE *pOut)52 { 53 fprintf(pOut,54 "usage: md5sum [-bt] [-o list-file] file(s)\n"55 " or: md5sum [-btwq] -c list-file(s)\n"56 " or: md5sum [-btq] -C MD5 file\n"57 "\n"58 " -c, --check Check MD5 and files found in the specified list file(s).\n"59 " The default is to compute MD5 sums of the specified files\n"60 " and print them to stdout in list form.\n"61 " -C, --check-file This is followed by an MD5 sum and the file to check.\n"62 " -b, --binary Read files in binary mode. (default)\n"63 " -t, --text Read files in text mode.\n"64 " -m, --manifest Output in kBuild fetch 'manifest' format.\n"65 " -p, --progress Show progress indicator on large files.\n"66 " -o, --output Name of the output list file. Useful with -p.\n"67 " -q, --status Be quiet.\n"68 " -w, --warn Ignored. Always warn, unless quiet.\n"69 " -h, --help This usage info.\n"70 " -v, --version Show version information and exit.\n"71 );51 static int usage(PKMKBUILTINCTX pCtx, int fIsErr) 52 { 53 kmk_builtin_ctx_printf(pCtx, fIsErr, 54 "usage: md5sum [-bt] [-o list-file] file(s)\n" 55 " or: md5sum [-btwq] -c list-file(s)\n" 56 " or: md5sum [-btq] -C MD5 file\n" 57 "\n" 58 " -c, --check Check MD5 and files found in the specified list file(s).\n" 59 " The default is to compute MD5 sums of the specified files\n" 60 " and print them to stdout in list form.\n" 61 " -C, --check-file This is followed by an MD5 sum and the file to check.\n" 62 " -b, --binary Read files in binary mode. (default)\n" 63 " -t, --text Read files in text mode.\n" 64 " -m, --manifest Output in kBuild fetch 'manifest' format.\n" 65 " -p, --progress Show progress indicator on large files.\n" 66 " -o, --output Name of the output list file. Useful with -p.\n" 67 " -q, --status Be quiet.\n" 68 " -w, --warn Ignored. Always warn, unless quiet.\n" 69 " -h, --help This usage info.\n" 70 " -v, --version Show version information and exit.\n" 71 ); 72 72 return 1; 73 73 } … … 405 405 * 406 406 * @returns 0 if it matches, 1 if it doesn't or an error occurs. 407 * @param pCtx The command execution context. 407 408 * @param pszFilename The name of the file to check. 408 409 * @param pszDigest The MD5 digest string. … … 411 412 * @param fProgress Whether to show an progress indicator on large files. 412 413 */ 413 static int check_one_file(const char *pszFilename, const char *pszDigest, unsigned fText, unsigned fQuiet, unsigned fProgress) 414 static int check_one_file(PKMKBUILTINCTX pCtx, const char *pszFilename, const char *pszDigest, unsigned fText, 415 unsigned fQuiet, unsigned fProgress) 414 416 { 415 417 unsigned char Digest[16]; … … 425 427 { 426 428 if (!fQuiet) 427 fprintf(stdout, "%s: ", pszFilename);429 kmk_builtin_ctx_printf(pCtx, 0, "%s: ", pszFilename); 428 430 rc = check_md5sum(pvFile, Digest, fProgress); 429 431 close_file(pvFile); 430 432 if (!fQuiet) 431 433 { 432 fprintf(stdout, "%s\n", !rc ? "OK" : rc < 0 ? "FAILURE" : "ERROR"); 433 fflush(stdout); 434 kmk_builtin_ctx_printf(pCtx, 0, "%s\n", !rc ? "OK" : rc < 0 ? "FAILURE" : "ERROR"); 434 435 if (rc > 0) 435 errx( 1, "Error reading '%s': %s", pszFilename, strerror(rc));436 errx(pCtx, 1, "Error reading '%s': %s", pszFilename, strerror(rc)); 436 437 } 437 438 if (rc) … … 441 442 { 442 443 if (!fQuiet) 443 errx( 1, "Failed to open '%s': %s", pszFilename, strerror(errno));444 errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); 444 445 rc = 1; 445 446 } … … 447 448 else 448 449 { 449 errx( 1, "Malformed MD5 digest '%s'!", pszDigest);450 errx( 1, " %*s^", rc - 1, "");450 errx(pCtx, 1, "Malformed MD5 digest '%s'!", pszDigest); 451 errx(pCtx, 1, " %*s^", rc - 1, ""); 451 452 rc = 1; 452 453 } … … 460 461 * 461 462 * @returns 0 if all checks out file, 1 if one or more fails or there are read errors. 463 * @param pCtx The command execution context. 462 464 * @param pszFilename The name of the file. 463 465 * @param fText The default mode, text or binary. Only used when fBinaryTextOpt is true. 464 466 * @param fBinaryTextOpt Whether a -b or -t option was specified and should be used. 465 467 * @param fQuiet Whether to be quiet. 466 * @param fProgress Whether to show an progress indicator on large files. 467 */ 468 static int check_files(const char *pszFilename, int fText, int fBinaryTextOpt, int fQuiet, unsigned fProgress) 468 * @param fProgress Whether to show an progress indicator on large files. 469 */ 470 static int check_files(PKMKBUILTINCTX pCtx, const char *pszFilename, int fText, int fBinaryTextOpt, 471 int fQuiet, unsigned fProgress) 469 472 { 470 473 int rc = 0; … … 539 542 { 540 543 if (!fQuiet) 541 fprintf(stdout, "%s: ", pszFilename);544 kmk_builtin_ctx_printf(pCtx, 0, "%s: ", pszFilename); 542 545 rc2 = check_md5sum(pvFile, Digest, fProgress); 543 546 close_file(pvFile); 544 547 if (!fQuiet) 545 548 { 546 fprintf(stdout, "%s\n", !rc2 ? "OK" : rc2 < 0 ? "FAILURE" : "ERROR"); 547 fflush(stdout); 549 kmk_builtin_ctx_printf(pCtx, 0, "%s\n", !rc2 ? "OK" : rc2 < 0 ? "FAILURE" : "ERROR"); 548 550 if (rc2 > 0) 549 errx( 1, "Error reading '%s': %s", pszFilename, strerror(rc2));551 errx(pCtx, 1, "Error reading '%s': %s", pszFilename, strerror(rc2)); 550 552 } 551 553 if (rc2) … … 555 557 { 556 558 if (!fQuiet) 557 errx( 1, "Failed to open '%s': %s", pszFilename, strerror(errno));559 errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); 558 560 rc = 1; 559 561 } … … 561 563 else if (!fQuiet) 562 564 { 563 errx( 1, "%s (%d): Ignoring malformed digest '%s' (digest)", pszFilename, iLine, pszDigest);564 errx( 1, "%s (%d): %*s^", pszFilename, iLine, rc2 - 1, "");565 errx(pCtx, 1, "%s (%d): Ignoring malformed digest '%s' (digest)", pszFilename, iLine, pszDigest); 566 errx(pCtx, 1, "%s (%d): %*s^", pszFilename, iLine, rc2 - 1, ""); 565 567 } 566 568 } 567 569 else if (!fQuiet) 568 errx( 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);570 errx(pCtx, 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine); 569 571 } 570 572 else if (!fQuiet) 571 errx( 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);573 errx(pCtx, 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine); 572 574 } /* while more lines */ 573 575 … … 576 578 else 577 579 { 578 errx( 1, "Failed to open '%s': %s", pszFilename, strerror(errno));580 errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); 579 581 rc = 1; 580 582 } … … 588 590 * 589 591 * @returns 0 on success, 1 on any kind of failure. 592 * @param pCtx Command context. 590 593 * @param pszFilename The file to process. 591 594 * @param fText The mode to open the file in. … … 595 598 * @param pOutput Where to write the list. Progress is always written to stdout. 596 599 */ 597 static int md5sum_file( const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress,600 static int md5sum_file(PKMKBUILTINCTX pCtx, const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress, 598 601 unsigned fManifest, FILE *pOutput) 599 602 { … … 631 634 if (pOutput) 632 635 fprintf(pOutput, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename); 633 fprintf(stdout, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename);636 kmk_builtin_ctx_printf(pCtx, 0, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename); 634 637 } 635 638 else … … 637 640 if (pOutput) 638 641 fprintf(pOutput, "%s_SIZE := %" KU64_PRI "\n%s_MD5 := %s\n", pszFilename, cbFile, pszFilename, szDigest); 639 fprintf(stdout, "%s_SIZE := %" KU64_PRI "\n%s_MD5 := %s\n", pszFilename, cbFile, pszFilename, szDigest); 642 kmk_builtin_ctx_printf(pCtx, 0, "%s_SIZE := %" KU64_PRI "\n%s_MD5 := %s\n", 643 pszFilename, cbFile, pszFilename, szDigest); 640 644 } 641 645 if (pOutput) 642 646 fflush(pOutput); 643 fflush(stdout);644 647 } 645 648 else 646 649 { 647 650 if (!fQuiet) 648 errx( 1, "Failed to open '%s': %s", pszFilename, strerror(rc));651 errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(rc)); 649 652 rc = 1; 650 653 } … … 653 656 { 654 657 if (!fQuiet) 655 errx( 1, "Failed to open '%s': %s", pszFilename, strerror(errno));658 errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno)); 656 659 rc = 1; 657 660 } … … 665 668 * Somewhat similar to the GNU coreutil md5sum command. 666 669 */ 667 int kmk_builtin_md5sum(int argc, char **argv, char **envp )670 int kmk_builtin_md5sum(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 668 671 { 669 672 int i; … … 679 682 FILE *pOutput = NULL; 680 683 681 g_progname = argv[0];682 683 684 /* 684 685 * Print usage if no arguments. 685 686 */ 686 687 if (argc <= 1) 687 return usage( stderr);688 return usage(pCtx, 1); 688 689 689 690 /* … … 751 752 752 753 case 'p': 753 fProgress = 1; 754 fProgress = 1 && isatty(fileno(stdout)) 755 #ifndef KMK_BUILTIN_STANDALONE 756 && (!pCtx->pOut || !pCtx->pOut->syncout) 757 #endif 758 ; 754 759 break; 755 760 … … 763 768 764 769 case 'h': 765 usage( stdout);770 usage(pCtx, 0); 766 771 return 0; 767 772 … … 783 788 else 784 789 { 785 errx( 1, "'-C' is missing the MD5 sum!");790 errx(pCtx, 1, "'-C' is missing the MD5 sum!"); 786 791 return 1; 787 792 } … … 790 795 else 791 796 { 792 errx( 1, "'-C' is missing the filename!");797 errx(pCtx, 1, "'-C' is missing the filename!"); 793 798 return 1; 794 799 } 795 800 796 rc |= check_one_file(p szFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet);801 rc |= check_one_file(pCtx, pszFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet); 797 802 psz = "\0"; 798 803 break; … … 806 811 if (fChecking) 807 812 { 808 errx( 1, "'-o' cannot be used with -c or -C!");813 errx(pCtx, 1, "'-o' cannot be used with -c or -C!"); 809 814 return 1; 810 815 } … … 816 821 else 817 822 { 818 errx( 1, "'-o' is missing the file name!");823 errx(pCtx, 1, "'-o' is missing the file name!"); 819 824 return 1; 820 825 } … … 825 830 826 831 default: 827 errx( 1, "Invalid option '%c'! (%s)", *psz, argv[i]);828 return usage( stderr);832 errx(pCtx, 1, "Invalid option '%c'! (%s)", *psz, argv[i]); 833 return usage(pCtx, 1); 829 834 } 830 835 } while (*++psz); 831 836 } 832 837 else if (fChecking) 833 rc |= check_files( argv[i], fText, fBinaryTextOpt, fQuiet, fProgress && !fQuiet);838 rc |= check_files(pCtx, argv[i], fText, fBinaryTextOpt, fQuiet, fProgress && !fQuiet); 834 839 else 835 840 { … … 842 847 if (!pOutput) 843 848 { 844 rc = err( 1, "fopen(\"%s\", \"w" KMK_FOPEN_NO_INHERIT_MODE "\") failed", pszOutput);849 rc = err(pCtx, 1, "fopen(\"%s\", \"w" KMK_FOPEN_NO_INHERIT_MODE "\") failed", pszOutput); 845 850 break; 846 851 } … … 848 853 } 849 854 850 rc |= md5sum_file( argv[i], fText, fQuiet, fProgress && !fQuiet && !fManifest, fManifest, pOutput);855 rc |= md5sum_file(pCtx, argv[i], fText, fQuiet, fProgress && !fQuiet && !fManifest, fManifest, pOutput); 851 856 } 852 857 i++; … … 858 863 } 859 864 865 866 #ifdef KMK_BUILTIN_STANDALONE 867 int main(int argc, char **argv, char **envp) 868 { 869 KMKBUILTINCTX Ctx = { "kmk_md5sum", NULL }; 870 return kmk_builtin_md5sum(argc, argv, envp, &Ctx); 871 } 872 #endif 873 874 -
trunk/src/kmk/kmkbuiltin/mkdir.c
r2546 r3192 72 72 73 73 74 static int vflag;75 74 static struct option long_options[] = 76 75 { … … 84 83 extern mode_t bsd_getmode(const void *bbox, mode_t omode); 85 84 86 static int build( char *, mode_t);87 static int usage( FILE *);85 static int build(PKMKBUILTINCTX pCtx, char *, mode_t, int); 86 static int usage(PKMKBUILTINCTX pCtx, int fIsErr); 88 87 89 88 90 89 int 91 kmk_builtin_mkdir(int argc, char * argv[], char **envp)92 { 93 int ch, exitval, success, pflag ;90 kmk_builtin_mkdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 91 { 92 int ch, exitval, success, pflag, vflag; 94 93 mode_t omode, *set = (mode_t *)NULL; 95 94 char *mode; 96 95 97 omode = pflag = 0;96 omode = pflag = vflag = 0; 98 97 mode = NULL; 99 98 100 /* reinitialize globals */101 vflag = 0;102 103 99 /* kmk: reset getopt and set progname */ 104 g_progname = argv[0];105 100 opterr = 1; 106 101 optarg = NULL; … … 119 114 break; 120 115 case 261: 121 usage( stdout);116 usage(pCtx, 0); 122 117 return 0; 123 118 case 262: 124 119 return kbuild_version(argv[0]); 125 120 case '?': 126 127 return usage( stderr);121 default: 122 return usage(pCtx, 1); 128 123 } 129 124 … … 131 126 argv += optind; 132 127 if (argv[0] == NULL) 133 return usage( stderr);128 return usage(pCtx, 1); 134 129 135 130 if (mode == NULL) { … … 137 132 } else { 138 133 if ((set = bsd_setmode(mode)) == NULL) 139 return errx( 1, "invalid file mode: %s", mode);134 return errx(pCtx, 1, "invalid file mode: %s", mode); 140 135 omode = bsd_getmode(set, S_IRWXU | S_IRWXG | S_IRWXO); 141 136 free(set); … … 145 140 success = 1; 146 141 if (pflag) { 147 if (build( *argv, omode))142 if (build(pCtx, *argv, omode, vflag)) 148 143 success = 0; 149 144 } else if (mkdir(*argv, omode) < 0) { 150 145 if (errno == ENOTDIR || errno == ENOENT) 151 warn( "mkdir: %s", dirname(*argv));146 warn(pCtx, "mkdir: %s", dirname(*argv)); 152 147 else 153 warn( "mkdir: %s", *argv);148 warn(pCtx, "mkdir: %s", *argv); 154 149 success = 0; 155 150 } else if (vflag) 156 (void)printf("%s\n", *argv);151 kmk_builtin_ctx_printf(pCtx, 0, "%s\n", *argv); 157 152 158 153 if (!success) … … 166 161 */ 167 162 if (success && mode != NULL && chmod(*argv, omode) == -1) { 168 warn( "chmod: %s", *argv);163 warn(pCtx, "chmod: %s", *argv); 169 164 exitval = 1; 170 165 } … … 173 168 } 174 169 170 #ifdef KMK_BUILTIN_STANDALONE 171 int main(int argc, char **argv, char **envp) 172 { 173 KMKBUILTINCTX Ctx = { "kmk_mkdir", NULL }; 174 return kmk_builtin_mkdir(argc, argv, envp, &Ctx); 175 } 176 #endif 177 175 178 static int 176 build( char *path, mode_t omode)179 build(PKMKBUILTINCTX pCtx, char *path, mode_t omode, int vflag) 177 180 { 178 181 struct stat sb; … … 251 254 || errno == EACCES /* (ditto) */) { 252 255 if (stat(path, &sb) < 0) { 253 warn( "stat: %s", path);256 warn(pCtx, "stat: %s", path); 254 257 retval = 1; 255 258 break; … … 259 262 else 260 263 errno = ENOTDIR; 261 warn( "st_mode: %s", path);264 warn(pCtx, "st_mode: %s", path); 262 265 retval = 1; 263 266 break; 264 267 } 265 268 } else { 266 warn( "mkdir: %s", path);269 warn(pCtx, "mkdir: %s", path); 267 270 retval = 1; 268 271 break; 269 272 } 270 273 } else if (vflag) 271 printf("%s\n", path);274 kmk_builtin_ctx_printf(pCtx, 0, "%s\n", path); 272 275 if (!last) 273 276 *p = '/'; … … 279 282 280 283 static int 281 usage(FILE *pf) 282 { 283 fprintf(pf, "usage: %s [-pv] [-m mode] directory ...\n" 284 " or: %s --help\n" 285 " or: %s --version\n", 286 g_progname, g_progname, g_progname); 284 usage(PKMKBUILTINCTX pCtx, int fIsErr) 285 { 286 kmk_builtin_ctx_printf(pCtx, fIsErr, 287 "usage: %s [-pv] [-m mode] directory ...\n" 288 " or: %s --help\n" 289 " or: %s --version\n", 290 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 287 291 return EX_USAGE; 288 292 } 293 -
trunk/src/kmk/kmkbuiltin/mscfakes.c
r3188 r3192 446 446 } 447 447 448 fprintf(stderr, "warning: symlink() is available on this version of Windows!\n"); 448 449 errno = ENOSYS; 449 err(1, "symlink() is not implemented on windows!");450 450 return -1; 451 451 } -
trunk/src/kmk/kmkbuiltin/mv.c
r3109 r3192 47 47 #endif 48 48 49 50 /********************************************************************************************************************************* 51 * Header Files * 52 *********************************************************************************************************************************/ 49 53 #include "config.h" 50 54 #include <sys/types.h> … … 89 93 90 94 91 static int fflg, iflg, nflg, vflg; 95 /********************************************************************************************************************************* 96 * Structures and Typedefs * 97 *********************************************************************************************************************************/ 98 typedef struct MVINSTANCE 99 { 100 PKMKBUILTINCTX pCtx; 101 int fflg, iflg, nflg, vflg; 102 } MVINSTANCE; 103 typedef MVINSTANCE *PMVINSTANCE; 104 105 106 /********************************************************************************************************************************* 107 * Global Variables * 108 *********************************************************************************************************************************/ 92 109 static struct option long_options[] = 93 110 { … … 98 115 99 116 100 static int do_move(char *, char *); 117 /********************************************************************************************************************************* 118 * Internal Functions * 119 *********************************************************************************************************************************/ 120 extern void bsd_strmode(mode_t mode, char *p); /* strmode.c */ 121 122 static int do_move(PMVINSTANCE, char *, char *); 101 123 #ifdef CROSS_DEVICE_MOVE 102 124 static int fastcopy(char *, char *, struct stat *); 103 125 static int copy(char *, char *); 104 126 #endif 105 static int usage(FILE *); 106 107 extern void bsd_strmode(mode_t mode, char *p); 127 static int usage(PKMKBUILTINCTX, int); 128 108 129 109 130 #if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__) … … 132 153 133 154 int 134 kmk_builtin_mv(int argc, char *argv[], char **envp) 135 { 155 kmk_builtin_mv(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 156 { 157 MVINSTANCE This; 136 158 size_t baselen, len; 137 159 int rval; … … 141 163 char path[PATH_MAX]; 142 164 143 /* kmk: reinitialize globals */ 144 fflg = iflg = nflg = vflg = 0; 165 /* Initialize instance. */ 166 This.pCtx = pCtx; 167 This.fflg = 0; 168 This.iflg = 0; 169 This.nflg = 0; 170 This.vflg = 0; 145 171 146 172 /* kmk: reset getopt and set progname */ 147 g_progname = argv[0];148 173 opterr = 1; 149 174 optarg = NULL; … … 154 179 switch (ch) { 155 180 case 'i': 156 iflg = 1;157 fflg =nflg = 0;181 This.iflg = 1; 182 This.fflg = This.nflg = 0; 158 183 break; 159 184 case 'f': 160 fflg = 1;161 iflg =nflg = 0;185 This.fflg = 1; 186 This.iflg = This.nflg = 0; 162 187 break; 163 188 case 'n': 164 nflg = 1;165 fflg =iflg = 0;189 This.nflg = 1; 190 This.fflg = This.iflg = 0; 166 191 break; 167 192 case 'v': 168 vflg = 1;193 This.vflg = 1; 169 194 break; 170 195 case 261: 171 usage( stdout);196 usage(pCtx, 0); 172 197 return 0; 173 198 case 262: 174 199 return kbuild_version(argv[0]); 175 200 default: 176 return usage( stderr);201 return usage(pCtx, 1); 177 202 } 178 203 argc -= optind; … … 180 205 181 206 if (argc < 2) 182 return usage( stderr);207 return usage(pCtx, 1); 183 208 184 209 /* … … 188 213 if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) { 189 214 if (argc > 2) 190 return usage( stderr);191 return do_move( argv[0], argv[1]);215 return usage(pCtx, 1); 216 return do_move(&This, argv[0], argv[1]); 192 217 } 193 218 194 219 /* It's a directory, move each file into it. */ 195 if (strlen(argv[argc - 1]) > sizeof(path) - 1)196 return errx(1, "%s: destination pathname too long", *argv);197 (void)strcpy(path, argv[argc - 1]);198 baselen = strlen(path);220 baselen = strlen(argv[argc - 1]); 221 if (baselen > sizeof(path) - 1) 222 return errx(pCtx, 1, "%s: destination pathname too long", *argv); 223 memcpy(path, argv[argc - 1], baselen); 199 224 endp = &path[baselen]; 225 *endp = '\0'; 200 226 #if defined(_MSC_VER) || defined(__EMX__) 201 227 if (!baselen || (*(endp - 1) != '/' && *(endp - 1) != '\\' && *(endp - 1) != ':')) { … … 225 251 226 252 if ((baselen + (len = strlen(p))) >= PATH_MAX) { 227 warnx( "%s: destination pathname too long", *argv);253 warnx(pCtx, "%s: destination pathname too long", *argv); 228 254 rval = 1; 229 255 } else { 230 256 memmove(endp, p, (size_t)len + 1); 231 if (do_move( *argv, path))257 if (do_move(&This, *argv, path)) 232 258 rval = 1; 233 259 } … … 236 262 } 237 263 264 #ifdef KMK_BUILTIN_STANDALONE 265 int main(int argc, char **argv, char **envp) 266 { 267 KMKBUILTINCTX Ctx = { "kmk_mv", NULL }; 268 return kmk_builtin_mv(argc, argv, envp, &Ctx); 269 } 270 #endif 271 238 272 static int 239 do_move( char *from, char *to)273 do_move(PMVINSTANCE pThis, char *from, char *to) 240 274 { 241 275 struct stat sb; … … 248 282 * make sure the user wants to clobber it. 249 283 */ 250 if (! fflg && !access(to, F_OK)) {284 if (!pThis->fflg && !access(to, F_OK)) { 251 285 252 286 /* prompt only if source exist */ 253 287 if (lstat(from, &sb) == -1) { 254 warn( "%s", from);288 warn(pThis->pCtx, "%s", from); 255 289 return (1); 256 290 } … … 258 292 #define YESNO "(y/n [n]) " 259 293 ask = 0; 260 if ( nflg) {261 if ( vflg)262 printf("%s not overwritten\n", to);294 if (pThis->nflg) { 295 if (pThis->vflg) 296 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s not overwritten\n", to); 263 297 return (0); 264 } else if ( iflg) {298 } else if (pThis->iflg) { 265 299 (void)fprintf(stderr, "overwrite %s? %s", to, YESNO); 266 300 ask = 1; … … 274 308 } 275 309 if (ask) { 310 fflush(stderr); 276 311 first = ch = getchar(); 277 312 while (ch != '\n' && ch != EOF) 278 313 ch = getchar(); 279 314 if (first != 'y' && first != 'Y') { 280 (void)fprintf(stderr, "not overwritten\n");315 kmk_builtin_ctx_printf(pThis->pCtx, 1, "not overwritten\n"); 281 316 return (0); 282 317 } … … 284 319 } 285 320 if (!rename(from, to)) { 286 if ( vflg)287 printf("%s -> %s\n", from, to);321 if (pThis->vflg) 322 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to); 288 323 return (0); 289 324 } … … 292 327 remove(to); 293 328 if (!rename(from, to)) { 294 if ( vflg)295 printf("%s -> %s\n", from, to);329 if (pThis->vflg) 330 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to); 296 331 return (0); 297 332 } … … 301 336 if (errno == EXDEV) { 302 337 #ifndef CROSS_DEVICE_MOVE 303 warnx( "cannot move `%s' to a different device: `%s'", from, to);338 warnx(pThis->pCtx, "cannot move `%s' to a different device: `%s'", from, to); 304 339 return (1); 305 340 #else … … 312 347 */ 313 348 if (lstat(from, &sb) == -1) { 314 warn( "%s", from);349 warn(pThis->pCtx, "%s", from); 315 350 return (1); 316 351 } … … 318 353 /* Can't mv(1) a mount point. */ 319 354 if (realpath(from, path) == NULL) { 320 warnx( "cannot resolve %s: %s", from, path);355 warnx(pThis->pCtx, "cannot resolve %s: %s", from, path); 321 356 return (1); 322 357 } 323 358 if (!statfs(path, &sfs) && 324 359 !strcmp(path, sfs.f_mntonname)) { 325 warnx( "cannot rename a mount point");360 warnx(pThis->pCtx, "cannot rename a mount point"); 326 361 return (1); 327 362 } … … 329 364 #endif 330 365 } else { 331 warn( "rename %s to %s", from, to);366 warn(pThis->pCtx, "rename %s to %s", from, to); 332 367 return (1); 333 368 } … … 340 375 */ 341 376 if (lstat(from, &sb)) { 342 warn( "%s", from);377 warn(pThis->pCtx, "%s", from); 343 378 return (1); 344 379 } 345 380 return (S_ISREG(sb.st_mode) ? 346 fastcopy( from, to, &sb) : copy(from, to));381 fastcopy(pThis, from, to, &sb) : copy(pThis, from, to)); 347 382 #endif 348 383 } … … 451 486 } 452 487 if (vflg) 453 printf("%s -> %s\n", from, to);488 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to); 454 489 return (0); 455 490 } … … 503 538 504 539 static int 505 usage(FILE *pf) 506 { 507 fprintf(pf, "usage: %s [-f | -i | -n] [-v] source target\n" 508 " or: %s [-f | -i | -n] [-v] source ... directory\n" 509 " or: %s --help\n" 510 " or: %s --version\n", 511 g_progname, g_progname, g_progname, g_progname); 540 usage(PKMKBUILTINCTX pCtx, int fIsErr) 541 { 542 kmk_builtin_ctx_printf(pCtx, fIsErr, 543 "usage: %s [-f | -i | -n] [-v] source target\n" 544 " or: %s [-f | -i | -n] [-v] source ... directory\n" 545 " or: %s --help\n" 546 " or: %s --version\n", 547 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 512 548 return EX_USAGE; 513 549 } -
trunk/src/kmk/kmkbuiltin/printf.c
r3188 r3192 46 46 #endif*/ /* not lint */ 47 47 48 #if !defined(kmk_builtin_printf) && !defined(BUILTIN) && !defined(SHELL) 48 49 /********************************************************************************************************************************* 50 * Header Files * 51 *********************************************************************************************************************************/ 52 #if !defined(KMK_BUILTIN_STANDALONE) && !defined(BUILTIN) && !defined(SHELL) 49 53 # include "../makeint.h" 50 54 # include "../filedef.h" … … 83 87 #endif 84 88 85 89 #if 0 90 #ifdef BUILTIN /* csh builtin */ 91 #define kmk_builtin_printf progprintf 92 #endif 93 94 #ifdef SHELL /* sh (aka ash) builtin */ 95 #define kmk_builtin_printf printfcmd 96 #include "../../bin/sh/bltin/bltin.h" 97 #endif /* SHELL */ 98 #endif 99 100 101 /********************************************************************************************************************************* 102 * Defined Constants And Macros * 103 *********************************************************************************************************************************/ 86 104 #if 0 /*def __GNUC__ - bird: gcc complains about non-ISO-standard escape. */ 87 105 #define ESCAPE '\e' … … 90 108 #endif 91 109 92 93 static size_t b_length;94 static char *b_fmt;95 static int rval;96 static char **gargv;97 #if !defined(kmk_builtin_printf) && !defined(BUILTIN) && !defined(SHELL)98 static char *g_o = NULL;99 #endif100 static struct option long_options[] =101 {102 { "help", no_argument, 0, 261 },103 { "version", no_argument, 0, 262 },104 { 0, 0, 0, 0 },105 };106 107 108 static int common_printf(int argc, char *argv[]);109 static void conv_escape_str(char *, void (*)(int));110 static char *conv_escape(char *, char *);111 static char *conv_expand(const char *);112 static int getchr(void);113 static double getdouble(void);114 static int getwidth(void);115 static intmax_t getintmax(void);116 static uintmax_t getuintmax(void);117 static char *getstr(void);118 static char *mklong(const char *, int);119 static void check_conversion(const char *, const char *);120 static int usage(FILE *);121 122 static int flush_buffer(void);123 static void b_count(int);124 static void b_output(int);125 static int wrap_putchar(int ch);126 static int wrap_printf(const char *, ...);127 128 #ifdef BUILTIN /* csh builtin */129 #define kmk_builtin_printf progprintf130 #endif131 132 #ifdef SHELL /* sh (aka ash) builtin */133 #define kmk_builtin_printf printfcmd134 #include "../../bin/sh/bltin/bltin.h"135 #endif /* SHELL */136 137 /* Buffer the output because windows doesn't do line buffering of stdout. */138 static char g_achBuf[256];139 static size_t g_cchBuf;140 141 110 #define PF(f, func) { \ 142 111 if (fieldwidth != -1) { \ 143 112 if (precision != -1) \ 144 (void)wrap_printf( f, fieldwidth, precision, func); \113 (void)wrap_printf(pThis, f, fieldwidth, precision, func); \ 145 114 else \ 146 (void)wrap_printf( f, fieldwidth, func); \115 (void)wrap_printf(pThis, f, fieldwidth, func); \ 147 116 } else if (precision != -1) \ 148 (void)wrap_printf( f, precision, func); \117 (void)wrap_printf(pThis, f, precision, func); \ 149 118 else \ 150 (void)wrap_printf( f, func); \119 (void)wrap_printf(pThis, f, func); \ 151 120 } 152 121 … … 163 132 } 164 133 165 int kmk_builtin_printf(int argc, char *argv[], char **envp) 166 { 167 int rc; 134 135 /********************************************************************************************************************************* 136 * Structures and Typedefs * 137 *********************************************************************************************************************************/ 138 typedef struct PRINTFINSTANCE 139 { 140 PKMKBUILTINCTX pCtx; 141 size_t b_length; 142 char *b_fmt; 143 int rval; 144 char **gargv; 145 #ifndef KMK_BUILTIN_STANDALONE 146 char *g_o; 147 #endif 148 /* Buffer the output because windows doesn't do line buffering of stdout. */ 149 size_t g_cchBuf; 150 char g_achBuf[256]; 151 } PRINTFINSTANCE; 152 typedef PRINTFINSTANCE *PPRINTFINSTANCE; 153 154 155 /********************************************************************************************************************************* 156 * Global Variables * 157 *********************************************************************************************************************************/ 158 static struct option long_options[] = 159 { 160 { "help", no_argument, 0, 261 }, 161 { "version", no_argument, 0, 262 }, 162 { 0, 0, 0, 0 }, 163 }; 164 165 166 /********************************************************************************************************************************* 167 * Internal Functions * 168 *********************************************************************************************************************************/ 169 static int common_printf(PPRINTFINSTANCE pThis, int argc, char *argv[]); 170 static void conv_escape_str(PPRINTFINSTANCE, char *, void (*)(PPRINTFINSTANCE, int)); 171 static char *conv_escape(PPRINTFINSTANCE, char *, char *); 172 static char *conv_expand(const char *); 173 static int getchr(PPRINTFINSTANCE); 174 static double getdouble(PPRINTFINSTANCE); 175 static int getwidth(PPRINTFINSTANCE); 176 static intmax_t getintmax(PPRINTFINSTANCE); 177 static uintmax_t getuintmax(PPRINTFINSTANCE); 178 static char *getstr(PPRINTFINSTANCE); 179 static char *mklong(PPRINTFINSTANCE, const char *, int, char[64]); 180 static void check_conversion(PPRINTFINSTANCE, const char *, const char *); 181 static int usage(PKMKBUILTINCTX, int); 182 183 static int flush_buffer(PPRINTFINSTANCE); 184 static void b_count(PPRINTFINSTANCE, int); 185 static void b_output(PPRINTFINSTANCE, int); 186 static int wrap_putchar(PPRINTFINSTANCE, int ch); 187 static int wrap_printf(PPRINTFINSTANCE, const char *, ...); 188 189 190 191 int kmk_builtin_printf(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 192 { 168 193 int ch; 194 PRINTFINSTANCE This; 195 This.pCtx = pCtx; 196 This.b_length = 0; 197 This.b_fmt = NULL; 198 This.rval = 0; 199 This.gargv = NULL; 200 #ifndef KMK_BUILTIN_STANDALONE 201 This.g_o = NULL; 202 #endif 203 This.g_cchBuf = 0; 169 204 170 205 /* kmk: reset getopt, set progname and reset buffer. */ 171 g_progname = argv[0];172 206 opterr = 1; 173 207 optarg = NULL; … … 175 209 optind = 0; /* init */ 176 210 177 #if !defined(SHELL) && !defined(BUILTIN) && !defined(kmk_builtin_printf) /* kmk did this already. */178 (void)setlocale (LC_ALL, "");179 #endif180 181 211 while ((ch = getopt_long(argc, argv, "", long_options, NULL)) != -1) { 182 212 switch (ch) { 183 213 case 261: 184 usage( stdout);214 usage(pCtx, 0); 185 215 return 0; 186 216 case 262: … … 188 218 case '?': 189 219 default: 190 return usage( stderr);220 return usage(pCtx, 1); 191 221 } 192 222 } … … 194 224 argv += optind; 195 225 196 if (argc < 1) { 197 return usage(stderr); 198 } 199 200 rc = common_printf(argc, argv); 201 return rc; 202 } 203 204 #ifndef kmk_builtin_printf 226 if (argc < 1) 227 return usage(pCtx, 1); 228 return common_printf(&This, argc, argv); 229 } 230 231 #ifdef KMK_BUILTIN_STANDALONE 232 int main(int argc, char **argv, char **envp) 233 { 234 KMKBUILTINCTX Ctx = { "kmk_printf", NULL }; 235 setlocale(LC_ALL, ""); 236 return kmk_builtin_printf(argc, argv, envp, &Ctx); 237 } 238 #else /* KMK_BUILTIN_STANDALONE */ 205 239 /* entry point used by function.c $(printf ..,..). */ 206 240 char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname) 207 241 { 242 PRINTFINSTANCE This; 208 243 int rc; 209 244 int argc; … … 211 246 for (argc = 0; argv[argc] != NULL; argc++) 212 247 /* nothing */; 213 214 g_o = o; 215 rc = common_printf(argc, argv); 216 o = g_o; 217 g_o = NULL; 248 if (argc == 0) 249 fatal(NILF, strlen(funcname) + INTSTR_LENGTH, _("$(%s): no format string\n"), funcname); 250 251 This.pCtx = NULL; 252 This.b_length = 0; 253 This.b_fmt = NULL; 254 This.rval = 0; 255 This.gargv = NULL; 256 This.g_cchBuf = 0; 257 This.g_o = o; 258 259 rc = common_printf(&This, argc, argv); 260 o = This.g_o; 218 261 219 262 if (rc != 0) … … 221 264 return o; 222 265 } 223 #endif 224 225 static int common_printf( int argc, char *argv[])266 #endif /* KMK_BUILTIN_STANDALONE */ 267 268 static int common_printf(PPRINTFINSTANCE pThis, int argc, char *argv[]) 226 269 { 227 270 char *fmt, *start; … … 230 273 char *format; 231 274 int ch; 275 char longbuf[64]; 232 276 233 277 /* kmk: reinitialize globals */ 234 b_length = 0; 235 b_fmt = NULL; 236 rval = 0; 237 gargv = NULL; 238 g_cchBuf = 0; 239 278 pThis->b_length = 0; 279 pThis->b_fmt = NULL; 280 pThis->rval = 0; 281 pThis->gargv = NULL; 282 pThis->g_cchBuf = 0; 240 283 format = *argv; 241 gargv = ++argv;284 pThis->gargv = ++argv; 242 285 243 286 #define SKIP1 "#-+ 0" … … 257 300 if (ch == '\\') { 258 301 char c_ch; 259 fmt = conv_escape( fmt, &c_ch);260 wrap_putchar( c_ch);302 fmt = conv_escape(pThis, fmt, &c_ch); 303 wrap_putchar(pThis, c_ch); 261 304 continue; 262 305 } 263 306 if (ch != '%' || (*fmt == '%' && ++fmt)) { 264 (void)wrap_putchar( ch);307 (void)wrap_putchar(pThis, ch); 265 308 continue; 266 309 } … … 272 315 /* skip to field width */ 273 316 fmt += strspn(fmt, SKIP1); 274 fieldwidth = *fmt == '*' ? getwidth( ) : -1;317 fieldwidth = *fmt == '*' ? getwidth(pThis) : -1; 275 318 276 319 /* skip to possible '.', get following precision */ … … 278 321 if (*fmt == '.') 279 322 ++fmt; 280 precision = *fmt == '*' ? getwidth( ) : -1;323 precision = *fmt == '*' ? getwidth(pThis) : -1; 281 324 282 325 fmt += strspn(fmt, SKIP2); … … 284 327 ch = *fmt; 285 328 if (!ch) { 286 flush_buffer( );287 warnx( "missing format character");329 flush_buffer(pThis); 330 warnx(pThis->pCtx, "missing format character"); 288 331 return (1); 289 332 } … … 295 338 296 339 case 'B': { 297 const char *p = conv_expand(getstr( ));340 const char *p = conv_expand(getstr(pThis)); 298 341 *fmt = 's'; 299 342 PF(start, p); … … 305 348 * embedded nulls. */ 306 349 static char *a, *t; 307 char *cp = getstr( );350 char *cp = getstr(pThis); 308 351 /* Free on entry in case shell longjumped out */ 309 352 if (a != NULL) … … 314 357 t = NULL; 315 358 /* Count number of bytes we want to output */ 316 b_length = 0;317 conv_escape_str( cp, b_count);318 t = malloc( b_length + 1);359 pThis->b_length = 0; 360 conv_escape_str(pThis, cp, b_count); 361 t = malloc(pThis->b_length + 1); 319 362 if (t == NULL) 320 363 break; 321 memset(t, 'x', b_length);322 t[ b_length] = 0;364 memset(t, 'x', pThis->b_length); 365 t[pThis->b_length] = 0; 323 366 /* Get printf to calculate the lengths */ 324 367 *fmt = 's'; 325 368 APF(&a, start, t); 326 b_fmt = a;369 pThis->b_fmt = a; 327 370 /* Output leading spaces and data bytes */ 328 conv_escape_str( cp, b_output);371 conv_escape_str(pThis, cp, b_output); 329 372 /* Add any trailing spaces */ 330 wrap_printf( "%s",b_fmt);373 wrap_printf(pThis, "%s", pThis->b_fmt); 331 374 break; 332 375 } 333 376 case 'c': { 334 char p = getchr( );377 char p = getchr(pThis); 335 378 PF(start, p); 336 379 break; 337 380 } 338 381 case 's': { 339 char *p = getstr( );382 char *p = getstr(pThis); 340 383 PF(start, p); 341 384 break; … … 343 386 case 'd': 344 387 case 'i': { 345 intmax_t p = getintmax( );346 char *f = mklong( start, ch);388 intmax_t p = getintmax(pThis); 389 char *f = mklong(pThis, start, ch, longbuf); 347 390 PF(f, p); 348 391 break; … … 352 395 case 'x': 353 396 case 'X': { 354 uintmax_t p = getuintmax( );355 char *f = mklong( start, ch);397 uintmax_t p = getuintmax(pThis); 398 char *f = mklong(pThis, start, ch, longbuf); 356 399 PF(f, p); 357 400 break; … … 362 405 case 'g': 363 406 case 'G': { 364 double p = getdouble( );407 double p = getdouble(pThis); 365 408 PF(start, p); 366 409 break; 367 410 } 368 411 default: 369 flush_buffer( );370 warnx( "%s: invalid directive", start);412 flush_buffer(pThis); 413 warnx(pThis->pCtx, "%s: invalid directive", start); 371 414 return 1; 372 415 } … … 374 417 *fmt = nextch; 375 418 /* escape if a \c was encountered */ 376 if ( rval & 0x100) {377 flush_buffer( );378 return rval & ~0x100;379 } 380 } 381 } while ( gargv != argv && *gargv);382 383 flush_buffer( );384 return rval;419 if (pThis->rval & 0x100) { 420 flush_buffer(pThis); 421 return pThis->rval & ~0x100; 422 } 423 } 424 } while (pThis->gargv != argv && *pThis->gargv); 425 426 flush_buffer(pThis); 427 return pThis->rval; 385 428 } 386 429 … … 390 433 static void 391 434 /*ARGSUSED*/ 392 b_count( int ch)393 { 394 b_length++;435 b_count(PPRINTFINSTANCE pThis, int ch) 436 { 437 pThis->b_length++; 395 438 (void)ch; 396 439 } … … 399 442 400 443 static void 401 b_output( int ch)444 b_output(PPRINTFINSTANCE pThis, int ch) 402 445 { 403 446 for (;;) { 404 switch (* b_fmt++) {447 switch (*pThis->b_fmt++) { 405 448 case 0: 406 b_fmt--;449 pThis->b_fmt--; 407 450 return; 408 451 case ' ': 409 wrap_putchar( ' ');452 wrap_putchar(pThis, ' '); 410 453 break; 411 454 default: 412 wrap_putchar( ch);455 wrap_putchar(pThis, ch); 413 456 return; 414 457 } … … 416 459 } 417 460 418 static int wrap_putchar( int ch)419 { 420 #ifndef kmk_builtin_printf421 if ( g_o) {461 static int wrap_putchar(PPRINTFINSTANCE pThis, int ch) 462 { 463 #ifndef KMK_BUILTIN_STANDALONE 464 if (pThis->g_o) { 422 465 char sz[2]; 423 466 sz[0] = ch; sz[1] = '\0'; 424 g_o = variable_buffer_output(g_o, sz, 1);425 return ch;426 }467 pThis->g_o = variable_buffer_output(pThis->g_o, sz, 1); 468 } 469 else 427 470 #endif 428 471 /* Buffered output. */ 429 if ( g_cchBuf + 1 < sizeof(g_achBuf)) {430 g_achBuf[g_cchBuf++] = ch;472 if (pThis->g_cchBuf + 1 < sizeof(pThis->g_achBuf)) { 473 pThis->g_achBuf[pThis->g_cchBuf++] = ch; 431 474 } else { 432 int rc = flush_buffer( );433 g_achBuf[g_cchBuf++] = ch;475 int rc = flush_buffer(pThis); 476 pThis->g_achBuf[pThis->g_cchBuf++] = ch; 434 477 if (rc) 435 478 return -1; … … 438 481 } 439 482 440 static int wrap_printf( const char * fmt, ...)483 static int wrap_printf(PPRINTFINSTANCE pThis, const char * fmt, ...) 441 484 { 442 485 ssize_t cchRet; … … 448 491 va_end(va); 449 492 if (cchRet >= 0) { 450 #ifndef kmk_builtin_printf451 if ( g_o) {452 g_o = variable_buffer_output(g_o, pszTmp, cchRet);493 #ifndef KMK_BUILTIN_STANDALONE 494 if (pThis->g_o) { 495 pThis->g_o = variable_buffer_output(pThis->g_o, pszTmp, cchRet); 453 496 } else 454 497 #endif 455 498 { 456 if (cchRet + g_cchBuf <= sizeof(g_achBuf)) {499 if (cchRet + pThis->g_cchBuf <= sizeof(pThis->g_achBuf)) { 457 500 /* We've got space in the buffer. */ 458 memcpy(& g_achBuf[g_cchBuf], pszTmp, cchRet);459 g_cchBuf += cchRet;501 memcpy(&pThis->g_achBuf[pThis->g_cchBuf], pszTmp, cchRet); 502 pThis->g_cchBuf += cchRet; 460 503 } else { 461 504 /* Try write out complete lines. */ … … 466 509 const char *pchNewLine = strchr(pszLeft, '\n'); 467 510 ssize_t cchLine = pchNewLine ? pchNewLine - pszLeft + 1 : cchLeft; 468 if ( g_cchBuf + cchLine <= sizeof(g_achBuf)) {469 memcpy(& g_achBuf[g_cchBuf], pszLeft, cchLine);470 g_cchBuf += cchLine;511 if (pThis->g_cchBuf + cchLine <= sizeof(pThis->g_achBuf)) { 512 memcpy(&pThis->g_achBuf[pThis->g_cchBuf], pszLeft, cchLine); 513 pThis->g_cchBuf += cchLine; 471 514 } else { 472 if (flush_buffer( ) < 0) {515 if (flush_buffer(pThis) < 0) { 473 516 return -1; 474 517 } 475 if (fwrite(pszLeft, cchLine, 1, stdout) < 1) { 518 #ifndef KMK_BUILTIN_STANDALONE 519 if (output_write_text(pThis->pCtx->pOut, 0,pszLeft, cchLine) < 1) 520 #else 521 if (fwrite(pszLeft, cchLine, 1, stdout) < 1) 522 #endif 523 476 524 return -1; 477 }478 525 } 479 526 pszLeft += cchLine; … … 490 537 * Flushes the g_abBuf/g_cchBuf. 491 538 */ 492 static int flush_buffer(void) 493 { 494 if (g_cchBuf > 0) { 495 ssize_t cchToWrite = g_cchBuf; 496 ssize_t cchWritten = fwrite(g_achBuf, 1, g_cchBuf, stdout); 497 g_cchBuf = 0; 539 static int flush_buffer(PPRINTFINSTANCE pThis) 540 { 541 ssize_t cchToWrite = pThis->g_cchBuf; 542 if (cchToWrite > 0) { 543 #ifndef KMK_BUILTIN_STANDALONE 544 ssize_t cchWritten = output_write_text(pThis->pCtx->pOut, 0, pThis->g_achBuf, cchToWrite); 545 #else 546 ssize_t cchWritten = fwrite(pThis->g_achBuf, 1, cchToWrite, stdout); 547 #endif 548 pThis->g_cchBuf = 0; 498 549 if (cchWritten >= cchToWrite) { 499 550 /* likely */ … … 509 560 510 561 while (off < cchToWrite) { 511 cchWritten = fwrite(&g_achBuf[off], 1, cchToWrite - off, stdout); 562 #ifndef KMK_BUILTIN_STANDALONE 563 cchWritten = output_write_text(pThis->pCtx->pOut, 0, &pThis->g_achBuf[off], cchToWrite - off); 564 #else 565 cchWritten = fwrite(&pThis->g_achBuf[off], 1, cchToWrite - off, stdout); 566 #endif 512 567 if (cchWritten > 0) { 513 568 off += cchWritten; … … 530 585 */ 531 586 static void 532 conv_escape_str( char *str, void (*do_putchar)(int))587 conv_escape_str(PPRINTFINSTANCE pThis, char *str, void (*do_putchar)(PPRINTFINSTANCE, int)) 533 588 { 534 589 int value; … … 538 593 while ((ch = *str++) != '\0') { 539 594 if (ch != '\\') { 540 do_putchar( ch);595 do_putchar(pThis, ch); 541 596 continue; 542 597 } … … 545 600 if (ch == 'c') { 546 601 /* \c as in SYSV echo - abort all processing.... */ 547 rval |= 0x100;602 pThis->rval |= 0x100; 548 603 break; 549 604 } … … 561 616 octnum = (octnum << 3) | (*str++ - '0'); 562 617 } 563 do_putchar( octnum);618 do_putchar(pThis, octnum); 564 619 continue; 565 620 } … … 567 622 /* \[M][^|-]C as defined by vis(3) */ 568 623 if (ch == 'M' && *str == '-') { 569 do_putchar( 0200 | str[1]);624 do_putchar(pThis, 0200 | str[1]); 570 625 str += 2; 571 626 continue; … … 583 638 else 584 639 value |= ch & 037; 585 do_putchar( value);640 do_putchar(pThis, value); 586 641 continue; 587 642 } 588 643 589 644 /* Finally test for sequences valid in the format string */ 590 str = conv_escape( str - 1, &c);591 do_putchar( c);645 str = conv_escape(pThis, str - 1, &c); 646 do_putchar(pThis, c); 592 647 } 593 648 } … … 597 652 */ 598 653 static char * 599 conv_escape( char *str, char *conv_ch)654 conv_escape(PPRINTFINSTANCE pThis, char *str, char *conv_ch) 600 655 { 601 656 int value; … … 643 698 644 699 default: 645 warnx( "unknown escape sequence `\\%c'", ch);646 rval = 1;700 warnx(pThis->pCtx, "unknown escape sequence `\\%c'", ch); 701 pThis->rval = 1; 647 702 value = ch; 648 703 break; … … 720 775 721 776 static char * 722 mklong(const char *str, int ch) 723 { 724 static char copy[64]; 777 mklong(PPRINTFINSTANCE pThis, const char *str, int ch, char copy[64]) 778 { 725 779 size_t len; 726 780 727 781 len = strlen(str) - 1; 728 if (len > sizeof(copy)- 5) {729 warnx( "format %s too complex\n", str);782 if (len > 64 - 5) { 783 warnx(pThis->pCtx, "format %s too complex\n", str); 730 784 len = 4; 731 785 } … … 744 798 745 799 static int 746 getchr( void)747 { 748 if (!* gargv)800 getchr(PPRINTFINSTANCE pThis) 801 { 802 if (!*pThis->gargv) 749 803 return 0; 750 return (int)** gargv++;804 return (int)**pThis->gargv++; 751 805 } 752 806 753 807 static char * 754 getstr( void)808 getstr(PPRINTFINSTANCE pThis) 755 809 { 756 810 static char empty[] = ""; 757 if (!* gargv)811 if (!*pThis->gargv) 758 812 return empty; 759 return * gargv++;813 return *pThis->gargv++; 760 814 } 761 815 762 816 static int 763 getwidth( void)817 getwidth(PPRINTFINSTANCE pThis) 764 818 { 765 819 long val; 766 820 char *s, *ep; 767 821 768 s = * gargv;769 if (! *gargv)822 s = *pThis->gargv; 823 if (!s) 770 824 return (0); 771 gargv++;825 pThis->gargv++; 772 826 773 827 errno = 0; 774 828 val = strtoul(s, &ep, 0); 775 check_conversion( s, ep);829 check_conversion(pThis, s, ep); 776 830 777 831 /* Arbitrarily 'restrict' field widths to 1Mbyte */ 778 832 if (val < 0 || val > 1 << 20) { 779 warnx( "%s: invalid field width", s);833 warnx(pThis->pCtx, "%s: invalid field width", s); 780 834 return 0; 781 835 } … … 785 839 786 840 static intmax_t 787 getintmax( void)841 getintmax(PPRINTFINSTANCE pThis) 788 842 { 789 843 intmax_t val; 790 844 char *cp, *ep; 791 845 792 cp = * gargv;846 cp = *pThis->gargv; 793 847 if (cp == NULL) 794 848 return 0; 795 gargv++;849 pThis->gargv++; 796 850 797 851 if (*cp == '\"' || *cp == '\'') … … 800 854 errno = 0; 801 855 val = strtoimax(cp, &ep, 0); 802 check_conversion( cp, ep);856 check_conversion(pThis, cp, ep); 803 857 return val; 804 858 } 805 859 806 860 static uintmax_t 807 getuintmax( void)861 getuintmax(PPRINTFINSTANCE pThis) 808 862 { 809 863 uintmax_t val; 810 864 char *cp, *ep; 811 865 812 cp = * gargv;866 cp = *pThis->gargv; 813 867 if (cp == NULL) 814 868 return 0; 815 gargv++;869 pThis->gargv++; 816 870 817 871 if (*cp == '\"' || *cp == '\'') … … 822 876 cp++; 823 877 if (*cp == '-') { 824 warnx( "%s: expected positive numeric value", cp);825 rval = 1;878 warnx(pThis->pCtx, "%s: expected positive numeric value", cp); 879 pThis->rval = 1; 826 880 return 0; 827 881 } … … 829 883 errno = 0; 830 884 val = strtoumax(cp, &ep, 0); 831 check_conversion( cp, ep);885 check_conversion(pThis, cp, ep); 832 886 return val; 833 887 } 834 888 835 889 static double 836 getdouble( void)890 getdouble(PPRINTFINSTANCE pThis) 837 891 { 838 892 double val; 839 893 char *ep; 840 841 if (!*gargv) 894 char *s; 895 896 s = *pThis->gargv; 897 if (!s) 842 898 return (0.0); 843 844 if (**gargv == '\"' || **gargv == '\'') 845 return (double) *((*gargv++)+1); 899 pThis->gargv++; 900 901 if (*s == '\"' || *s == '\'') 902 return (double) s[1]; 846 903 847 904 errno = 0; 848 val = strtod( *gargv, &ep);849 check_conversion( *gargv++, ep);905 val = strtod(s, &ep); 906 check_conversion(pThis, s, ep); 850 907 return val; 851 908 } 852 909 853 910 static void 854 check_conversion( const char *s, const char *ep)911 check_conversion(PPRINTFINSTANCE pThis, const char *s, const char *ep) 855 912 { 856 913 if (*ep) { 857 914 if (ep == s) 858 warnx( "%s: expected numeric value", s);915 warnx(pThis->pCtx, "%s: expected numeric value", s); 859 916 else 860 warnx( "%s: not completely converted", s);861 rval = 1;917 warnx(pThis->pCtx, "%s: not completely converted", s); 918 pThis->rval = 1; 862 919 } else if (errno == ERANGE) { 863 warnx( "%s: %s", s, strerror(ERANGE));864 rval = 1;920 warnx(pThis->pCtx, "%s: %s", s, strerror(ERANGE)); 921 pThis->rval = 1; 865 922 } 866 923 } 867 924 868 925 static int 869 usage(FILE *pf) 870 { 871 fprintf(pf, "usage: %s format [arg ...]\n" 872 " or: %s --help\n" 873 " or: %s --version\n", 874 g_progname, g_progname, g_progname); 926 usage(PKMKBUILTINCTX pCtx, int fIsErr) 927 { 928 kmk_builtin_ctx_printf(pCtx, fIsErr, 929 "usage: %s format [arg ...]\n" 930 " or: %s --help\n" 931 " or: %s --version\n", 932 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 875 933 return 1; 876 934 } 935 -
trunk/src/kmk/kmkbuiltin/redirect.c
r3179 r3192 69 69 # include "nt/nt_child_inject_standard_handles.h" 70 70 #endif 71 #if defined(__gnu_hurd__) && !defined( kmk_builtin_redirect) /* need constant */71 #if defined(__gnu_hurd__) && !defined(KMK_BUILTIN_STANDALONE) /* need constant */ 72 72 # undef GET_PATH_MAX 73 73 # undef PATH_MAX … … 107 107 108 108 109 static const char *name(const char *pszName)109 static int kmk_redirect_usage(PKMKBUILTINCTX pCtx, int fIsErr) 110 110 { 111 const char *psz = strrchr(pszName, '/'); 112 #if defined(_MSC_VER) || defined(__OS2__) 113 const char *psz2 = strrchr(pszName, '\\'); 114 if (!psz2) 115 psz2 = strrchr(pszName, ':'); 116 if (psz2 && (!psz || psz2 > psz)) 117 psz = psz2; 118 #endif 119 return psz ? psz + 1 : pszName; 120 } 121 122 123 static int usage(FILE *pOut, const char *argv0) 124 { 125 argv0 = name(argv0); 126 fprintf(pOut, 127 "usage: %s [-[rwa+tb]<fd> <file>] [-d<fd>=<src-fd>] [-c<fd>]\n" 128 " [-Z] [-E <var=val>] [-C <dir>] [--wcc-brain-damage]\n" 129 " [-v] -- <program> [args]\n" 130 " or: %s --help\n" 131 " or: %s --version\n" 132 "\n" 133 "The rwa+tb is like for fopen, if not specified it defaults to w+.\n" 134 "The <fd> is either a number or an alias for the standard handles:\n" 135 " i = stdin\n" 136 " o = stdout\n" 137 " e = stderr\n" 138 "\n" 139 "The -d switch duplicate the right hand file descriptor (src-fd) to the left\n" 140 "hand side one (fd). The latter is limited to standard handles on windows.\n" 141 "\n" 142 "The -c switch will close the specified file descriptor. Limited to standard\n" 143 "handles on windows.\n" 144 "\n" 145 "The -Z switch zaps the environment.\n" 146 "\n" 147 "The -E switch is for making changes to the environment in a putenv\n" 148 "fashion.\n" 149 "\n" 150 "The -C switch is for changing the current directory. Please specify an\n" 151 "absolute program path as it's platform dependent whether this takes effect\n" 152 "before or after the executable is located.\n" 153 "\n" 154 "The --wcc-brain-damage switch is to work around wcc and wcc386 (Open Watcom)\n" 155 "not following normal quoting conventions on Windows, OS/2, and DOS.\n" 156 "\n" 157 "The -v switch is for making the thing more verbose.\n" 158 "\n" 159 "This command was originally just a quick hack to avoid invoking the shell\n" 160 "on Windows (cygwin) where forking is very expensive and has exhibited\n" 161 "stability issues on SMP machines. It has since grown into something like\n" 162 "/usr/bin/env on steroids.\n" 163 , 164 argv0, argv0, argv0); 111 kmk_builtin_ctx_printf(pCtx, fIsErr, 112 "usage: %s [-[rwa+tb]<fd> <file>] [-d<fd>=<src-fd>] [-c<fd>]\n" 113 " [-Z] [-E <var=val>] [-C <dir>] [--wcc-brain-damage]\n" 114 " [-v] -- <program> [args]\n" 115 " or: %s --help\n" 116 " or: %s --version\n" 117 "\n" 118 "The rwa+tb is like for fopen, if not specified it defaults to w+.\n" 119 "The <fd> is either a number or an alias for the standard handles:\n" 120 " i = stdin\n" 121 " o = stdout\n" 122 " e = stderr\n" 123 "\n" 124 "The -d switch duplicate the right hand file descriptor (src-fd) to the left\n" 125 "hand side one (fd). The latter is limited to standard handles on windows.\n" 126 "\n" 127 "The -c switch will close the specified file descriptor. Limited to standard\n" 128 "handles on windows.\n" 129 "\n" 130 "The -Z switch zaps the environment.\n" 131 "\n" 132 "The -E switch is for making changes to the environment in a putenv\n" 133 "fashion.\n" 134 "\n" 135 "The -C switch is for changing the current directory. Please specify an\n" 136 "absolute program path as it's platform dependent whether this takes effect\n" 137 "before or after the executable is located.\n" 138 "\n" 139 "The --wcc-brain-damage switch is to work around wcc and wcc386 (Open Watcom)\n" 140 "not following normal quoting conventions on Windows, OS/2, and DOS.\n" 141 "\n" 142 "The -v switch is for making the thing more verbose.\n" 143 "\n" 144 "This command was originally just a quick hack to avoid invoking the shell\n" 145 "on Windows (cygwin) where forking is very expensive and has exhibited\n" 146 "stability issues on SMP machines. It has since grown into something like\n" 147 "/usr/bin/env on steroids.\n" 148 , 149 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 165 150 return 2; 166 151 } … … 198 183 199 184 200 #ifdef _MSC_VER201 202 /** Used by mscGetOsHandle. */203 static void __cdecl ignore_invalid_parameter(const wchar_t *a, const wchar_t *b, const wchar_t *c, unsigned d, uintptr_t e)204 {205 }206 207 /**208 * Safe way of getting the OS handle of a file descriptor without triggering209 * invalid parameter handling.210 *211 * @returns The handle value if open, INVALID_HANDLE_VALUE if not.212 * @param fd The file descriptor in question.213 */214 static HANDLE mscGetOsHandle(int fd)215 {216 intptr_t hHandle;217 _invalid_parameter_handler pfnOld = _get_invalid_parameter_handler();218 _set_invalid_parameter_handler(ignore_invalid_parameter);219 hHandle = _get_osfhandle(fd);220 _set_invalid_parameter_handler(pfnOld);221 return hHandle != -1 ? (HANDLE)hHandle : INVALID_HANDLE_VALUE;222 }223 224 /**225 * Checks if the specified file descriptor is open.226 *227 * @returns K_TRUE if open, K_FALSE if not.228 * @param fd The file descriptor in question.229 */230 static KBOOL mscIsOpenFile(int fd)231 {232 return mscGetOsHandle(fd) != INVALID_HANDLE_VALUE;233 }234 235 /**236 * Checks if the native handle is inheritable.237 *238 * @returns K_TRUE if it is, K_FALSE if it isn't or isn't a valid handle.239 * @param hHandle The native handle.240 */241 static KBOOL mscIsNativeHandleInheritable(HANDLE hHandle)242 {243 DWORD fFlags = 0;244 if (GetHandleInformation(hHandle, &fFlags))245 return (fFlags & HANDLE_FLAG_INHERIT) != 0;246 return K_FALSE;247 }248 249 /**250 * Checks if the file descriptor is inheritable or not.251 *252 * @returns K_TRUE if it is, K_FALSE if it isn't or isn't a valid descriptor.253 * @param fd The file descriptor in question.254 */255 static KBOOL mscIsInheritable(int fd)256 {257 HANDLE hHandle = mscGetOsHandle(fd);258 if (hHandle != INVALID_HANDLE_VALUE)259 return mscIsNativeHandleInheritable(hHandle);260 return K_FALSE;261 }262 263 /**264 * A dup3 like function.265 *266 * @returns fdNew on success, -1 on failure w/ error details written to pStdErr.267 * @param fdSource The source descriptor.268 * @param fdNew The new descriptor.269 * @param fFlags The inherit and text/binary mode flag.270 * @param pStdErr Working stderr to write error details to.271 */272 static int mscDup3(int fdSource, int fdNew, int fFlags, FILE *pStdErr)273 {274 if (!fFlags & _O_NOINHERIT)275 {276 /* ASSUMES fFlags doesn't include any changing _O_TEXT/_O_BINARY. */277 int fdDup = _dup2(fdSource, fdNew);278 if (fdDup != -1)279 return fdDup;280 fprintf(pStdErr, "%s: _dup2(%d,%d) failed: %s\n", g_progname, fdSource, fdNew, strerror(errno));281 }282 else283 {284 HANDLE hSource = mscGetOsHandle(fdSource);285 unsigned cTries = 0;286 int aFdTries[48];287 288 if (hSource != INVALID_HANDLE_VALUE)289 {290 HANDLE hCurProc = GetCurrentProcess();291 BOOL fInherit = !(fFlags & _O_NOINHERIT);292 293 /*294 * Make sure the old descriptor is closed and can be used again.295 */296 _invalid_parameter_handler pfnOld = _get_invalid_parameter_handler();297 _set_invalid_parameter_handler(ignore_invalid_parameter);298 close(fdNew);299 _set_invalid_parameter_handler(pfnOld);300 301 /*302 * Duplicate the source handle till we've got a match.303 */304 for (;;)305 {306 HANDLE hDup = INVALID_HANDLE_VALUE;307 if (DuplicateHandle(hCurProc, hSource, hCurProc, &hDup, 0 /* DesiredAccess */,308 fInherit, DUPLICATE_SAME_ACCESS))309 {310 int fdDup = _open_osfhandle((intptr_t)hDup, fFlags);311 if (fdDup != -1)312 {313 if (fdDup == fdNew)314 {315 while (cTries-- > 0)316 close(aFdTries[cTries]);317 return fdDup;318 }319 320 aFdTries[cTries++] = fdDup;321 if ( fdDup < fdNew322 && cTries < K_ELEMENTS(aFdTries))323 continue;324 fprintf(pStdErr, "%s: mscDup3(%d,%d): giving up! (last fdDup=%d)\n",325 g_progname, fdSource, fdNew, fdDup);326 }327 else328 {329 fprintf(pStdErr, "%s: _open_osfhandle(%#x) failed: %u\n", g_progname, hDup, strerror(errno));330 CloseHandle(hDup);331 }332 }333 else334 fprintf(pStdErr, "%s: DuplicateHandle(%#x) failed: %u\n", g_progname, hSource, GetLastError());335 break;336 }337 338 while (cTries-- > 0)339 close(aFdTries[cTries]);340 }341 else342 fprintf(pStdErr, "%s: mscDup3(%d,%d): source descriptor is invalid!\n", g_progname, fdSource, fdNew);343 }344 return -1;345 }346 347 #endif /* _MSC_VER */348 349 185 static KBOOL kRedirectHasConflict(int fd, unsigned cOrders, REDIRECTORDERS *paOrders) 350 186 { … … 374 210 * unless it matches @a fdTarget 375 211 * 212 * @param pCtx The command execution context. 376 213 * @param pszFilename The filename to open. 377 214 * @param fOpen The open flags. … … 382 219 * @param fdTarget The target descriptor. 383 220 */ 384 static int kRedirectOpenWithoutConflict( const char *pszFilename, int fOpen, mode_t fMode,221 static int kRedirectOpenWithoutConflict(PKMKBUILTINCTX pCtx, const char *pszFilename, int fOpen, mode_t fMode, 385 222 unsigned cOrders, REDIRECTORDERS *paOrders, int fRemoveOnFailure, int fdTarget) 386 223 { … … 407 244 fdOpened = open(pszFilename, fOpen | fNoInherit, fMode); 408 245 if (fdOpened < 0) 409 return err( -1, "open(%s,%#x,) failed", pszFilename, fOpen);246 return err(pCtx, -1, "open(%s,%#x,) failed", pszFilename, fOpen); 410 247 411 248 /* Check for conflicts. */ … … 453 290 else 454 291 { 455 err( -1, "open(%s,%#x,) #%u failed", pszFilename, cTries + 1, fOpen);292 err(pCtx, -1, "open(%s,%#x,) #%u failed", pszFilename, cTries + 1, fOpen); 456 293 break; 457 294 } … … 463 300 */ 464 301 if (fdOpened >= 0) 465 errx( -1, "failed to find a conflict free file descriptor for '%s'!", pszFilename);302 errx(pCtx, -1, "failed to find a conflict free file descriptor for '%s'!", pszFilename); 466 303 467 304 while (cTries-- > 0) … … 499 336 500 337 338 /** 339 * Wrapper that chooses between fprintf and kmk_builtin_ctx_printf to get 340 * an error message to the user. 341 * 342 * @param pCtx The command execution context. 343 * @param pWorkingStdErr Work stderr. 344 * @param pszFormat The message format string. 345 * @param ... Format arguments. 346 */ 347 static void safe_err_printf(PKMKBUILTINCTX pCtx, FILE *pWorkingStdErr, const char *pszFormat, ...) 348 { 349 char szMsg[4096]; 350 size_t cchMsg; 351 va_list va; 352 353 va_start(va, pszFormat); 354 vsnprintf(szMsg, sizeof(szMsg) - 1, pszFormat, va); 355 va_end(va); 356 szMsg[sizeof(szMsg) - 1] = '\0'; 357 cchMsg = strlen(szMsg); 358 359 #ifdef KMK_BUILTIN_STANDALONE 360 (void)pCtx; 361 #else 362 if (pCtx->pOut && pCtx->pOut->syncout) 363 output_write_text(pCtx->pOut, 1, szMsg, cchMsg); 364 else 365 #endif 366 fwrite(szMsg, cchMsg, 1, pWorkingStdErr); 367 } 368 501 369 #if !defined(USE_POSIX_SPAWN) && !defined(KBUILD_OS_WINDOWS) 502 370 … … 506 374 * 507 375 * @returns 0 on success, non-zero exit code on failure. 376 * @param pCtx The command execution context. 508 377 * @param pToSave Pointer to the file order to save the target 509 378 * descriptor of. … … 514 383 * keep having a working one to report failures to. 515 384 */ 516 static int kRedirectSaveHandle(REDIRECTORDERS *pToSave, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) 385 static int kRedirectSaveHandle(PKMKBUILTINCTX pCtx, REDIRECTORDERS *pToSave, unsigned cOrders, 386 REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) 517 387 { 518 388 int fdToSave = pToSave->fdTarget; … … 537 407 if (fdDup == -1) 538 408 { 539 fprintf(*ppWorkingStdErr, "%s: dup(%#x) failed: %u\n", g_progname, fdToSave, strerror(errno));409 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup(%#x) failed: %u\n", pCtx->pszProgName, fdToSave, strerror(errno)); 540 410 break; 541 411 } … … 550 420 if (*ppWorkingStdErr == NULL) 551 421 { 552 fprintf(stderr, "%s: fdopen(%d,\"wt\") failed: %s\n", g_progname, fdDup, strerror(errno));422 safe_err_printf(pCtx, stderr, "%s: fdopen(%d,\"wt\") failed: %s\n", pCtx->pszProgName, fdDup, strerror(errno)); 553 423 *ppWorkingStdErr = stderr; 554 424 close(fdDup); … … 585 455 * Restores the target file descriptors affected by the file operation orders. 586 456 * 457 * @param pCtx The command execution context. 587 458 * @param cOrders Number of file operation orders. 588 459 * @param paOrders The file operation orders. … … 591 462 * it to stderr. 592 463 */ 593 static void kRedirectRestoreFdOrders( unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)464 static void kRedirectRestoreFdOrders(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) 594 465 { 595 466 int iSavedErrno = errno; … … 613 484 } 614 485 else 615 fprintf(*ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n",616 g_progname, paOrders[i].fdSaved, paOrders[i].fdTarget, strerror(errno));486 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n", 487 pCtx->pszProgName, paOrders[i].fdSaved, paOrders[i].fdTarget, strerror(errno)); 617 488 } 618 489 … … 622 493 paOrders[i].fSaved = -1; 623 494 else 624 fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,%s) failed: %s\n", 625 g_progname, paOrders[i].fdTarget, paOrders[i].fSaved & FD_CLOEXEC ? "FD_CLOEXEC" : "0", strerror(errno)); 495 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,%s) failed: %s\n", 496 pCtx->pszProgName, paOrders[i].fdTarget, paOrders[i].fSaved & FD_CLOEXEC ? "FD_CLOEXEC" : "0", 497 strerror(errno)); 626 498 } 627 499 } … … 634 506 * 635 507 * @returns 0 on success, exit code on failure. 508 * @param pCtx The command execution context. 636 509 * @param cOrders Number of file operation orders. 637 510 * @param paOrders File operation orders to execute. … … 639 512 * kRedirectRestoreFdOrders). 640 513 */ 641 static int kRedirectExecFdOrders( unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)514 static int kRedirectExecFdOrders(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr) 642 515 { 643 516 unsigned i; … … 669 542 rcExit = 0; 670 543 else 671 fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,FD_CLOEXEC) failed: %s\n",672 g_progname, fdTarget, strerror(errno));544 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,FD_CLOEXEC) failed: %s\n", 545 pCtx->pszProgName, fdTarget, strerror(errno)); 673 546 } 674 547 else if (errno == EBADF) 675 548 rcExit = 0; 676 549 else 677 fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_GETFD,0) failed: %s\n", g_progname, fdTarget, strerror(errno)); 550 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: fcntl(%d,F_GETFD,0) failed: %s\n", 551 pCtx->pszProgName, fdTarget, strerror(errno)); 678 552 } 679 553 else 680 rcExit = kRedirectSaveHandle( &paOrders[i], cOrders, paOrders, ppWorkingStdErr);554 rcExit = kRedirectSaveHandle(pCtx, &paOrders[i], cOrders, paOrders, ppWorkingStdErr); 681 555 break; 682 556 } … … 684 558 case kRedirectOrder_Dup: 685 559 case kRedirectOrder_Open: 686 rcExit = kRedirectSaveHandle( &paOrders[i], cOrders, paOrders, ppWorkingStdErr);560 rcExit = kRedirectSaveHandle(pCtx, &paOrders[i], cOrders, paOrders, ppWorkingStdErr); 687 561 if (rcExit == 0) 688 562 { … … 692 566 { 693 567 if (paOrders[i].enmOrder == kRedirectOrder_Open) 694 fprintf(*ppWorkingStdErr, "%s: dup2(%d [%s],%d) failed: %s\n", g_progname, paOrders[i].fdSource,695 paOrders[i].pszFilename, paOrders[i].fdTarget, strerror(errno));568 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup2(%d [%s],%d) failed: %s\n", pCtx->pszProgName, 569 paOrders[i].fdSource, paOrders[i].pszFilename, paOrders[i].fdTarget, strerror(errno)); 696 570 else 697 fprintf(*ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n",698 g_progname, paOrders[i].fdSource, paOrders[i].fdTarget, strerror(errno));571 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n", 572 pCtx->pszProgName, paOrders[i].fdSource, paOrders[i].fdTarget, strerror(errno)); 699 573 rcExit = 10; 700 574 } … … 703 577 704 578 default: 705 fprintf(*ppWorkingStdErr, "%s: error! invalid enmOrder=%d\n", g_progname, paOrders[i].enmOrder);579 safe_err_printf(pCtx, *ppWorkingStdErr, "%s: error! invalid enmOrder=%d\n", pCtx->pszProgName, paOrders[i].enmOrder); 706 580 rcExit = 99; 707 581 break; … … 710 584 if (rcExit != 0) 711 585 { 712 kRedirectRestoreFdOrders( i, paOrders, ppWorkingStdErr);586 kRedirectRestoreFdOrders(pCtx, i, paOrders, ppWorkingStdErr); 713 587 return rcExit; 714 588 } … … 799 673 * 800 674 * @returns 0 on success, non-zero on failure to create. 675 * @param pCtx The command execution context. 801 676 * @param pszExecutable The child process executable. 802 677 * @param cArgs Number of arguments. … … 808 683 * @param phProcess Where to return process handle. 809 684 */ 810 static int kRedirectCreateProcessWindows(const char *pszExecutable, int cArgs, char **papszArgs, char **papszEnvVars, 811 const char *pszCwd, unsigned cOrders, REDIRECTORDERS *paOrders, HANDLE *phProcess) 685 static int kRedirectCreateProcessWindows(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, 686 char **papszEnvVars, const char *pszCwd, unsigned cOrders, 687 REDIRECTORDERS *paOrders, HANDLE *phProcess) 812 688 { 813 689 size_t cbArgs; … … 828 704 pszCmdLine = pch = (char *)malloc(cbArgs); 829 705 if (!pszCmdLine) 830 return errx( 9, "out of memory!");706 return errx(pCtx, 9, "out of memory!"); 831 707 for (i = 0; i < cArgs; i++) 832 708 { … … 901 777 } 902 778 else 903 rc = errx( 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError());779 rc = errx(pCtx, 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError()); 904 780 } 905 781 else … … 923 799 if ( (paOrders[i].fOpen & O_APPEND) 924 800 && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0) 925 rc = err( 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget);801 rc = err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget); 926 802 case kRedirectOrder_Dup: 927 803 ahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource); 928 804 if (ahChild[fdTarget] == NULL || ahChild[fdTarget] == INVALID_HANDLE_VALUE) 929 rc = err( 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget);805 rc = err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget); 930 806 break; 931 807 case kRedirectOrder_Close: … … 949 825 rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg)); 950 826 if (rc) 951 rc = errx( 10, "%s", szErrMsg);827 rc = errx(pCtx, 10, "%s", szErrMsg); 952 828 else if (!ResumeThread(ProcInfo.hThread)) 953 rc = errx( 10, "ResumeThread failed: %u", GetLastError());829 rc = errx(pCtx, 10, "ResumeThread failed: %u", GetLastError()); 954 830 955 831 /* Kill it if any of that fails. */ … … 962 838 } 963 839 else 964 rc = errx( 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError());840 rc = errx(pCtx, 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError()); 965 841 } 966 842 } … … 968 844 } 969 845 else 970 rc = errx( 9, "out of memory!");846 rc = errx(pCtx, 9, "out of memory!"); 971 847 free(pszCmdLine); 972 848 return rc; … … 979 855 * 980 856 * @returns Exit code. 857 * @param pCtx The command execution context. 981 858 * @param pszExecutable The child process executable. 982 859 * @param cArgs Number of arguments. … … 998 875 * is from the child or from our setup efforts. 999 876 */ 1000 static int kRedirectDoSpawn( const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage,877 static int kRedirectDoSpawn(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage, 1001 878 char **papszEnvVars, const char *pszCwd, const char *pszSavedCwd, 1002 879 unsigned cOrders, REDIRECTORDERS *paOrders, … … 1025 902 memcpy(papszArgs, papszArgsOriginal, (cArgs + 1) * sizeof(papszArgs[0])); 1026 903 else 1027 return errx( 9, "out of memory!");904 return errx(pCtx, 9, "out of memory!"); 1028 905 1029 906 rcExit = quote_argv(cArgs, papszArgs, fWatcomBrainDamage, 0 /*fFreeOrLeak*/); … … 1037 914 { 1038 915 for (i = 0; i < cArgs; i++) 1039 warnx( "debug: argv[%i]=%s<eos>", i, papszArgs[i]);916 warnx(pCtx, "debug: argv[%i]=%s<eos>", i, papszArgs[i]); 1040 917 for (i = 0; i < (int)cOrders; i++) 1041 918 switch (paOrders[i].enmOrder) 1042 919 { 1043 920 case kRedirectOrder_Close: 1044 warnx( "debug: close %d\n", paOrders[i].fdTarget);921 warnx(pCtx, "debug: close %d\n", paOrders[i].fdTarget); 1045 922 break; 1046 923 case kRedirectOrder_Dup: 1047 warnx( "debug: dup %d to %d\n", paOrders[i].fdSource, paOrders[i].fdTarget);924 warnx(pCtx, "debug: dup %d to %d\n", paOrders[i].fdSource, paOrders[i].fdTarget); 1048 925 break; 1049 926 case kRedirectOrder_Open: 1050 warnx( "debug: open '%s' (%#x) as [%d ->] %d\n",927 warnx(pCtx, "debug: open '%s' (%#x) as [%d ->] %d\n", 1051 928 paOrders[i].pszFilename, paOrders[i].fOpen, paOrders[i].fdSource, paOrders[i].fdTarget); 1052 929 break; 1053 930 default: 1054 warnx( "error! invalid enmOrder=%d", paOrders[i].enmOrder);931 warnx(pCtx, "error! invalid enmOrder=%d", paOrders[i].enmOrder); 1055 932 assert(0); 1056 933 break; 1057 934 } 1058 935 if (pszSavedCwd) 1059 warnx( "debug: chdir %s\n", pszCwd);936 warnx(pCtx, "debug: chdir %s\n", pszCwd); 1060 937 } 1061 938 … … 1067 944 { 1068 945 if (chdir(pszCwd) < 0) 1069 rcExit = errx( 10, "Failed to change directory to '%s'", pszCwd);946 rcExit = errx(pCtx, 10, "Failed to change directory to '%s'", pszCwd); 1070 947 } 1071 948 #endif /* KBUILD_OS_WINDOWS */ … … 1077 954 */ 1078 955 FILE *pWorkingStdErr = NULL; 1079 rcExit = kRedirectExecFdOrders( cOrders, paOrders, &pWorkingStdErr);956 rcExit = kRedirectExecFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr); 1080 957 if (rcExit == 0) 1081 958 # endif … … 1088 965 /* Windows is slightly complicated due to handles and winchildren.c. */ 1089 966 HANDLE hProcess = INVALID_HANDLE_VALUE; 1090 rcExit = kRedirectCreateProcessWindows(p szExecutable, cArgs, papszArgs, papszEnvVars,967 rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, 1091 968 pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess); 1092 969 if (rcExit == 0) … … 1100 977 { 1101 978 if (cVerbosity > 0) 1102 warnx( "debug: spawned %d", *pPidSpawned);979 warnx(pCtx, "debug: spawned %d", *pPidSpawned); 1103 980 } 1104 981 else … … 1106 983 DWORD dwTmp; 1107 984 # ifndef CONFIG_NEW_WIN_CHILDREN 1108 warn( "sub_proc is out of slots, waiting for child...");985 warn(pCtx, "sub_proc is out of slots, waiting for child..."); 1109 986 # else 1110 987 if (pPidSpawned) 1111 warn( "MkWinChildCreateRedirect failed...");988 warn(pCtx, "MkWinChildCreateRedirect failed..."); 1112 989 # endif 1113 990 dwTmp = WaitForSingleObject(hProcess, INFINITE); 1114 991 if (dwTmp != WAIT_OBJECT_0) 1115 warn ("WaitForSingleObject failed: %#x\n", dwTmp);992 warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp); 1116 993 1117 994 if (GetExitCodeProcess(hProcess, &dwTmp)) … … 1119 996 else 1120 997 { 1121 warn ("GetExitCodeProcess failed: %u\n", GetLastError());998 warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError()); 1122 999 TerminateProcess(hProcess, 127); 1123 1000 rcExit = 127; … … 1133 1010 # elif defined(KBUILD_OS_OS2) 1134 1011 *pPidSpawned = _spawnvpe(P_NOWAIT, pszExecutable, papszArgs, papszEnvVars); 1135 kRedirectRestoreFdOrders( cOrders, paOrders, &pWorkingStdErr);1012 kRedirectRestoreFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr); 1136 1013 if (*pPidSpawned != -1) 1137 1014 { 1138 1015 if (cVerbosity > 0) 1139 warnx( "debug: spawned %d", *pPidSpawned);1016 warnx(pCtx, "debug: spawned %d", *pPidSpawned); 1140 1017 } 1141 1018 else 1142 1019 { 1143 rcExit = err( 10, "_spawnvpe(%s) failed", pszExecutable);1020 rcExit = err(pCtx, 10, "_spawnvpe(%s) failed", pszExecutable); 1144 1021 *pPidSpawned = 0; 1145 1022 } … … 1149 1026 { 1150 1027 if (cVerbosity > 0) 1151 warnx( "debug: spawned %d", *pPidSpawned);1028 warnx(pCtx, "debug: spawned %d", *pPidSpawned); 1152 1029 } 1153 1030 else 1154 1031 { 1155 rcExit = errx( 10, "posix_spawnp(%s) failed: %s", pszExecutable, strerror(rcExit));1032 rcExit = errx(pCtx, 10, "posix_spawnp(%s) failed: %s", pszExecutable, strerror(rcExit)); 1156 1033 *pPidSpawned = 0; 1157 1034 } … … 1164 1041 # ifdef KBUILD_OS_WINDOWS 1165 1042 HANDLE hProcess = INVALID_HANDLE_VALUE; 1166 rcExit = kRedirectCreateProcessWindows(p szExecutable, cArgs, papszArgs, papszEnvVars,1043 rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, 1167 1044 pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess); 1168 1045 if (rcExit == 0) … … 1177 1054 rcExit = dwWait; 1178 1055 else 1179 rcExit = errx( 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError());1056 rcExit = errx(pCtx, 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError()); 1180 1057 } 1181 1058 … … 1183 1060 errno = 0; 1184 1061 rcExit = (int)_spawnvpe(P_WAIT, pszExecutable, papszArgs, papszEnvVars); 1185 kRedirectRestoreFdOrders( cOrders, paOrders, &pWorkingStdErr);1062 kRedirectRestoreFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr); 1186 1063 if (rcExit != -1 || errno == 0) 1187 1064 { 1188 1065 *pfIsChildExitCode = K_TRUE; 1189 1066 if (cVerbosity > 0) 1190 warnx( "debug: exit code: %d", rcExit);1067 warnx(pCtx, "debug: exit code: %d", rcExit); 1191 1068 } 1192 1069 else 1193 rcExit = err( 10, "_spawnvpe(%s) failed", pszExecutable);1070 rcExit = err(pCtx, 10, "_spawnvpe(%s) failed", pszExecutable); 1194 1071 1195 1072 # else … … 1200 1077 *pfIsChildExitCode = K_TRUE; 1201 1078 if (cVerbosity > 0) 1202 warnx( "debug: spawned %d", pidChild);1079 warnx(pCtx, "debug: spawned %d", pidChild); 1203 1080 1204 1081 /* Wait for the child. */ … … 1209 1086 { 1210 1087 if (cVerbosity > 0) 1211 warnx( "debug: %d exit code: %d", pidChild, rcExit);1088 warnx(pCtx, "debug: %d exit code: %d", pidChild, rcExit); 1212 1089 break; 1213 1090 } … … 1218 1095 ) 1219 1096 { 1220 rcExit = err( 11, "waitpid failed");1097 rcExit = err(pCtx, 11, "waitpid failed"); 1221 1098 kill(pidChild, SIGKILL); 1222 1099 break; … … 1225 1102 } 1226 1103 else 1227 rcExit = errx( 10, "posix_spawnp(%s) failed: %s", pszExecutable, strerror(rcExit));1104 rcExit = errx(pCtx, 10, "posix_spawnp(%s) failed: %s", pszExecutable, strerror(rcExit)); 1228 1105 # endif 1229 1106 #endif /* !KMK */ … … 1238 1115 { 1239 1116 if (chdir(pszSavedCwd) < 0) 1240 warn( "Failed to restore directory to '%s'", pszSavedCwd);1117 warn(pCtx, "Failed to restore directory to '%s'", pszSavedCwd); 1241 1118 } 1242 1119 #endif … … 1244 1121 #ifdef _MSC_VER 1245 1122 else 1246 rcExit = errx( 9, "quite_argv failed: %u", rcExit);1123 rcExit = errx(pCtx, 9, "quite_argv failed: %u", rcExit); 1247 1124 1248 1125 /* Restore the original argv strings, freeing the quote_argv replacements. */ … … 1260 1137 * The function that does almost everything here... ugly. 1261 1138 */ 1262 #ifdef KMK 1263 int kmk_builtin_redirect(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned) 1264 #else 1265 int main(int argc, char **argv, char **envp) 1266 #endif 1139 int kmk_builtin_redirect(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) 1267 1140 { 1268 1141 int rcExit = 0; … … 1290 1163 1291 1164 1292 g_progname = argv[0];1293 1294 1165 if (argc <= 1) 1295 return usage(stderr, argv[0]);1166 return kmk_redirect_usage(pCtx, 1); 1296 1167 1297 1168 /* … … 1305 1176 { /* likely */ } 1306 1177 else 1307 return err( 9, "getcwd failed");1178 return err(pCtx, 9, "getcwd failed"); 1308 1179 1309 1180 /* We start out with a read-only enviornment from kmk or the crt, and will … … 1321 1192 rcExit = posix_spawn_file_actions_init(&FileActions); 1322 1193 if (rcExit != 0) 1323 rcExit = errx( 9, "posix_spawn_file_actions_init failed: %s", strerror(rcExit));1194 rcExit = errx(pCtx, 9, "posix_spawn_file_actions_init failed: %s", strerror(rcExit)); 1324 1195 #endif 1325 1196 … … 1384 1255 else 1385 1256 { 1386 errx( 2, "Unknown option: '%s'", pszArg - 2);1387 rcExit = usage(stderr, argv[0]);1257 errx(pCtx, 2, "Unknown option: '%s'", pszArg - 2); 1258 rcExit = kmk_redirect_usage(pCtx, 1); 1388 1259 break; 1389 1260 } … … 1396 1267 if (chOpt == 'h') 1397 1268 { 1398 usage(stdout, argv[0]);1269 kmk_redirect_usage(pCtx, 0); 1399 1270 rcExit = -1; 1400 1271 break; … … 1425 1296 else 1426 1297 { 1427 errx( 2, "syntax error: Option -%c requires a value!", chOpt);1428 rcExit = usage(stderr, argv[0]);1298 errx(pCtx, 2, "syntax error: Option -%c requires a value!", chOpt); 1299 rcExit = kmk_redirect_usage(pCtx, 1); 1429 1300 break; 1430 1301 } … … 1457 1328 if (rc) 1458 1329 { 1459 rcExit = errx( 9, "DosQueryExtLIBPATH(,%u) failed: %lu", ulVar, rc);1330 rcExit = errx(pCtx, 9, "DosQueryExtLIBPATH(,%u) failed: %lu", ulVar, rc); 1460 1331 free(apszSavedLibPaths[ulVar]); 1461 1332 apszSavedLibPaths[ulVar] = NULL; … … 1463 1334 } 1464 1335 else 1465 rcExit = errx( 9, "out of memory!");1336 rcExit = errx(pCtx, 9, "out of memory!"); 1466 1337 } 1467 1338 if (rcExit == 0) … … 1469 1340 rc = DosSetExtLIBPATH(pchEqual + 1, ulVar); 1470 1341 if (rc) 1471 rcExit = errx( 9, "error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu",1342 rcExit = errx(pCtx, 9, "error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu", 1472 1343 pchEqual, pchEqual - pszValue, pchEqual + 1, ulVar, rc); 1473 1344 } … … 1480 1351 { 1481 1352 if (pchEqual[1] != '\0') 1482 rcExit = kBuiltinOptEnvSet( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1353 rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1483 1354 else 1484 1355 { … … 1487 1358 { 1488 1359 pszCopy[pchEqual - pszValue] = '\0'; 1489 rcExit = kBuiltinOptEnvUnset( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszCopy);1360 rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszCopy); 1490 1361 free(pszCopy); 1491 1362 } 1492 1363 else 1493 rcExit = errx( 1, "out of memory!");1364 rcExit = errx(pCtx, 1, "out of memory!"); 1494 1365 } 1495 1366 continue; … … 1508 1379 || strcmp(pszValue, "ENDLIBPATH") == 0 1509 1380 || strcmp(pszValue, "LIBPATHSTRICT") == 0) 1510 rcExit = errx( 2, "error: '%s' cannot currently be appended or prepended to. Please use -E/--set for now.", pszValue);1381 rcExit = errx(pCtx, 2, "error: '%s' cannot currently be appended or prepended to. Please use -E/--set for now.", pszValue); 1511 1382 else 1512 1383 #endif 1513 1384 if (chOpt == 'A') 1514 rcExit = kBuiltinOptEnvAppend( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1385 rcExit = kBuiltinOptEnvAppend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1515 1386 else 1516 rcExit = kBuiltinOptEnvPrepend( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1387 rcExit = kBuiltinOptEnvPrepend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1517 1388 continue; 1518 1389 } … … 1527 1398 || strcmp(pszValue, "ENDLIBPATH") == 0 1528 1399 || strcmp(pszValue, "LIBPATHSTRICT") == 0) 1529 rcExit = errx( 2, "error: '%s' cannot be unset, only set to an empty value using -E/--set.", pszValue);1400 rcExit = errx(pCtx, 2, "error: '%s' cannot be unset, only set to an empty value using -E/--set.", pszValue); 1530 1401 else 1531 1402 #endif 1532 rcExit = kBuiltinOptEnvUnset( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1403 rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1533 1404 continue; 1534 1405 } … … 1540 1411 || chOpt == 'i' /* GNU env compatibility. */ ) 1541 1412 { 1542 rcExit = kBuiltinOptEnvZap( &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity);1413 rcExit = kBuiltinOptEnvZap(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity); 1543 1414 continue; 1544 1415 } … … 1552 1423 pszSavedCwd = strdup(szCwd); 1553 1424 if (pszSavedCwd) 1554 rcExit = kBuiltinOptChDir( szCwd, cbCwdBuf, pszValue);1425 rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue); 1555 1426 else 1556 rcExit = err( 9, "out of memory!");1427 rcExit = err(pCtx, 9, "out of memory!"); 1557 1428 continue; 1558 1429 } … … 1593 1464 else 1594 1465 { 1595 rcExit = errx( 2, "error: too many file actions (max: %d)", K_ELEMENTS(aOrders));1466 rcExit = errx(pCtx, 2, "error: too many file actions (max: %d)", K_ELEMENTS(aOrders)); 1596 1467 break; 1597 1468 } … … 1605 1476 fd = (int)strtol(pszValue, &pszTmp, 0); 1606 1477 if (pszTmp == pszValue || *pszTmp != '\0') 1607 rcExit = errx( 2, "error: failed to convert '%s' to a number", pszValue);1478 rcExit = errx(pCtx, 2, "error: failed to convert '%s' to a number", pszValue); 1608 1479 else if (fd < 0) 1609 rcExit = errx( 2, "error: negative fd %d (%s)", fd, pszValue);1480 rcExit = errx(pCtx, 2, "error: negative fd %d (%s)", fd, pszValue); 1610 1481 #ifdef ONLY_TARGET_STANDARD_HANDLES 1611 1482 else if (fd > 2) 1612 rcExit = errx( 2, "error: %d is not a standard descriptor number", fd);1483 rcExit = errx(pCtx, 2, "error: %d is not a standard descriptor number", fd); 1613 1484 #endif 1614 1485 else … … 1620 1491 rcExit = posix_spawn_file_actions_addclose(&FileActions, fd); 1621 1492 if (rcExit != 0) 1622 rcExit = errx( 2, "posix_spawn_file_actions_addclose(%d) failed: %s", fd, strerror(rcExit));1493 rcExit = errx(pCtx, 2, "posix_spawn_file_actions_addclose(%d) failed: %s", fd, strerror(rcExit)); 1623 1494 #endif 1624 1495 } … … 1632 1503 fd = (int)strtol(pszValue, &pszEqual, 0); 1633 1504 if (pszEqual == pszValue) 1634 rcExit = errx( 2, "error: failed to convert target descriptor of '-d %s' to a number", pszValue);1505 rcExit = errx(pCtx, 2, "error: failed to convert target descriptor of '-d %s' to a number", pszValue); 1635 1506 else if (fd < 0) 1636 rcExit = errx( 2, "error: negative target descriptor %d ('-d %s')", fd, pszValue);1507 rcExit = errx(pCtx, 2, "error: negative target descriptor %d ('-d %s')", fd, pszValue); 1637 1508 #ifdef ONLY_TARGET_STANDARD_HANDLES 1638 1509 else if (fd > 2) 1639 rcExit = errx( 2, "error: target %d is not a standard descriptor number", fd);1510 rcExit = errx(pCtx, 2, "error: target %d is not a standard descriptor number", fd); 1640 1511 #endif 1641 1512 else if (*pszEqual != '=') 1642 rcExit = errx( 2, "syntax error: expected '=' to follow target descriptor: '-d %s'", pszValue);1513 rcExit = errx(pCtx, 2, "syntax error: expected '=' to follow target descriptor: '-d %s'", pszValue); 1643 1514 else 1644 1515 { … … 1646 1517 int fdSource = (int)strtol(++pszEqual, &pszEnd, 0); 1647 1518 if (pszEnd == pszEqual || *pszEnd != '\0') 1648 rcExit = errx( 2, "error: failed to convert source descriptor of '-d %s' to a number", pszValue);1519 rcExit = errx(pCtx, 2, "error: failed to convert source descriptor of '-d %s' to a number", pszValue); 1649 1520 else if (fdSource < 0) 1650 rcExit = errx( 2, "error: negative source descriptor %d ('-d %s')", fdSource, pszValue);1521 rcExit = errx(pCtx, 2, "error: negative source descriptor %d ('-d %s')", fdSource, pszValue); 1651 1522 else 1652 1523 { … … 1658 1529 rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdSource, fd); 1659 1530 if (rcExit != 0) 1660 rcExit = errx( 2, "posix_spawn_file_actions_addclose(%d) failed: %s", fd, strerror(rcExit));1531 rcExit = errx(pCtx, 2, "posix_spawn_file_actions_addclose(%d) failed: %s", fd, strerror(rcExit)); 1661 1532 #endif 1662 1533 } … … 1713 1584 1714 1585 case '+': 1715 rcExit = errx( 2, "syntax error: Unexpected '+' in '%s'", argv[iArg]);1586 rcExit = errx(pCtx, 2, "syntax error: Unexpected '+' in '%s'", argv[iArg]); 1716 1587 continue; 1717 1588 … … 1780 1651 fd = (int)strtol(pszValue, &pszArg, 0); 1781 1652 if (pszArg == pszValue) 1782 rcExit = errx( 2, "error: failed to convert '%s' to a number", argv[iArg]);1653 rcExit = errx(pCtx, 2, "error: failed to convert '%s' to a number", argv[iArg]); 1783 1654 else if (fd < 0) 1784 rcExit = errx( 2, "error: negative fd %d (%s)", fd, argv[iArg]);1655 rcExit = errx(pCtx, 2, "error: negative fd %d (%s)", fd, argv[iArg]); 1785 1656 #ifdef ONLY_TARGET_STANDARD_HANDLES 1786 1657 else if (fd > 2) 1787 rcExit = errx( 2, "error: %d is not a standard descriptor number", fd);1658 rcExit = errx(pCtx, 2, "error: %d is not a standard descriptor number", fd); 1788 1659 #endif 1789 1660 else … … 1795 1666 */ 1796 1667 default: 1797 rcExit = errx( 2, "error: failed to convert '%s' ('%s') to a file descriptor", pszArg, argv[iArg]);1668 rcExit = errx(pCtx, 2, "error: failed to convert '%s' ('%s') to a file descriptor", pszArg, argv[iArg]); 1798 1669 continue; 1799 1670 } … … 1806 1677 if (*pszArg != ':' && *pszArg != '=') 1807 1678 { 1808 rcExit = errx( 2, "syntax error: characters following the file descriptor: '%s' ('%s')",1679 rcExit = errx(pCtx, 2, "syntax error: characters following the file descriptor: '%s' ('%s')", 1809 1680 pszArg, argv[iArg]); 1810 1681 break; … … 1816 1687 else 1817 1688 { 1818 rcExit = errx( 2, "syntax error: missing filename argument.");1689 rcExit = errx(pCtx, 2, "syntax error: missing filename argument."); 1819 1690 break; 1820 1691 } … … 1825 1696 * this for windows anyway, just do it the same way everywhere. 1826 1697 */ 1827 fdOpened = kRedirectOpenWithoutConflict(p szArg, fOpen, 0666, cOrders, aOrders,1698 fdOpened = kRedirectOpenWithoutConflict(pCtx, pszArg, fOpen, 0666, cOrders, aOrders, 1828 1699 aOrders[cOrders].fRemoveOnFailure, fd); 1829 1700 if (fdOpened >= 0) … … 1841 1712 rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdOpened, fd); 1842 1713 if (rcExit != 0) 1843 rcExit = err( 9, "posix_spawn_file_actions_adddup2(,%d [%s], %d) failed: %s",1714 rcExit = err(pCtx, 9, "posix_spawn_file_actions_adddup2(,%d [%s], %d) failed: %s", 1844 1715 fdOpened, fd, pszArg, strerror(rcExit)); 1845 1716 } … … 1852 1723 else 1853 1724 { 1854 errx( 2, "syntax error: Invalid argument '%s'.", argv[iArg]);1855 rcExit = usage(stderr, argv[0]);1725 errx(pCtx, 2, "syntax error: Invalid argument '%s'.", argv[iArg]); 1726 rcExit = kmk_redirect_usage(pCtx, 1); 1856 1727 } 1857 1728 } … … 1867 1738 * Do the spawning in a separate function (main is far to large as it is by now). 1868 1739 */ 1869 rcExit = kRedirectDoSpawn(p szExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage,1740 rcExit = kRedirectDoSpawn(pCtx, pszExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage, 1870 1741 papszEnvVars, 1871 1742 szCwd, pszSavedCwd, … … 1882 1753 else if (rcExit == 0) 1883 1754 { 1884 errx( 2, "syntax error: nothing to execute!");1885 rcExit = usage(stderr, argv[0]);1755 errx(pCtx, 2, "syntax error: nothing to execute!"); 1756 rcExit = kmk_redirect_usage(pCtx, 1); 1886 1757 } 1887 1758 /* Help and version sets rcExit to -1. Change it to zero. */ … … 1905 1776 APIRET rc = DosSetExtLIBPATH(apszSavedLibPaths[ulLibPath], ulLibPath); 1906 1777 if (rc != 0) 1907 warnx( "DosSetExtLIBPATH('%s',%u) failed with %u when restoring the original values!",1778 warnx(pCtx, "DosSetExtLIBPATH('%s',%u) failed with %u when restoring the original values!", 1908 1779 apszSavedLibPaths[ulLibPath], ulLibPath, rc); 1909 1780 free(apszSavedLibPaths[ulLibPath]); … … 1914 1785 } 1915 1786 1787 #ifdef KMK_BUILTIN_STANDALONE 1788 int main(int argc, char **argv, char **envp) 1789 { 1790 KMKBUILTINCTX Ctx = { "kmk_redirect", NULL }; 1791 return kmk_builtin_redirect(argc, argv, envp, &Ctx, NULL, NULL); 1792 } 1793 #endif 1794 1795 -
trunk/src/kmk/kmkbuiltin/rm.c
r3148 r3192 42 42 #endif 43 43 44 45 /********************************************************************************************************************************* 46 * Header Files * 47 *********************************************************************************************************************************/ 44 48 #include "config.h" 45 49 #include <sys/stat.h> … … 90 94 #include "k/kDefs.h" /* for K_OS */ 91 95 96 97 /********************************************************************************************************************************* 98 * Defined Constants And Macros * 99 *********************************************************************************************************************************/ 92 100 #if defined(__EMX__) || defined(KBUILD_OS_WINDOWS) 93 101 # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) … … 110 118 #endif 111 119 112 extern void bsd_strmode(mode_t mode, char *p); 113 114 static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; 120 #if 1 121 #define CUR_LINE_H2(x) "[line " #x "]" 122 #define CUR_LINE_H1(x) CUR_LINE_H2(x) 123 #define CUR_LINE() CUR_LINE_H1(__LINE__) 124 #else 125 # define CUR_LINE() 126 #endif 127 128 129 /********************************************************************************************************************************* 130 * Structures and Typedefs * 131 *********************************************************************************************************************************/ 132 typedef struct RMINSTANCE 133 { 134 PKMKBUILTINCTX pCtx; 135 int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; 115 136 #ifdef KBUILD_OS_WINDOWS 116 static int fUseNtDeleteFile; 117 #endif 118 static uid_t uid; 119 120 static char *argv0; 121 static KBUILDPROTECTION g_ProtData; 122 137 int fUseNtDeleteFile; 138 #endif 139 uid_t uid; 140 KBUILDPROTECTION g_ProtData; 141 } RMINSTANCE; 142 typedef RMINSTANCE *PRMINSTANCE; 143 144 145 /********************************************************************************************************************************* 146 * Global Variables * 147 *********************************************************************************************************************************/ 123 148 static struct option long_options[] = 124 149 { … … 137 162 138 163 139 static int check(char *, char *, struct stat *); 140 static void checkdot(char **); 141 static int rm_file(char **); 142 static int rm_overwrite(char *, struct stat *); 143 static int rm_tree(char **); 144 static int usage(FILE *); 145 146 #if 1 147 #define CUR_LINE_H2(x) "[line " #x "]" 148 #define CUR_LINE_H1(x) CUR_LINE_H2(x) 149 #define CUR_LINE() CUR_LINE_H1(__LINE__) 150 #else 151 # define CUR_LINE() 152 #endif 164 /********************************************************************************************************************************* 165 * Internal Functions * 166 *********************************************************************************************************************************/ 167 extern void bsd_strmode(mode_t mode, char *p); /* strmode.c */ 168 169 static int check(PRMINSTANCE, char *, char *, struct stat *); 170 static void checkdot(PRMINSTANCE, char **); 171 static int rm_file(PRMINSTANCE, char **); 172 static int rm_overwrite(PRMINSTANCE, char *, struct stat *); 173 static int rm_tree(PRMINSTANCE, char **); 174 static int usage(PKMKBUILTINCTX, int); 175 153 176 154 177 … … 161 184 */ 162 185 int 163 kmk_builtin_rm(int argc, char *argv[], char **envp) 164 { 186 kmk_builtin_rm(int argc, char *argv[], char **envp, PKMKBUILTINCTX pCtx) 187 { 188 RMINSTANCE This; 165 189 int ch, rflag; 166 190 167 /* reinitialize globals */ 168 argv0 = argv[0]; 169 dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0; 191 /* Init global instance data */ 192 This.pCtx = pCtx; 193 This.dflag = 0; 194 This.eval = 0; 195 This.fflag = 0; 196 This.iflag = 0; 197 This.Pflag = 0; 198 This.vflag = 0; 199 This.Wflag = 0; 200 This.stdin_ok = 0; 170 201 #ifdef KBUILD_OS_WINDOWS 171 fUseNtDeleteFile = 0;172 #endif 173 uid = 0;174 kBuildProtectionInit(& g_ProtData);202 This.fUseNtDeleteFile = 0; 203 #endif 204 This.uid = 0; 205 kBuildProtectionInit(&This.g_ProtData, pCtx); 175 206 176 207 /* kmk: reset getopt and set program name. */ 177 g_progname = argv[0];178 208 opterr = 1; 179 209 optarg = NULL; … … 181 211 optind = 0; /* init */ 182 212 183 Pflag =rflag = 0;213 rflag = 0; 184 214 while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1) 185 switch (ch) {215 switch (ch) { 186 216 case 'd': 187 dflag = 1;217 This.dflag = 1; 188 218 break; 189 219 case 'f': 190 fflag = 1;191 iflag = 0;220 This.fflag = 1; 221 This.iflag = 0; 192 222 break; 193 223 case 'i': 194 fflag = 0;195 iflag = 1;224 This.fflag = 0; 225 This.iflag = 1; 196 226 break; 197 227 case 'P': 198 Pflag = 1;228 This.Pflag = 1; 199 229 break; 200 230 case 'R': … … 205 235 break; 206 236 case 'v': 207 vflag = 1;237 This.vflag = 1; 208 238 break; 209 239 #ifdef FTS_WHITEOUT 210 240 case 'W': 211 Wflag = 1;241 This.Wflag = 1; 212 242 break; 213 243 #endif 214 244 case 261: 215 kBuildProtectionTerm(& g_ProtData);216 usage( stdout);245 kBuildProtectionTerm(&This.g_ProtData); 246 usage(pCtx, 0); 217 247 return 0; 218 248 case 262: 219 kBuildProtectionTerm(& g_ProtData);249 kBuildProtectionTerm(&This.g_ProtData); 220 250 return kbuild_version(argv[0]); 221 251 case 263: 222 kBuildProtectionDisable(& g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);252 kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); 223 253 break; 224 254 case 264: 225 kBuildProtectionEnable(& g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);255 kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); 226 256 break; 227 257 case 265: 228 kBuildProtectionEnable(& g_ProtData, KBUILDPROTECTIONTYPE_FULL);258 kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); 229 259 break; 230 260 case 266: 231 kBuildProtectionDisable(& g_ProtData, KBUILDPROTECTIONTYPE_FULL);261 kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); 232 262 break; 233 263 case 267: 234 if (kBuildProtectionSetDepth(& g_ProtData, optarg)) {235 kBuildProtectionTerm(& g_ProtData);264 if (kBuildProtectionSetDepth(&This.g_ProtData, optarg)) { 265 kBuildProtectionTerm(&This.g_ProtData); 236 266 return 1; 237 267 } … … 239 269 #ifdef KBUILD_OS_WINDOWS 240 270 case 268: 241 fUseNtDeleteFile = 1;271 This.fUseNtDeleteFile = 1; 242 272 break; 243 273 #endif 244 274 case '?': 245 275 default: 246 kBuildProtectionTerm(& g_ProtData);247 return usage( stderr);276 kBuildProtectionTerm(&This.g_ProtData); 277 return usage(pCtx, 1); 248 278 } 249 279 argc -= optind; … … 251 281 252 282 if (argc < 1) { 253 kBuildProtectionTerm(& g_ProtData);254 if ( fflag)283 kBuildProtectionTerm(&This.g_ProtData); 284 if (This.fflag) 255 285 return (0); 256 return usage( stderr);257 } 258 259 if (!kBuildProtectionScanEnv(& g_ProtData, envp, "KMK_RM_")) {260 checkdot( argv);261 uid = geteuid();286 return usage(pCtx, 1); 287 } 288 289 if (!kBuildProtectionScanEnv(&This.g_ProtData, envp, "KMK_RM_")) { 290 checkdot(&This, argv); 291 This.uid = geteuid(); 262 292 263 293 if (*argv) { 264 stdin_ok = isatty(STDIN_FILENO);294 This.stdin_ok = isatty(STDIN_FILENO); 265 295 if (rflag) 266 eval |= rm_tree(argv);296 This.eval |= rm_tree(&This, argv); 267 297 else 268 eval |= rm_file(argv);298 This.eval |= rm_file(&This, argv); 269 299 } 270 300 } else { 271 eval = 1;272 } 273 274 kBuildProtectionTerm(& g_ProtData);275 return eval;301 This.eval = 1; 302 } 303 304 kBuildProtectionTerm(&This.g_ProtData); 305 return This.eval; 276 306 } 277 307 308 #ifdef KMK_BUILTIN_STANDALONE 309 int main(int argc, char **argv, char **envp) 310 { 311 KMKBUILTINCTX Ctx = { "kmk_rm", NULL }; 312 return kmk_builtin_rm(argc, argv, envp, &Ctx); 313 } 314 #endif 315 278 316 static int 279 rm_tree( char **argv)317 rm_tree(PRMINSTANCE pThis, char **argv) 280 318 { 281 319 FTS *fts; … … 291 329 int i; 292 330 for (i = 0; argv[i]; i++) { 293 if (kBuildProtectionEnforce(& g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) {331 if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) { 294 332 return 1; 295 333 } … … 300 338 * (-i) or can't ask anyway (stdin_ok), don't stat the file. 301 339 */ 302 needstat = ! uid || (!fflag && !iflag &&stdin_ok);340 needstat = !pThis->uid || (!pThis->fflag && !pThis->iflag && pThis->stdin_ok); 303 341 304 342 /* … … 312 350 flags |= FTS_NOSTAT; 313 351 #ifdef FTS_WHITEOUT 314 if ( Wflag)352 if (pThis->Wflag) 315 353 flags |= FTS_WHITEOUT; 316 354 #endif 317 355 if (!(fts = fts_open(argv, flags, NULL))) { 318 return err( 1, "fts_open");356 return err(pThis->pCtx, 1, "fts_open"); 319 357 } 320 358 while ((p = fts_read(fts)) != NULL) { … … 322 360 switch (p->fts_info) { 323 361 case FTS_DNR: 324 if (!fflag || p->fts_errno != ENOENT) { 325 fprintf(stderr, "fts: %s: %s: %s" CUR_LINE() "\n", 326 argv0, p->fts_path, strerror(p->fts_errno)); 327 eval = 1; 328 } 362 if (!pThis->fflag || p->fts_errno != ENOENT) 363 pThis->eval = errx(pThis->pCtx, 1, "fts: %s: %s" CUR_LINE() "\n", 364 p->fts_path, strerror(p->fts_errno)); 329 365 continue; 330 366 case FTS_ERR: 331 367 fts_close(fts); 332 return errx( 1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno));368 return errx(pThis->pCtx, 1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno)); 333 369 case FTS_NS: 334 370 /* … … 338 374 if (!needstat) 339 375 break; 340 if (!fflag || p->fts_errno != ENOENT) { 341 fprintf(stderr, "fts: %s: %s: %s " CUR_LINE() "\n", 342 argv0, p->fts_path, strerror(p->fts_errno)); 343 eval = 1; 344 } 376 if (!pThis->fflag || p->fts_errno != ENOENT) 377 pThis->eval = errx(pThis->pCtx, 1, "fts: %s: %s " CUR_LINE() "\n", 378 p->fts_path, strerror(p->fts_errno)); 345 379 continue; 346 380 case FTS_D: 347 381 /* Pre-order: give user chance to skip. */ 348 if (!fflag && !check(p->fts_path, p->fts_accpath, 349 p->fts_statp)) { 382 if (!pThis->fflag && !check(pThis, p->fts_path, p->fts_accpath, p->fts_statp)) { 350 383 (void)fts_set(fts, p, FTS_SKIP); 351 384 p->fts_number = SKIPPED; 352 385 } 353 386 #ifdef UF_APPEND 354 else if (! uid &&387 else if (!pThis->uid && 355 388 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && 356 389 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && … … 366 399 break; 367 400 default: 368 if (!fflag && 369 !check(p->fts_path, p->fts_accpath, p->fts_statp)) 401 if (!pThis->fflag && !check(pThis, p->fts_path, p->fts_accpath, p->fts_statp)) 370 402 continue; 371 403 } … … 374 406 * Protect against deleting root files and directories. 375 407 */ 376 if (kBuildProtectionEnforce(& g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {408 if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) { 377 409 fts_close(fts); 378 410 return 1; … … 381 413 rval = 0; 382 414 #ifdef UF_APPEND 383 if (! uid &&415 if (!pThis->uid && 384 416 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && 385 417 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE))) … … 405 437 rval = rmdir(p->fts_accpath); 406 438 #endif 407 if (rval == 0 || (fflag && errno == ENOENT)) { 408 if (rval == 0 && vflag) 409 (void)printf("%s\n", 410 p->fts_path); 439 if (rval == 0 || (pThis->fflag && errno == ENOENT)) { 440 if (rval == 0 && pThis->vflag) 441 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path); 411 442 #if defined(KMK) && defined(KBUILD_OS_WINDOWS) 412 443 if (rval == 0) { … … 423 454 case FTS_W: 424 455 rval = undelete(p->fts_accpath); 425 if (rval == 0 && ( fflag && errno == ENOENT)) {456 if (rval == 0 && (pThis->fflag && errno == ENOENT)) { 426 457 if (vflag) 427 (void)printf("%s\n", 428 p->fts_path); 458 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path); 429 459 continue; 430 460 } … … 438 468 * the file, it can't be unlinked. 439 469 */ 440 if ( fflag)470 if (pThis->fflag) 441 471 continue; 442 472 /* FALLTHROUGH */ 443 473 default: 444 if ( Pflag)445 if (!rm_overwrite(p ->fts_accpath, NULL))474 if (pThis->Pflag) 475 if (!rm_overwrite(pThis, p->fts_accpath, NULL)) 446 476 continue; 447 477 #ifdef KBUILD_OS_WINDOWS … … 455 485 #endif 456 486 457 if (rval == 0 || (fflag && errno == ENOENT)) { 458 if (rval == 0 && vflag) 459 (void)printf("%s\n", 460 p->fts_path); 487 if (rval == 0 || (pThis->fflag && errno == ENOENT)) { 488 if (rval == 0 && pThis->vflag) 489 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path); 461 490 continue; 462 491 } … … 468 497 err: 469 498 #endif 470 fprintf(stderr, "%s: %s: %s: %s " CUR_LINE() "\n", operation, argv0, p->fts_path, strerror(errno)); 471 eval = 1; 499 pThis->eval = errx(pThis->pCtx, 1, "%s: %s failed: %s " CUR_LINE() "\n", p->fts_path, operation, strerror(errno)); 472 500 } 473 501 if (errno) { 474 fprintf(stderr, "%s: fts_read: %s " CUR_LINE() "\n", argv0, strerror(errno)); 475 eval = 1; 502 pThis->eval = errx(pThis->pCtx, 1, "fts_read: %s " CUR_LINE() "\n", strerror(errno)); 476 503 } 477 504 fts_close(fts); 478 return eval;505 return pThis->eval; 479 506 } 480 507 481 508 static int 482 rm_file( char **argv)509 rm_file(PRMINSTANCE pThis, char **argv) 483 510 { 484 511 struct stat sb; … … 491 518 int i; 492 519 for (i = 0; argv[i]; i++) { 493 if (kBuildProtectionEnforce(& g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i]))520 if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i])) 494 521 return 1; 495 522 } … … 504 531 if (lstat(f, &sb)) { 505 532 #ifdef FTS_WHITEOUT 506 if ( Wflag) {533 if (pThis->Wflag) { 507 534 sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; 508 535 } else { … … 510 537 { 511 538 #endif 512 if (!fflag || errno != ENOENT) { 513 fprintf(stderr, "lstat: %s: %s: %s " CUR_LINE() "\n", argv0, f, strerror(errno)); 514 eval = 1; 515 } 539 if (!pThis->fflag || errno != ENOENT) 540 pThis->eval = errx(pThis->pCtx, 1, "%s: lstat failed: %s " CUR_LINE() "\n", 541 f, strerror(errno)); 516 542 continue; 517 543 } 518 544 #ifdef FTS_WHITEOUT 519 } else if ( Wflag) {520 fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(EEXIST));521 eval = 1;545 } else if (pThis->Wflag) { 546 errx(pThis->pCtx, "%s: %s\n", f, strerror(EEXIST)); 547 pThis->eval = 1; 522 548 continue; 523 549 #endif 524 550 } 525 551 526 if (S_ISDIR(sb.st_mode) && !dflag) { 527 fprintf(stderr, "%s: %s: is a directory\n", argv0, f); 528 eval = 1; 552 if (S_ISDIR(sb.st_mode) && !pThis->dflag) { 553 pThis->eval = errx(pThis->pCtx, 1, "%s: is a directory\n", f); 529 554 continue; 530 555 } 531 if (! fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))556 if (!pThis->fflag && !S_ISWHT(sb.st_mode) && !check(pThis, f, f, &sb)) 532 557 continue; 533 558 rval = 0; … … 546 571 operation = "rmdir"; 547 572 } else { 548 if ( Pflag)549 if (!rm_overwrite( f, &sb))573 if (pThis->Pflag) 574 if (!rm_overwrite(pThis, f, &sb)) 550 575 continue; 551 576 #ifndef KBUILD_OS_WINDOWS … … 553 578 operation = "unlink"; 554 579 #else 555 if ( fUseNtDeleteFile) {580 if (pThis->fUseNtDeleteFile) { 556 581 rval = birdUnlinkForcedFast(f); 557 582 operation = "NtDeleteFile"; … … 563 588 } 564 589 } 565 if (rval && (!fflag || errno != ENOENT)) { 566 fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, f, strerror(errno)); 567 eval = 1; 568 } 569 if (vflag && rval == 0) 570 (void)printf("%s\n", f); 571 } 572 return eval; 590 if (rval && (!pThis->fflag || errno != ENOENT)) 591 pThis->eval = errx(pThis->pCtx, 1, "%s: %s failed: %s" CUR_LINE() "\n", f, operation, strerror(errno)); 592 if (pThis->vflag && rval == 0) 593 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", f); 594 } 595 return pThis->eval; 573 596 } 574 597 … … 585 608 */ 586 609 static int 587 rm_overwrite( char *file, struct stat *sbp)610 rm_overwrite(PRMINSTANCE pThis, char *file, struct stat *sbp) 588 611 { 589 612 struct stat sb; … … 595 618 char *buf = NULL; 596 619 const char *operation = "lstat"; 620 int error; 597 621 598 622 fd = -1; … … 605 629 return (1); 606 630 operation = "open"; 607 if ((fd = open(file, O_WRONLY , 0)) == -1)631 if ((fd = open(file, O_WRONLY | KMK_OPEN_NO_INHERIT, 0)) == -1) 608 632 goto err; 609 633 #ifdef HAVE_FSTATFS … … 616 640 bsize = 1024; 617 641 #endif 618 if ((buf = malloc(bsize)) == NULL) 619 exit(err(1, "%s: malloc", file)); 642 if ((buf = malloc(bsize)) == NULL) { 643 err(pThis->pCtx, 1, "%s: malloc", file); 644 close(fd); 645 return 1; 646 } 620 647 621 648 #define PASS(byte) { \ … … 643 670 operation = "fsync/close"; 644 671 645 err: eval = 1; 672 err: pThis->eval = 1; 673 error = errno; 646 674 if (buf) 647 675 free(buf); 648 676 if (fd != -1) 649 677 close(fd); 650 fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, file, strerror(errno));678 errx(pThis->pCtx, 1, "%s: %s: %s: %s" CUR_LINE() "\n", operation, pThis->pCtx->pszProgName, file, strerror(error)); 651 679 return (0); 652 680 } … … 654 682 655 683 static int 656 check( char *path, char *name, struct stat *sp)684 check(PRMINSTANCE pThis, char *path, char *name, struct stat *sp) 657 685 { 658 686 int ch, first; … … 660 688 661 689 /* Check -i first. */ 662 if ( iflag)663 (void)fprintf(stderr, " remove %s? ", path);690 if (pThis->iflag) 691 (void)fprintf(stderr, "%s: remove %s? ", pThis->pCtx->pszProgName, path); 664 692 else { 665 693 /* … … 672 700 * barf later. 673 701 */ 674 if (! stdin_ok || S_ISLNK(sp->st_mode) ||Pflag ||702 if (!pThis->stdin_ok || S_ISLNK(sp->st_mode) || pThis->Pflag || 675 703 (!access(name, W_OK) && 676 704 #ifdef SF_APPEND 677 705 !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && 678 (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || ! uid))706 (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !pThis->uid)) 679 707 #else 680 708 1) … … 684 712 bsd_strmode(sp->st_mode, modep); 685 713 #if defined(SF_APPEND) && K_OS != K_OS_GNU_KFBSD && K_OS != K_OS_GNU_HURD 686 if ((flagsp = fflagstostr(sp->st_flags)) == NULL) 687 exit(err(1, "fflagstostr")); 714 if ((flagsp = fflagstostr(sp->st_flags)) == NULL) { 715 err(pThis->pCtx, 1, "fflagstostr"); 716 flagsp = "<bad-fflagstostr>"; 717 } 688 718 (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ", 689 719 modep + 1, modep[9] == ' ' ? "" : " ", … … 710 740 #define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) 711 741 static void 712 checkdot( char **argv)742 checkdot(PRMINSTANCE pThis, char **argv) 713 743 { 714 744 char *p, **save, **t; … … 737 767 if (ISDOT(p)) { 738 768 if (!complained++) 739 fprintf(stderr, "%s: \".\" and \"..\" may not be removed\n", argv0);740 eval = 1;769 warnx(pThis->pCtx, "\".\" and \"..\" may not be removed\n"); 770 pThis->eval = 1; 741 771 for (save = t; (t[0] = t[1]) != NULL; ++t) 742 772 continue; … … 748 778 749 779 static int 750 usage( FILE *pf)751 { 752 fprintf(pf,753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 g_progname, g_progname, g_progname,803 780 usage(PKMKBUILTINCTX pCtx, int fIsErr) 781 { 782 kmk_builtin_ctx_printf(pCtx, fIsErr, 783 "usage: %s [options] file ...\n" 784 " or: %s --help\n" 785 " or: %s --version\n" 786 "\n" 787 "Options:\n" 788 " -f\n" 789 " Attempt to remove files without prompting, regardless of the file\n" 790 " permission. Ignore non-existing files. Overrides previous -i's.\n" 791 " -i\n" 792 " Prompt for each file. Always.\n" 793 " -d\n" 794 " Attempt to remove directories as well as other kinds of files.\n" 795 " -P\n" 796 " Overwrite regular files before deleting; three passes: ff,0,ff\n" 797 " -R\n" 798 " Attempt to remove the file hierachy rooted in each file argument.\n" 799 " This option implies -d and file protection.\n" 800 " -v\n" 801 " Be verbose, show files as they are removed.\n" 802 " -W\n" 803 " Undelete without files.\n" 804 " --disable-protection\n" 805 " Will disable the protection file protection applied with -R.\n" 806 " --enable-protection\n" 807 " Will enable the protection file protection applied with -R.\n" 808 " --enable-full-protection\n" 809 " Will enable the protection file protection for all operations.\n" 810 " --disable-full-protection\n" 811 " Will disable the protection file protection for all operations.\n" 812 " --protection-depth\n" 813 " Number or path indicating the file protection depth. Default: %d\n" 814 "\n" 815 "Environment:\n" 816 " KMK_RM_DISABLE_PROTECTION\n" 817 " Same as --disable-protection. Overrides command line.\n" 818 " KMK_RM_ENABLE_PROTECTION\n" 819 " Same as --enable-protection. Overrides everyone else.\n" 820 " KMK_RM_ENABLE_FULL_PROTECTION\n" 821 " Same as --enable-full-protection. Overrides everyone else.\n" 822 " KMK_RM_DISABLE_FULL_PROTECTION\n" 823 " Same as --disable-full-protection. Overrides command line.\n" 824 " KMK_RM_PROTECTION_DEPTH\n" 825 " Same as --protection-depth. Overrides command line.\n" 826 "\n" 827 "The file protection of the top %d layers of the file hierarchy is there\n" 828 "to try prevent makefiles from doing bad things to your system. This\n" 829 "protection is not bulletproof, but should help prevent you from shooting\n" 830 "yourself in the foot.\n" 831 , 832 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, 833 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); 804 834 return EX_USAGE; 805 835 } 836 -
trunk/src/kmk/kmkbuiltin/rmdir.c
r2912 r3192 44 44 #endif 45 45 46 47 /********************************************************************************************************************************* 48 * Header Files * 49 *********************************************************************************************************************************/ 46 50 #include "config.h" 47 51 #include "err.h" … … 60 64 # include "mscfakes.h" 61 65 #endif 62 #if defined(KMK) && defined(KBUILD_OS_WINDOWS) 63 extern int dir_cache_deleted_directory(const char *pszDir); 64 #endif 65 66 static int rm_path(char *); 67 static int usage(FILE *); 68 69 static int pflag; 70 static int vflag; 71 static int ignore_fail_on_non_empty; 72 static int ignore_fail_on_not_exist; 73 66 67 68 /********************************************************************************************************************************* 69 * Structures and Typedefs * 70 *********************************************************************************************************************************/ 71 typedef struct RMDIRINSTANCE 72 { 73 PKMKBUILTINCTX pCtx; 74 int pflag; 75 int vflag; 76 int ignore_fail_on_non_empty; 77 int ignore_fail_on_not_exist; 78 } RMDIRINSTANCE; 79 typedef RMDIRINSTANCE *PRMDIRINSTANCE; 80 81 82 /********************************************************************************************************************************* 83 * Global Variables * 84 *********************************************************************************************************************************/ 74 85 static struct option long_options[] = 75 86 { … … 84 95 85 96 97 98 /********************************************************************************************************************************* 99 * Internal Functions * 100 *********************************************************************************************************************************/ 101 #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) 102 extern int dir_cache_deleted_directory(const char *pszDir); 103 #endif 104 static int rm_path(PRMDIRINSTANCE, char *); 105 static int usage(PKMKBUILTINCTX, int); 106 107 86 108 int 87 kmk_builtin_rmdir(int argc, char *argv[], char **envp) 88 { 109 kmk_builtin_rmdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 110 { 111 RMDIRINSTANCE This; 89 112 int ch, errors; 90 113 91 /* reinitialize globals */ 92 ignore_fail_on_not_exist = ignore_fail_on_non_empty = vflag = pflag = 0; 114 /* Initialize global instance. */ 115 This.pCtx = pCtx; 116 This.ignore_fail_on_not_exist = 0; 117 This.ignore_fail_on_non_empty = 0; 118 This.vflag = 0; 119 This.pflag = 0; 93 120 94 121 /* kmk: reset getopt and set progname */ 95 g_progname = argv[0];96 122 opterr = 1; 97 123 optarg = NULL; … … 101 127 switch(ch) { 102 128 case 'p': 103 pflag = 1;129 This.pflag = 1; 104 130 break; 105 131 case 'v': 106 vflag = 1;132 This.vflag = 1; 107 133 break; 108 134 case 260: 109 ignore_fail_on_non_empty = 1;135 This.ignore_fail_on_non_empty = 1; 110 136 break; 111 137 case 261: 112 ignore_fail_on_not_exist = 1;138 This.ignore_fail_on_not_exist = 1; 113 139 break; 114 140 case 262: 115 usage( stdout);141 usage(pCtx, 0); 116 142 return 0; 117 143 case 263: … … 119 145 case '?': 120 146 default: 121 return usage( stderr);147 return usage(pCtx, 1); 122 148 } 123 149 argc -= optind; … … 129 155 for (errors = 0; *argv; argv++) { 130 156 if (rmdir(*argv) < 0) { 131 if ( (!ignore_fail_on_non_empty || (errno != ENOTEMPTY && errno != EPERM && errno != EACCES && errno != EINVAL && errno != EEXIST)) 132 && (!ignore_fail_on_not_exist || errno != ENOENT)) { 133 warn("rmdir: %s", *argv); 157 if ( ( !This.ignore_fail_on_non_empty 158 || (errno != ENOTEMPTY && errno != EPERM && errno != EACCES && errno != EINVAL && errno != EEXIST)) 159 && ( !This.ignore_fail_on_not_exist 160 || errno != ENOENT)) { 161 warn(pCtx, "rmdir: %s", *argv); 134 162 errors = 1; 135 163 continue; 136 164 } 137 if (! ignore_fail_on_not_exist || errno != ENOENT)165 if (!This.ignore_fail_on_not_exist || errno != ENOENT) 138 166 continue; 139 167 /* (only ignored doesn't exist errors fall thru) */ 140 168 } else { 141 #if defined(KMK) && defined(KBUILD_OS_WINDOWS)169 #if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS) 142 170 dir_cache_deleted_directory(*argv); 143 171 #endif 144 if (vflag) { 145 printf("%s\n", *argv); 146 } 147 } 148 if (pflag) 149 errors |= rm_path(*argv); 172 if (This.vflag) 173 kmk_builtin_ctx_printf(pCtx, 0, "%s\n", *argv); 174 } 175 if (This.pflag) 176 errors |= rm_path(&This, *argv); 150 177 } 151 178 … … 153 180 } 154 181 182 #ifdef KMK_BUILTIN_STANDALONE 183 int main(int argc, char **argv, char **envp) 184 { 185 KMKBUILTINCTX Ctx = { "kmk_rmdir", NULL }; 186 return kmk_builtin_rmdir(argc, argv, envp, &Ctx); 187 } 188 #endif 189 155 190 static int 156 rm_path( char *path)191 rm_path(PRMDIRINSTANCE pThis, char *path) 157 192 { 158 193 char *p; … … 186 221 187 222 if (rmdir(path) < 0) { 188 if ( ignore_fail_on_non_empty223 if ( pThis->ignore_fail_on_non_empty 189 224 && ( errno == ENOTEMPTY || errno == EPERM || errno == EACCES || errno == EINVAL || errno == EEXIST)) 190 225 break; 191 if (! ignore_fail_on_not_exist || errno != ENOENT) {192 warn( "rmdir: %s", path);226 if (!pThis->ignore_fail_on_not_exist || errno != ENOENT) { 227 warn(pThis->pCtx, "rmdir: %s", path); 193 228 return (1); 194 229 } … … 199 234 } 200 235 #endif 201 if ( vflag)202 printf("%s\n", path);236 if (pThis->vflag) 237 kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", path); 203 238 } 204 239 … … 207 242 208 243 static int 209 usage(FILE *pf) 210 { 211 (void)fprintf(pf, "usage: %s [-pv --ignore-fail-on-non-empty --ignore-fail-on-not-exist] directory ...\n" 212 " or: %s --help\n" 213 " or: %s --version\n", 214 g_progname, g_progname, g_progname); 244 usage(PKMKBUILTINCTX pCtx, int fIsErr) 245 { 246 kmk_builtin_ctx_printf(pCtx, fIsErr, 247 "usage: %s [-pv --ignore-fail-on-non-empty --ignore-fail-on-not-exist] directory ...\n" 248 " or: %s --help\n" 249 " or: %s --version\n", 250 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 215 251 return 1; 216 252 } 253 -
trunk/src/kmk/kmkbuiltin/sleep.c
r2413 r3192 40 40 #endif 41 41 42 #include "err.h" 42 43 #include "../kmkbuiltin.h" 43 44 44 45 45 static const char *name(const char *pszName)46 static int kmk_builtin_sleep_usage(PKMKBUILTINCTX pCtx, int fIsErr) 46 47 { 47 const char *psz = strrchr(pszName, '/'); 48 #if defined(_MSC_VER) || defined(__OS2__) 49 const char *psz2 = strrchr(pszName, '\\'); 50 if (!psz2) 51 psz2 = strrchr(pszName, ':'); 52 if (psz2 && (!psz || psz2 > psz)) 53 psz = psz2; 54 #endif 55 return psz ? psz + 1 : pszName; 56 } 57 58 59 static int usage(FILE *pOut, const char *argv0) 60 { 61 argv0 = name(argv0); 62 fprintf(pOut, 63 "usage: %s <seconds>[s]\n" 64 " or: %s <milliseconds>ms\n" 65 " or: %s <minutes>m\n" 66 " or: %s <hours>h\n" 67 " or: %s <days>d\n" 68 " or: %s --help\n" 69 " or: %s --version\n" 70 "\n" 71 "Only integer values are accepted.\n" 72 , 73 argv0, argv0, argv0, argv0, argv0, argv0, argv0); 48 kmk_builtin_ctx_printf(pCtx, fIsErr, 49 "usage: %s <seconds>[s]\n" 50 " or: %s <milliseconds>ms\n" 51 " or: %s <minutes>m\n" 52 " or: %s <hours>h\n" 53 " or: %s <days>d\n" 54 " or: %s --help\n" 55 " or: %s --version\n" 56 "\n" 57 "Only integer values are accepted.\n" 58 , 59 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, 60 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName); 74 61 return 1; 75 62 } 76 63 77 64 78 int kmk_builtin_sleep(int argc, char **argv, char **envp )65 int kmk_builtin_sleep(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 79 66 { 80 67 long cMsToSleep; … … 88 75 */ 89 76 if (argc != 2) 90 return usage(stderr, argv[0]);77 return kmk_builtin_sleep_usage(pCtx, 1); 91 78 92 79 /* help request */ … … 96 83 || !strcmp(argv[1], "--help")) 97 84 { 98 usage(stdout, argv[0]);85 kmk_builtin_sleep_usage(pCtx, 0); 99 86 return 0; 100 87 } … … 121 108 cMsToSleep = strtol(pszInterval, &pszSuff, 0); 122 109 if (pszSuff == pszInterval) 123 { 124 fprintf(stderr, "%s: malformed interval '%s'!\n", name(argv[0]), pszInterval); 125 return 1; 126 } 110 return errx(pCtx, 1, "malformed interval '%s'!\n", pszInterval); 127 111 128 112 while (isspace(*pszSuff)) … … 142 126 { 143 127 if (!isspace(pszSuff[i])) 144 { 145 fprintf(stderr, "%s: malformed interval '%s'!\n", name(argv[0]), pszInterval); 146 return 1; 147 } 128 return errx(pCtx, 1, "malformed interval '%s'!\n", pszInterval); 148 129 i++; 149 130 } … … 160 141 ulFactor = 24*60*60*1000; 161 142 else 162 { 163 fprintf(stderr, "%s: unknown suffix '%.*s'!\n", name(argv[0]), cchSuff, pszSuff); 164 return 1; 165 } 143 return errx(pCtx, 1, "unknown suffix '%.*s'!\n", cchSuff, pszSuff); 166 144 } 167 145 … … 169 147 cMsToSleep *= ulFactor; 170 148 if ((cMsToSleep / ulFactor) != (unsigned long)lTmp) 171 { 172 fprintf(stderr, "%s: time interval overflow!\n", name(argv[0])); 173 return 1; 174 } 149 return errx(pCtx, 1, "time interval overflow!\n"); 175 150 176 151 /* … … 195 170 } 196 171 172 #ifdef KMK_BUILTIN_STANDALONE 173 int main(int argc, char **argv, char **envp) 174 { 175 KMKBUILTINCTX Ctx = { "kmk_sleep", NULL }; 176 return kmk_builtin_sleep(argc, argv, envp, &Ctx); 177 } 178 #endif 179 -
trunk/src/kmk/kmkbuiltin/test.c
r3065 r3192 16 16 #endif*/ 17 17 18 19 /********************************************************************************************************************************* 20 * Header Files * 21 *********************************************************************************************************************************/ 18 22 #include "config.h" 19 23 #include <sys/stat.h> … … 32 36 # include <process.h> 33 37 # include "mscfakes.h" 38 # include "quote_argv.h" 34 39 #else 35 40 # include <unistd.h> … … 40 45 #include "kmkbuiltin.h" 41 46 47 48 /********************************************************************************************************************************* 49 * Defined Constants And Macros * 50 *********************************************************************************************************************************/ 42 51 #ifndef __arraycount 43 52 # define __arraycount(a) ( sizeof(a) / sizeof(a[0]) ) … … 45 54 46 55 56 /********************************************************************************************************************************* 57 * Structures and Typedefs * 58 *********************************************************************************************************************************/ 47 59 /* test(1) accepts the following grammar: 48 60 oexpr ::= aexpr | aexpr "-o" oexpr ; … … 118 130 }; 119 131 132 /** kmk_test instance data. */ 133 typedef struct TESTINSTANCE 134 { 135 PKMKBUILTINCTX pCtx; 136 char **t_wp; 137 struct t_op const *t_wp_op; 138 } TESTINSTANCE; 139 typedef TESTINSTANCE *PTESTINSTANCE; 140 141 142 /********************************************************************************************************************************* 143 * Global Variables * 144 *********************************************************************************************************************************/ 120 145 static const struct t_op cop[] = { 121 146 {"!", UNOT, BUNOP}, … … 169 194 }; 170 195 171 static char **t_wp; 172 static struct t_op const *t_wp_op; 173 174 static int syntax(const char *, const char *); 175 static int oexpr(enum token); 176 static int aexpr(enum token); 177 static int nexpr(enum token); 178 static int primary(enum token); 179 static int binop(void); 196 197 /********************************************************************************************************************************* 198 * Internal Functions * 199 *********************************************************************************************************************************/ 200 static int syntax(PTESTINSTANCE, const char *, const char *); 201 static int oexpr(PTESTINSTANCE, enum token); 202 static int aexpr(PTESTINSTANCE, enum token); 203 static int nexpr(PTESTINSTANCE, enum token); 204 static int primary(PTESTINSTANCE, enum token); 205 static int binop(PTESTINSTANCE); 180 206 static int test_access(struct stat *, mode_t); 181 207 static int filstat(char *, enum token); 182 static enum token t_lex( char *);183 static int isoperand( void);184 static int getn( const char *);208 static enum token t_lex(PTESTINSTANCE, char *); 209 static int isoperand(PTESTINSTANCE); 210 static int getn(PTESTINSTANCE, const char *); 185 211 static int newerf(const char *, const char *); 186 212 static int olderf(const char *, const char *); 187 213 static int equalf(const char *, const char *); 188 static int usage( const char *);189 190 #if !defined( kmk_builtin_test) || defined(ELECTRIC_HEAP)214 static int usage(PKMKBUILTINCTX, int); 215 216 #if !defined(KMK_BUILTIN_STANDALONE) || defined(ELECTRIC_HEAP) 191 217 extern void *xmalloc(unsigned int); 192 218 #else … … 195 221 void *p = malloc(sz); 196 222 if (!p) { 197 fprintf(stderr, " %s: malloc(%u) failed\n", g_progname, sz);223 fprintf(stderr, "kmk_test: malloc(%u) failed\n", sz); 198 224 exit(1); 199 225 } … … 202 228 #endif 203 229 204 int kmk_builtin_test(int argc, char **argv, char **envp 205 #ifndef kmk_builtin_test 206 , char ***ppapszArgvSpawn 207 #endif 208 ) 209 { 230 231 232 int kmk_builtin_test(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvSpawn) 233 { 234 TESTINSTANCE This; 210 235 int res; 211 236 char **argv_spawn; 212 237 int i; 213 238 214 g_progname = argv[0]; 239 This.pCtx = pCtx; 240 This.t_wp = NULL; 241 This.t_wp_op = NULL; 215 242 216 243 /* look for the '--', '--help' and '--version'. */ … … 235 262 } 236 263 if (!strcmp(argv[i], "--help")) 237 return usage( argv[0]);264 return usage(pCtx, 0); 238 265 if (!strcmp(argv[i], "--version")) 239 266 return kbuild_version(argv[0]); … … 242 269 243 270 /* are we '['? then check for ']'. */ 244 if (strcmp( g_progname, "[") == 0) { /** @todo should skip the path in g_progname */271 if (strcmp(argv[0], "[") == 0) { /** @todo should skip the path in g_progname */ 245 272 if (strcmp(argv[--argc], "]")) 246 return errx( 1, "missing ]");273 return errx(pCtx, 1, "missing ]"); 247 274 argv[argc] = NULL; 248 275 } … … 252 279 res = 1; 253 280 else { 254 t_wp = &argv[1];255 res = oexpr( t_lex(*t_wp));256 if (res != -42 && * t_wp != NULL && *++t_wp != NULL)257 res = syntax( *t_wp, "unexpected operator");281 This.t_wp = &argv[1]; 282 res = oexpr(&This, t_lex(&This, *This.t_wp)); 283 if (res != -42 && *This.t_wp != NULL && *++This.t_wp != NULL) 284 res = syntax(&This, *This.t_wp, "unexpected operator"); 258 285 if (res == -42) 259 286 return 1; /* don't mix syntax errors with the argv_spawn ignore */ … … 266 293 res = 0; /* ignored */ 267 294 else { 268 #ifdef kmk_builtin_test295 #ifdef KMK_BUILTIN_STANDALONE 269 296 /* try exec the specified process */ 270 297 # if defined(_MSC_VER) 271 res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn); 272 if (res == -1) 273 res = err(1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]); 298 int argc_spawn = 0; 299 while (argv_spawn[argc_spawn]) 300 argc_spawn++; 301 if (quote_argv(argc, argv_spawn, 0 /*fWatcomBrainDamage*/, 0/*fFreeOrLeak*/) != -1) 302 { 303 res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn); 304 if (res == -1) 305 res = err(pCtx, 1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]); 306 } 307 else 308 res = err(pCtx, 1, "quote_argv: out of memory"); 274 309 # else 275 310 execvp(argv_spawn[0], argv_spawn); … … 305 340 } 306 341 307 static int 308 syntax(const char *op, const char *msg) 342 #ifdef KMK_BUILTIN_STANDALONE 343 int main(int argc, char **argv, char **envp) 344 { 345 KMKBUILTINCTX Ctx = { "kmk_test", NULL }; 346 return kmk_builtin_test(argc, argv, envp, &Ctx, NULL); 347 } 348 #endif 349 350 static int 351 syntax(PTESTINSTANCE pThis, const char *op, const char *msg) 309 352 { 310 353 311 354 if (op && *op) 312 errx( 1, "%s: %s", op, msg);355 errx(pThis->pCtx, 1, "%s: %s", op, msg); 313 356 else 314 errx( 1, "%s", msg);357 errx(pThis->pCtx, 1, "%s", msg); 315 358 return -42; 316 359 } 317 360 318 361 static int 319 oexpr( enum token n)362 oexpr(PTESTINSTANCE pThis, enum token n) 320 363 { 321 364 int res; 322 365 323 res = aexpr( n);324 if (res == -42 || * t_wp == NULL)366 res = aexpr(pThis, n); 367 if (res == -42 || *pThis->t_wp == NULL) 325 368 return res; 326 if (t_lex( *++t_wp) == BOR) {327 int res2 = oexpr( t_lex(*++t_wp));369 if (t_lex(pThis, *++(pThis->t_wp)) == BOR) { 370 int res2 = oexpr(pThis, t_lex(pThis, *++(pThis->t_wp))); 328 371 return res2 != -42 ? res2 || res : res2; 329 372 } 330 t_wp--;373 pThis->t_wp--; 331 374 return res; 332 375 } 333 376 334 377 static int 335 aexpr( enum token n)378 aexpr(PTESTINSTANCE pThis, enum token n) 336 379 { 337 380 int res; 338 381 339 res = nexpr( n);340 if (res == -42 || * t_wp == NULL)382 res = nexpr(pThis, n); 383 if (res == -42 || *pThis->t_wp == NULL) 341 384 return res; 342 if (t_lex( *++t_wp) == BAND) {343 int res2 = aexpr( t_lex(*++t_wp));385 if (t_lex(pThis, *++(pThis->t_wp)) == BAND) { 386 int res2 = aexpr(pThis, t_lex(pThis, *++(pThis->t_wp))); 344 387 return res2 != -42 ? res2 && res : res2; 345 388 } 346 t_wp--;389 pThis->t_wp--; 347 390 return res; 348 391 } 349 392 350 393 static int 351 nexpr( enum token n)394 nexpr(PTESTINSTANCE pThis, enum token n) 352 395 { 353 396 if (n == UNOT) { 354 int res = nexpr( t_lex(*++t_wp));397 int res = nexpr(pThis, t_lex(pThis, *++(pThis->t_wp))); 355 398 return res != -42 ? !res : res; 356 399 } 357 return primary( n);358 } 359 360 static int 361 primary( enum token n)400 return primary(pThis, n); 401 } 402 403 static int 404 primary(PTESTINSTANCE pThis, enum token n) 362 405 { 363 406 enum token nn; … … 367 410 return 0; /* missing expression */ 368 411 if (n == LPAREN) { 369 if ((nn = t_lex( *++t_wp)) == RPAREN)412 if ((nn = t_lex(pThis, *++(pThis->t_wp))) == RPAREN) 370 413 return 0; /* missing expression */ 371 res = oexpr( nn);372 if (res != -42 && t_lex( *++t_wp) != RPAREN)373 return syntax( NULL, "closing paren expected");414 res = oexpr(pThis, nn); 415 if (res != -42 && t_lex(pThis, *++(pThis->t_wp)) != RPAREN) 416 return syntax(pThis, NULL, "closing paren expected"); 374 417 return res; 375 418 } 376 if ( t_wp_op &&t_wp_op->op_type == UNOP) {419 if (pThis->t_wp_op && pThis->t_wp_op->op_type == UNOP) { 377 420 /* unary expression */ 378 if (*++ t_wp== NULL)379 return syntax( t_wp_op->op_text, "argument expected");421 if (*++(pThis->t_wp) == NULL) 422 return syntax(pThis, pThis->t_wp_op->op_text, "argument expected"); 380 423 switch (n) { 381 424 case STREZ: 382 return strlen(* t_wp) == 0;425 return strlen(*pThis->t_wp) == 0; 383 426 case STRNZ: 384 return strlen(* t_wp) != 0;427 return strlen(*pThis->t_wp) != 0; 385 428 case FILTT: 386 return isatty(getn( *t_wp));429 return isatty(getn(pThis, *pThis->t_wp)); 387 430 default: 388 return filstat(* t_wp, n);431 return filstat(*pThis->t_wp, n); 389 432 } 390 433 } 391 434 392 if (t_lex( t_wp[1]), t_wp_op &&t_wp_op->op_type == BINOP) {393 return binop( );394 } 395 396 return strlen(* t_wp) > 0;397 } 398 399 static int 400 binop( void)435 if (t_lex(pThis, pThis->t_wp[1]), pThis->t_wp_op && pThis->t_wp_op->op_type == BINOP) { 436 return binop(pThis); 437 } 438 439 return strlen(*pThis->t_wp) > 0; 440 } 441 442 static int 443 binop(PTESTINSTANCE pThis) 401 444 { 402 445 const char *opnd1, *opnd2; 403 446 struct t_op const *op; 404 447 405 opnd1 = * t_wp;406 (void) t_lex( *++t_wp);407 op = t_wp_op;408 409 if ((opnd2 = *++ t_wp) == NULL)410 return syntax( op->op_text, "argument expected");448 opnd1 = *pThis->t_wp; 449 (void) t_lex(pThis, *++(pThis->t_wp)); 450 op = pThis->t_wp_op; 451 452 if ((opnd2 = *++(pThis->t_wp)) == NULL) 453 return syntax(pThis, op->op_text, "argument expected"); 411 454 412 455 switch (op->op_num) { … … 420 463 return strcmp(opnd1, opnd2) > 0; 421 464 case INTEQ: 422 return getn( opnd1) == getn(opnd2);465 return getn(pThis, opnd1) == getn(pThis, opnd2); 423 466 case INTNE: 424 return getn( opnd1) != getn(opnd2);467 return getn(pThis, opnd1) != getn(pThis, opnd2); 425 468 case INTGE: 426 return getn( opnd1) >= getn(opnd2);469 return getn(pThis, opnd1) >= getn(pThis, opnd2); 427 470 case INTGT: 428 return getn( opnd1) > getn(opnd2);471 return getn(pThis, opnd1) > getn(pThis, opnd2); 429 472 case INTLE: 430 return getn( opnd1) <= getn(opnd2);473 return getn(pThis, opnd1) <= getn(pThis, opnd2); 431 474 case INTLT: 432 return getn( opnd1) < getn(opnd2);475 return getn(pThis, opnd1) < getn(pThis, opnd2); 433 476 case FILNT: 434 477 return newerf(opnd1, opnd2); … … 714 757 return NULL; 715 758 if (s[2] == '\0') 716 return bsearch(s + 1, mop2, __arraycount(mop2), 717 sizeof(*mop2), compare1); 759 return bsearch(s + 1, mop2, __arraycount(mop2), sizeof(*mop2), compare1); 718 760 else if (s[3] != '\0') 719 761 return NULL; 720 762 else 721 return bsearch(s + 1, mop3, __arraycount(mop3), 722 sizeof(*mop3), compare2); 763 return bsearch(s + 1, mop3, __arraycount(mop3), sizeof(*mop3), compare2); 723 764 } else { 724 765 if (s[1] == '\0') 725 return bsearch(s, cop, __arraycount(cop), sizeof(*cop), 726 compare1); 766 return bsearch(s, cop, __arraycount(cop), sizeof(*cop), compare1); 727 767 else if (strcmp(s, cop2[0].op_text) == 0) 728 768 return cop2; … … 733 773 734 774 static enum token 735 t_lex( char *s)775 t_lex(PTESTINSTANCE pThis, char *s) 736 776 { 737 777 struct t_op const *op; 738 778 739 779 if (s == NULL) { 740 t_wp_op = NULL;780 pThis->t_wp_op = NULL; 741 781 return EOI; 742 782 } 743 783 744 784 if ((op = findop(s)) != NULL) { 745 if (!((op->op_type == UNOP && isoperand( )) ||746 (op->op_num == LPAREN && *( t_wp+1) == 0))) {747 t_wp_op = op;785 if (!((op->op_type == UNOP && isoperand(pThis)) || 786 (op->op_num == LPAREN && *(pThis->t_wp+1) == 0))) { 787 pThis->t_wp_op = op; 748 788 return op->op_num; 749 789 } 750 790 } 751 t_wp_op = NULL;791 pThis->t_wp_op = NULL; 752 792 return OPERAND; 753 793 } 754 794 755 795 static int 756 isoperand( void)796 isoperand(PTESTINSTANCE pThis) 757 797 { 758 798 struct t_op const *op; 759 799 char *s, *t; 760 800 761 if ((s = *( t_wp+1)) == 0)801 if ((s = *(pThis->t_wp+1)) == 0) 762 802 return 1; 763 if ((t = *( t_wp+2)) == 0)803 if ((t = *(pThis->t_wp+2)) == 0) 764 804 return 0; 765 805 if ((op = findop(s)) != NULL) … … 770 810 /* atoi with error detection */ 771 811 static int 772 getn( const char *s)812 getn(PTESTINSTANCE pThis, const char *s) 773 813 { 774 814 char *p; … … 779 819 780 820 if (errno != 0) 781 return errx( -42, "%s: out of range", s);821 return errx(pThis->pCtx, -42, "%s: out of range", s); 782 822 783 823 while (isspace((unsigned char)*p)) … … 785 825 786 826 if (*p) 787 return errx( -42, "%s: bad number", s);827 return errx(pThis->pCtx, -42, "%s: bad number", s); 788 828 789 829 return (int) r; … … 822 862 823 863 static int 824 usage(const char *argv0) 825 { 826 fprintf(stdout, 827 "usage: %s expression [-- <prog> [args]]\n", argv0); 864 usage(PKMKBUILTINCTX pCtx, int fIsErr) 865 { 866 kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s expression [-- <prog> [args]]\n", pCtx->pszProgName); 828 867 return 0; /* only used in --help. */ 829 868 } 869 -
trunk/src/kmk/kmkbuiltin/touch.c
r3140 r3192 91 91 typedef struct KMKTOUCHOPTS 92 92 { 93 /** Command execution context. */ 94 PKMKBUILTINCTX pCtx; 93 95 /** What timestamps to modify on the files. */ 94 96 KMKTOUCHTARGET enmWhatToTouch; … … 111 113 typedef KMKTOUCHOPTS *PKMKTOUCHOPTS; 112 114 113 114 115 static int touch_error(const char *pszMsg, ...)116 {117 va_list va;118 fputs(TOUCH_NAME ": error: ", stderr);119 va_start(va, pszMsg);120 vfprintf(stderr, pszMsg, va);121 va_end(va);122 fputc('\n', stderr);123 return 1;124 }125 126 static int touch_syntax(const char *pszMsg, ...)127 {128 va_list va;129 fputs(TOUCH_NAME ": syntax error: ", stderr);130 va_start(va, pszMsg);131 vfprintf(stderr, pszMsg, va);132 va_end(va);133 fputc('\n', stderr);134 return 2;135 }136 115 137 116 static int touch_usage(void) … … 189 168 * Parses adjustment value: [-][[hh]mm]SS 190 169 */ 191 static int touch_parse_adjust( const char *pszValue, int *piAdjustValue)170 static int touch_parse_adjust(PKMKBUILTINCTX pCtx, const char *pszValue, int *piAdjustValue) 192 171 { 193 172 const char * const pszInValue = pszValue; … … 210 189 if ( !IS_DIGIT(pszValue[0], 9) 211 190 || !IS_DIGIT(pszValue[0], 9)) 212 return touch_syntax("Malformed hour part of -A value: %s", pszInValue);191 return errx(pCtx, 2, "Malformed hour part of -A value: %s", pszInValue); 213 192 *piAdjustValue = TWO_CHARS_TO_INT(pszValue[0], pszValue[1]) * 60 * 60; 214 193 /* fall thru */ … … 216 195 if ( !IS_DIGIT(pszValue[cchValue - 4], 9) /* don't bother limit to 60 minutes */ 217 196 || !IS_DIGIT(pszValue[cchValue - 3], 9)) 218 return touch_syntax("Malformed minute part of -A value: %s", pszInValue);197 return errx(pCtx, 2, "Malformed minute part of -A value: %s", pszInValue); 219 198 *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 4], pszValue[cchValue - 3]) * 60; 220 199 /* fall thru */ … … 222 201 if ( !IS_DIGIT(pszValue[cchValue - 2], 9) /* don't bother limit to 60 seconds */ 223 202 || !IS_DIGIT(pszValue[cchValue - 1], 9)) 224 return touch_syntax("Malformed second part of -A value: %s", pszInValue);203 return errx(pCtx, 2, "Malformed second part of -A value: %s", pszInValue); 225 204 *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 2], pszValue[cchValue - 1]); 226 205 break; 227 206 228 207 default: 229 return touch_syntax("Invalid -A value (length): %s", pszInValue);208 return errx(pCtx, 2, "Invalid -A value (length): %s", pszInValue); 230 209 } 231 210 … … 241 220 * Parse -d timestamp: YYYY-MM-DDThh:mm:SS[.frac][tz] 242 221 */ 243 static int touch_parse_d_ts( const char *pszTs, struct timeval *pDst)222 static int touch_parse_d_ts(PKMKBUILTINCTX pCtx, const char *pszTs, struct timeval *pDst) 244 223 { 245 224 const char * const pszTsIn = pszTs; … … 257 236 || !IS_DIGIT(pszTs[3], 9) 258 237 || pszTs[4] != '-') 259 return touch_error("Malformed timestamp '%s' given to -d: expected to start with 4 digit year followed by a dash",260 238 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to start with 4 digit year followed by a dash", 239 pszTsIn); 261 240 ExpTime.tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) * 100 262 241 + TWO_CHARS_TO_INT(pszTs[2], pszTs[3]) … … 268 247 || !IS_DIGIT(pszTs[1], 9) 269 248 || pszTs[2] != '-') 270 return touch_error("Malformed timestamp '%s' given to -d: expected to two digit month at position 6 followed by a dash",271 249 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit month at position 6 followed by a dash", 250 pszTsIn); 272 251 ExpTime.tm_mon = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) - 1; 273 252 pszTs += 3; … … 277 256 || !IS_DIGIT(pszTs[1], 9) 278 257 || (pszTs[2] != 'T' && pszTs[2] != 't' && pszTs[2] != ' ') ) 279 return touch_error("Malformed timestamp '%s' given to -d: expected to two digit day of month at position 9 followed by 'T' or space",280 258 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit day of month at position 9 followed by 'T' or space", 259 pszTsIn); 281 260 ExpTime.tm_mday = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); 282 261 pszTs += 3; … … 286 265 || !IS_DIGIT(pszTs[1], 9) 287 266 || pszTs[2] != ':') 288 return touch_error("Malformed timestamp '%s' given to -d: expected to two digit hour at position 12 followed by colon",289 267 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit hour at position 12 followed by colon", 268 pszTsIn); 290 269 ExpTime.tm_hour = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); 291 270 pszTs += 3; … … 295 274 || !IS_DIGIT(pszTs[1], 9) 296 275 || pszTs[2] != ':') 297 return touch_error("Malformed timestamp '%s' given to -d: expected to two digit minute at position 15 followed by colon",298 276 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit minute at position 15 followed by colon", 277 pszTsIn); 299 278 ExpTime.tm_min = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); 300 279 pszTs += 3; … … 303 282 if ( !IS_DIGIT(pszTs[0], 5) 304 283 || !IS_DIGIT(pszTs[1], 9)) 305 return touch_error("Malformed timestamp '%s' given to -d: expected to two digit seconds at position 12", pszTsIn);284 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit seconds at position 12", pszTsIn); 306 285 ExpTime.tm_sec = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]); 307 286 pszTs += 2; … … 315 294 pszTs++; 316 295 if (!IS_DIGIT(*pszTs, 9)) 317 return touch_error("Malformed timestamp '%s' given to -d: empty fraction", pszTsIn);296 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: empty fraction", pszTsIn); 318 297 319 298 iFactor = 100000; … … 333 312 pszTs++; 334 313 if (*pszTs != '\0') 335 return touch_error("Malformed timestamp '%s' given to -d: Unexpected character(s) after zulu time indicator at end of timestamp", 336 pszTsIn); 314 return errx(pCtx, 2, 315 "Malformed timestamp '%s' given to -d: Unexpected character(s) after zulu time indicator at end of timestamp", 316 pszTsIn); 337 317 } 338 318 else if (*pszTs != '\0') 339 return touch_error("Malformed timestamp '%s' given to -d: expected to 'Z' (zulu) or nothing at end of timestamp", pszTsIn);319 return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to 'Z' (zulu) or nothing at end of timestamp", pszTsIn); 340 320 341 321 /* … … 352 332 #endif 353 333 if (pDst->tv_sec == -1) 354 return touch_error("timegm failed on '%s': %s", pszTs, strerror(errno));334 return errx(pCtx, 1, "timegm failed on '%s': %s", pszTs, strerror(errno)); 355 335 } 356 336 else … … 358 338 pDst->tv_sec = mktime(&ExpTime); 359 339 if (pDst->tv_sec == -1) 360 return touch_error("mktime failed on '%s': %s", pszTs, strerror(errno));340 return errx(pCtx, 1, "mktime failed on '%s': %s", pszTs, strerror(errno)); 361 341 } 362 342 return 0; … … 367 347 * Parse -t timestamp: [[CC]YY]MMDDhhmm[.SS] 368 348 */ 369 static int touch_parse_ts( const char *pszTs, struct timeval *pDst)349 static int touch_parse_ts(PKMKBUILTINCTX pCtx, const char *pszTs, struct timeval *pDst) 370 350 { 371 351 size_t const cchTs = strlen(pszTs); … … 380 360 */ 381 361 if ((cchTs & 1) && pszTs[cchTs - 3] != '.') 382 return touch_error("Invalid timestamp given to -t: %s", pszTs);362 return errx(pCtx, 2, "Invalid timestamp given to -t: %s", pszTs); 383 363 switch (cchTs) 384 364 { … … 392 372 case 8 + 3 + 2 + 2: /* CCYYMMDDhhmm.SS */ 393 373 if (pszTs[cchTs - 3] != '.') 394 return touch_error("Invalid timestamp (-t) '%s': missing dot for seconds part", pszTs);374 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': missing dot for seconds part", pszTs); 395 375 if ( !IS_DIGIT(pszTs[cchTs - 2], 5) 396 376 || !IS_DIGIT(pszTs[cchTs - 1], 9)) 397 return touch_error("Invalid timestamp (-t) '%s': malformed seconds part", pszTs);377 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed seconds part", pszTs); 398 378 cchTsNoSec = cchTs - 3; 399 379 break; 400 380 default: 401 return touch_error("Invalid timestamp (-t) '%s': wrong length (%d)", pszTs, (int)cchTs);381 return errx(pCtx, 1, "Invalid timestamp (-t) '%s': wrong length (%d)", pszTs, (int)cchTs); 402 382 } 403 383 … … 407 387 if ( !IS_DIGIT(pszTs[cchTsNoSec - 12], 9) 408 388 || !IS_DIGIT(pszTs[cchTsNoSec - 11], 9)) 409 return touch_error("Invalid timestamp (-t) '%s': malformed CC part", pszTs);389 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed CC part", pszTs); 410 390 /* fall thru */ 411 391 case 8 + 2: /* YYMMDDhhmm */ 412 392 if ( !IS_DIGIT(pszTs[cchTsNoSec - 10], 9) 413 393 || !IS_DIGIT(pszTs[cchTsNoSec - 9], 9)) 414 return touch_error("Invalid timestamp (-t) '%s': malformed YY part", pszTs);394 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed YY part", pszTs); 415 395 /* fall thru */ 416 396 case 8: /* MMDDhhmm */ 417 397 if ( !IS_DIGIT(pszTs[cchTsNoSec - 8], 1) 418 398 || !IS_DIGIT(pszTs[cchTsNoSec - 7], 9) ) 419 return touch_error("Invalid timestamp (-t) '%s': malformed month part", pszTs);399 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed month part", pszTs); 420 400 if ( !IS_DIGIT(pszTs[cchTsNoSec - 6], 3) 421 401 || !IS_DIGIT(pszTs[cchTsNoSec - 5], 9) ) 422 return touch_error("Invalid timestamp (-t) '%s': malformed day part", pszTs);402 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed day part", pszTs); 423 403 if ( !IS_DIGIT(pszTs[cchTsNoSec - 4], 2) 424 404 || !IS_DIGIT(pszTs[cchTsNoSec - 3], 9) ) 425 return touch_error("Invalid timestamp (-t) '%s': malformed hour part", pszTs);405 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed hour part", pszTs); 426 406 if ( !IS_DIGIT(pszTs[cchTsNoSec - 2], 5) 427 407 || !IS_DIGIT(pszTs[cchTsNoSec - 1], 9) ) 428 return touch_error("Invalid timestamp (-t) '%s': malformed minute part", pszTs);408 return errx(pCtx, 2, "Invalid timestamp (-t) '%s': malformed minute part", pszTs); 429 409 break; 430 410 } … … 435 415 rc = gettimeofday(&Now, NULL); 436 416 if (rc != 0) 437 return touch_error("gettimeofday failed: %s", strerror(errno));417 return errx(pCtx, 1, "gettimeofday failed: %s", strerror(errno)); 438 418 439 419 pExpTime = localtime_r(&Now.tv_sec, &ExpTime); 440 420 if (pExpTime == NULL) 441 return touch_error("localtime_r failed: %s", strerror(errno));421 return errx(pCtx, 1, "localtime_r failed: %s", strerror(errno)); 442 422 443 423 /* … … 475 455 if (pDst->tv_sec != -1) 476 456 return 0; 477 return touch_error("mktime failed on '%s': %s", pszTs, strerror(errno));457 return errx(pCtx, 1, "mktime failed on '%s': %s", pszTs, strerror(errno)); 478 458 } 479 459 … … 482 462 * Check for old timestamp: MMDDhhmm[YY] 483 463 */ 484 static int touch_parse_old_ts( const char *pszOldTs, time_t Now, struct timeval *pDst)464 static int touch_parse_old_ts(PKMKBUILTINCTX pCtx, const char *pszOldTs, time_t Now, struct timeval *pDst) 485 465 { 486 466 /* … … 509 489 pExpTime = localtime_r(&Now, &ExpTime); 510 490 if (pExpTime == NULL) 511 return touch_error("localtime_r failed: %s", strerror(errno));491 return errx(pCtx, 1, "localtime_r failed: %s", strerror(errno)); 512 492 513 493 /* … … 535 515 if (pDst->tv_sec != -1) 536 516 return 0; 537 return touch_error("mktime failed on '%s': %s", pszOldTs, strerror(errno));517 return errx(pCtx, 1, "mktime failed on '%s': %s", pszOldTs, strerror(errno)); 538 518 } 539 519 … … 544 524 545 525 /** 546 * Parses the arguments into p Opts.526 * Parses the arguments into pThis. 547 527 * 548 528 * @returns exit code. 549 * @param p Opts Options structure to return the parsed info in.529 * @param pThis Options structure to return the parsed info in. 550 530 * Caller initalizes this with defaults. 551 531 * @param cArgs The number of arguments. … … 554 534 * files. 555 535 */ 556 static int touch_parse_args(PKMKTOUCHOPTS p Opts, int cArgs, char **papszArgs, KBOOL *pfExit)536 static int touch_parse_args(PKMKTOUCHOPTS pThis, int cArgs, char **papszArgs, KBOOL *pfExit) 557 537 { 558 538 int iAdjustValue = 0; … … 583 563 { 584 564 while (++iArg < cArgs) 585 p Opts->papszFiles[pOpts->cFiles++] = papszArgs[iArg];565 pThis->papszFiles[pThis->cFiles++] = papszArgs[iArg]; 586 566 break; /* '--' */ 587 567 } … … 626 606 return kbuild_version(papszArgs[0]); 627 607 else 628 return touch_syntax("Unknown option: --%s", pszLong);608 return errx(pThis->pCtx, 2, "Unknown option: --%s", pszLong); 629 609 } 630 610 … … 651 631 pszValue = papszArgs[++iArg]; 652 632 else 653 return touch_syntax("Option -%c requires a value", ch);633 return errx(pThis->pCtx, 2, "Option -%c requires a value", ch); 654 634 break; 655 635 … … 663 643 /* -A [-][[HH]MM]SS */ 664 644 case 'A': 665 rc = touch_parse_adjust(p szValue, &iAdjustValue);645 rc = touch_parse_adjust(pThis->pCtx, pszValue, &iAdjustValue); 666 646 if (rc != 0) 667 647 return rc; 668 if (p Opts->enmAction != kTouchActionSet)648 if (pThis->enmAction != kTouchActionSet) 669 649 { 670 p Opts->enmAction = kTouchActionAdjust;671 p Opts->NewATime.tv_sec = iAdjustValue;672 p Opts->NewATime.tv_usec = 0;673 p Opts->NewMTime = pOpts->NewATime;650 pThis->enmAction = kTouchActionAdjust; 651 pThis->NewATime.tv_sec = iAdjustValue; 652 pThis->NewATime.tv_usec = 0; 653 pThis->NewMTime = pThis->NewATime; 674 654 } 675 655 /* else: applied after parsing everything. */ … … 677 657 678 658 case 'a': 679 p Opts->enmWhatToTouch = kTouchAccessOnly;659 pThis->enmWhatToTouch = kTouchAccessOnly; 680 660 break; 681 661 682 662 case 'c': 683 p Opts->fCreate = K_FALSE;663 pThis->fCreate = K_FALSE; 684 664 break; 685 665 686 666 case 'd': 687 rc = touch_parse_d_ts(p szValue, &pOpts->NewATime);667 rc = touch_parse_d_ts(pThis->pCtx, pszValue, &pThis->NewATime); 688 668 if (rc != 0) 689 669 return rc; 690 p Opts->enmAction = kTouchActionSet;691 p Opts->NewMTime = pOpts->NewATime;670 pThis->enmAction = kTouchActionSet; 671 pThis->NewMTime = pThis->NewATime; 692 672 break; 693 673 … … 697 677 698 678 case 'h': 699 p Opts->fDereference = K_FALSE;679 pThis->fDereference = K_FALSE; 700 680 break; 701 681 702 682 case 'm': 703 p Opts->enmWhatToTouch = kTouchModifyOnly;683 pThis->enmWhatToTouch = kTouchModifyOnly; 704 684 break; 705 685 … … 708 688 struct stat St; 709 689 if (stat(pszValue, &St) != 0) 710 return touch_error("Failed to stat '%s' (-r option): %s", pszValue, strerror(errno));711 712 p Opts->enmAction = kTouchActionSet;713 p Opts->NewATime.tv_sec = St.st_atime;714 p Opts->NewMTime.tv_sec = St.st_mtime;690 return errx(pThis->pCtx, 1, "Failed to stat '%s' (-r option): %s", pszValue, strerror(errno)); 691 692 pThis->enmAction = kTouchActionSet; 693 pThis->NewATime.tv_sec = St.st_atime; 694 pThis->NewMTime.tv_sec = St.st_mtime; 715 695 #if FILE_TIMESTAMP_HI_RES 716 p Opts->NewATime.tv_usec = St.st_atim.tv_nsec / 1000;717 p Opts->NewMTime.tv_usec = St.st_mtim.tv_nsec / 1000;696 pThis->NewATime.tv_usec = St.st_atim.tv_nsec / 1000; 697 pThis->NewMTime.tv_usec = St.st_mtim.tv_nsec / 1000; 718 698 #else 719 p Opts->NewATime.tv_usec = 0;720 p Opts->NewMTime.tv_usec = 0;699 pThis->NewATime.tv_usec = 0; 700 pThis->NewMTime.tv_usec = 0; 721 701 #endif 722 702 break; … … 724 704 725 705 case 't': 726 rc = touch_parse_ts(p szValue, &pOpts->NewATime);706 rc = touch_parse_ts(pThis->pCtx, pszValue, &pThis->NewATime); 727 707 if (rc != 0) 728 708 return rc; 729 p Opts->enmAction = kTouchActionSet;730 p Opts->NewMTime = pOpts->NewATime;709 pThis->enmAction = kTouchActionSet; 710 pThis->NewMTime = pThis->NewATime; 731 711 break; 732 712 … … 734 714 if ( strcmp(pszValue, "atime") == 0 735 715 || strcmp(pszValue, "access") == 0) 736 p Opts->enmWhatToTouch = kTouchAccessOnly;716 pThis->enmWhatToTouch = kTouchAccessOnly; 737 717 else if ( strcmp(pszValue, "mtime") == 0 738 718 || strcmp(pszValue, "modify") == 0) 739 p Opts->enmWhatToTouch = kTouchModifyOnly;719 pThis->enmWhatToTouch = kTouchModifyOnly; 740 720 else 741 return touch_syntax("Unknown --time value: %s", pszValue);721 return errx(pThis->pCtx, 2, "Unknown --time value: %s", pszValue); 742 722 break; 743 723 … … 746 726 747 727 default: 748 return touch_syntax("Unknown option: -%c (%c%s)", ch, ch, pszArg);728 return errx(pThis->pCtx, 2, "Unknown option: -%c (%c%s)", ch, ch, pszArg); 749 729 } 750 730 … … 752 732 } 753 733 else 754 p Opts->papszFiles[pOpts->cFiles++] = papszArgs[iArg];734 pThis->papszFiles[pThis->cFiles++] = papszArgs[iArg]; 755 735 } 756 736 … … 758 738 * Allow adjusting specified timestamps too like BSD does. 759 739 */ 760 if ( p Opts->enmAction == kTouchActionSet740 if ( pThis->enmAction == kTouchActionSet 761 741 && iAdjustValue != 0) 762 742 { 763 if ( p Opts->enmWhatToTouch == kTouchAccessAndModify764 || p Opts->enmWhatToTouch == kTouchAccessOnly)765 p Opts->NewATime.tv_sec += iAdjustValue;766 if ( p Opts->enmWhatToTouch == kTouchAccessAndModify767 || p Opts->enmWhatToTouch == kTouchModifyOnly)768 p Opts->NewMTime.tv_sec += iAdjustValue;743 if ( pThis->enmWhatToTouch == kTouchAccessAndModify 744 || pThis->enmWhatToTouch == kTouchAccessOnly) 745 pThis->NewATime.tv_sec += iAdjustValue; 746 if ( pThis->enmWhatToTouch == kTouchAccessAndModify 747 || pThis->enmWhatToTouch == kTouchModifyOnly) 748 pThis->NewMTime.tv_sec += iAdjustValue; 769 749 } 770 750 … … 772 752 * Check for old timestamp: MMDDhhmm[YY] 773 753 */ 774 if ( p Opts->enmAction == kTouchActionCurrent775 && p Opts->cFiles >= 2)754 if ( pThis->enmAction == kTouchActionCurrent 755 && pThis->cFiles >= 2) 776 756 { 777 757 struct timeval OldTs; 778 rc = touch_parse_old_ts(p Opts->papszFiles[0], pOpts->NewATime.tv_sec, &OldTs);758 rc = touch_parse_old_ts(pThis->pCtx, pThis->papszFiles[0], pThis->NewATime.tv_sec, &OldTs); 779 759 if (rc == 0) 780 760 { 781 761 int iFile; 782 762 783 p Opts->NewATime = OldTs;784 p Opts->NewMTime = OldTs;785 p Opts->enmAction = kTouchActionSet;786 787 for (iFile = 1; iFile < p Opts->cFiles; iFile++)788 p Opts->papszFiles[iFile - 1] = pOpts->papszFiles[iFile];789 p Opts->cFiles--;763 pThis->NewATime = OldTs; 764 pThis->NewMTime = OldTs; 765 pThis->enmAction = kTouchActionSet; 766 767 for (iFile = 1; iFile < pThis->cFiles; iFile++) 768 pThis->papszFiles[iFile - 1] = pThis->papszFiles[iFile]; 769 pThis->cFiles--; 790 770 } 791 771 else if (rc > 0) … … 796 776 * Check that we've found at least one file argument. 797 777 */ 798 if (p Opts->cFiles > 0)778 if (pThis->cFiles > 0) 799 779 { 800 780 *pfExit = K_FALSE; 801 781 return 0; 802 782 } 803 return touch_syntax("No file specified");783 return errx(pThis->pCtx, 2, "No file specified"); 804 784 } 805 785 … … 809 789 * 810 790 * @returns exit code. 811 * @param p Opts The options.791 * @param pThis The options. 812 792 * @param pszFile The file to touch. 813 793 */ 814 static int touch_process_file(PKMKTOUCHOPTS p Opts, const char *pszFile)794 static int touch_process_file(PKMKTOUCHOPTS pThis, const char *pszFile) 815 795 { 816 796 int fd; … … 823 803 * in effect, we silently skip the file if it doesn't already exist. 824 804 */ 825 if (p Opts->fDereference)805 if (pThis->fDereference) 826 806 rc = stat(pszFile, &St); 827 807 else … … 830 810 { 831 811 if (errno != ENOENT) 832 return touch_error("Failed to stat '%s': %s", pszFile, strerror(errno));833 834 if (!p Opts->fCreate)812 return errx(pThis->pCtx, 1, "Failed to stat '%s': %s", pszFile, strerror(errno)); 813 814 if (!pThis->fCreate) 835 815 return 0; 836 fd = open(pszFile, O_WRONLY | O_CREAT , 0666);816 fd = open(pszFile, O_WRONLY | O_CREAT | KMK_OPEN_NO_INHERIT, 0666); 837 817 if (fd == -1) 838 return touch_error("Failed to create '%s': %s", pszFile, strerror(errno));818 return errx(pThis->pCtx, 1, "Failed to create '%s': %s", pszFile, strerror(errno)); 839 819 840 820 /* If we're not setting the current time, we may need value stat info 841 821 on the file, so get it thru the file descriptor before closing it. */ 842 if (p Opts->enmAction == kTouchActionCurrent)822 if (pThis->enmAction == kTouchActionCurrent) 843 823 rc = 0; 844 824 else 845 825 rc = fstat(fd, &St); 846 826 if (close(fd) != 0) 847 return touch_error("Failed to close '%s' after creation: %s", pszFile, strerror(errno));827 return errx(pThis->pCtx, 1, "Failed to close '%s' after creation: %s", pszFile, strerror(errno)); 848 828 if (rc != 0) 849 return touch_error("Failed to fstat '%s' after creation: %s", pszFile, strerror(errno));829 return errx(pThis->pCtx, 1, "Failed to fstat '%s' after creation: %s", pszFile, strerror(errno)); 850 830 851 831 /* We're done now if we're setting the current time. */ 852 if (p Opts->enmAction == kTouchActionCurrent)832 if (pThis->enmAction == kTouchActionCurrent) 853 833 return 0; 854 834 } … … 866 846 aTimes[1].tv_usec = 0; 867 847 #endif 868 if ( p Opts->enmWhatToTouch == kTouchAccessAndModify869 || p Opts->enmWhatToTouch == kTouchAccessOnly)870 { 871 if ( p Opts->enmAction == kTouchActionCurrent872 || p Opts->enmAction == kTouchActionSet)873 aTimes[0] = p Opts->NewATime;848 if ( pThis->enmWhatToTouch == kTouchAccessAndModify 849 || pThis->enmWhatToTouch == kTouchAccessOnly) 850 { 851 if ( pThis->enmAction == kTouchActionCurrent 852 || pThis->enmAction == kTouchActionSet) 853 aTimes[0] = pThis->NewATime; 874 854 else 875 aTimes[0].tv_sec += p Opts->NewATime.tv_sec;876 } 877 if ( p Opts->enmWhatToTouch == kTouchAccessAndModify878 || p Opts->enmWhatToTouch == kTouchModifyOnly)879 { 880 if ( p Opts->enmAction == kTouchActionCurrent881 || p Opts->enmAction == kTouchActionSet)882 aTimes[1] = p Opts->NewMTime;855 aTimes[0].tv_sec += pThis->NewATime.tv_sec; 856 } 857 if ( pThis->enmWhatToTouch == kTouchAccessAndModify 858 || pThis->enmWhatToTouch == kTouchModifyOnly) 859 { 860 if ( pThis->enmAction == kTouchActionCurrent 861 || pThis->enmAction == kTouchActionSet) 862 aTimes[1] = pThis->NewMTime; 883 863 else 884 aTimes[1].tv_sec += p Opts->NewMTime.tv_sec;864 aTimes[1].tv_sec += pThis->NewMTime.tv_sec; 885 865 } 886 866 … … 891 871 * may do more than what we want (st_ctime).) 892 872 */ 893 if (p Opts->fDereference)873 if (pThis->fDereference) 894 874 rc = utimes(pszFile, aTimes); 895 875 else … … 897 877 if (rc != 0) 898 878 { 899 if (p Opts->enmAction == kTouchActionCurrent)879 if (pThis->enmAction == kTouchActionCurrent) 900 880 { 901 if (p Opts->fDereference)881 if (pThis->fDereference) 902 882 rc = utimes(pszFile, NULL); 903 883 else … … 905 885 } 906 886 if (rc != 0) 907 rc = touch_error("%stimes failed on '%s': %s", pOpts->fDereference ? "" : "l", pszFile, strerror(errno));887 rc = errx(pThis->pCtx, 1, "%stimes failed on '%s': %s", pThis->fDereference ? "" : "l", pszFile, strerror(errno)); 908 888 } 909 889 … … 913 893 914 894 /** 915 * The function that does almost everything here... ugly.895 * Actual main function for the touch command. 916 896 */ 917 #ifdef KMK 918 int kmk_builtin_touch(int argc, char **argv, char **envp) 919 #else 920 int main(int argc, char **argv, char **envp) 921 #endif 897 int kmk_builtin_touch(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 922 898 { 923 899 int rc; 924 KMKTOUCHOPTS Opts;900 KMKTOUCHOPTS This; 925 901 K_NOREF(envp); 926 902 … … 928 904 * Initialize options with defaults and parse them. 929 905 */ 930 Opts.enmWhatToTouch = kTouchAccessAndModify; 931 Opts.enmAction = kTouchActionCurrent; 932 Opts.fCreate = K_TRUE; 933 Opts.fDereference = K_TRUE; 934 Opts.cFiles = 0; 935 Opts.papszFiles = (char **)calloc(argc, sizeof(char *)); 936 if (Opts.papszFiles) 937 { 938 rc = gettimeofday(&Opts.NewATime, NULL); 906 This.pCtx = pCtx; 907 This.enmWhatToTouch = kTouchAccessAndModify; 908 This.enmAction = kTouchActionCurrent; 909 This.fCreate = K_TRUE; 910 This.fDereference = K_TRUE; 911 This.cFiles = 0; 912 This.papszFiles = (char **)calloc(argc, sizeof(char *)); 913 if (This.papszFiles) 914 { 915 rc = gettimeofday(&This.NewATime, NULL); 939 916 if (rc == 0) 940 917 { 941 918 KBOOL fExit; 942 Opts.NewMTime = Opts.NewATime;943 944 rc = touch_parse_args(& Opts, argc, argv, &fExit);919 This.NewMTime = This.NewATime; 920 921 rc = touch_parse_args(&This, argc, argv, &fExit); 945 922 if (rc == 0 && !fExit) 946 923 { … … 949 926 */ 950 927 int iFile; 951 for (iFile = 0; iFile < Opts.cFiles; iFile++)928 for (iFile = 0; iFile < This.cFiles; iFile++) 952 929 { 953 int rc2 = touch_process_file(& Opts, Opts.papszFiles[iFile]);930 int rc2 = touch_process_file(&This, This.papszFiles[iFile]); 954 931 if (rc2 != 0 && rc == 0) 955 932 rc = rc2; … … 958 935 } 959 936 else 960 rc = touch_error("gettimeofday failed: %s", strerror(errno));961 free( Opts.papszFiles);937 rc = errx(pCtx, 2, "gettimeofday failed: %s", strerror(errno)); 938 free(This.papszFiles); 962 939 } 963 940 else 964 rc = touch_error("calloc failed");941 rc = errx(pCtx, 2, "calloc failed"); 965 942 return rc; 966 943 } 967 944 945 #ifdef KMK_BUILTIN_STANDALONE 946 int main(int argc, char **argv, char **envp) 947 { 948 KMKBUILTINCTX Ctx = { "kmk_touch", NULL }; 949 return kmk_builtin_touch(argc, argv, envp, &Ctx); 950 } 951 #endif 952 -
trunk/src/kmk/output.c
r3191 r3192 373 373 374 374 /* write/fwrite like function, binary mode. */ 375 void 375 ssize_t 376 376 output_write_bin (struct output *out, int is_err, const char *src, size_t len) 377 377 { 378 size_t ret = len; 378 379 if (!out || !out->syncout) 379 380 { 380 381 FILE *f = is_err ? stderr : stdout; 381 382 # ifdef KBUILD_OS_WINDOWS 382 /* On windows we need to disable \n -> \r\n conver s that is common on383 /* On windows we need to disable \n -> \r\n converts that is common on 383 384 standard output/error. Also optimize for console output. */ 385 int saved_errno; 384 386 int fd = fileno (f); 385 387 int prev_mode = _setmode (fd, _O_BINARY); 386 388 maybe_con_fwrite (src, len, 1, f); 387 fflush (f); 389 if (fflush (f) == EOF) 390 ret = -1; 391 saved_errno = errno; 388 392 _setmode (fd, prev_mode); 393 errno = saved_errno; 389 394 # else 390 395 fwrite (src, len, 1, f); 391 fflush (f); 396 if (fflush (f) == EOF) 397 ret = -1; 392 398 # endif 393 399 } … … 410 416 } 411 417 } 418 return ret; 412 419 } 413 420 414 421 /* write/fwrite like function, text mode. */ 415 void 422 ssize_t 416 423 output_write_text (struct output *out, int is_err, const char *src, size_t len) 417 424 { 418 425 # if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS) 419 if (out && out->syncout) 426 ssize_t ret = len; 427 if (!out || !out->syncout) 420 428 { 421 429 /* ASSUME fwrite does the desired conversion. */ 422 430 FILE *f = is_err ? stderr : stdout; 423 431 # ifdef KBUILD_OS_WINDOWS 424 maybe_con_fwrite (src, len, 1, f); 432 if (maybe_con_fwrite (src, len, 1, f) < 0) 433 ret = -1; 425 434 # else 426 435 fwrite (src, len, 1, f); 427 436 # endif 428 fflush (f); 437 if (fflush (f) == EOF) 438 ret = -1; 429 439 } 430 440 else … … 443 453 } 444 454 } 455 return len; 445 456 # else 446 output_write_bin (out, is_err, src, len);457 return output_write_bin (out, is_err, src, len); 447 458 # endif 448 459 } -
trunk/src/kmk/output.h
r3190 r3192 14 14 You should have received a copy of the GNU General Public License along with 15 15 this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #ifndef INCLUDED_MAKE_OUTPUT_H 18 #define INCLUDED_MAKE_OUTPUT_H 16 19 17 20 #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY … … 81 84 void outputs (int is_err, const char *msg); 82 85 #ifdef CONFIG_WITH_OUTPUT_IN_MEMORY 83 voidoutput_write_bin (struct output *out, int is_err, const char *src, size_t len);84 voidoutput_write_text (struct output *out, int is_err, const char *src, size_t len);86 ssize_t output_write_bin (struct output *out, int is_err, const char *src, size_t len); 87 ssize_t output_write_text (struct output *out, int is_err, const char *src, size_t len); 85 88 #endif 86 89 … … 90 93 void output_dump (struct output *out); 91 94 #endif 95 96 #endif /* INLCUDED_MAKE_OUTPUT_H */ 97 -
trunk/src/kmk/w32/winchildren.c
r3191 r3192 1958 1958 { 1959 1959 PCKMKBUILTINENTRY pBuiltIn = pChild->u.BuiltIn.pBuiltIn; 1960 KMKBUILTINCTX Ctx = { pBuiltIn->uName.s.sz, pChild->pMkChild ? &pChild->pMkChild->output : NULL }; 1960 1961 if (pBuiltIn->uFnSignature == FN_SIG_MAIN) 1961 pChild->iExitCode = pBuiltIn->u.pfnMain(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, pChild->u.BuiltIn.papszEnv); 1962 pChild->iExitCode = pBuiltIn->u.pfnMain(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, 1963 pChild->u.BuiltIn.papszEnv, &Ctx); 1962 1964 else if (pBuiltIn->uFnSignature == FN_SIG_MAIN_SPAWNS) 1963 1965 pChild->iExitCode = pBuiltIn->u.pfnMainSpawns(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs, 1964 pChild->u.BuiltIn.papszEnv, pChild->pMkChild, NULL);1966 pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL); 1965 1967 else 1966 1968 {
Note:
See TracChangeset
for help on using the changeset viewer.