VirtualBox

Changeset 3192 in kBuild


Ignore:
Timestamp:
Mar 26, 2018 8:25:56 PM (7 years ago)
Author:
bird
Message:

kmkbuiltin: funnel output thru output.c (usually via err.c).

Location:
trunk/src
Files:
42 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker/Makefile.kmk

    r3188 r3192  
    3636kWorker_SOURCES = \
    3737        kWorker.c \
    38        ../kmk/kmkbuiltin/kDepObj.c
     38       ../kmk/kmkbuiltin/kDepObj.c \
     39       ../kmk/kmkbuiltin/err.c
    3940kWorker_INCS = \
    4041        ../kmk/ \
  • trunk/src/kWorker/kWorker.c

    r3188 r3192  
    1029010290    /* Command switch. */
    1029110291    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    }
    1029310296
    1029410297    return kwErrPrintfRc(42 + 5 , "Unknown post command: '%s'\n", pszCmd);
  • trunk/src/kmk/Makefile.kmk

    r3189 r3192  
    8383endif
    8484
     85#
     86# Template for building standalone built-in utilities.
     87#
     88TEMPLATE_BIN-KMK-BUILTIN = Template for standalone built-in utilies.
     89TEMPLATE_BIN-KMK-BUILTIN_EXTENDS = BIN-KMK
     90TEMPLATE_BIN-KMK-BUILTIN_EXTENDS_BY = appending
     91TEMPLATE_BIN-KMK-BUILTIN_DEFS += KMK_BUILTIN_STANDALONE
     92TEMPLATE_BIN-KMK-BUILTIN_SOURCES += kmkbuiltin/err.c
    8593
    8694#
     
    93101kmkmissing_NOINST = 1
    94102kmkmissing_SOURCES = \
    95         kmkbuiltin/err.c \
    96103        kmkbuiltin/fts.c \
    97104        kmkbuiltin/setmode.c \
     
    328335        kmkbuiltin/sleep.c \
    329336        kmkbuiltin/test.c \
    330         kmkbuiltin/touch.c
     337        kmkbuiltin/touch.c \
     338       \
     339        kmkbuiltin/err.c
     340
    331341
    332342## @todo kmkbuiltin/redirect.c
     
    364374        kDepObj \
    365375
    366 kmk_append_TEMPLATE = BIN-KMK
    367 kmk_append_DEFS = kmk_builtin_append=main
     376kmk_append_TEMPLATE = BIN-KMK-BUILTIN
    368377kmk_append_INCS = .
    369378kmk_append_SOURCES = \
    370379        kmkbuiltin/append.c
    371380
    372 kmk_cat_TEMPLATE = BIN-KMK
    373 kmk_cat_DEFS = kmk_builtin_cat=main
     381kmk_cat_TEMPLATE = BIN-KMK-BUILTIN
    374382kmk_cat_SOURCES = \
    375383        kmkbuiltin/cat.c
    376384
    377 kmk_chmod_TEMPLATE = BIN-KMK
    378 kmk_chmod_DEFS = kmk_builtin_chmod=main
     385kmk_chmod_TEMPLATE = BIN-KMK-BUILTIN
    379386kmk_chmod_SOURCES = \
    380387        kmkbuiltin/chmod.c
    381388
    382 kmk_cmp_TEMPLATE = BIN-KMK
    383 kmk_cmp_DEFS = kmk_builtin_cmp=main
     389kmk_cmp_TEMPLATE = BIN-KMK-BUILTIN
    384390kmk_cmp_SOURCES = \
    385391        kmkbuiltin/cmp.c \
    386392        kmkbuiltin/cmp_util.c
    387393
    388 kmk_cp_TEMPLATE = BIN-KMK
    389 kmk_cp_DEFS = kmk_builtin_cp=main
     394kmk_cp_TEMPLATE = BIN-KMK-BUILTIN
    390395kmk_cp_SOURCES = \
    391396        kmkbuiltin/cp.c \
     
    393398        kmkbuiltin/cmp_util.c
    394399
    395 kmk_echo_TEMPLATE = BIN-KMK
    396 kmk_echo_DEFS = kmk_builtin_echo=main
     400kmk_echo_TEMPLATE = BIN-KMK-BUILTIN
    397401kmk_echo_SOURCES = \
    398402        kmkbuiltin/echo.c
    399403
    400 kmk_expr_TEMPLATE = BIN-KMK
    401 kmk_expr_DEFS = kmk_builtin_expr=main
     404kmk_expr_TEMPLATE = BIN-KMK-BUILTIN
    402405kmk_expr_SOURCES = \
    403406        kmkbuiltin/expr.c
    404407
    405 kmk_install_TEMPLATE = BIN-KMK
    406 kmk_install_DEFS = kmk_builtin_install=main
     408kmk_install_TEMPLATE = BIN-KMK-BUILTIN
    407409kmk_install_SOURCES = \
    408410        kmkbuiltin/install.c
    409411
    410 kmk_ln_TEMPLATE = BIN-KMK
    411 kmk_ln_DEFS = kmk_builtin_ln=main
     412kmk_ln_TEMPLATE = BIN-KMK-BUILTIN
    412413kmk_ln_SOURCES = \
    413414        kmkbuiltin/ln.c
    414415
    415 kmk_mkdir_TEMPLATE = BIN-KMK
    416 kmk_mkdir_DEFS = kmk_builtin_mkdir=main
     416kmk_mkdir_TEMPLATE = BIN-KMK-BUILTIN
    417417kmk_mkdir_SOURCES = \
    418418        kmkbuiltin/mkdir.c
    419419
    420 kmk_md5sum_TEMPLATE = BIN-KMK
    421 kmk_md5sum_DEFS = kmk_builtin_md5sum=main
     420kmk_md5sum_TEMPLATE = BIN-KMK-BUILTIN
    422421kmk_md5sum_SOURCES = \
    423422        kmkbuiltin/md5sum.c
    424423kmk_md5sum_LIBS = $(LIB_KUTIL)
    425424
    426 kmk_mv_TEMPLATE = BIN-KMK
    427 kmk_mv_DEFS = kmk_builtin_mv=main
     425kmk_mv_TEMPLATE = BIN-KMK-BUILTIN
    428426kmk_mv_SOURCES = \
    429427        kmkbuiltin/mv.c
    430428
    431 kmk_printf_TEMPLATE = BIN-KMK
    432 kmk_printf_DEFS = kmk_builtin_printf=main
     429kmk_printf_TEMPLATE = BIN-KMK-BUILTIN
    433430kmk_printf_SOURCES = \
    434431        kmkbuiltin/printf.c
    435432
    436 kmk_rm_TEMPLATE = BIN-KMK
    437 kmk_rm_DEFS = kmk_builtin_rm=main
     433kmk_rm_TEMPLATE = BIN-KMK-BUILTIN
    438434kmk_rm_SOURCES = \
    439435        kmkbuiltin/rm.c
    440436
    441 kmk_redirect_TEMPLATE = BIN-KMK
     437kmk_redirect_TEMPLATE = BIN-KMK-BUILTIN
    442438kmk_redirect_SOURCES = \
    443439        kmkbuiltin/redirect.c
     
    445441        ../lib/startuphacks-win.c
    446442
    447 kmk_rmdir_TEMPLATE = BIN-KMK
    448 kmk_rmdir_DEFS = kmk_builtin_rmdir=main
     443kmk_rmdir_TEMPLATE = BIN-KMK-BUILTIN
    449444kmk_rmdir_SOURCES = \
    450445        kmkbuiltin/rmdir.c
    451446
    452 kmk_sleep_TEMPLATE = BIN-KMK
    453 kmk_sleep_DEFS = kmk_builtin_sleep=main
     447kmk_sleep_TEMPLATE = BIN-KMK-BUILTIN
    454448kmk_sleep_SOURCES = \
    455449        kmkbuiltin/sleep.c
    456450
    457 kmk_test_TEMPLATE = BIN-KMK
    458 kmk_test_DEFS = kmk_builtin_test=main
     451kmk_test_TEMPLATE = BIN-KMK-BUILTIN
    459452kmk_test_SOURCES = \
    460453        kmkbuiltin/test.c
    461454
    462 kmk_touch_TEMPLATE = BIN-KMK
    463 kmk_touch_DEFS = kmk_builtin_touch=main
     455kmk_touch_TEMPLATE = BIN-KMK-BUILTIN
    464456kmk_touch_SOURCES = \
    465457        kmkbuiltin/touch.c
    466458
    467 kDepIDB_TEMPLATE = BIN-KMK
    468 kDepIDB_DEFS = kmk_builtin_kDepIDB=main
     459kDepIDB_TEMPLATE = BIN-KMK-BUILTIN
    469460kDepIDB_INCS = .
    470461kDepIDB_LIBS = $(LIB_KDEP) $(LIB_KUTIL)
     
    472463        kmkbuiltin/kDepIDB.c
    473464
    474 kDepObj_TEMPLATE = BIN-KMK
    475 kDepObj_DEFS = kmk_builtin_kDepObj=main
     465kDepObj_TEMPLATE = BIN-KMK-BUILTIN
    476466kDepObj_INCS = .
    477467kDepObj_LIBS = $(LIB_KDEP) $(LIB_KUTIL)
  • trunk/src/kmk/dir-nt-bird.c

    r3184 r3192  
    4040#endif
    4141#include <assert.h>
     42#include "kmkbuiltin.h"
     43#include "kmkbuiltin/err.h"
    4244
    4345#include "nt_fullpath.h" /* for the time being - will be implemented here later on. */
     
    730732
    731733
    732 int kmk_builtin_dircache(int argc, char **argv, char **envp)
     734int kmk_builtin_dircache(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    733735{
    734736    assert(GetCurrentThreadId() == g_idMainThread);
     
    743745                return 0;
    744746            }
    745             fprintf(stderr, "kmk_builtin_dircache: the 'invalidate' command takes no arguments!\n");
     747            errx(pCtx, 2, "the 'invalidate' command takes no arguments!\n");
    746748        }
    747749        else if (strcmp(pszCmd, "invalidate-missing") == 0)
     
    752754                return 0;
    753755            }
    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");
    755757        }
    756758        else if (strcmp(pszCmd, "volatile") == 0)
     
    769771        }
    770772        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");
    775777
    776778    K_NOREF(envp);
  • trunk/src/kmk/job.c

    r3186 r3192  
    14811481    }
    14821482
     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
    14831491#ifdef CONFIG_WITH_KMK_BUILTIN
    14841492  /* If builtin command then pass it on to the builtin shell interpreter. */
     
    15381546    }
    15391547#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);
    15481548
    15491549  /* Decide whether to give this child the 'good' standard input
  • trunk/src/kmk/kmkbuiltin.c

    r3173 r3192  
    392392                    big_int nsStart = print_stats_flag ? nano_timestamp() : 0;
    393393#endif
     394                    KMKBUILTINCTX Ctx;
    394395                    int const iUmask = umask(0);        /* save umask */
    395396                    umask(iUmask);
    396397
     398                    Ctx.pszProgName = pEntry->uName.s.sz;
     399                    Ctx.pOut = pChild ? &pChild->output : NULL;
     400
    397401                    if (pEntry->uFnSignature == FN_SIG_MAIN)
    398                         rc = pEntry->u.pfnMain(argc, argv, papszEnvVars);
     402                        rc = pEntry->u.pfnMain(argc, argv, papszEnvVars, &Ctx);
    399403                    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);
    401405                    else if (pEntry->uFnSignature == FN_SIG_MAIN_TO_SPAWN)
    402406                    {
     
    406410                         * problem then (the call stack shows what's been going on).
    407411                         */
    408                         rc = pEntry->u.pfnMainToSpawn(argc, argv, papszEnvVars, ppapszArgvToSpawn);
     412                        rc = pEntry->u.pfnMainToSpawn(argc, argv, papszEnvVars, &Ctx, ppapszArgvToSpawn);
    409413                        if (   !rc
    410414                            && *ppapszArgvToSpawn
     
    429433                        rc = 99;
    430434
    431                     g_progname = "kmk";                 /* paranoia, make sure it's not pointing at a freed argv[0]. */
    432435                    umask(iUmask);                      /* restore it */
    433436
  • trunk/src/kmk/kmkbuiltin.h

    r3173 r3192  
    3434# include <sys/types.h>
    3535#endif
     36#include <fcntl.h>
    3637
    3738/* For the GNU/hurd weirdo. */
     
    5758#endif
    5859
     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
    5972#include "kbuild_version.h"
     73#ifndef KMK_BUILTIN_STANDALONE
     74# include "../output.h"
     75#endif
    6076
    6177struct child;
    6278int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned);
    6379int 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 */
     85typedef 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. */
     93typedef KMKBUILTINCTX *PKMKBUILTINCTX;
    6494
    6595/**
     
    81111        uintptr_t uPfn;
    82112#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);
    84114#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);
    86116#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);
    88118    } u;
    89119    size_t      uFnSignature : 8;
     
    94124typedef KMKBUILTINENTRY const *PCKMKBUILTINENTRY;
    95125
    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);
     126extern int kmk_builtin_append(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned);
     127extern int kmk_builtin_cp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     128extern int kmk_builtin_cat(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     129extern int kmk_builtin_chmod(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     130extern int kmk_builtin_cmp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     131extern int kmk_builtin_dircache(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     132extern int kmk_builtin_echo(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     133extern int kmk_builtin_expr(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     134extern int kmk_builtin_install(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     135extern int kmk_builtin_ln(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     136extern int kmk_builtin_md5sum(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     137extern int kmk_builtin_mkdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     138extern int kmk_builtin_mv(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     139extern int kmk_builtin_printf(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     140extern int kmk_builtin_redirect(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned);
     141extern int kmk_builtin_rm(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     142extern int kmk_builtin_rmdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     143extern int kmk_builtin_sleep(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     144extern int kmk_builtin_test(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvSpawn);
     145extern int kmk_builtin_touch(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
    122146#ifdef KBUILD_OS_WINDOWS
    123 extern int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned);
     147extern int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned);
    124148extern int kSubmitSubProcGetResult(intptr_t pvUser, int *prcExit, int *piSigNo);
    125149extern int kSubmitSubProcKill(intptr_t pvUser, int iSignal);
    126150extern void kSubmitSubProcCleanup(intptr_t pvUser);
    127151#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);
     152extern int kmk_builtin_kDepIDB(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
     153extern int kmk_builtin_kDepObj(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx);
    130154
    131155extern char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname);
    132156
    133157/* common-env-and-cwd-opt.c: */
    134 extern int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     158extern int kBuiltinOptEnvSet(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
    135159                             int cVerbosity, const char *pszValue);
    136 extern int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     160extern int kBuiltinOptEnvAppend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
    137161                                int cVerbosity, const char *pszValue);
    138 extern int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     162extern int kBuiltinOptEnvPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
    139163                                 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);
     164extern int kBuiltinOptEnvUnset(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     165                               int cVerbosity, const char *pszVarToRemove);
     166extern int kBuiltinOptEnvZap(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     167                             int cVerbosity);
    142168extern void kBuiltinOptEnvCleanup(char ***ppapszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars);
    143 extern int kBuiltinOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue);
     169extern int kBuiltinOptChDir(PKMKBUILTINCTX pCtx, char *pszCwd, size_t cbCwdBuf, const char *pszValue);
    144170
    145171#ifdef CONFIG_WITH_KMK_BUILTIN_STATS
  • trunk/src/kmk/kmkbuiltin/append.c

    r3177 r3192  
    2424 */
    2525
    26 /*******************************************************************************
    27 *   Header Files                                                               *
    28 *******************************************************************************/
    29 #ifndef kmk_builtin_append
     26/*********************************************************************************************************************************
     27*   Header Files                                                                                                                 *
     28*********************************************************************************************************************************/
     29#ifndef KMK_BUILTIN_STANDALONE
    3030# include "makeint.h"
    3131# include "filedef.h"
     
    4646# include <alloca.h>
    4747#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)
    4949# include "../w32/winchildren.h"
    5050#endif
     
    173173 * Appends text to a textfile, creating the textfile if necessary.
    174174 */
    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
     175int kmk_builtin_append(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned)
    180176{
    181177#if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2)
     
    195191    int fVariables = 0;
    196192    int fCommands = 0;
    197 #ifndef kmk_builtin_append
     193#ifndef KMK_BUILTIN_STANDALONE
    198194    int fLookForInserts = 0;
    199 #endif
    200 
    201     g_progname = argv[0];
     195#else
     196    (void)pChild; (void)pPidSpawned;
     197#endif
    202198
    203199    /*
     
    221217                        if (fVariables)
    222218                        {
    223                             errx(1, "Option '-c' clashes with '-v'.");
     219                            errx(pCtx, 1, "Option '-c' clashes with '-v'.");
    224220                            return kmk_builtin_append_usage(argv[0], stderr);
    225221                        }
    226 #ifndef kmk_builtin_append
     222#ifndef KMK_BUILTIN_STANDALONE
    227223                        fCommands = 1;
    228224                        break;
    229225#else
    230                         errx(1, "Option '-c' isn't supported in external mode.");
     226                        errx(pCtx, 1, "Option '-c' isn't supported in external mode.");
    231227                        return kmk_builtin_append_usage(argv[0], stderr);
    232228#endif
     
    234230                        if (fVariables)
    235231                        {
    236                             errx(1, "Option '-d' must come before '-v'!");
     232                            errx(pCtx, 1, "Option '-d' must come before '-v'!");
    237233                            return kmk_builtin_append_usage(argv[0], stderr);
    238234                        }
     
    242238                        if (fVariables || fCommands)
    243239                        {
    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'.");
    245241                            return kmk_builtin_append_usage(argv[0], stderr);
    246242                        }
    247 #ifndef kmk_builtin_append
     243#ifndef KMK_BUILTIN_STANDALONE
    248244                        fLookForInserts = 1;
    249245                        break;
    250246#else
    251                         errx(1, "Option '-C' isn't supported in external mode.");
     247                        errx(pCtx, 1, "Option '-C' isn't supported in external mode.");
    252248                        return kmk_builtin_append_usage(argv[0], stderr);
    253249#endif
     
    264260                        if (fCommands)
    265261                        {
    266                             errx(1, "Option '-v' clashes with '-c'.");
     262                            errx(pCtx, 1, "Option '-v' clashes with '-c'.");
    267263                            return kmk_builtin_append_usage(argv[0], stderr);
    268264                        }
    269 #ifndef kmk_builtin_append
     265#ifndef KMK_BUILTIN_STANDALONE
    270266                        fVariables = 1;
    271267                        break;
    272268#else
    273                         errx(1, "Option '-v' isn't supported in external mode.");
     269                        errx(pCtx, 1, "Option '-v' isn't supported in external mode.");
    274270                        return kmk_builtin_append_usage(argv[0], stderr);
    275271#endif
    276272                    default:
    277                         errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]);
     273                        errx(pCtx, 1, "Invalid option '%c'! (%s)", *psz, argv[i]);
    278274                        return kmk_builtin_append_usage(argv[0], stderr);
    279275                }
     
    300296    {
    301297        if (i <= argc)
    302             errx(1, "missing filename!");
     298            errx(pCtx, 1, "missing filename!");
    303299        else
    304             errx(1, "missing define name!");
     300            errx(pCtx, 1, "missing define name!");
    305301        return kmk_builtin_append_usage(argv[0], stderr);
    306302    }
     
    334330                write_to_buf(&OutBuf, STR_TUPLE(" "));
    335331        }
    336 #ifndef kmk_builtin_append
     332#ifndef KMK_BUILTIN_STANDALONE
    337333        if (fCommands)
    338334        {
     
    417413     * Write the buffer (unless we ran out of heap already).
    418414     */
    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)
    420416    if (!OutBuf.fOutOfMemory)
    421417    {
    422418        rc = MkWinChildCreateAppend(pszFilename, &OutBuf.pszBuf, OutBuf.offBuf, fTruncate, pChild, pPidSpawned);
    423419        if (rc != 0)
    424             rc = errx(rc, "MkWinChildCreateAppend failed: %u", rc);
     420            rc = errx(pCtx, rc, "MkWinChildCreateAppend failed: %u", rc);
    425421        if (OutBuf.pszBuf)
    426422            free(OutBuf.pszBuf);
     
    440436                rc = 0;
    441437            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);
    443439            if (close(fd) < 0)
    444                 rc = err(1, "error closing '%s'", pszFilename);
     440                rc = err(pCtx, 1, "error closing '%s'", pszFilename);
    445441        }
    446442        else
    447             rc = err(1, "failed to open '%s'", pszFilename);
     443            rc = err(pCtx, 1, "failed to open '%s'", pszFilename);
    448444        free(OutBuf.pszBuf);
    449445    }
    450446    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);
    452448    return rc;
    453449}
    454450
     451#ifdef KMK_BUILTIN_STANDALONE
     452int 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  
    9393
    9494
    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);
     95static int usage(PKMKBUILTINCTX pCtx, int fIsErr);
     96static int scanfiles(PKMKBUILTINCTX pCtx, char *argv[], int cooked);
     97static int cook_cat(PKMKBUILTINCTX pCtx, FILE *);
     98static int raw_cat(PKMKBUILTINCTX pCtx, int);
    9999
    100100#ifndef NO_UDOM_SUPPORT
    101 static int udom_open(const char *path, int flags);
     101static int udom_open(PKMKBUILTINCTX pCtx, const char *path, int flags);
    102102#endif
    103103
    104104int
    105 kmk_builtin_cat(int argc, char *argv[], char **envp)
     105kmk_builtin_cat(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    106106{
    107107        int ch, rc;
     
    112112
    113113        /* kmk: reset getopt and set progname */
    114         g_progname = argv[0];
    115114        opterr = 1;
    116115        optarg = NULL;
     
    118117        optind = 0; /* init */
    119118
    120 #ifdef kmk_builtin_cat /* kmk did this already. */
     119#ifdef KMK_BUILTIN_STANDALONE /* kmk did this already. */
    121120        setlocale(LC_CTYPE, "");
    122 #else
    123         fflush(stdout);
    124121#endif
    125122
     
    142139                        break;
    143140                case 'u':
     141#ifdef KMK_BUILTIN_STANDALONE /* don't allow messing with stdout */
    144142                        setbuf(stdout, NULL);
     143#endif
    145144                        break;
    146145                case 'v':
     
    148147                        break;
    149148                case 261:
    150                         usage(stdout);
     149                        usage(pCtx, 0);
    151150                        return 0;
    152151                case 262:
    153152                        return kbuild_version(argv[0]);
    154153                default:
    155                         return usage(stderr);
     154                        return usage(pCtx, 1);
    156155                }
    157156        argv += optind;
    158157
    159158        if (bflag || eflag || nflag || sflag || tflag || vflag)
    160                 rc = scanfiles(argv, 1);
     159                rc = scanfiles(pCtx, argv, 1);
    161160        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 */
    164163        if (fclose(stdout))
    165                 return err(1, "stdout");
     164                return err(pCtx, 1, "stdout");
    166165#endif
    167166        return rc;
    168167}
    169168
    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
     170int 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
     177static int
     178usage(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);
    177186        return 1;
    178187}
    179188
    180189static int
    181 scanfiles(char *argv[], int cooked)
     190scanfiles(PKMKBUILTINCTX pCtx, char *argv[], int cooked)
    182191{
    183192        int i = 0;
     
    198207#ifndef NO_UDOM_SUPPORT
    199208                        if (fd < 0 && errno == EOPNOTSUPP)
    200                                 fd = udom_open(path, O_RDONLY);
     209                                fd = udom_open(pCtx, path, O_RDONLY);
    201210#endif
    202211                }
    203212                if (fd < 0) {
    204                         warn("%s", path);
     213                        warn(pCtx, "%s", path);
    205214                        rc2 = 1; /* non fatal */
    206215                } else if (cooked) {
    207216                        if (fd == STDIN_FILENO)
    208                                 rc = cook_cat(stdin);
     217                                rc = cook_cat(pCtx, stdin);
    209218                        else {
    210219                                fp = fdopen(fd, "r");
    211                                 rc = cook_cat(fp);
     220                                rc = cook_cat(pCtx, fp);
    212221                                fclose(fp);
    213222                        }
    214223                } else {
    215                         rc = raw_cat(fd);
     224                        rc = raw_cat(pCtx, fd);
    216225                        if (fd != STDIN_FILENO)
    217226                                close(fd);
     
    224233}
    225234
    226 static int
    227 cook_cat(FILE *fp)
     235static 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
     246static int
     247cook_cat(PKMKBUILTINCTX pCtx, FILE *fp)
    228248{
    229249        int ch, gobble, line, prev;
     
    246266                        }
    247267                        if (nflag && (!bflag || ch != '\n')) {
    248                                 (void)fprintf(stdout, "%6d\t", ++line);
     268                                kmk_builtin_ctx_printf(pCtx, 0, "%6d\t", ++line);
    249269                                if (ferror(stdout))
    250270                                        break;
     
    252272                }
    253273                if (ch == '\n') {
    254                         if (eflag && putchar('$') == EOF)
     274                        if (eflag && cat_putchar(pCtx, '$') == EOF)
    255275                                break;
    256276                } else if (ch == '\t') {
    257277                        if (tflag) {
    258                                 if (putchar('^') == EOF || putchar('I') == EOF)
     278                                if (cat_putchar(pCtx, '^') == EOF || cat_putchar(pCtx, 'I') == EOF)
    259279                                        break;
    260280                                continue;
     
    262282                } else if (vflag) {
    263283                        if (!isascii(ch) && !isprint(ch)) {
    264                                 if (putchar('M') == EOF || putchar('-') == EOF)
     284                                if (cat_putchar(pCtx, 'M') == EOF || cat_putchar(pCtx, '-') == EOF)
    265285                                        break;
    266286                                ch = toascii(ch);
    267287                        }
    268288                        if (iscntrl(ch)) {
    269                                 if (putchar('^') == EOF ||
    270                                     putchar(ch == '\177' ? '?' :
     289                                if (cat_putchar(pCtx, '^') == EOF ||
     290                                    cat_putchar(pCtx, ch == '\177' ? '?' :
    271291                                    ch | 0100) == EOF)
    272292                                        break;
     
    274294                        }
    275295                }
    276                 if (putchar(ch) == EOF)
     296                if (cat_putchar(pCtx, ch) == EOF)
    277297                        break;
    278298        }
    279299        if (ferror(fp)) {
    280                 warn("%s", filename);
     300                warn(pCtx, "%s", filename);
    281301                rc = 1;
    282302                clearerr(fp);
    283303        }
    284304        if (ferror(stdout))
    285                 return err(1, "stdout");
     305                return err(pCtx, 1, "stdout");
    286306        return rc;
    287307}
    288308
    289309static int
    290 raw_cat(int rfd)
     310raw_cat(PKMKBUILTINCTX pCtx, int rfd)
    291311{
    292312        int off, wfd = fileno(stdout);
     
    299319        if (buf == NULL) {
    300320                if (fstat(wfd, &sbuf))
    301                         return err(1, "%s", filename);
     321                        return err(pCtx, 1, "%s", filename);
    302322#ifdef KBUILD_OS_WINDOWS
    303323                bsize = 16384;
     
    306326#endif
    307327                if ((buf = malloc(bsize)) == NULL)
    308                         return err(1, "buffer");
     328                        return err(pCtx, 1, "buffer");
    309329        }
    310330        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                }
    314341        if (nr < 0) {
    315                 warn("%s", filename);
     342                warn(pCtx, "%s", filename);
    316343                return 1;
    317344        }
     
    322349
    323350static int
    324 udom_open(const char *path, int flags)
     351udom_open(PKMKBUILTINCTX pCtx, const char *path, int flags)
    325352{
    326353        struct sockaddr_un sou;
     
    356383                case O_RDONLY:
    357384                        if (shutdown(fd, SHUT_WR) == -1)
    358                                 warn(NULL);
     385                                warn(pCtx, NULL);
    359386                        break;
    360387                case O_WRONLY:
    361388                        if (shutdown(fd, SHUT_RD) == -1)
    362                                 warn(NULL);
     389                                warn(pCtx, NULL);
    363390                        break;
    364391                default:
     
    370397
    371398#endif
     399
  • trunk/src/kmk/kmkbuiltin/chmod.c

    r3148 r3192  
    7575#endif
    7676
    77 static int usage(FILE *);
     77static int usage(PKMKBUILTINCTX pCtx, int is_err);
    7878
    7979static struct option long_options[] =
     
    8686
    8787int
    88 kmk_builtin_chmod(int argc, char *argv[], char **envp)
     88kmk_builtin_chmod(int argc, char *argv[], char **envp, PKMKBUILTINCTX pCtx)
    8989{
    9090        FTS *ftsp;
     
    9898
    9999        /* kmk: reset getopt and set progname */
    100         g_progname = argv[0];
    101100        opterr = 1;
    102101        optarg = NULL;
     
    153152                        break;
    154153                case 261:
    155                         usage(stdout);
     154                        usage(pCtx, 0);
    156155                        return 0;
    157156                case 262:
     
    159158                case '?':
    160159                default:
    161                         return usage(stderr);
     160                        return usage(pCtx, 1);
    162161                }
    163162done:   argv += optind;
     
    165164
    166165        if (argc < 2)
    167                 return usage(stderr);
     166                return usage(pCtx, 1);
    168167
    169168        if (Rflag) {
    170169                fts_options = FTS_PHYSICAL;
    171170                if (hflag)
    172                         return errx(1,
     171                        return errx(pCtx, 1,
    173172                "the -R and -h options may not be specified together.");
    174173                if (Hflag)
     
    188187        mode = *argv;
    189188        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);
    191190
    192191        if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
    193                 return err(1, "fts_open");
     192                return err(pCtx, 1, "fts_open");
    194193        for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
    195194                switch (p->fts_info) {
     
    199198                        continue;
    200199                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));
    202201                        rval = 1;
    203202                        break;
    204203                case FTS_ERR:                   /* Warn, continue. */
    205204                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));
    207206                        rval = 1;
    208207                        continue;
     
    225224                        continue;
    226225                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);
    228227                        rval = 1;
    229228                } else {
    230229                        if (vflag) {
    231                                 (void)printf("%s", p->fts_path);
     230                                kmk_builtin_ctx_printf(pCtx, 0, "%s", p->fts_path);
    232231
    233232                                if (vflag > 1) {
     
    238237                                            S_IFMT) | newmode, m2);
    239238
    240                                         (void)printf(": 0%o [%s] -> 0%o [%s]",
     239                                        kmk_builtin_ctx_printf(pCtx, 0, ": 0%o [%s] -> 0%o [%s]",
    241240                                            (unsigned int)p->fts_statp->st_mode, m1,
    242241                                            (unsigned int)((p->fts_statp->st_mode & S_IFMT) | newmode), m2);
    243242                                }
    244                                 (void)printf("\n");
     243                                kmk_builtin_ctx_printf(pCtx, 0, "\n");
    245244                        }
    246245
     
    248247        }
    249248        if (errno)
    250                 rval = err(1, "fts_read");
     249                rval = err(pCtx, 1, "fts_read");
    251250        free(set);
    252251        fts_close(ftsp);
     
    255254
    256255int
    257 usage(FILE *out)
    258 {
    259         (void)fprintf(out,
     256usage(PKMKBUILTINCTX pCtx, int is_err)
     257{
     258        kmk_builtin_ctx_printf(pCtx, is_err,
    260259            "usage: %s [-fhv] [-R [-H | -L | -P]] mode file ...\n"
    261260            "   or: %s --version\n"
    262261            "   or: %s --help\n",
    263             g_progname, g_progname, g_progname);
     262            pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName);
    264263
    265264        return 1;
    266265}
     266
     267#ifdef KMK_BUILTIN_STANDALONE
     268int 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  
    6464
    6565
    66 static int usage(FILE *);
     66static int usage(PKMKBUILTINCTX pCtx, int is_err);
    6767
    6868int
    69 kmk_builtin_cmp(int argc, char *argv[], char **envp)
     69kmk_builtin_cmp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    7070{
    7171    off_t skip1 = 0, skip2 = 0;
     
    7474    char *file1, *file2;
    7575
    76 #ifdef kmk_builtin_cmp
     76#ifdef KMK_BUILTIN_STANDALONE
    7777    setlocale(LC_ALL, "");
    7878#endif
    7979
    8080    /* reset getopt and set progname. */
    81     g_progname = argv[0];
    8281    opterr = 1;
    8382    optarg = NULL;
     
    9695                break;
    9796            case 261:
    98                 usage(stdout);
     97                usage(pCtx, 0);
    9998                return 0;
    10099            case 262:
     
    102101            case '?':
    103102            default:
    104                 return usage(stderr);
     103                return usage(pCtx, 1);
    105104        }
    106105    }
     
    109108
    110109    if (argc < 2 || argc > 4)
    111         return usage(stderr);
     110        return usage(pCtx, 1);
    112111
    113112    file1 = argv[0];
     
    121120        skip1 = strtoll(argv[2], &ep, 0);
    122121        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]);
    124123
    125124        if (argc == 4)
     
    127126            skip2 = strtoll(argv[3], &ep, 0);
    128127            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]);
    130129        }
    131130    }
    132131
    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);
    134133}
    135134
    136135static int
    137 usage(FILE *fp)
     136usage(PKMKBUILTINCTX pCtx, int is_err)
    138137{
    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);
    143143    return ERR_EXIT;
    144144}
     145
     146#ifdef KMK_BUILTIN_STANDALONE
     147int 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  
    3636#define ERR_EXIT        2       /* error exit code */
    3737
    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,
     38int cmp_file_and_file(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, int sflag, int lflag, int special);
     39int cmp_file_and_file_ex(PKMKBUILTINCTX pCtx, const char *file1, off_t skip1,
    4040                         const char *file2, off_t skip2, int sflag, int lflag, int special);
    41 int cmp_fd_and_file(int fd1, const char *file1,
     41int cmp_fd_and_file(PKMKBUILTINCTX pCtx, int fd1, const char *file1,
    4242                    const char *file2, int sflag, int lflag, int special);
    43 int cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1,
     43int cmp_fd_and_file_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1,
    4444                       const char *file2, off_t skip2, int sflag, int lflag, int special);
    45 int cmp_fd_and_fd(int fd1, const char *file1,
     45int cmp_fd_and_fd(PKMKBUILTINCTX pCtx, int fd1, const char *file1,
    4646                  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,
     47int cmp_fd_and_fd_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1,
    4848                     int fd2, const char *file2, off_t skip2,  int sflag, int lflag, int special);
    4949
  • trunk/src/kmk/kmkbuiltin/cmp_util.c

    r3095 r3192  
    6666
    6767static int
    68 errmsg(const char *file, off_t byte, off_t line, int lflag)
     68errmsg(PKMKBUILTINCTX pCtx, const char *file, off_t byte, off_t line, int lflag)
    6969{
    7070    if (lflag)
    7171#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);
    7777}
    7878
    7979
    8080static int
    81 eofmsg(const char *file, off_t byte, off_t line, int sflag, int lflag)
     81eofmsg(PKMKBUILTINCTX pCtx, const char *file, off_t byte, off_t line, int sflag, int lflag)
    8282{
    8383    if (!sflag)
    8484    {
    8585        if (!lflag)
    86             warnx("EOF on %s", file);
     86            warnx(pCtx, "EOF on %s", file);
    8787        else
    8888        {
    8989#ifdef _MSC_VER
    9090            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);
    9292            else
    93                 warnx("EOF on %s: char %I64d", file, (__int64)byte);
     93                warnx(pCtx, "EOF on %s: char %I64d", file, (__int64)byte);
    9494#else
    9595            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);
    9797            else
    98                 warnx("EOF on %s: char %lld", file, (long long)byte);
     98                warnx(pCtx, "EOF on %s: char %lld", file, (long long)byte);
    9999#endif
    100100        }
     
    105105
    106106static int
    107 diffmsg(const char *file1, const char *file2, off_t byte, off_t line, int sflag)
     107diffmsg(PKMKBUILTINCTX pCtx, const char *file1, const char *file2, off_t byte, off_t line, int sflag)
    108108{
    109109    if (!sflag)
    110110#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",
    112112               file1, file2, (__int64)byte, (__int64)line);
    113113#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",
    115115               file1, file2, (long long)byte, (long long)line);
    116116#endif
     
    123123 */
    124124static int
    125 c_special(int fd1, const char *file1, off_t skip1,
     125c_special(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1,
    126126          int fd2, const char *file2, off_t skip2,
    127127          int lflag, int sflag)
     
    134134    fd1dup = dup(fd1);
    135135    if (fd1 < 0)
    136         return err(ERR_EXIT, "%s", file1);
     136        return err(pCtx, ERR_EXIT, "%s", file1);
    137137    fp1 = fdopen(fd1dup, "rb");
    138138    if (!fp1)
     
    140140    if (!fp1)
    141141    {
    142         err(ERR_EXIT, "%s", file1);
     142        err(pCtx, ERR_EXIT, "%s", file1);
    143143        close(fd1dup);
    144144        return ERR_EXIT;
     
    189189                        if (!lflag)
    190190                        {
    191                             rc = diffmsg(file1, file2, byte, line, sflag);
     191                            rc = diffmsg(pCtx, file1, file2, byte, line, sflag);
    192192                            break;
    193193                        }
    194194                        rc = DIFF_EXIT;
    195195#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);
    199199#endif
    200200                    }
     
    206206            /* Check for errors and length differences (EOF). */
    207207            if (ferror(fp1) && rc != ERR_EXIT)
    208                 rc = errmsg(file1, byte, line, lflag);
     208                rc = errmsg(pCtx, file1, byte, line, lflag);
    209209            if (ferror(fp2) && rc != ERR_EXIT)
    210                 rc = errmsg(file2, byte, line, lflag);
     210                rc = errmsg(pCtx, file2, byte, line, lflag);
    211211            if (rc == OK_EXIT)
    212212            {
     
    214214                {
    215215                    if (!feof(fp2))
    216                         rc = eofmsg(file1, byte, line, sflag, lflag);
     216                        rc = eofmsg(pCtx, file1, byte, line, sflag, lflag);
    217217                }
    218218                else if (feof(fp2))
    219                     rc = eofmsg(file2, byte, line, sflag, lflag);
     219                    rc = eofmsg(pCtx, file2, byte, line, sflag, lflag);
    220220            }
    221221
     
    224224        else
    225225        {
    226             rc = err(ERR_EXIT, "%s", file2);
     226            rc = err(pCtx, ERR_EXIT, "%s", file2);
    227227            close(fd2dup);
    228228        }
    229229    }
    230230    else
    231         rc = err(ERR_EXIT, "%s", file2);
     231        rc = err(pCtx, ERR_EXIT, "%s", file2);
    232232
    233233    fclose(fp1);
     
    241241 */
    242242static int
    243 c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
     243c_regular(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, off_t len1,
    244244          int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
    245245{
     
    253253
    254254    if (skip1 > len1)
    255         return eofmsg(file1, len1 + 1, 0, sflag, lflag);
     255        return eofmsg(pCtx, file1, len1 + 1, 0, sflag, lflag);
    256256    len1 -= skip1;
    257257    if (skip2 > len2)
    258         return eofmsg(file2, len2 + 1, 0, sflag, lflag);
     258        return eofmsg(pCtx, file2, len2 + 1, 0, sflag, lflag);
    259259    len2 -= skip2;
    260260
     
    290290                dfound = 1;
    291291#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);
    295295#endif
    296296            }
     
    305305
    306306    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);
    308308    if (dfound)
    309309        return DIFF_EXIT;
     
    311311
    312312l_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);
    314314}
    315315
     
    320320 */
    321321static int
    322 c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
     322c_regular(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1, off_t len1,
    323323          int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag)
    324324{
     
    332332
    333333    if (skip1 > len1)
    334         return eofmsg(file1, len1 + 1, 0, sflag, lflag);
     334        return eofmsg(pCtx, file1, len1 + 1, 0, sflag, lflag);
    335335    len1 -= skip1;
    336336    if (skip2 > len2)
    337         return eofmsg(file2, len2 + 1, 0, sflag, lflag);
     337        return eofmsg(pCtx, file2, len2 + 1, 0, sflag, lflag);
    338338    len2 -= skip2;
    339339
     
    343343    {
    344344        if (skip1 && lseek(fd1, 0, SEEK_SET) < 0)
    345             return err(1, "seek failed");
     345            return err(pCtx, 1, "seek failed");
    346346        goto l_special;
    347347    }
     
    383383                    free(b1);
    384384                    free(b2);
    385                     return diffmsg(file1, file2, byte, line, sflag);
     385                    return diffmsg(pCtx, file1, file2, byte, line, sflag);
    386386                }
    387387                dfound = 1;
    388388#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);
    392392#endif
    393393            }
     
    400400
    401401    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);
    403403    if (dfound)
    404404        return DIFF_EXIT;
     
    409409        ||  lseek(fd2, 0, SEEK_SET) < 0)
    410410    {
    411         err(1, "seek failed");
     411        err(pCtx, 1, "seek failed");
    412412        free(b1);
    413413        free(b2);
     
    418418    free(b2);
    419419l_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);
    421421}
    422422#endif  /* non-mmap c_regular */
     
    427427 */
    428428int
    429 cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1,
     429cmp_fd_and_fd_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1,
    430430                 int fd2, const char *file2, off_t skip2,
    431431                 int sflag, int lflag, int special)
     
    435435
    436436    if (fstat(fd1, &st1))
    437         return err(ERR_EXIT, "%s", file1);
     437        return err(pCtx, ERR_EXIT, "%s", file1);
    438438    if (fstat(fd2, &st2))
    439         return err(ERR_EXIT, "%s", file2);
     439        return err(pCtx, ERR_EXIT, "%s", file2);
    440440
    441441    if (    !S_ISREG(st1.st_mode)
    442442        ||  !S_ISREG(st2.st_mode)
    443443        ||  special)
    444         rc = c_special(fd1, file1, skip1,
     444        rc = c_special(pCtx, fd1, file1, skip1,
    445445                       fd2, file2, skip2, sflag, lflag);
    446446    else
    447         rc = c_regular(fd1, file1, skip1, st1.st_size,
     447        rc = c_regular(pCtx, fd1, file1, skip1, st1.st_size,
    448448                       fd2, file2, skip2, st2.st_size, sflag, lflag);
    449449    return rc;
     
    455455 */
    456456int
    457 cmp_fd_and_fd(int fd1, const char *file1,
     457cmp_fd_and_fd(PKMKBUILTINCTX pCtx, int fd1, const char *file1,
    458458              int fd2, const char *file2,
    459459              int sflag, int lflag, int special)
    460460{
    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);
    462462}
    463463
     
    467467 */
    468468int
    469 cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1,
     469cmp_fd_and_file_ex(PKMKBUILTINCTX pCtx, int fd1, const char *file1, off_t skip1,
    470470                   const char *file2, off_t skip2,
    471471                   int sflag, int lflag, int special)
     
    484484    if (fd2 >= 0)
    485485    {
    486         rc = cmp_fd_and_fd_ex(fd1, file1, skip1,
     486        rc = cmp_fd_and_fd_ex(pCtx, fd1, file1, skip1,
    487487                              fd2, file2, skip2, sflag, lflag, special);
    488488        close(fd2);
     
    491491    {
    492492        if (!sflag)
    493             warn("%s", file2);
     493            warn(pCtx, "%s", file2);
    494494        rc = ERR_EXIT;
    495495    }
     
    502502 */
    503503int
    504 cmp_fd_and_file(int fd1, const char *file1,
     504cmp_fd_and_file(PKMKBUILTINCTX pCtx, int fd1, const char *file1,
    505505                const char *file2,
    506506                int sflag, int lflag, int special)
    507507{
    508     return cmp_fd_and_file_ex(fd1, file1, 0,
     508    return cmp_fd_and_file_ex(pCtx, fd1, file1, 0,
    509509                                   file2, 0, sflag, lflag, special);
    510510}
     
    515515 */
    516516int
    517 cmp_file_and_file_ex(const char *file1, off_t skip1,
     517cmp_file_and_file_ex(PKMKBUILTINCTX pCtx, const char *file1, off_t skip1,
    518518                     const char *file2, off_t skip2,
    519519                     int sflag, int lflag, int special)
     
    523523
    524524    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");
    526526
    527527    if (!strcmp(file1, "-"))
    528528    {
    529529        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");
    531531        file1 = "stdin";
    532532        fd1 = 1;
     
    537537    if (fd1 >= 0)
    538538    {
    539         rc = cmp_fd_and_file_ex(fd1, file1, skip1,
     539        rc = cmp_fd_and_file_ex(pCtx, fd1, file1, skip1,
    540540                                     file2, skip2, sflag, lflag, special);
    541541        close(fd1);
     
    544544    {
    545545        if (!sflag)
    546             warn("%s", file1);
     546            warn(pCtx, "%s", file1);
    547547        rc = ERR_EXIT;
    548548    }
     
    556556 */
    557557int
    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 
     558cmp_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  
    5050 *
    5151 * @returns The duplicate enviornment.
     52 * @param   pCtx                The built-in command context.
    5253 * @param   papszEnv            The read-only vector.
    5354 * @param   cEnvVars            The number of variables.
     
    5657 * @param   cVerbosity          The verbosity level.
    5758 */
    58 static char **kBuiltinOptEnvDuplicate(char **papszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity)
     59static char **kBuiltinOptEnvDuplicate(PKMKBUILTINCTX pCtx, char **papszEnv, unsigned cEnvVars, unsigned *pcAllocatedEnvVars,
     60                                      int cVerbosity)
    5961{
    6062    unsigned cAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
     
    7274                    free(papszEnvNew[i]);
    7375                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);
    7577                return NULL;
    7678            }
     
    8082    }
    8183    else
    82         errx(1, "out of memory for duplicating environment vector!");
     84        errx(pCtx, 1, "out of memory for duplicating environment vector!");
    8385    return papszEnvNew;
    8486}
     
    9092 *
    9193 * @returns 0 on success, non-zero exit code on error.
     94 * @param   pCtx                The built-in command context.
    9295 * @param   papszEnv            The environment vector.
    9396 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    98101 * @param   pszValue            The var=value string to apply.
    99102 */
    100 static int kBuiltinOptEnvAddVar(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     103static int kBuiltinOptEnvAddVar(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
    101104                                int cVerbosity, const char *pszValue)
    102105{
     
    109112        papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
    110113        if (!papszEnv)
    111             return errx(1, "out of memory growing environment vector!");
     114            return errx(pCtx, 1, "out of memory growing environment vector!");
    112115        *ppapszEnv = papszEnv;
    113116    }
    114117    papszEnv[cEnvVars] = strdup(pszValue);
    115118    if (!papszEnv[cEnvVars])
    116         return errx(1, "out of memory adding environment variable!");
     119        return errx(pCtx, 1, "out of memory adding environment variable!");
    117120    papszEnv[++cEnvVars]   = NULL;
    118121    *pcEnvVars = cEnvVars;
    119122    if (cVerbosity > 0)
    120         warnx("added '%s'", papszEnv[cEnvVars - 1]);
     123        warnx(pCtx, "added '%s'", papszEnv[cEnvVars - 1]);
    121124    return 0;
    122125}
     
    128131 *
    129132 * @returns 0 on success, non-zero exit code on error.
     133 * @param   pCtx                The built-in command context.
    130134 * @param   papszEnv            The environment vector.
    131135 * @param   cEnvVars            Number of environment variables.
     
    135139 * @param   iEnvVar             Where to start searching after.
    136140 */
    137 static int kBuiltinOptEnvRemoveDuplicates(char **papszEnv, unsigned cEnvVars, int cVerbosity,
     141static int kBuiltinOptEnvRemoveDuplicates(PKMKBUILTINCTX pCtx, char **papszEnv, unsigned cEnvVars, int cVerbosity,
    138142                                          const char *pszValue, size_t cchVar, unsigned iEnvVar)
    139143{
     
    143147        {
    144148            if (cVerbosity > 0)
    145                 warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
     149                warnx(pCtx, "removing duplicate '%s'", papszEnv[iEnvVar]);
    146150            free(papszEnv[iEnvVar]);
    147151            cEnvVars--;
     
    159163 *
    160164 * @returns 0 on success, non-zero exit code on error.
     165 * @param   pCtx                The built-in command context.
    161166 * @param   ppapszEnv           The environment vector pointer.
    162167 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    167172 * @param   pszValue            The var=value string to apply.
    168173 */
    169 int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
     174int kBuiltinOptEnvSet(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     175                      int cVerbosity, const char *pszValue)
    170176{
    171177    const char *pszEqual = strchr(pszValue, '=');
     
    179185        if (!*pcAllocatedEnvVars)
    180186        {
    181             papszEnv = kBuiltinOptEnvDuplicate(papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);
     187            papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);
    182188            if (!papszEnv)
    183                 return errx(1, "out of memory duplicating enviornment (setenv)!");
     189                return errx(pCtx, 1, "out of memory duplicating enviornment (setenv)!");
    184190            *ppapszEnv = papszEnv;
    185191        }
     
    192198            {
    193199                if (cVerbosity > 0)
    194                     warnx("replacing '%s' with '%s'", papszEnv[iEnvVar], pszValue);
     200                    warnx(pCtx, "replacing '%s' with '%s'", papszEnv[iEnvVar], pszValue);
    195201                free(papszEnv[iEnvVar]);
    196202                papszEnv[iEnvVar] = strdup(pszValue);
    197203                if (!papszEnv[iEnvVar])
    198                     return errx(1, "out of memory for modified environment variable!");
    199 
    200                 return kBuiltinOptEnvRemoveDuplicates(papszEnv, 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);
    201207            }
    202208        }
    203         return kBuiltinOptEnvAddVar(ppapszEnv, 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);
    206212}
    207213
     
    211217 *
    212218 * @returns 0 on success, non-zero exit code on error.
     219 * @param   pCtx                The built-in command context.
    213220 * @param   ppapszEnv           The environment vector pointer.
    214221 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    219226 * @param   pszValue            The var=value string to apply.
    220227 */
    221 static int kBuiltinOptEnvAppendPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     228static int kBuiltinOptEnvAppendPrepend(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
    222229                                       int cVerbosity, const char *pszValue, int fAppend)
    223230{
     
    232239        if (!*pcAllocatedEnvVars)
    233240        {
    234             papszEnv = kBuiltinOptEnvDuplicate(papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);
     241            papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);
    235242            if (!papszEnv)
    236                 return errx(1, "out of memory duplicating environment (append)!");
     243                return errx(pCtx, 1, "out of memory duplicating environment (append)!");
    237244            *ppapszEnv = papszEnv;
    238245        }
     
    248255                char  *pszNew      = malloc(cchVar + 1 + cchOldValue + cchNewValue + 1);
    249256                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!");
    251258                if (fAppend)
    252259                {
     
    262269
    263270                if (cVerbosity > 0)
    264                     warnx("replacing '%s' with '%s'", pszCur, pszNew);
     271                    warnx(pCtx, "replacing '%s' with '%s'", pszCur, pszNew);
    265272                free(pszCur);
    266273                papszEnv[iEnvVar] = pszNew;
    267274
    268                 return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
     275                return kBuiltinOptEnvRemoveDuplicates(pCtx, papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
    269276            }
    270277        }
    271         return kBuiltinOptEnvAddVar(ppapszEnv, 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);
    274281}
    275282
     
    279286 *
    280287 * @returns 0 on success, non-zero exit code on error.
     288 * @param   pCtx                The built-in command context.
    281289 * @param   ppapszEnv           The environment vector pointer.
    282290 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    287295 * @param   pszValue            The var=value string to apply.
    288296 */
    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*/);
     297int 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*/);
    292301}
    293302
     
    297306 *
    298307 * @returns 0 on success, non-zero exit code on error.
     308 * @param   pCtx                The built-in command context.
    299309 * @param   ppapszEnv           The environment vector pointer.
    300310 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    305315 * @param   pszValue            The var=value string to apply.
    306316 */
    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*/);
     317int 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*/);
    310321}
    311322
     
    315326 *
    316327 * @returns 0 on success, non-zero exit code on error.
     328 * @param   pCtx                The built-in command context.
    317329 * @param   ppapszEnv           The environment vector pointer.
    318330 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    324336 * @param   pszVarToRemove      The name of the variable to remove.
    325337 */
    326 int kBuiltinOptEnvUnset(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszVarToRemove)
     338int kBuiltinOptEnvUnset(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
     339                        int cVerbosity, const char *pszVarToRemove)
    327340{
    328341    if (strchr(pszVarToRemove, '=') == NULL)
     
    339352            {
    340353                if (cVerbosity > 0)
    341                     warnx(!cRemoved ? "removing '%s'" : "removing duplicate '%s'", papszEnv[iEnvVar]);
     354                    warnx(pCtx, !cRemoved ? "removing '%s'" : "removing duplicate '%s'", papszEnv[iEnvVar]);
    342355
    343356                if (!*pcAllocatedEnvVars)
    344357                {
    345                     papszEnv = kBuiltinOptEnvDuplicate(papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);
     358                    papszEnv = kBuiltinOptEnvDuplicate(pCtx, papszEnv, cEnvVars, pcAllocatedEnvVars, cVerbosity);
    346359                    if (!papszEnv)
    347                         return errx(1, "out of memory duplicating environment (unset)!");
     360                        return errx(pCtx, 1, "out of memory duplicating environment (unset)!");
    348361                    *ppapszEnv = papszEnv;
    349362                }
     
    360373
    361374        if (cVerbosity > 0 && !cRemoved)
    362             warnx("not found '%s'", pszVarToRemove);
     375            warnx(pCtx, "not found '%s'", pszVarToRemove);
    363376    }
    364377    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);
    366379    return 0;
    367380}
     
    372385 *
    373386 * @returns 0 on success, non-zero exit code on error.
     387 * @param   pCtx                The built-in command context.
    374388 * @param   ppapszEnv           The environment vector pointer.
    375389 * @param   pcEnvVars           Pointer to the variable holding the number of
     
    380394 * @param   cVerbosity          The verbosity level.
    381395 */
    382 int kBuiltinOptEnvZap(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity)
     396int kBuiltinOptEnvZap(PKMKBUILTINCTX pCtx, char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity)
    383397{
    384398    if (*pcAllocatedEnvVars > 0)
     
    396410        char **papszEnv = calloc(4, sizeof(char *));
    397411        if (!papszEnv)
    398             return err(1, "out of memory!");
     412            return err(pCtx, 1, "out of memory!");
    399413        *ppapszEnv = papszEnv;
    400414        *pcAllocatedEnvVars = 4;
     
    435449 *
    436450 * @returns 0 on success, non-zero exit code on error.
     451 * @param   pCtx                The built-in command context.
    437452 * @param   pszCwd              The CWD buffer.  Contains current CWD on input,
    438453 *                              modified by @a pszValue on output.
     
    440455 * @param   pszValue            The --chdir value to apply.
    441456 */
    442 int kBuiltinOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue)
     457int kBuiltinOptChDir(PKMKBUILTINCTX pCtx, char *pszCwd, size_t cbCwdBuf, const char *pszValue)
    443458{
    444459    size_t cchNewCwd = strlen(pszValue);
     
    454469                offDst = 2; /* Take drive letter from CWD. */
    455470            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);
    457472        }
    458473        else if (   pszValue[1] == ':'
     
    473488                int iDrive = tolower(pszValue[0]) - 'a' + 1;
    474489                if (!_getdcwd(iDrive, pszCwd, cbCwdBuf))
    475                     return err(1, "_getdcwd(%d,,) failed", iDrive);
     490                    return err(pCtx, 1, "_getdcwd(%d,,) failed", iDrive);
    476491                pszValue += 2;
    477492                cchNewCwd -= 2;
     
    493508             pszCwd[offDst++] = '/';
    494509        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);
    496511        memcpy(&pszCwd[offDst], pszValue, cchNewCwd + 1);
    497512    }
  • trunk/src/kmk/kmkbuiltin/cp.c

    r3148 r3192  
    157157
    158158
    159 static int copy(char *[], enum op, int);
     159static int copy(PKMKBUILTINCTX pCtx, char *[], enum op, int);
    160160static int mastercmp(const FTSENT **, const FTSENT **);
    161161#ifdef SIGINFO
    162162static void siginfo(int __unused);
    163163#endif
    164 static int usage(FILE *);
     164static int usage(PKMKBUILTINCTX, int);
    165165
    166166int
    167 kmk_builtin_cp(int argc, char *argv[], char **envp)
     167kmk_builtin_cp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    168168{
    169169        struct stat to_stat, tmp_stat;
     
    180180        info = 0;
    181181        cp_ignore_non_existing = cp_changed_only = 0;
    182         kBuildProtectionInit(&g_ProtData);
     182        kBuildProtectionInit(&g_ProtData, pCtx);
    183183
    184184        /* reset getopt and set progname. */
    185         g_progname = argv[0];
    186185        opterr = 1;
    187186        optarg = NULL;
     
    229228                        break;
    230229                case CP_OPT_HELP:
    231                         usage(stdout);
     230                        usage(pCtx, 0);
    232231                        kBuildProtectionTerm(&g_ProtData);
    233232                        return 0;
     
    261260                default:
    262261                        kBuildProtectionTerm(&g_ProtData);
    263                         return usage(stderr);
     262                        return usage(pCtx, 1);
    264263                }
    265264        argc -= optind;
     
    268267        if (argc < 2) {
    269268                kBuildProtectionTerm(&g_ProtData);
    270                 return usage(stderr);
     269                return usage(pCtx, 1);
    271270        }
    272271
     
    275274                if (Rflag) {
    276275                        kBuildProtectionTerm(&g_ProtData);
    277                         return errx(1,
     276                        return errx(pCtx, 1,
    278277                    "the -R and -r options may not be specified together.");
    279278                }
    280279                if (Hflag || Lflag || Pflag)
    281                         errx(1,
     280                        errx(pCtx, 1,
    282281        "the -H, -L, and -P options may not be specified with the -r option.");
    283282                fts_options &= ~FTS_PHYSICAL;
     
    303302        if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) {
    304303                kBuildProtectionTerm(&g_ProtData);
    305                 return errx(1, "%s: name too long", target);
     304                return errx(pCtx, 1, "%s: name too long", target);
    306305        }
    307306        to.p_end = to.p_path + strlen(to.p_path);
     
    335334        if (r == -1 && errno != ENOENT) {
    336335                kBuildProtectionTerm(&g_ProtData);
    337                 return err(1, "stat: %s", to.p_path);
     336                return err(pCtx, 1, "stat: %s", to.p_path);
    338337        }
    339338        if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
     
    343342                if (argc > 1) {
    344343                        kBuildProtectionTerm(&g_ProtData);
    345                         return usage(stderr);
     344                        return usage(pCtx, 1);
    346345                }
    347346                /*
     
    368367                        kBuildProtectionTerm(&g_ProtData);
    369368                        if (r == -1)
    370                                 return errx(1, "directory %s does not exist",
     369                                return errx(pCtx, 1, "directory %s does not exist",
    371370                                            to.p_path);
    372371                        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);
    374373                }
    375374        } else
     
    387386                                     : KBUILDPROTECTIONTYPE_FULL,
    388387                                     to.p_path)) {
    389             rc = copy(argv, type, fts_options);
     388            rc = copy(pCtx, argv, type, fts_options);
    390389        }
    391390
     
    394393}
    395394
     395#ifdef KMK_BUILTIN_STANDALONE
     396int 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
    396403static int
    397 copy(char *argv[], enum op type, int fts_options)
     404copy(PKMKBUILTINCTX pCtx, char *argv[], enum op type, int fts_options)
    398405{
    399406        struct stat to_stat;
     
    413420
    414421        if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
    415                 return err(1, "fts_open");
     422                return err(pCtx, 1, "fts_open");
    416423        for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
    417424                int copied = 0;
     
    422429                            && curr->fts_errno == ENOENT) {
    423430                                if (vflag) {
    424                                         warnx("fts: %s: %s", curr->fts_path,
     431                                        warnx(pCtx, "fts: %s: %s", curr->fts_path,
    425432                                              strerror(curr->fts_errno));
    426433                                }
     
    430437                case FTS_DNR:
    431438                case FTS_ERR:
    432                         warnx("fts: %s: %s",
     439                        warnx(pCtx, "fts: %s: %s",
    433440                            curr->fts_path, strerror(curr->fts_errno));
    434441                        badcp = rval = 1;
    435442                        continue;
    436443                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);
    438445                        badcp = rval = 1;
    439446                        continue;
     
    490497                        *target_mid = 0;
    491498                        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)",
    493500                                    to.p_path, p);
    494501                                badcp = rval = 1;
     
    519526                         */
    520527                        if (pflag) {
    521                                 if (setfile(curr->fts_statp, -1))
     528                                if (setfile(pCtx, curr->fts_statp, -1))
    522529                                    rval = 1;
    523530                        } else {
     
    526533                                    ((mode | S_IRWXU) & mask) != (mode & mask))
    527534                                        if (chmod(to.p_path, mode & mask) != 0){
    528                                                 warn("chmod: %s", to.p_path);
     535                                                warn(pCtx, "chmod: %s", to.p_path);
    529536                                                rval = 1;
    530537                                        }
     
    541548                            to_stat.st_ino == curr->fts_statp->st_ino &&
    542549                            to_stat.st_ino != 0) {
    543                                 warnx("%s and %s are identical (not copied).",
     550                                warnx(pCtx, "%s and %s are identical (not copied).",
    544551                                    to.p_path, curr->fts_path);
    545552                                badcp = rval = 1;
     
    550557                        if (!S_ISDIR(curr->fts_statp->st_mode) &&
    551558                            S_ISDIR(to_stat.st_mode)) {
    552                                 warnx("cannot overwrite directory %s with "
     559                                warnx(pCtx, "cannot overwrite directory %s with "
    553560                                    "non-directory %s",
    554561                                    to.p_path, curr->fts_path);
     
    566573                            ((fts_options & FTS_COMFOLLOW) &&
    567574                            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))
    569576                                        badcp = rval = 1;
    570577                        } else {
    571                                 if (copy_link(curr, !dne))
     578                                if (copy_link(pCtx, curr, !dne))
    572579                                        badcp = rval = 1;
    573580                        }
     
    576583                case S_IFDIR:
    577584                        if (!Rflag && !rflag) {
    578                                 warnx("%s is a directory (not copied).",
     585                                warnx(pCtx, "%s is a directory (not copied).",
    579586                                    curr->fts_path);
    580587                                (void)fts_set(ftsp, curr, FTS_SKIP);
     
    593600                                if (mkdir(to.p_path,
    594601                                    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);
    596603                        } else if (!S_ISDIR(to_stat.st_mode)) {
    597604                                errno = ENOTDIR;
    598                                 return err(1, "to-mode: %s", to.p_path);
     605                                return err(pCtx, 1, "to-mode: %s", to.p_path);
    599606                        }
    600607                        /*
     
    610617                case S_IFCHR:
    611618                        if (Rflag) {
    612                                 if (copy_special(curr->fts_statp, !dne))
     619                                if (copy_special(pCtx, curr->fts_statp, !dne))
    613620                                        badcp = rval = 1;
    614621                        } else {
    615                                 if (copy_file(curr, dne, cp_changed_only, &copied))
     622                                if (copy_file(pCtx, curr, dne, cp_changed_only, &copied))
    616623                                        badcp = rval = 1;
    617624                        }
     
    621628#endif
    622629                        if (Rflag) {
    623                                 if (copy_fifo(curr->fts_statp, !dne))
     630                                if (copy_fifo(pCtx, curr->fts_statp, !dne))
    624631                                        badcp = rval = 1;
    625632                        } else {
    626                                 if (copy_file(curr, dne, cp_changed_only, &copied))
     633                                if (copy_file(pCtx, curr, dne, cp_changed_only, &copied))
    627634                                        badcp = rval = 1;
    628635                        }
    629636                        break;
    630637                default:
    631                         if (copy_file(curr, dne, cp_changed_only, &copied))
     638                        if (copy_file(pCtx, curr, dne, cp_changed_only, &copied))
    632639                                badcp = rval = 1;
    633640                        break;
    634641                }
    635642                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);
    638645        }
    639646        if (errno)
    640                 return err(1, "fts_read");
     647                return err(pCtx, 1, "fts_read");
    641648        return (rval);
    642649}
     
    679686
    680687static int
    681 usage(FILE *fp)
     688usage(PKMKBUILTINCTX pCtx, int fIsErr)
    682689{
    683         fprintf(fp,
     690        kmk_builtin_ctx_printf(pCtx, fIsErr,
    684691"usage: %s [options] src target\n"
    685692"   or: %s [options] src1 ... srcN directory\n"
     
    728735"yourself in the foot.\n"
    729736                ,
    730                 g_progname, g_progname, g_progname, g_progname,
     737                pCtx->pszProgName, pCtx->pszProgName,
     738                pCtx->pszProgName, pCtx->pszProgName,
    731739                kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
    732740        return 1;
  • trunk/src/kmk/kmkbuiltin/cp_extern.h

    r3107 r3192  
    5555extern volatile sig_atomic_t info;
    5656
    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);
     57int     copy_fifo(PKMKBUILTINCTX pCtx, struct stat *, int);
     58int     copy_file(PKMKBUILTINCTX pCtx, const FTSENT *, int, int, int *);
     59int     copy_link(PKMKBUILTINCTX pCtx, const FTSENT *, int);
     60int     copy_special(PKMKBUILTINCTX pCtx, struct stat *, int);
     61int     setfile(PKMKBUILTINCTX pCtx, struct stat *, int);
  • trunk/src/kmk/kmkbuiltin/cp_utils.c

    r3148 r3192  
    8787
    8888int
    89 copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
     89copy_file(PKMKBUILTINCTX pCtx, const FTSENT *entp, int dne, int changed_only, int *pcopied)
    9090{
    9191        static char buf[MAXBSIZE];
     
    103103
    104104        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);
    106106                return (1);
    107107        }
     
    120120                /* compare the files first if requested */
    121121                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,
    123123                                            1 /* silent */, 0 /* lflag */,
    124124                                            0 /* special */) == OK_EXIT) {
     
    129129                                close(from_fd);
    130130                                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);
    132132                                        return (1);
    133133                                }
     
    138138                if (nflag) {
    139139                        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);
    141141                        return (0);
    142142                } else if (iflag) {
     
    148148                        if (checkch != 'y' && checkch != 'Y') {
    149149                                (void)close(from_fd);
    150                                 (void)fprintf(stderr, "not overwritten\n");
     150                                kmk_builtin_ctx_printf(pCtx, 1, "not overwritten\n");
    151151                                return (1);
    152152                        }
     
    167167
    168168        if (to_fd == -1) {
    169                 warn("open: %s", to.p_path);
     169                warn(pCtx, "open: %s", to.p_path);
    170170                (void)close(from_fd);
    171171                return (1);
     
    185185                if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
    186186                    MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
    187                         warn("mmap: %s", entp->fts_path);
     187                        warn(pCtx, "mmap: %s", entp->fts_path);
    188188                        rval = 1;
    189189                } else {
     
    195195                                if (info) {
    196196                                        info = 0;
    197                                         (void)fprintf(stderr,
     197                                        kmk_builtin_ctx_printf(pCtx, 1,
    198198                                                "%s -> %s %3d%%\n",
    199199                                                entp->fts_path, to.p_path,
     
    205205                        }
    206206                        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);
    208208                                rval = 1;
    209209                        }
    210210                        /* Some systems don't unmap on close(2). */
    211211                        if (munmap(p, fs->st_size) < 0) {
    212                                 warn("munmap: %s", entp->fts_path);
     212                                warn(pCtx, "munmap: %s", entp->fts_path);
    213213                                rval = 1;
    214214                        }
     
    225225                                if (info) {
    226226                                        info = 0;
    227                                         (void)fprintf(stderr,
     227                                        kmk_builtin_ctx_printf(pCtx, 1,
    228228                                                "%s -> %s %3d%%\n",
    229229                                                entp->fts_path, to.p_path,
     
    235235                        }
    236236                        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);
    238238                                rval = 1;
    239239                                break;
     
    241241                }
    242242                if (rcount < 0) {
    243                         warn("read: %s", entp->fts_path);
     243                        warn(pCtx, "read: %s", entp->fts_path);
    244244                        rval = 1;
    245245                }
     
    253253         */
    254254
    255         if (pflag && setfile(fs, to_fd))
     255        if (pflag && setfile(pCtx, fs, to_fd))
    256256                rval = 1;
    257257        (void)close(from_fd);
    258258        if (close(to_fd)) {
    259                 warn("close: %s", to.p_path);
     259                warn(pCtx, "close: %s", to.p_path);
    260260                rval = 1;
    261261        }
     
    264264
    265265int
    266 copy_link(const FTSENT *p, int exists)
     266copy_link(PKMKBUILTINCTX pCtx, const FTSENT *p, int exists)
    267267{
    268268        int len;
     
    270270
    271271        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);
    273273                return (1);
    274274        }
    275275        llink[len] = '\0';
    276276        if (exists && unlink(to.p_path)) {
    277                 warn("unlink: %s", to.p_path);
     277                warn(pCtx, "unlink: %s", to.p_path);
    278278                return (1);
    279279        }
    280280        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
     287int
     288copy_fifo(PKMKBUILTINCTX pCtx, struct stat *from_stat, int exists)
    289289{
    290290        if (exists && unlink(to.p_path)) {
    291                 warn("unlink: %s", to.p_path);
     291                warn(pCtx, "unlink: %s", to.p_path);
    292292                return (1);
    293293        }
    294294        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
     301int
     302copy_special(PKMKBUILTINCTX pCtx, struct stat *from_stat, int exists)
    303303{
    304304        if (exists && unlink(to.p_path)) {
    305                 warn("unlink: %s", to.p_path);
     305                warn(pCtx, "unlink: %s", to.p_path);
    306306                return (1);
    307307        }
    308308        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
     315int
     316setfile(PKMKBUILTINCTX pCtx, struct stat *fs, int fd)
    317317{
    318318        static struct timeval tv[2];
     
    335335#endif
    336336        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);
    338338                rval = 1;
    339339        }
     
    357357                    chown(to.p_path, fs->st_uid, fs->st_gid))) {
    358358                        if (errno != EPERM) {
    359                                 warn("chown: %s", to.p_path);
     359                                warn(pCtx, "chown: %s", to.p_path);
    360360                                rval = 1;
    361361                        }
     
    367367                    (islink ? lchmod(to.p_path, fs->st_mode) :
    368368                    chmod(to.p_path, fs->st_mode))) {
    369                         warn("chmod: %s", to.p_path);
     369                        warn(pCtx, "chmod: %s", to.p_path);
    370370                        rval = 1;
    371371                }
     
    377377                    (islink ? (errno = ENOSYS) :
    378378                    chflags(to.p_path, fs->st_flags))) {
    379                         warn("chflags: %s", to.p_path);
     379                        warn(pCtx, "chflags: %s", to.p_path);
    380380                        rval = 1;
    381381                }
  • 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
    284 */
    295
    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 */
    3625
    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>
    4240#endif
    4341
    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
     46int 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
     119int main(int argc, char **argv, char **envp)
     120{
     121    KMKBUILTINCTX Ctx = { "kmk_echo", NULL };
     122    return kmk_builtin_echo(argc, argv, envp, &Ctx);
     123}
    48124#endif
    49125
    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_VER
    57 #include <unistd.h>
    58 #else
    59 #include "mscfakes.h"
    60 #endif
    61 
    62 #ifndef IOV_MAX
    63 #define IOV_MAX 1024
    64 #endif
    65 
    66 
    67 /*
    68  * Report an error and exit.
    69  * Use it instead of err(3) to avoid linking-in stdio.
    70  */
    71 static void
    72 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_VER
    77         int doserrno = _doserrno;
    78         char szDosErr[48];
    79         sprintf(szDosErr, " (doserrno=%d)", doserrno);
    80 #endif
    81         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_VER
    87         cchIgn += write(STDERR_FILENO, szDosErr, strlen(szDosErr));
    88 #endif
    89         cchIgn += write(STDERR_FILENO, "\n", 1);
    90         (void)cchIgn;
    91 }
    92 
    93 int
    94 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         } else
    109                 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 this
    125                  * the last argument, therefore we need to check
    126                  * 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  
    2727*   Header Files                                                               *
    2828*******************************************************************************/
    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
    3035#include <stdio.h>
    3136#include <stdarg.h>
     
    3338#include <errno.h>
    3439#include "err.h"
     40#if !defined(KMK_BUILTIN_STANDALONE) && !defined(KWORKER)
     41# include "../output.h"
     42#endif
    3543
    3644#ifdef KBUILD_OS_WINDOWS
     
    4149#endif
    4250
    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
     51int 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
    6973                && cchMsg2 >= 0)
    7074            {
    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
     112int 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);
    72154                return eval;
    73155            }
    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");
    110166            return eval;
    111167        }
    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
     171void 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
    146193                && cchMsg2 >= 0)
    147194            {
    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
     231void 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);
    149273                return;
    150274            }
    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");
    183285            return;
    184286        }
    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
     290void 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  
    2727#define ___err_h
    2828
    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
     31int  err(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...);
     32int  errx(PKMKBUILTINCTX pCtx, int eval, const char *fmt, ...);
     33void warn(PKMKBUILTINCTX pCtx, const char *fmt, ...);
     34void warnx(PKMKBUILTINCTX pCtx, const char *fmt, ...);
     35void kmk_builtin_ctx_printf(PKMKBUILTINCTX pCtx, int fIsErr, const char *pszFormat, ...);
    3436
    3537#endif
  • trunk/src/kmk/kmkbuiltin/expr.c

    r3140 r3192  
    2222#endif
    2323#include "err.h"
    24 #include "getopt.h"
    2524#include "kmkbuiltin.h"
    2625
    27 static struct val       *make_int(int);
    28 static struct val       *make_str(char *);
    29 static void              free_value(struct val *);
     26typedef struct EXPRINSTANCE *PEXPRINSTANCE;
     27
     28static struct val       *make_int(PEXPRINSTANCE, int);
     29static struct val       *make_str(PEXPRINSTANCE, char *);
     30static void              free_value(PEXPRINSTANCE, struct val *);
    3031static 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);
     32static int               to_integer(PEXPRINSTANCE, struct val *);
     33static void              to_string(PEXPRINSTANCE, struct val *);
     34static int               is_zero_or_null(PEXPRINSTANCE, struct val *);
     35static void              nexttoken(PEXPRINSTANCE, int);
     36static struct val       *eval6(PEXPRINSTANCE);
     37static struct val       *eval5(PEXPRINSTANCE);
     38static struct val       *eval4(PEXPRINSTANCE);
     39static struct val       *eval3(PEXPRINSTANCE);
     40static struct val       *eval2(PEXPRINSTANCE);
     41static struct val       *eval1(PEXPRINSTANCE);
     42static struct val       *eval0(PEXPRINSTANCE);
    4243
    4344enum token {
     
    5859};
    5960
    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 *));
     61typedef 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
     72static 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 *));
    7276                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
     84static void expr_mem_record_free(PEXPRINSTANCE pThis, void *ptr)
     85{
     86        int i = pThis->num_recorded_allocations;
    8387        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];
    8791                        return;
    8892                }
     
    9094}
    9195
    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)
     96static void expr_mem_init(PEXPRINSTANCE pThis)
     97{
     98        pThis->num_recorded_allocations = 0;
     99        pThis->recorded_allocations = NULL;
     100}
     101
     102static 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
     113static struct val *
     114make_int(PEXPRINSTANCE pThis, int i)
    111115{
    112116        struct val     *vp;
     
    114118        vp = (struct val *) malloc(sizeof(*vp));
    115119        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);
    118122        vp->type = integer;
    119123        vp->u.i = i;
     
    123127
    124128static struct val *
    125 make_str(char *s)
     129make_str(PEXPRINSTANCE pThis, char *s)
    126130{
    127131        struct val     *vp;
     
    129133        vp = (struct val *) malloc(sizeof(*vp));
    130134        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);
    134138        vp->type = string;
    135139        return vp;
     
    138142
    139143static void
    140 free_value(struct val *vp)
     144free_value(PEXPRINSTANCE pThis, struct val *vp)
    141145{
    142146        if (vp->type == string) {
    143                 expr_mem_record_free(vp->u.s);
     147                expr_mem_record_free(pThis, vp->u.s);
    144148                free(vp->u.s);
    145149        }
    146150        free(vp);
    147         expr_mem_record_free(vp);
     151        expr_mem_record_free(pThis, vp);
    148152}
    149153
     
    193197/* coerce to vp to an integer */
    194198static int
    195 to_integer(struct val *vp)
     199to_integer(PEXPRINSTANCE pThis, struct val *vp)
    196200{
    197201        int             r;
     
    201205
    202206        if (is_integer(vp, &r)) {
    203                 expr_mem_record_free(vp->u.s);
     207                expr_mem_record_free(pThis, vp->u.s);
    204208                free(vp->u.s);
    205209                vp->u.i = r;
     
    214218/* coerce to vp to an string */
    215219static void
    216 to_string(struct val *vp)
     220to_string(PEXPRINSTANCE pThis, struct val *vp)
    217221{
    218222        char           *tmp;
     
    222226
    223227        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);
    226230
    227231        vp->type = string;
     
    230234
    231235static int
    232 is_zero_or_null(struct val *vp)
     236is_zero_or_null(PEXPRINSTANCE pThis, struct val *vp)
    233237{
    234238        if (vp->type == integer) {
    235239                return (vp->u.i == 0);
    236240        } 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));
    238242        }
    239243        /* NOTREACHED */
     
    241245
    242246static void
    243 nexttoken(int pat)
     247nexttoken(PEXPRINSTANCE pThis, int pat)
    244248{
    245249        char           *p;
    246250
    247         if ((p = *av) == NULL) {
    248                 token = EOI;
     251        if ((p = *pThis->av) == NULL) {
     252                pThis->token = EOI;
    249253                return;
    250254        }
    251         av++;
     255        pThis->av++;
    252256
    253257
     
    258262
    259263                        if ((i = strchr(x, *p)) != NULL) {
    260                                 token = i - x;
     264                                pThis->token = i - x;
    261265                                return;
    262266                        }
     
    264268                        switch (*p) {
    265269                        case '<':
    266                                 token = LE;
     270                                pThis->token = LE;
    267271                                return;
    268272                        case '>':
    269                                 token = GE;
     273                                pThis->token = GE;
    270274                                return;
    271275                        case '!':
    272                                 token = NE;
     276                                pThis->token = NE;
    273277                                return;
    274278                        }
    275279                }
    276280        }
    277         tokval = make_str(p);
    278         token = OPERAND;
     281        pThis->tokval = make_str(pThis, p);
     282        pThis->token = OPERAND;
    279283        return;
    280284}
     
    287291#endif
    288292static void
    289 error(void)
    290 {
    291         longjmp(g_expr_jmp, errx(2, "syntax error"));
     293error(PEXPRINSTANCE pThis)
     294{
     295        longjmp(pThis->g_expr_jmp, errx(pThis->pCtx, 2, "syntax error"));
    292296        /* NOTREACHED */
    293297}
    294298
    295299static struct val *
    296 eval6(void)
     300eval6(PEXPRINSTANCE pThis)
    297301{
    298302        struct val     *v;
    299303
    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);
    310314                        /* NOTREACHED */
    311315                }
    312                 nexttoken(0);
     316                nexttoken(pThis, 0);
    313317                return v;
    314318        } else {
    315                 error();
     319                error(pThis);
    316320        }
    317321        /* NOTREACHED */
     
    320324/* Parse and evaluate match (regex) expressions */
    321325static struct val *
    322 eval5(void)
     326eval5(PEXPRINSTANCE pThis)
    323327{
    324328#ifdef KMK_WITH_REGEX
     
    332336        struct val     *l;
    333337
    334         l = eval6();
    335         while (token == MATCH) {
     338        l = eval6(pThis);
     339        while (pThis->token == MATCH) {
    336340#ifdef KMK_WITH_REGEX
    337                 nexttoken(1);
    338                 r = eval6();
     341                nexttoken(pThis, 1);
     342                r = eval6(pThis);
    339343
    340344                /* coerce to both arguments to strings */
    341                 to_string(l);
    342                 to_string(r);
     345                to_string(pThis, l);
     346                to_string(pThis, r);
    343347
    344348                /* compile regular expression */
    345349                if ((eval = regcomp(&rp, r->u.s, 0)) != 0) {
    346350                        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));
    348352                }
    349353
     
    353357                        if (rm[1].rm_so >= 0) {
    354358                                *(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);
    356360
    357361                        } 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));
    359363                        }
    360364                } else {
    361365                        if (rp.re_nsub == 0) {
    362                                 v = make_int(0);
     366                                v = make_int(pThis, 0);
    363367                        } else {
    364                                 v = make_str("");
     368                                v = make_str(pThis, "");
    365369                        }
    366370                }
    367371
    368372                /* free arguments and pattern buffer */
    369                 free_value(l);
    370                 free_value(r);
     373                free_value(pThis, l);
     374                free_value(pThis, r);
    371375                regfree(&rp);
    372376
    373377                l = v;
    374378#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."));
    376380#endif
    377381        }
     
    382386/* Parse and evaluate multiplication and division expressions */
    383387static struct val *
    384 eval4(void)
     388eval4(PEXPRINSTANCE pThis)
    385389{
    386390        struct val     *l, *r;
    387391        enum token      op;
    388392
    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"));
    396400                }
    397401
     
    400404                } else {
    401405                        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"));
    403407                        }
    404408                        if (op == DIV) {
     
    409413                }
    410414
    411                 free_value(r);
     415                free_value(pThis, r);
    412416        }
    413417
     
    417421/* Parse and evaluate addition and subtraction expressions */
    418422static struct val *
    419 eval3(void)
     423eval3(PEXPRINSTANCE pThis)
    420424{
    421425        struct val     *l, *r;
    422426        enum token      op;
    423427
    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"));
    431435                }
    432436
     
    437441                }
    438442
    439                 free_value(r);
     443                free_value(pThis, r);
    440444        }
    441445
     
    445449/* Parse and evaluate comparison expressions */
    446450static struct val *
    447 eval2(void)
     451eval2(PEXPRINSTANCE pThis)
    448452{
    449453        struct val     *l, *r;
     
    451455        int             v = 0, li, ri;
    452456
    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 ||
    455459            op == LE || op == GE) {
    456                 nexttoken(0);
    457                 r = eval3();
     460                nexttoken(pThis, 0);
     461                r = eval3(pThis);
    458462
    459463                if (is_integer(l, &li) && is_integer(r, &ri)) {
     
    481485                        }
    482486                } else {
    483                         to_string(l);
    484                         to_string(r);
     487                        to_string(pThis, l);
     488                        to_string(pThis, r);
    485489
    486490                        switch (op) {
     
    508512                }
    509513
    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);
    513517        }
    514518
     
    518522/* Parse and evaluate & expressions */
    519523static struct val *
    520 eval1(void)
     524eval1(PEXPRINSTANCE pThis)
    521525{
    522526        struct val     *l, *r;
    523527
    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);
    533537                } else {
    534                         free_value(r);
     538                        free_value(pThis, r);
    535539                }
    536540        }
     
    541545/* Parse and evaluate | expressions */
    542546static struct val *
    543 eval0(void)
     547eval0(PEXPRINSTANCE pThis)
    544548{
    545549        struct val     *l, *r;
    546550
    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);
    554558                        l = r;
    555559                } else {
    556                         free_value(r);
     560                        free_value(pThis, r);
    557561                }
    558562        }
     
    563567
    564568int
    565 kmk_builtin_expr(int argc, char *argv[], char **envp)
    566 {
    567         struct val     *vp;
     569kmk_builtin_expr(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
     570{
     571        EXPRINSTANCE This;
     572        struct val *vp;
    568573        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 #endif
    579574
    580575        if (argc > 1 && !strcmp(argv[1], "--"))
    581576                argv++;
    582577
    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);
    586586        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);
    592592                        /* NOTREACHED */
    593593                }
    594594
    595595                if (vp->type == integer)
    596                         printf("%d\n", vp->u.i);
     596                        kmk_builtin_ctx_printf(pCtx, 0, "%d\n", vp->u.i);
    597597                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);
    601601        }
    602602        /* else: longjmp */
    603603
    604604        /* cleanup */
    605         expr_mem_cleanup();
     605        expr_mem_cleanup(&This);
    606606        return rval;
    607607}
     608
     609#ifdef KMK_BUILTIN_STANDALONE
     610int 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  
    122122#endif
    123123
    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*********************************************************************************************************************************/
     127typedef 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;
     140typedef INSTALLINSTANCE *PINSTALLINSTANCE;
     141
     142
     143/*********************************************************************************************************************************
     144*   Global Variables                                                                                                             *
     145*********************************************************************************************************************************/
    133146static struct option long_options[] =
    134147{
     
    145158
    146159
    147 static int      copy(int, const char *, int *, const char *);
     160static int      copy(PINSTALLINSTANCE, int, const char *, int *, const char *);
    148161static int      compare(int, size_t, int, size_t);
    149 static int      create_newfile(const char *, int, struct stat *);
     162static int      create_newfile(PINSTALLINSTANCE, const char *, int, struct stat *);
    150163static 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 *);
     164static int      install(PINSTALLINSTANCE, const char *, const char *, u_long, u_int);
     165static int      install_dir(PINSTALLINSTANCE, char *);
     166static u_long   numeric_id(PINSTALLINSTANCE, const char *, const char *);
     167static int      strip(PINSTALLINSTANCE, const char *);
     168static int      usage(PKMKBUILTINCTX, int);
    156169static char    *last_slash(const char *);
    157170static KBOOL    needs_dos2unix_conversion(const char *pszFilename);
     
    159172
    160173int
    161 kmk_builtin_install(int argc, char *argv[], char ** envp)
    162 {
     174kmk_builtin_install(int argc, char *argv[], char ** envp, PKMKBUILTINCTX pCtx)
     175{
     176        INSTALLINSTANCE This;
    163177        struct stat from_sb, to_sb;
    164178        mode_t *set;
     
    170184        (void)envp;
    171185
    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;
    181204
    182205        /* reset getopt and set progname. */
    183         g_progname = argv[0];
    184206        opterr = 1;
    185207        optarg = NULL;
     
    192214                switch(ch) {
    193215                case 'B':
    194                         suffix = optarg;
     216                        This.suffix = optarg;
    195217                        /* FALLTHROUGH */
    196218                case 'b':
    197                         dobackup = 1;
     219                        This.dobackup = 1;
    198220                        break;
    199221                case 'C':
    200                         docompare = 1;
     222                        This.docompare = 1;
    201223                        break;
    202224                case 'c':
     
    204226                        break;
    205227                case 'd':
    206                         dodir = 1;
     228                        This.dodir = 1;
    207229                        break;
    208230                case 'f':
     
    210232                        flags = optarg;
    211233                        if (strtofflags(&flags, &fset, NULL))
    212                                 return errx(EX_USAGE, "%s: invalid flag", flags);
     234                                return errx(pCtx, EX_USAGE, "%s: invalid flag", flags);
    213235                        iflags |= SETFLAGS;
    214236#else
     
    220242                        break;
    221243                case 'M':
    222                         nommap = 1;
     244                        This.nommap = 1;
    223245                        break;
    224246                case 'm':
    225247                        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);
    229250                        free(set);
    230                         mode_given = 1;
     251                        This.mode_given = 1;
    231252                        break;
    232253                case 'o':
     
    234255                        break;
    235256                case 'p':
    236                         docompare = dopreserve = 1;
     257                        This.docompare = This.dopreserve = 1;
    237258                        break;
    238259                case 'S':
    239                         safecopy = 1;
     260                        This.safecopy = 1;
    240261                        break;
    241262                case 's':
    242                         dostrip = 1;
     263                        This.dostrip = 1;
    243264                        break;
    244265                case 'v':
    245                         verbose = 1;
     266                        This.verbose = 1;
    246267                        break;
    247268                case 261:
    248                         usage(stdout);
     269                        usage(pCtx, 0);
    249270                        return 0;
    250271                case 262:
    251272                        return kbuild_version(argv[0]);
    252273                case 263:
    253                         ignore_perm_errors = 1;
     274                        This.ignore_perm_errors = 1;
    254275                        break;
    255276                case 264:
    256                         ignore_perm_errors = 0;
     277                        This.ignore_perm_errors = 0;
    257278                        break;
    258279                case 265:
    259                         hard_link_files_when_possible = 1;
     280                        This.hard_link_files_when_possible = 1;
    260281                        break;
    261282                case 266:
    262                         hard_link_files_when_possible = 0;
     283                        This.hard_link_files_when_possible = 0;
    263284                        break;
    264285                case 267:
    265                         dos2unix = 1;
     286                        This.dos2unix = 1;
    266287                        break;
    267288                case 268:
    268                         dos2unix = -1;
     289                        This.dos2unix = -1;
    269290                        break;
    270291                case '?':
    271292                default:
    272                         return usage(stderr);
     293                        return usage(pCtx, 1);
    273294                }
    274295        argc -= optind;
     
    276297
    277298        /* 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);
    281302        }
    282303
    283304        /* 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);
    286307
    287308        /*   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);
    296317                }
    297318        }
    298319
    299320        /* 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;
    302323
    303324        /* get group and owner id's */
     
    310331#endif
    311332                {
    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)
    314335                                return 1;
    315336                }
    316337        } else
    317                 gid = (gid_t)-1;
     338                This.gid = (gid_t)-1;
    318339
    319340        if (owner != NULL) {
     
    325346#endif
    326347                {
    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)
    329350                                return 1;
    330351                }
    331352        } else
    332                 uid = (uid_t)-1;
    333 
    334         if (dodir) {
     353                This.uid = (uid_t)-1;
     354
     355        if (This.dodir) {
    335356                for (; *argv != NULL; ++argv) {
    336                         int rc = install_dir(*argv);
     357                        int rc = install_dir(&This, *argv);
    337358                        if (rc)
    338359                                return rc;
     
    345366        if (!no_target && S_ISDIR(to_sb.st_mode)) {
    346367                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);
    348369                        if (rc)
    349370                                return rc;
     
    354375        /* can't do file1 file2 directory/file */
    355376        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);
    358379        }
    359380
    360381        if (!no_target) {
    361382                if (stat(*argv, &from_sb))
    362                         return err(EX_OSERR, "%s", *argv);
     383                        return err(pCtx, EX_OSERR, "%s", *argv);
    363384                if (!S_ISREG(to_sb.st_mode)) {
    364385                        errno = EFTYPE;
    365                         return err(EX_OSERR, "%s", to_name);
     386                        return err(pCtx, EX_OSERR, "%s", to_name);
    366387                }
    367388                if (to_sb.st_dev == from_sb.st_dev &&
     
    369390                    to_sb.st_ino == from_sb.st_ino &&
    370391                    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,
    373394                                    "%s and %s are the same file", *argv, to_name);
    374395        }
    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
     400int 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
    377406
    378407static u_long
    379 numeric_id(const char *name, const char *type)
     408numeric_id(PINSTALLINSTANCE pThis, const char *name, const char *type)
    380409{
    381410        u_long val;
     
    389418        val = strtoul(name, &ep, 10);
    390419        if (errno)
    391                 return err(-1, "%s", name);
     420                return err(pThis->pCtx, -1, "%s", name);
    392421        if (*ep != '\0')
    393                 return errx(-1, "unknown %s %s", type, name);
     422                return errx(pThis->pCtx, -1, "unknown %s %s", type, name);
    394423        return (val);
    395424}
     
    400429 */
    401430static int
    402 install(const char *from_name, const char *to_name, u_long fset, u_int flags)
     431install(PINSTALLINSTANCE pThis, const char *from_name, const char *to_name, u_long fset, u_int flags)
    403432{
    404433        struct stat from_sb, temp_sb, to_sb;
     
    428457            ) {
    429458                if (stat(from_name, &from_sb))
    430                         return err(EX_OSERR, "%s", from_name);
     459                        return err(pThis->pCtx, EX_OSERR, "%s", from_name);
    431460                if (!S_ISREG(from_sb.st_mode)) {
    432461                        errno = EFTYPE;
    433                         return err(EX_OSERR, "%s", from_name);
     462                        return err(pThis->pCtx, EX_OSERR, "%s", from_name);
    434463                }
    435464                /* Build the target path. */
     
    450479        if (target && !S_ISREG(to_sb.st_mode)) {
    451480                errno = EFTYPE;
    452                 warn("%s", to_name);
     481                warn(pThis->pCtx, "%s", to_name);
    453482                return EX_OK;
    454483        }
    455484
    456485        /* Only copy safe if the target exists. */
    457         tempcopy = safecopy && target;
     486        tempcopy = pThis->safecopy && target;
    458487
    459488        /* Try hard linking if wanted and possible. */
    460         if (hard_link_files_when_possible)
     489        if (pThis->hard_link_files_when_possible)
    461490        {
    462491#ifdef KBUILD_OS_OS2
     
    466495                if (devnull) {
    467496                        why_not = "/dev/null";
    468                 } else if (dostrip) {
     497                } else if (pThis->dostrip) {
    469498                        why_not = "strip (-s)";
    470                 } else if (docompare) {
     499                } else if (pThis->docompare) {
    471500                        why_not = "compare (-C)";
    472                 } else if (dobackup) {
     501                } else if (pThis->dobackup) {
    473502                        why_not = "backup (-b/-B)";
    474                 } else if (safecopy) {
     503                } else if (pThis->safecopy) {
    475504                        why_not = "safe copy (-S)";
    476505                } else if (lstat(from_name, &temp_sb)) {
     
    481510                        why_not = "not regular file";
    482511# 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)) {
    484513# else
    485                 } else if (mode != (from_sb.st_mode & ALLPERMS)) {
     514                } else if (pThis->mode != (from_sb.st_mode & ALLPERMS)) {
    486515# 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);
    491521                        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) {
    493523                        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) {
    495525                        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)) {
    497527                        why_not = "dos2unix";
    498                 } else if (dos2unix < 0 && needs_unix2dos_conversion(from_name)) {
     528                } else if (pThis->dos2unix < 0 && needs_unix2dos_conversion(from_name)) {
    499529                        why_not = "unix2dos";
    500530                } else {
     
    505535                        }
    506536                        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);
    509540                            goto l_done;
    510541                        }
    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",
    513544                                       to_name, from_name, strerror(errno));
    514545                        why_not = NULL;
    515546                }
    516547#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);
    520551
    521552                /* Can't hard link or we failed, continue as nothing happend. */
     
    523554
    524555        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);
    526557
    527558        /* If we don't strip, we can compare first. */
    528         if (docompare && !dostrip && target) {
     559        if (pThis->docompare && !pThis->dostrip && target) {
    529560                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);
    531562                        goto l_done;
    532563                }
     
    549580                            sizeof(tempfile));
    550581                        if (to_fd < 0) {
    551                                 rc = err(EX_OSERR, "%s", tempfile);
     582                                rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile);
    552583                                goto l_done;
    553584                        }
    554585                } 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);
    558588                                goto l_done;
    559589                        }
    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);
    563592                }
    564593                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);
    566595                        if (rc)
    567596                                goto l_done;
     
    569598        }
    570599
    571         if (dostrip) {
     600        if (pThis->dostrip) {
    572601#if defined(__EMX__) || defined(_MSC_VER)
    573602                /* close before we strip. */
     
    575604                to_fd = -1;
    576605#endif
    577                 rc = strip(tempcopy ? tempfile : to_name);
     606                rc = strip(pThis, tempcopy ? tempfile : to_name);
    578607                if (rc)
    579608                        goto l_done;
     
    588617                to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0);
    589618                if (to_fd < 0) {
    590                         rc = err(EX_OSERR, "stripping %s", to_name);
     619                        rc = err(pThis->pCtx, EX_OSERR, "stripping %s", to_name);
    591620                        goto l_done;
    592621                }
     
    596625         * Compare the stripped temp file with the target.
    597626         */
    598         if (docompare && dostrip && target) {
     627        if (pThis->docompare && pThis->dostrip && target) {
    599628                temp_fd = to_fd;
    600629
    601630                /* Re-open to_fd using the real target name. */
    602631                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);
    604633                        goto l_done;
    605634                }
     
    609638                        (void)unlink(tempfile);
    610639                        errno = serrno;
    611                         rc = err(EX_OSERR, "%s", tempfile);
     640                        rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile);
    612641                        goto l_done;
    613642                }
     
    649678                        (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS);
    650679#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)) {
    654683                                unlink(tempfile);
    655                                 rc = errx(EX_OSERR, "%s: backup filename too long",
     684                                rc = errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long",
    656685                                          to_name);
    657686                                goto l_done;
    658687                        }
    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);
    661690                        if (rename(to_name, backup) < 0) {
    662691                                serrno = errno;
    663692                                unlink(tempfile);
    664693                                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,
    666695                                         backup);
    667696                                goto l_done;
    668697                        }
    669698                }
    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);
    672701                if (rename(tempfile, to_name) < 0) {
    673702                        serrno = errno;
    674703                        unlink(tempfile);
    675704                        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);
    678706                        goto l_done;
    679707                }
     
    682710                (void) close(to_fd);
    683711                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);
    685713                        goto l_done;
    686714                }
     
    690718         * Preserve the timestamp of the source file if necessary.
    691719         */
    692         if (dopreserve && !files_match && !devnull) {
     720        if (pThis->dopreserve && !files_match && !devnull) {
    693721                tvb[0].tv_sec = from_sb.st_atime;
    694722                tvb[0].tv_usec = 0;
     
    702730                (void)unlink(to_name);
    703731                errno = serrno;
    704                 rc = err(EX_OSERR, "%s", to_name);
     732                rc = err(pThis->pCtx, EX_OSERR, "%s", to_name);
    705733                goto l_done;
    706734        }
     
    720748#endif
    721749
    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);
    727756                        } else {
    728757                                serrno = errno;
    729758                                (void)unlink(to_name);
    730759                                errno = serrno;
    731                                 rc = err(EX_OSERR,"%s: chown/chgrp", to_name);
     760                                rc = err(pThis->pCtx, EX_OSERR,"%s: chown/chgrp", to_name);
    732761                                goto l_done;
    733762                        }
    734763                }
    735764
    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)) {
    738767                        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));
    741770                                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));
    743772                        } else  {
    744773                                serrno = errno;
    745774                                (void)unlink(to_name);
    746775                                errno = serrno;
    747                                 rc = err(EX_OSERR, "%s: chmod", to_name);
     776                                rc = err(pThis->pCtx, EX_OSERR, "%s: chmod", to_name);
    748777                                goto l_done;
    749778                        }
     
    758787         */
    759788#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)) {
    764792                if (flags & SETFLAGS) {
    765793                        if (errno == EOPNOTSUPP)
    766                                 warn("%s: chflags", to_name);
     794                                warn(pThis->pCtx, "%s: chflags", to_name);
    767795                        else {
    768796                                serrno = errno;
    769797                                (void)unlink(to_name);
    770798                                errno = serrno;
    771                                 rc = err(EX_OSERR, "%s: chflags", to_name);
     799                                rc = err(pThis->pCtx, EX_OSERR, "%s: chflags", to_name);
    772800                                goto l_done;
    773801                        }
     
    851879 */
    852880int
    853 create_newfile(const char *path, int target, struct stat *sbp)
     881create_newfile(PINSTALLINSTANCE pThis, const char *path, int target, struct stat *sbp)
    854882{
    855883        char backup[MAXPATHLEN];
     
    868896#endif
    869897
    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);
    875902                                errno = ENAMETOOLONG;
    876903                                return -1;
    877904                        }
    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);
    883908                        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);
    885910                                return -1;
    886911                        }
     
    899924 * Write error handler.
    900925 */
    901 static int write_error(int *ptr_to_fd, const char *to_name, int nw)
     926static int write_error(PINSTALLINSTANCE pThis, int *ptr_to_fd, const char *to_name, int nw)
    902927{
    903928    int serrno = errno;
     
    906931    (void)unlink(to_name);
    907932    errno = nw > 0 ? EIO : serrno;
    908     return err(EX_OSERR, "%s", to_name);
     933    return err(pThis->pCtx, EX_OSERR, "%s", to_name);
    909934}
    910935
     
    912937 * Read error handler.
    913938 */
    914 static int read_error(const char *from_name, int *ptr_to_fd, const char *to_name)
     939static int read_error(PINSTALLINSTANCE pThis, const char *from_name, int *ptr_to_fd, const char *to_name)
    915940{
    916941    int serrno = errno;
     
    919944    (void)unlink(to_name);
    920945    errno = serrno;
    921     return err(EX_OSERR, "%s", from_name);
     946    return err(pThis->pCtx, EX_OSERR, "%s", from_name);
    922947}
    923948
     
    927952 */
    928953static int
    929 copy(int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name)
     954copy(PINSTALLINSTANCE pThis, int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name)
    930955{
    931956        KBOOL fPendingCr = K_FALSE;
     
    937962        /* Rewind file descriptors. */
    938963        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);
    940965        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) {
    944969                /*
    945970                 * Copy bytes, no conversion.
     
    947972                while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
    948973                        if ((nw = write(to_fd, buf, nr)) != nr)
    949                                 return write_error(ptr_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) {
    951976                /*
    952977                 * CRLF -> LF is a reduction, so we can work with full buffers.
     
    956981                                && buf[0] != '\n'
    957982                                && (nw = write(to_fd, "\r", 1)) != 1)
    958                                 return write_error(ptr_to_fd, to_name, nw);
     983                                return write_error(pThis, ptr_to_fd, to_name, nw);
    959984
    960985                        fPendingCr = dos2unix_convert_to_unix(buf, nr, buf, &cchDst);
     
    962987                        nw = write(to_fd, buf, cchDst);
    963988                        if (nw != (int)cchDst)
    964                                 return write_error(ptr_to_fd, to_name, nw);
     989                                return write_error(pThis, ptr_to_fd, to_name, nw);
    965990                }
    966991        } else {
     
    9781003                                && pchSrc[0] != '\n'
    9791004                                && (nw = write(to_fd, "\r", 1))!= 1)
    980                                 return write_error(ptr_to_fd, to_name, nw);
     1005                                return write_error(pThis, ptr_to_fd, to_name, nw);
    9811006
    9821007                        fPendingCr = dos2unix_convert_to_dos(pchSrc, nr, buf, &cchDst);
     
    9841009                        nw = write(to_fd, buf, cchDst);
    9851010                        if (nw != (int)cchDst)
    986                                 return write_error(ptr_to_fd, to_name, nw);
     1011                                return write_error(pThis, ptr_to_fd, to_name, nw);
    9871012                }
    9881013        }
     
    9901015        /* Check for read error. */
    9911016        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);
    9931018
    9941019        /* When converting, we might have a pending final CR to write. */
    995     if (   fPendingCr
    996                 && (nw = write(to_fd, "\r", 1))!= 1)
    997                 return write_error(ptr_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);
    9981023
    9991024    return EX_OK;
     
    10051030 */
    10061031static int
    1007 strip(const char *to_name)
     1032strip(PINSTALLINSTANCE pThis, const char *to_name)
    10081033{
    10091034#if defined(__EMX__) || defined(_MSC_VER)
     
    10111036        if (stripbin == NULL)
    10121037                stripbin = "strip";
     1038        (void)pThis;
    10131039        return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL);
    10141040#else
     
    10231049                (void)unlink(to_name);
    10241050                errno = serrno;
    1025                 return err(EX_TEMPFAIL, "fork");
     1051                return err(pThis->pCtx, EX_TEMPFAIL, "fork");
    10261052        case 0:
    10271053                stripbin = getenv("STRIPBIN");
     
    10291055                        stripbin = "strip";
    10301056                execlp(stripbin, stripbin, to_name, (char *)NULL);
    1031                 err(EX_OSERR, "exec(%s)", stripbin);
     1057                err(pThis->pCtx, EX_OSERR, "exec(%s)", stripbin);
    10321058                exit(EX_OSERR);
    10331059        default:
     
    10361062                        (void)unlink(to_name);
    10371063                        errno = serrno;
    1038                         return err(EX_SOFTWARE, "waitpid");
     1064                        return err(pThis->pCtx, EX_SOFTWARE, "waitpid");
    10391065                        /* NOTREACHED */
    10401066                }
     
    10491075 */
    10501076static int
    1051 install_dir(char *path)
     1077install_dir(PINSTALLINSTANCE pThis, char *path)
    10521078{
    10531079        char *p;
     
    10671093                        if (stat(path, &sb)) {
    10681094                                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);
    10701096                                        /* 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);
    10741099                        } 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);
    10761101                        if (!(*p = ch))
    10771102                                break;
    10781103                }
    10791104
    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);
    10841109        return EX_OK;
    10851110}
     
    10901115 */
    10911116static int
    1092 usage(FILE *pf)
    1093 {
    1094         fprintf(pf,
     1117usage(PKMKBUILTINCTX pCtx, int fIsErr)
     1118{
     1119        kmk_builtin_ctx_printf(pCtx, fIsErr,
    10951120"usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n"
    10961121"            [--[no-]ignore-perm-errors] [-B suffix] [-f flags] [-g group]\n"
     
    11011126"   or: %s --help\n"
    11021127"   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);
    11041130        return EX_USAGE;
    11051131}
  • trunk/src/kmk/kmkbuiltin/kDepIDB.c

    r3167 r3192  
    4646#include "k/kTypes.h"
    4747#include "kDep.h"
     48#include "err.h"
    4849#include "kmkbuiltin.h"
    4950
     
    6667typedef struct KDEPIDBGLOBALS
    6768{
     69    PKMKBUILTINCTX pCtx;
    6870    DEPGLOBALS  Core;
    69     const char *argv0;
    7071} KDEPIDBGLOBALS;
    7172typedef KDEPIDBGLOBALS *PKDEPIDBGLOBALS;
     
    197198{
    198199    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.");
    203201    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);
    209204    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);
    215207    return 0;
    216208}
     
    251243            else
    252244            {
    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);
    255246                memset(pbBuf + iPage * cbPage, 0, cbPage);
    256247            }
     
    261252    }
    262253    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    }
    264258    return pbBuf;
    265259}
     
    311305        ||  cbStream == ~(KU32)0)
    312306    {
    313         fprintf(stderr, "%s: error: Invalid stream %d\n", pThis->argv0, iStream);
     307        errx(pThis->pCtx, 1, "Invalid stream %d", iStream);
    314308        return NULL;
    315309    }
     
    493487{
    494488    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.");
    499490    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.");
    504492    return 0;
    505493}
     
    529517    }
    530518    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));
    532520    return pbBuf;
    533521}
     
    573561        ||  cbStream == ~(KU32)0)
    574562    {
    575         fprintf(stderr, "%s: error: Invalid stream %d\n", pThis->argv0, iStream);
     563        errx(pThis->pCtx, 1, "Invalid stream %d", iStream);
    576564        return NULL;
    577565    }
     
    653641        rc = Pdb20Process(pThis, pbFile, cbFile);
    654642    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.");
    659644
    660645    depFreeFileMemory(pbFile, pvOpaque);
     
    663648
    664649
    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)
     650static 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
     660int kmk_builtin_kDepIDB(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    675661{
    676662    int             i;
     
    689675
    690676    /* Init the instance data. */
    691     This.argv0 = argv[0];
     677    This.pCtx = pCtx;
    692678
    693679    /*
     
    696682    if (argc <= 1)
    697683    {
    698         kDepIDBUsage(This.argv0);
     684        kDepIDBUsage(pCtx, 0);
    699685        return 1;
    700686    }
     
    723709                    pszOutput = &argv[i][2];
    724710                    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!");
    729712                    if (!*pszOutput)
    730713                    {
    731714                        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.");
    736716                        pszOutput = argv[i];
    737717                    }
     
    741721                        pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE);
    742722                    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);
    747724                    break;
    748725                }
     
    754731                {
    755732                    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!");
    760734                    pszTarget = &argv[i][2];
    761735                    if (!*pszTarget)
    762736                    {
    763737                        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.");
    768739                        pszTarget = argv[i];
    769740                    }
     
    802773                 */
    803774                case '?':
    804                     kDepIDBUsage(This.argv0);
     775                    kDepIDBUsage(pCtx, 0);
    805776                    return 0;
    806777                case 'V':
    807778                case 'v':
    808                     return kbuild_version(This.argv0);
     779                    return kbuild_version(pCtx->pszProgName);
    809780
    810781                /*
     
    812783                 */
    813784                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;
    817788            }
    818789        }
     
    821792            pInput = fopen(argv[i], "rb" KMK_FOPEN_NO_INHERIT_MODE);
    822793            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]);
    827795            fInput = 1;
    828796        }
     
    834802        {
    835803            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.");
    840805            break;
    841806        }
     
    846811     */
    847812    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!");
    852814    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!");
    857816    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!");
    862818
    863819    /*
     
    884840     */
    885841    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);
    890843    fclose(pOutput);
    891844    if (i)
    892845    {
    893846        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);
    895848    }
    896849
     
    899852}
    900853
     854#ifdef KMK_BUILTIN_STANDALONE
     855int 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  
    3939#else
    4040# include <io.h>
     41typedef intptr_t ssize_t;
    4142#endif
    4243#include "k/kDefs.h"
     
    4445#include "k/kLdrFmts/pe.h"
    4546#include "kDep.h"
     47#include "err.h"
    4648#include "kmkbuiltin.h"
    4749
     
    170172typedef struct KDEPOBJGLOBALS
    171173{
     174    /** The command execution context. */
     175    PKMKBUILTINCTX pCtx;
    172176    /** Core instance. */
    173177    DEPGLOBALS Core;
    174     /** the executable name. */
    175     const char *argv0;
    176178    /** The file.    */
    177179    const char *pszFile;
     
    194196static int kDepErr(PKDEPOBJGLOBALS pThis, int rc, const char *pszFormat, ...)
    195197{
     198    char szMsg[2048];
    196199    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';
    205204
    206205    if (pThis->pszFile)
    207         fprintf(stderr, "%s: %s: error: ", pszName, pThis->pszFile);
     206        warnx(pThis->pCtx, "%s: error: %s", pThis->pszFile, szMsg);
    208207    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);
    216209    return rc;
    217210}
     
    294287                PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr;
    295288                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.",
    297290                                   (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L');
    298291                if (    (   pTHeadr->Name.cch > 2
     
    325318
    326319                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);
    328321                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);
    330323                uClass = uData.pb[1];
    331324                uData.pb += 2;
     
    344337                            if (pHdr->cbRec == 2 + 1)
    345338                                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)",
    347340                                           (long)((const KU8 *)pHdr - pbFile),
    348341                                           K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1,
     
    398391                    KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft);
    399392                    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));
    401394                    K_NOREF(uGrp);
    402395
     
    415408
    416409                        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));
    418411                        cbRecLeft  -= 2+1+1+2+2+4;
    419412                        uLine       = *uData.pu16++;
     
    431424
    432425                        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);
    434427                        cLinFiles = iLinFile = KU32_MAX;
    435428                        if (   uLinNumType == 3 /* file names table */
     
    437430                            cLinNums = 0; /* no line numbers */
    438431                        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);
    440433                    }
    441434                    else
     
    452445                        {
    453446                            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));
    455448
    456449                            switch (uLinNumType)
     
    492485
    493486                            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));
    495488                            cbRecLeft -= 4+4+4;
    496489
     
    501494                                     uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols));
    502495                            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));
    504497                            iLinFile = 0;
    505498                        }
     
    510503                            int cbName = *uData.pb++;
    511504                            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));
    513506                            iLinFile++;
    514507                            dprintf(("#%" KU32_PRI": %.*s\n", iLinFile, cbName, uData.pch));
     
    542535
    543536    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);
    545538
    546539    if (iSrc == 0 && iMaybeSrc <= 1)
     
    612605        if (off + sizeof(*pHdr) >= cbSyms)
    613606        {
    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);
    616609            return 1; /* FIXME */
    617610        }
     
    620613        if (off + cbData + sizeof(*pHdr) > cbSyms)
    621614        {
    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);
    624617            return 1; /* FIXME */
    625618        }
     
    645638                dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData));
    646639                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);
    648641                pchStrTab = uData.pch;
    649642                cbStrTab = cbData;
     
    654647                dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData));
    655648                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);
    657650                uSrcFiles = uData;
    658651                cbSrcFiles = cbData;
     
    703696         */
    704697        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);
    710700        uSrc.pb = uSrcFiles.pb + off;
    711701        u16Type = uSrc.pu16[2];
    712702        cbSrc = u16Type == 0x0110 ? 6 + 16 + 2 : 6 + 2;
    713703        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);
    719706
    720707        offFile = *uSrc.pu32;
    721708        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);
    727711        pszFile = pchStrTab + offFile;
    728712        cchFile = strlen(pszFile);
    729713        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);
    735716
    736717        /*
     
    822803 * @returns K_TRUE if it's COFF, K_FALSE otherwise.
    823804 *
     805 * @param   pThis   The kDepObj instance data.
    824806 * @param   pb      The start of the file.
    825807 * @param   cb      The file size.
    826808 */
    827 KBOOL kDepObjCOFFTest(const KU8 *pbFile, KSIZE cbFile)
     809KBOOL kDepObjCOFFTest(PKDEPOBJGLOBALS pThis, const KU8 *pbFile, KSIZE cbFile)
    828810{
    829811    IMAGE_FILE_HEADER const         *pFileHdr   = (IMAGE_FILE_HEADER const *)pbFile;
     
    864846            && pBigObjHdr->Machine != IMAGE_FILE_MACHINE_EBC)
    865847        {
    866             fprintf(stderr, "kDepObj: error: bigobj Machine not supported: %#x\n", pBigObjHdr->Machine);
     848            kDepErr(pThis, 1, "bigobj Machine not supported: %#x", pBigObjHdr->Machine);
    867849            return K_FALSE;
    868850        }
    869851        if (pBigObjHdr->Flags != 0)
    870852        {
    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);
    872854            return K_FALSE;
    873855        }
    874856        if (pBigObjHdr->SizeOfData != 0)
    875857        {
    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);
    877859            return K_FALSE;
    878860        }
     
    977959    if (kDepObjOMFTest(pbFile, cbFile))
    978960        rc = kDepObjOMFParse(pThis, pbFile, cbFile);
    979     else if (kDepObjCOFFTest(pbFile, cbFile))
     961    else if (kDepObjCOFFTest(pThis, pbFile, cbFile))
    980962        rc = kDepObjCOFFParse(pThis, pbFile, cbFile);
    981963    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.");
    986965
    987966    depFreeFileMemory(pbFile, pvOpaque);
     
    990969
    991970
    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);
     971static 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);
    998978}
    999979
    1000980
    1001 int kmk_builtin_kDepObj(int argc, char *argv[], char **envp)
     981int kmk_builtin_kDepObj(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    1002982{
    1003983    int             i;
     
    1017997
    1018998    /* Init instance data.   */
    1019     This.argv0  = argv[0];
     999    This.pCtx = pCtx;
    10201000    This.pszFile = NULL;
    10211001
     
    10251005    if (argc <= 1)
    10261006    {
    1027         kDebObjUsage(argv[0]);
     1007        kDebObjUsage(pCtx, 0);
    10281008        return 1;
    10291009    }
     
    10471027                else
    10481028                {
    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);
    10511031                    return 2;
    10521032                }
     
    10671047                        pszValue = argv[i];
    10681048                    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);
    10731050                    break;
    10741051
     
    10871064                {
    10881065                    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!");
    10931067                    pszOutput = pszValue;
    10941068                    if (pszOutput[0] == '-' && !pszOutput[1])
     
    10971071                        pOutput = fopen(pszOutput, "w");
    10981072                    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);
    11031074                    break;
    11041075                }
     
    11101081                {
    11111082                    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!");
    11161084                    pszTarget = pszValue;
    11171085                    break;
     
    11511119                {
    11521120                    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!");
    11571122                    pszIgnoreExt = pszValue;
    11581123                    break;
     
    11631128                 */
    11641129                case '?':
    1165                     kDebObjUsage(argv[0]);
     1130                    kDebObjUsage(pCtx, 0);
    11661131                    return 0;
    11671132                case 'V':
     
    11731138                 */
    11741139                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);
    11771142                    return 2;
    11781143            }
     
    11821147            pInput = fopen(argv[i], "rb");
    11831148            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]);
    11881150            fInput = 1;
    11891151        }
     
    11951157        {
    11961158            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.");
    12011160            break;
    12021161        }
     
    12071166     */
    12081167    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!");
    12131169    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!");
    12181171    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!");
    12231173
    12241174    /*
     
    12451195     */
    12461196    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);
    12511198    fclose(pOutput);
    12521199    if (i)
    12531200    {
    12541201        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);
    12561203    }
    12571204
     
    12601207}
    12611208
     1209#ifdef KMK_BUILTIN_STANDALONE
     1210int 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  
    293293 *
    294294 * @returns 0 on success, non-zero value on failure.
     295 * @param   pCtx                The command execution context.
    295296 * @param   pWorker             The worker structure.  Caller does the linking
    296297 *                              (as we might be reusing an existing worker
     
    299300 * @param   cVerbosity          The verbosity level.
    300301 */
    301 static int kSubmitSpawnWorker(PWORKERINSTANCE pWorker, int cVerbosity)
     302static int kSubmitSpawnWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity)
    302303{
    303304#if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2)
     
    319320        pVarVolatile = lookup_variable(TUPLE("PATH_OUT_BASE"));
    320321        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.");
    322323    }
    323324
     
    346347            if (   cchBinPath < sizeof(g_szArch)
    347348                || 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);
    349351            cchExectuable -= sizeof(g_szArch) - 1;
    350352            memcpy(&szExecutable[cchExectuable], g_szAltArch, sizeof(g_szAltArch) - 1);
     
    417419                        pWorker->pid = GetProcessId(pWorker->hProcess);
    418420                        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);
    420422                        return 0;
    421423                    }
    422                     err(1, "_spawnve(,%s,,)", szExecutable);
     424                    err(pCtx, 1, "_spawnve(,%s,,)", szExecutable);
    423425                    CloseHandle(pWorker->OverlappedRead.hEvent);
    424426                    pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE;
    425427                }
    426428                else
    427                     errx(1, "CreateEventW failed: %u", GetLastError());
     429                    errx(pCtx, 1, "CreateEventW failed: %u", GetLastError());
    428430                CloseHandle(pWorker->hPipe);
    429431                pWorker->hPipe = INVALID_HANDLE_VALUE;
    430432            }
    431433            else
    432                 errx(1, "Opening named pipe failed: %u", GetLastError());
     434                errx(pCtx, 1, "Opening named pipe failed: %u", GetLastError());
    433435            CloseHandle(hWorkerPipe);
    434436        }
    435437        else
    436             errx(1, "CreateNamedPipeW failed: %u", GetLastError());
     438            errx(pCtx, 1, "CreateNamedPipeW failed: %u", GetLastError());
    437439
    438440#else
     
    441443         */
    442444        if (socketpair(AF_LOCAL, SOCK_STREAM, 0, aiPair) == 0)
    443         {
    444445            pWorker->fdSocket = aiPair[1];
    445         }
    446446        else
    447             err(1, "socketpair");
     447            err(pCtx, 1, "socketpair");
    448448#endif
    449449    }
    450450    else
    451         errx(1, "KBUILD_BIN_PATH is too long");
     451        errx(pCtx, 1, "KBUILD_BIN_PATH is too long");
    452452    return -1;
    453453}
     
    458458 *
    459459 * @returns Pointer to the selected worker instance.  NULL on error.
     460 * @param   pCtx                The command execution context.
    460461 * @param   pWorker             The idle worker instance to respawn.
    461462 *                              On failure this will be freed!
    462463 * @param   cBitsWorker         The worker bitness - 64 or 32.
    463464 */
    464 static int kSubmitRespawnWorker(PWORKERINSTANCE pWorker, int cVerbosity)
     465static int kSubmitRespawnWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity)
    465466{
    466467    /*
     
    475476    {
    476477        if (!CloseHandle(pWorker->hPipe))
    477             warnx("CloseHandle(pWorker->hPipe): %u", GetLastError());
     478            warnx(pCtx, "CloseHandle(pWorker->hPipe): %u", GetLastError());
    478479        pWorker->hPipe = INVALID_HANDLE_VALUE;
    479480    }
    480481
    481482    if (!CloseHandle(pWorker->OverlappedRead.hEvent))
    482         warnx("CloseHandle(pWorker->OverlappedRead.hEvent): %u", GetLastError());
     483        warnx(pCtx, "CloseHandle(pWorker->OverlappedRead.hEvent): %u", GetLastError());
    483484    pWorker->OverlappedRead.hEvent = INVALID_HANDLE_VALUE;
    484485
     
    491492        rcWait = WaitForSingleObject(pWorker->hProcess, 100);
    492493        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);
    494495    }
    495496
    496497    if (!CloseHandle(pWorker->hProcess))
    497         warnx("CloseHandle(pWorker->hProcess): %u", GetLastError());
     498        warnx(pCtx, "CloseHandle(pWorker->hProcess): %u", GetLastError());
    498499    pWorker->hProcess = INVALID_HANDLE_VALUE;
    499500
     
    505506    {
    506507        if (close(pWorker->fdSocket) != 0)
    507             warn("close(pWorker->fdSocket)");
     508            warn(pCtx, "close(pWorker->fdSocket)");
    508509        pWorker->fdSocket = -1;
    509510    }
     
    512513    pidWait = waitpid(pWorker->pid, &rc, 0);
    513514    if (pidWait != pWorker->pid)
    514         warn("waitpid(pWorker->pid,,0)");
     515        warn(pCtx, "waitpid(pWorker->pid,,0)");
    515516#endif
    516517
     
    523524     * Respawn it.
    524525     */
    525     if (kSubmitSpawnWorker(pWorker, cVerbosity) == 0)
     526    if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0)
    526527    {
    527528        /*
     
    546547 * @param   cBitsWorker         The worker bitness - 64 or 32.
    547548 */
    548 static PWORKERINSTANCE kSubmitSelectWorkSpawnNewIfNecessary(unsigned cBitsWorker, int cVerbosity)
     549static PWORKERINSTANCE kSubmitSelectWorkSpawnNewIfNecessary(PKMKBUILTINCTX pCtx, unsigned cBitsWorker, int cVerbosity)
    549550{
    550551    /*
     
    564565    pWorker = (PWORKERINSTANCE)xcalloc(sizeof(*pWorker));
    565566    pWorker->cBits = cBitsWorker;
    566     if (kSubmitSpawnWorker(pWorker, cVerbosity) == 0)
     567    if (kSubmitSpawnWorker(pCtx, pWorker, cVerbosity) == 0)
    567568    {
    568569        /*
     
    715716 * @returns 0 on success, non-zero on failure.
    716717 *
     718 * @param   pCtx                The command execution context.
    717719 * @param   pWorker             The work to send the request to.  The worker is
    718720 *                              on the idle list.
     
    722724 * @param   cVerbosity          The verbosity level.
    723725 */
    724 static int kSubmitSendJobMessage(PWORKERINSTANCE pWorker, void const *pvMsg, uint32_t cbMsg, int fNoRespawning, int cVerbosity)
     726static int kSubmitSendJobMessage(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, void const *pvMsg, uint32_t cbMsg,
     727                                 int fNoRespawning, int cVerbosity)
    725728{
    726729    int cRetries;
     
    738741        {
    739742            if (cVerbosity > 0)
    740                 fprintf(stderr,  "kSubmit: Respawning worker (#1)...\n");
    741             if (kSubmitRespawnWorker(pWorker, cVerbosity) != 0)
     743                warnx(pCtx, "Respawning worker (#1)...\n");
     744            if (kSubmitRespawnWorker(pCtx, pWorker, cVerbosity) != 0)
    742745                return 2;
    743746        }
     
    772775                && dwErr != ERROR_NO_DATA)
    773776            || cRetries <= 0)
    774             return errx(1, "Error writing to worker: %u", dwErr);
     777            return errx(pCtx, 1, "Error writing to worker: %u", dwErr);
    775778#else
    776779        ssize_t cbWritten
     
    788791               && errno != ECONNRESET))
    789792            || cRetries <= 0)
    790             return err(1, "Error writing to worker");
     793            return err(pCtx, 1, "Error writing to worker");
    791794# error "later"
    792795#endif
     
    796799         */
    797800        if (cVerbosity > 0)
    798             fprintf(stderr,  "kSubmit: Respawning worker (#2)...\n");
    799         if (kSubmitRespawnWorker(pWorker, cVerbosity) != 0)
     801            warnx(pCtx, "Respawning worker (#2)...\n");
     802        if (kSubmitRespawnWorker(pCtx, pWorker, cVerbosity) != 0)
    800803            return 2;
    801804    }
     
    814817 * which the process can terminate without us having to actively wait for it.
    815818 *
     819 * @param   pCtx                The command execution context.
    816820 * @param   pWorker             The worker instance.
    817821 */
    818 static void kSubmitCloseConnectOnExitingWorker(PWORKERINSTANCE pWorker)
     822static void kSubmitCloseConnectOnExitingWorker(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker)
    819823{
    820824#ifdef KBUILD_OS_WINDOWS
    821825    if (!CloseHandle(pWorker->hPipe))
    822         warnx("CloseHandle(pWorker->hPipe): %u", GetLastError());
     826        warnx(pCtx, "CloseHandle(pWorker->hPipe): %u", GetLastError());
    823827    pWorker->hPipe = INVALID_HANDLE_VALUE;
    824828#else
    825829    if (close(pWorker->fdSocket) != 0)
    826         warn("close(pWorker->fdSocket)");
     830        warn(pCtx, "close(pWorker->fdSocket)");
    827831    pWorker->fdSocket = -1;
    828832#endif
     
    836840 *
    837841 * @returns Exit code.
     842 * @param   pCtx                The command execution context.
    838843 * @param   pWorker             The worker instance.
    839844 * @param   dwErr               The error code.
    840845 * @param   pszWhere            Where it failed.
    841846 */
    842 static int kSubmitWinReadFailed(PWORKERINSTANCE pWorker, DWORD dwErr, const char *pszWhere)
     847static int kSubmitWinReadFailed(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, DWORD dwErr, const char *pszWhere)
    843848{
    844849    DWORD dwExitCode;
    845850
    846851    if (pWorker->cbResultRead == 0)
    847         errx(1, "%s/ReadFile failed: %u", pszWhere, dwErr);
     852        errx(pCtx, 1, "%s/ReadFile failed: %u", pszWhere, dwErr);
    848853    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);
    850855    assert(dwErr != 0);
    851856
     
    870875 * @returns 0 if we got the whole result, -1 if I/O is pending, and windows last
    871876 *          error on ReadFile failure.
     877 * @param   pCtx                The command execution context.
    872878 * @param   pWorker             The worker instance.
    873879 */
    874 static int kSubmitReadMoreResultWin(PWORKERINSTANCE pWorker, const char *pszWhere)
     880static int kSubmitReadMoreResultWin(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, const char *pszWhere)
    875881{
    876882    /*
     
    895901            if (dwErr == ERROR_IO_PENDING)
    896902                return -1;
    897             return kSubmitWinReadFailed(pWorker, dwErr, pszWhere);
     903            return kSubmitWinReadFailed(pCtx, pWorker, dwErr, pszWhere);
    898904        }
    899905
     
    913919 *
    914920 * @returns Exit code.
     921 * @param   pCtx                The command execution context.
    915922 * @param   pWorker             The worker instance to mark as active.
    916923 * @param   cVerbosity          The verbosity level.
     
    920927 *                              and we've returned the exit code of the job.
    921928 */
    922 static int kSubmitMarkActive(PWORKERINSTANCE pWorker, int cVerbosity, struct child *pChild, pid_t *pPidSpawned)
     929static int kSubmitMarkActive(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker, int cVerbosity, struct child *pChild, pid_t *pPidSpawned)
    923930{
    924931#ifdef KBUILD_OS_WINDOWS
     
    934941     */
    935942l_again:
    936     rc = kSubmitReadMoreResultWin(pWorker, "kSubmitMarkActive");
     943    rc = kSubmitReadMoreResultWin(pCtx, pWorker, "kSubmitMarkActive");
    937944    if (rc == -1)
    938945    {
     
    943950        {
    944951            /* 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!");
    946953            WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE);
    947954            goto l_again;
     
    953960        {
    954961            /* 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!");
    956963            WaitForSingleObject(pWorker->OverlappedRead.hEvent, INFINITE);
    957964            goto l_again;
     
    963970        assert(rc == 0 || pWorker->Result.s.rcExit != 0);
    964971        if (pWorker->Result.s.bWorkerExiting)
    965             kSubmitCloseConnectOnExitingWorker(pWorker);
     972            kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
    966973        *pPidSpawned = 0;
    967974        return pWorker->Result.s.rcExit;
     
    9981005{
    9991006    PWORKERINSTANCE pWorker = (PWORKERINSTANCE)pvUser;
     1007    KMKBUILTINCTX   FakeCtx = { "kSubmit/GetResult", NULL };
     1008    PKMKBUILTINCTX  pCtx = &FakeCtx;
    10001009
    10011010    /*
     
    10121021        while (pWorker->cbResultRead < sizeof(pWorker->Result))
    10131022        {
    1014             int rc = kSubmitReadMoreResultWin(pWorker, "kSubmitSubProcGetResult/more");
     1023            int rc = kSubmitReadMoreResultWin(pCtx, pWorker, "kSubmitSubProcGetResult/more");
    10151024            if (rc == -1)
    10161025                return -1;
     
    10221031    {
    10231032        DWORD dwErr = GetLastError();
    1024         kSubmitWinReadFailed(pWorker, dwErr, "kSubmitSubProcGetResult/result");
     1033        kSubmitWinReadFailed(pCtx, pWorker, dwErr, "kSubmitSubProcGetResult/result");
    10251034    }
    10261035
     
    10391048    }
    10401049    if (pWorker->Result.s.bWorkerExiting)
    1041         kSubmitCloseConnectOnExitingWorker(pWorker);
     1050        kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
    10421051
    10431052    return 0;
     
    10741083    DWORD           msStartTick;
    10751084    DWORD           cKillRaids = 0;
     1085    KMKBUILTINCTX   FakeCtx = { "kSubmit/atexit", NULL };
     1086    PKMKBUILTINCTX  pCtx = &FakeCtx;
    10761087
    10771088    /*
     
    10791090     */
    10801091    for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
    1081         kSubmitCloseConnectOnExitingWorker(pWorker);
     1092        kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
    10821093    for (pWorker = g_BusyList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
    1083         kSubmitCloseConnectOnExitingWorker(pWorker);
     1094        kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
    10841095
    10851096    /*
     
    11571168                if (cKillRaids == 1 && getenv("KMK_KSUBMIT_NO_KILL") == NULL)
    11581169                {
    1159                     fprintf(stderr, "kmk/kSubmit: Killing %u lingering worker processe(s)!\n", cHandles);
     1170                    warnx(pCtx, "Killing %u lingering worker processe(s)!\n", cHandles);
    11601171                    for (pWorker = g_IdleList.pHead; pWorker != NULL; pWorker = pWorker->pNext)
    11611172                        if (pWorker->hProcess != INVALID_HANDLE_VALUE)
     
    11671178                else
    11681179                {
    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);
    11701181                    return;
    11711182                }
     
    11761187                   bad ones as well as completed ones. */
    11771188                size_t idx;
    1178                 fprintf(stderr, "kmk/kSubmit: WaitForMultipleObjects unexpectedly returned %#u (err=%u)\n",
    1179                         dwWait, GetLastError());
     1189                warnx(pCtx, "WaitForMultipleObjects unexpectedly returned %#u (err=%u)\n",
     1190                      dwWait, GetLastError());
    11801191                for (idx = 0; idx < cHandles; idx++)
    11811192                {
     
    11941205
    11951206
    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);
     1207static 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);
    12431254    return 2;
    12441255}
    12451256
    12461257
    1247 int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned)
     1258int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned)
    12481259{
    12491260    int             rcExit = 0;
     
    12621273    PATH_VAR(szCwd);
    12631274
    1264     g_progname = argv[0];
    1265 
    12661275    /*
    12671276     * Create default program environment.
     
    12731282    { /* likely */ }
    12741283    else
    1275         return err(1, "getcwd_fs failed\n");
     1284        return err(pCtx, 1, "getcwd_fs failed\n");
    12761285
    12771286    /* The environment starts out in read-only mode and will be duplicated if modified. */
     
    12981307                else
    12991308                {
    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);
    13021311                }
    13031312            }
     
    13541363                else
    13551364                {
    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);
    13581367                }
    13591368                pszArg = "";
     
    13781387                        else
    13791388                        {
    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);
    13821391                        }
    13831392                        break;
     
    13881397                    case 'Z':
    13891398                    case 'i': /* GNU env compatibility. */
    1390                         rcExit = kBuiltinOptEnvZap(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity);
     1399                        rcExit = kBuiltinOptEnvZap(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity);
    13911400                        if (rcExit == 0)
    13921401                            break;
     
    13941403
    13951404                    case 'E':
    1396                         rcExit = kBuiltinOptEnvSet(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1405                        rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    13971406                        if (rcExit == 0)
    13981407                            break;
     
    14001409
    14011410                    case 'A':
    1402                         rcExit = kBuiltinOptEnvAppend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1411                        rcExit = kBuiltinOptEnvAppend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    14031412                        if (rcExit == 0)
    14041413                            break;
     
    14061415
    14071416                    case 'D':
    1408                         rcExit = kBuiltinOptEnvPrepend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1417                        rcExit = kBuiltinOptEnvPrepend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    14091418                        if (rcExit == 0)
    14101419                            break;
     
    14121421
    14131422                    case 'U':
    1414                         rcExit = kBuiltinOptEnvUnset(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1423                        rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    14151424                        if (rcExit == 0)
    14161425                            break;
     
    14181427
    14191428                    case 'C':
    1420                         rcExit = kBuiltinOptChDir(szCwd, cbCwdBuf, pszValue);
     1429                        rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue);
    14211430                        if (rcExit == 0)
    14221431                            break;
     
    14251434                    case 'P':
    14261435                        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!");
    14281437                        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!");
    14301439                        iPostCmd = ++iArg;
    14311440                        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!");
    14331442                        while (iArg < argc && strcmp(argv[iArg], "--") != 0)
    14341443                            iArg++;
     
    14541463
    14551464                    case 'h':
    1456                         usage(stdout, argv[0]);
     1465                        kmk_builtin_kSubmit_usage(pCtx, 0);
    14571466                        kBuiltinOptEnvCleanup(&papszEnvVars, cEnvVars, &cAllocatedEnvVars);
    14581467                        return 0;
     
    14661475        else
    14671476        {
    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);
    14701479        }
    14711480    }
     
    14801489                                                           fWatcomBrainDamage, fNoPchCaching,
    14811490                                                           &argv[iPostCmd], cPostCmdArgs, &cbMsg);
    1482         PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(cBitsWorker, cVerbosity);
     1491        PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity);
    14831492        if (pWorker)
    14841493        {
     
    14861495                pszExecutable = argv[iArg];
    14871496
    1488             rcExit = kSubmitSendJobMessage(pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);
     1497            rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);
    14891498            if (rcExit == 0)
    1490                 rcExit = kSubmitMarkActive(pWorker, cVerbosity, pChild, pPidSpawned);
     1499                rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned);
    14911500
    14921501            if (!g_fAtExitRegistered)
     
    15001509    else
    15011510    {
    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);
    15041513    }
    15051514
  • trunk/src/kmk/kmkbuiltin/kbuild_protection.c

    r2413 r3192  
    116116 *          On failure an error is printed, eval is set and -1 is returned.
    117117 */
    118 static int countPathComponents(const char *pszPath)
     118static int countPathComponents(PCKBUILDPROTECTION pThis, const char *pszPath)
    119119{
    120120    int cComponents = 0;
     
    158158            if (!pszTmp)
    159159            {
    160                 err(1, "_getdcwd");
     160                err(pThis->pCtx, 1, "_getdcwd");
    161161                return -1;
    162162            }
     
    196196        if (!getcwd(szCwd, sizeof(szCwd)))
    197197        {
    198             err(1, "getcwd");
     198            err(pThis->pCtx, 1, "getcwd");
    199199            return -1;
    200200        }
     
    217217 * @param   pThis   Pointer to the instance data.
    218218 */
    219 void kBuildProtectionInit(PKBUILDPROTECTION pThis)
     219void kBuildProtectionInit(PKBUILDPROTECTION pThis, PKMKBUILTINCTX pCtx)
    220220{
    221221    pThis->uMagic = KBUILD_PROTECTION_MAGIC;
     222    pThis->pCtx = pCtx;
    222223    pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] = 0;
    223224    pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] = 1;
     
    268269    /* number or path? */
    269270    if (!isdigit(*pszValue) || strpbrk(pszValue, ":/\\"))
    270         pThis->cProtectionDepth = countPathComponents(pszValue);
     271        pThis->cProtectionDepth = countPathComponents(pThis, pszValue);
    271272    else
    272273    {
     
    280281        }
    281282        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);
    283284    }
    284285
    285286    if (pThis->cProtectionDepth < 1)
    286         return  errx(1, "bogus protection depth: %s", pszValue);
     287        return  errx(pThis->pCtx, 1, "bogus protection depth: %s", pszValue);
    287288    return 0;
    288289}
     
    351352         * Count the path and compare it with the required depth.
    352353         */
    353         int cComponents = countPathComponents(pszPath);
     354        int cComponents = countPathComponents(pThis, pszPath);
    354355        if (cComponents < 0)
    355356            return -1;
    356357        if ((unsigned int)cComponents <= pThis->cProtectionDepth)
    357358        {
    358             errx(1, "%s: protected", pszPath);
     359            errx(pThis->pCtx, 1, "%s: protected", pszPath);
    359360            return -1;
    360361        }
  • trunk/src/kmk/kmkbuiltin/kbuild_protection.h

    r2413 r3192  
    2727#define ___kbuild_protection_h
    2828
     29
    2930/**
    3031 * The different protection types.
     
    4748    unsigned int    uMagic;
    4849    unsigned int    cProtectionDepth;
     50    struct KMKBUILTINCTX *pCtx;
    4951    unsigned char   afTypes[KBUILDPROTECTIONTYPE_MAX];
    5052} KBUILDPROTECTION;
     
    5355
    5456
    55 void kBuildProtectionInit(PKBUILDPROTECTION pThis);
     57void kBuildProtectionInit(PKBUILDPROTECTION pThis, struct KMKBUILTINCTX *pCtx);
    5658void kBuildProtectionTerm(PKBUILDPROTECTION pThis);
    5759int  kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix);
  • trunk/src/kmk/kmkbuiltin/ln.c

    r2466 r3192  
    6161#include "kmkbuiltin.h"
    6262
    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*********************************************************************************************************************************/
     66typedef 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;
     77typedef LNINSTANCE *PLNINSTANCE;
     78
    7179static struct option long_options[] =
    7280{
     
    7785
    7886
    79 static int      linkit(const char *, const char *, int);
    80 static int      usage(FILE *);
     87static int      linkit(PLNINSTANCE,const char *, const char *, int);
     88static int      usage(PKMKBUILTINCTX, int);
    8189
    8290
    8391int
    84 kmk_builtin_ln(int argc, char *argv[], char **envp)
    85 {
     92kmk_builtin_ln(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
     93{
     94        LNINSTANCE This;
    8695        struct stat sb;
    8796        char *sourcedir;
     
    8998
    9099        /* 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;
    94108
    95109        /* kmk: reset getopt() and set program name. */
    96         g_progname = argv[0];
    97110        opterr = 1;
    98111        optarg = NULL;
     
    103116                switch (ch) {
    104117                case 'f':
    105                         fflag = 1;
    106                         iflag = 0;
     118                        This.fflag = 1;
     119                        This.iflag = 0;
    107120                        break;
    108121                case 'h':
    109122                case 'n':
    110                         hflag = 1;
     123                        This.hflag = 1;
    111124                        break;
    112125                case 'i':
    113                         iflag = 1;
    114                         fflag = 0;
     126                        This.iflag = 1;
     127                        This.fflag = 0;
    115128                        break;
    116129                case 's':
    117                         sflag = 1;
     130                        This.sflag = 1;
    118131                        break;
    119132                case 'v':
    120                         vflag = 1;
     133                        This.vflag = 1;
    121134                        break;
    122135                case 261:
    123                         usage(stdout);
     136                        usage(pCtx, 0);
    124137                        return 0;
    125138                case 262:
     
    127140                case '?':
    128141                default:
    129                         return usage(stderr);
     142                        return usage(pCtx, 1);
    130143                }
    131144
     
    133146        argc -= optind;
    134147
    135         linkf = sflag ? symlink : link;
    136         linkch = sflag ? '-' : '=';
     148        This.linkf = This.sflag ? symlink : link;
     149        This.linkch = This.sflag ? '-' : '=';
    137150
    138151        switch(argc) {
    139152        case 0:
    140                 return usage(stderr);
     153                return usage(pCtx, 1);
    141154                /* NOTREACHED */
    142155        case 1:                         /* ln target */
    143                 return linkit(argv[0], ".", 1);
     156                return linkit(&This, argv[0], ".", 1);
    144157        case 2:                         /* ln target source */
    145                 return linkit(argv[0], argv[1], 0);
     158                return linkit(&This, argv[0], argv[1], 0);
    146159        default:
    147160                ;
     
    149162                                        /* ln target1 target2 directory */
    150163        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)) {
    152165                /*
    153166                 * We were asked not to follow symlinks, but found one at
     
    155168                 */
    156169                errno = ENOTDIR;
    157                 return err(1, "st_mode: %s", sourcedir);
     170                return err(pCtx, 1, "st_mode: %s", sourcedir);
    158171        }
    159172        if (stat(sourcedir, &sb))
    160                 return err(1, "stat: %s", sourcedir);
     173                return err(pCtx, 1, "stat: %s", sourcedir);
    161174        if (!S_ISDIR(sb.st_mode))
    162                 return usage(stderr);
     175                return usage(pCtx, 1);
    163176        for (exitval = 0; *argv != sourcedir; ++argv)
    164                 exitval |= linkit(*argv, sourcedir, 1);
     177                exitval |= linkit(&This, *argv, sourcedir, 1);
    165178        return exitval;
    166179}
    167180
    168181static int
    169 linkit(const char *target, const char *source, int isdir)
     182linkit(PLNINSTANCE pThis, const char *target, const char *source, int isdir)
    170183{
    171184        struct stat sb;
     
    174187        char path[PATH_MAX];
    175188
    176         if (!sflag) {
     189        if (!pThis->sflag) {
    177190                /* If target doesn't exist, quit now. */
    178191                if (stat(target, &sb)) {
    179                         warn("stat: %s", target);
     192                        warn(pThis->pCtx, "stat: %s", target);
    180193                        return (1);
    181194                }
     
    183196                if (S_ISDIR(sb.st_mode)) {
    184197                        errno = EISDIR;
    185                         warn("st_mode: %s", target);
     198                        warn(pThis->pCtx, "st_mode: %s", target);
    186199                        return (1);
    187200                }
     
    194207        if (isdir ||
    195208            (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))) {
    197210#if defined(_MSC_VER) || defined(__OS2__)
    198211                char *p2 = strrchr(target, '\\');
     
    210223                    (ssize_t)sizeof(path)) {
    211224                        errno = ENAMETOOLONG;
    212                         warn("snprintf: %s", target);
     225                        warn(pThis->pCtx, "snprintf: %s", target);
    213226                        return (1);
    214227                }
     
    221234         * and interactively if -i was specified.
    222235         */
    223         if (fflag && exists) {
     236        if (pThis->fflag && exists) {
    224237                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) {
    229242                fflush(stdout);
    230243                fprintf(stderr, "replace %s? ", source);
     
    234247                        ch = getchar();
    235248                if (first != 'y' && first != 'Y') {
    236                         fprintf(stderr, "not replaced\n");
     249                        kmk_builtin_ctx_printf(pThis->pCtx, 1, "not replaced\n");
    237250                        return (1);
    238251                }
    239252
    240253                if (unlink(source)) {
    241                         warn("unlink: %s", source);
     254                        warn(pThis->pCtx, "unlink: %s", source);
    242255                        return (1);
    243256                }
     
    245258
    246259        /* 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);
    249262                return (1);
    250263        }
    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);
    253266        return (0);
    254267}
    255268
    256269static 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);
     270usage(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);
    265280        return 1;
    266281}
     282
     283#ifdef KMK_BUILTIN_STANDALONE
     284int 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  
    4949 * Prints the usage and return 1.
    5050 */
    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             );
     51static 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                           );
    7272    return 1;
    7373}
     
    405405 *
    406406 * @returns 0 if it matches, 1 if it doesn't or an error occurs.
     407 * @param   pCtx        The command execution context.
    407408 * @param   pszFilename The name of the file to check.
    408409 * @param   pszDigest   The MD5 digest string.
     
    411412 * @param   fProgress   Whether to show an progress indicator on large files.
    412413 */
    413 static int check_one_file(const char *pszFilename, const char *pszDigest, unsigned fText, unsigned fQuiet, unsigned fProgress)
     414static int check_one_file(PKMKBUILTINCTX pCtx, const char *pszFilename, const char *pszDigest, unsigned fText,
     415                          unsigned fQuiet, unsigned fProgress)
    414416{
    415417    unsigned char Digest[16];
     
    425427        {
    426428            if (!fQuiet)
    427                 fprintf(stdout, "%s: ", pszFilename);
     429                kmk_builtin_ctx_printf(pCtx, 0, "%s: ", pszFilename);
    428430            rc = check_md5sum(pvFile, Digest, fProgress);
    429431            close_file(pvFile);
    430432            if (!fQuiet)
    431433            {
    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");
    434435                if (rc > 0)
    435                     errx(1, "Error reading '%s': %s", pszFilename, strerror(rc));
     436                    errx(pCtx, 1, "Error reading '%s': %s", pszFilename, strerror(rc));
    436437            }
    437438            if (rc)
     
    441442        {
    442443            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));
    444445            rc = 1;
    445446        }
     
    447448    else
    448449    {
    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, "");
    451452        rc = 1;
    452453    }
     
    460461 *
    461462 * @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.
    462464 * @param   pszFilename     The name of the file.
    463465 * @param   fText           The default mode, text or binary. Only used when fBinaryTextOpt is true.
    464466 * @param   fBinaryTextOpt  Whether a -b or -t option was specified and should be used.
    465467 * @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 */
     470static int check_files(PKMKBUILTINCTX pCtx, const char *pszFilename, int fText, int fBinaryTextOpt,
     471                       int fQuiet, unsigned fProgress)
    469472{
    470473    int rc = 0;
     
    539542                        {
    540543                            if (!fQuiet)
    541                                 fprintf(stdout, "%s: ", pszFilename);
     544                                kmk_builtin_ctx_printf(pCtx, 0, "%s: ", pszFilename);
    542545                            rc2 = check_md5sum(pvFile, Digest, fProgress);
    543546                            close_file(pvFile);
    544547                            if (!fQuiet)
    545548                            {
    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");
    548550                                if (rc2 > 0)
    549                                     errx(1, "Error reading '%s': %s", pszFilename, strerror(rc2));
     551                                    errx(pCtx, 1, "Error reading '%s': %s", pszFilename, strerror(rc2));
    550552                            }
    551553                            if (rc2)
     
    555557                        {
    556558                            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));
    558560                            rc = 1;
    559561                        }
     
    561563                    else if (!fQuiet)
    562564                    {
    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, "");
    565567                    }
    566568                }
    567569                else if (!fQuiet)
    568                     errx(1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);
     570                    errx(pCtx, 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);
    569571            }
    570572            else if (!fQuiet)
    571                 errx(1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);
     573                errx(pCtx, 1, "%s (%d): Ignoring malformed line!", pszFilename, iLine);
    572574        } /* while more lines */
    573575
     
    576578    else
    577579    {
    578         errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno));
     580        errx(pCtx, 1, "Failed to open '%s': %s", pszFilename, strerror(errno));
    579581        rc = 1;
    580582    }
     
    588590 *
    589591 * @returns 0 on success, 1 on any kind of failure.
     592 * @param   pCtx            Command context.
    590593 * @param   pszFilename     The file to process.
    591594 * @param   fText           The mode to open the file in.
     
    595598 * @param   pOutput         Where to write the list. Progress is always written to stdout.
    596599 */
    597 static int md5sum_file(const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress,
     600static int md5sum_file(PKMKBUILTINCTX pCtx, const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress,
    598601                       unsigned fManifest, FILE *pOutput)
    599602{
     
    631634                if (pOutput)
    632635                    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);
    634637            }
    635638            else
     
    637640                if (pOutput)
    638641                    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);
    640644            }
    641645            if (pOutput)
    642646                fflush(pOutput);
    643             fflush(stdout);
    644647        }
    645648        else
    646649        {
    647650            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));
    649652            rc = 1;
    650653        }
     
    653656    {
    654657        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));
    656659        rc = 1;
    657660    }
     
    665668 * Somewhat similar to the GNU coreutil md5sum command.
    666669 */
    667 int kmk_builtin_md5sum(int argc, char **argv, char **envp)
     670int kmk_builtin_md5sum(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    668671{
    669672    int i;
     
    679682    FILE *pOutput = NULL;
    680683
    681     g_progname = argv[0];
    682 
    683684    /*
    684685     * Print usage if no arguments.
    685686     */
    686687    if (argc <= 1)
    687         return usage(stderr);
     688        return usage(pCtx, 1);
    688689
    689690    /*
     
    751752
    752753                    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                                  ;
    754759                        break;
    755760
     
    763768
    764769                    case 'h':
    765                         usage(stdout);
     770                        usage(pCtx, 0);
    766771                        return 0;
    767772
     
    783788                        else
    784789                        {
    785                             errx(1, "'-C' is missing the MD5 sum!");
     790                            errx(pCtx, 1, "'-C' is missing the MD5 sum!");
    786791                            return 1;
    787792                        }
     
    790795                        else
    791796                        {
    792                             errx(1, "'-C' is missing the filename!");
     797                            errx(pCtx, 1, "'-C' is missing the filename!");
    793798                            return 1;
    794799                        }
    795800
    796                         rc |= check_one_file(pszFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet);
     801                        rc |= check_one_file(pCtx, pszFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet);
    797802                        psz = "\0";
    798803                        break;
     
    806811                        if (fChecking)
    807812                        {
    808                             errx(1, "'-o' cannot be used with -c or -C!");
     813                            errx(pCtx, 1, "'-o' cannot be used with -c or -C!");
    809814                            return 1;
    810815                        }
     
    816821                        else
    817822                        {
    818                             errx(1, "'-o' is missing the file name!");
     823                            errx(pCtx, 1, "'-o' is missing the file name!");
    819824                            return 1;
    820825                        }
     
    825830
    826831                    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);
    829834                }
    830835            } while (*++psz);
    831836        }
    832837        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);
    834839        else
    835840        {
     
    842847                if (!pOutput)
    843848                {
    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);
    845850                    break;
    846851                }
     
    848853            }
    849854
    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);
    851856        }
    852857        i++;
     
    858863}
    859864
     865
     866#ifdef KMK_BUILTIN_STANDALONE
     867int 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  
    7272
    7373
    74 static int vflag;
    7574static struct option long_options[] =
    7675{
     
    8483extern mode_t bsd_getmode(const void *bbox, mode_t omode);
    8584
    86 static int      build(char *, mode_t);
    87 static int      usage(FILE *);
     85static int      build(PKMKBUILTINCTX pCtx, char *, mode_t, int);
     86static int      usage(PKMKBUILTINCTX pCtx, int fIsErr);
    8887
    8988
    9089int
    91 kmk_builtin_mkdir(int argc, char *argv[], char **envp)
    92 {
    93         int ch, exitval, success, pflag;
     90kmk_builtin_mkdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
     91{
     92        int ch, exitval, success, pflag, vflag;
    9493        mode_t omode, *set = (mode_t *)NULL;
    9594        char *mode;
    9695
    97         omode = pflag = 0;
     96        omode = pflag = vflag = 0;
    9897        mode = NULL;
    9998
    100         /* reinitialize globals */
    101         vflag = 0;
    102 
    10399        /* kmk: reset getopt and set progname */
    104         g_progname = argv[0];
    105100        opterr = 1;
    106101        optarg = NULL;
     
    119114                        break;
    120115                case 261:
    121                         usage(stdout);
     116                        usage(pCtx, 0);
    122117                        return 0;
    123118                case 262:
    124119                        return kbuild_version(argv[0]);
    125120                case '?':
    126                         default:
    127                         return usage(stderr);
     121                default:
     122                        return usage(pCtx, 1);
    128123                }
    129124
     
    131126        argv += optind;
    132127        if (argv[0] == NULL)
    133                 return usage(stderr);
     128                return usage(pCtx, 1);
    134129
    135130        if (mode == NULL) {
     
    137132        } else {
    138133                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);
    140135                omode = bsd_getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
    141136                free(set);
     
    145140                success = 1;
    146141                if (pflag) {
    147                         if (build(*argv, omode))
     142                        if (build(pCtx, *argv, omode, vflag))
    148143                                success = 0;
    149144                } else if (mkdir(*argv, omode) < 0) {
    150145                        if (errno == ENOTDIR || errno == ENOENT)
    151                                 warn("mkdir: %s", dirname(*argv));
     146                                warn(pCtx, "mkdir: %s", dirname(*argv));
    152147                        else
    153                                 warn("mkdir: %s", *argv);
     148                                warn(pCtx, "mkdir: %s", *argv);
    154149                        success = 0;
    155150                } else if (vflag)
    156                         (void)printf("%s\n", *argv);
     151                        kmk_builtin_ctx_printf(pCtx, 0, "%s\n", *argv);
    157152
    158153                if (!success)
     
    166161                 */
    167162                if (success && mode != NULL && chmod(*argv, omode) == -1) {
    168                         warn("chmod: %s", *argv);
     163                        warn(pCtx, "chmod: %s", *argv);
    169164                        exitval = 1;
    170165                }
     
    173168}
    174169
     170#ifdef KMK_BUILTIN_STANDALONE
     171int 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
    175178static int
    176 build(char *path, mode_t omode)
     179build(PKMKBUILTINCTX pCtx, char *path, mode_t omode, int vflag)
    177180{
    178181        struct stat sb;
     
    251254                            || errno == EACCES /* (ditto) */) {
    252255                                if (stat(path, &sb) < 0) {
    253                                         warn("stat: %s", path);
     256                                        warn(pCtx, "stat: %s", path);
    254257                                        retval = 1;
    255258                                        break;
     
    259262                                        else
    260263                                                errno = ENOTDIR;
    261                                         warn("st_mode: %s", path);
     264                                        warn(pCtx, "st_mode: %s", path);
    262265                                        retval = 1;
    263266                                        break;
    264267                                }
    265268                        } else {
    266                                 warn("mkdir: %s", path);
     269                                warn(pCtx, "mkdir: %s", path);
    267270                                retval = 1;
    268271                                break;
    269272                        }
    270273                } else if (vflag)
    271                         printf("%s\n", path);
     274                        kmk_builtin_ctx_printf(pCtx, 0, "%s\n", path);
    272275                if (!last)
    273276                    *p = '/';
     
    279282
    280283static 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);
     284usage(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);
    287291        return EX_USAGE;
    288292}
     293
  • trunk/src/kmk/kmkbuiltin/mscfakes.c

    r3188 r3192  
    446446    }
    447447
     448    fprintf(stderr, "warning: symlink() is available on this version of Windows!\n");
    448449    errno = ENOSYS;
    449     err(1, "symlink() is not implemented on windows!");
    450450    return -1;
    451451}
  • trunk/src/kmk/kmkbuiltin/mv.c

    r3109 r3192  
    4747#endif
    4848
     49
     50/*********************************************************************************************************************************
     51*   Header Files                                                                                                                 *
     52*********************************************************************************************************************************/
    4953#include "config.h"
    5054#include <sys/types.h>
     
    8993
    9094
    91 static int fflg, iflg, nflg, vflg;
     95/*********************************************************************************************************************************
     96*   Structures and Typedefs                                                                                                      *
     97*********************************************************************************************************************************/
     98typedef struct MVINSTANCE
     99{
     100    PKMKBUILTINCTX pCtx;
     101    int fflg, iflg, nflg, vflg;
     102} MVINSTANCE;
     103typedef MVINSTANCE *PMVINSTANCE;
     104
     105
     106/*********************************************************************************************************************************
     107*   Global Variables                                                                                                             *
     108*********************************************************************************************************************************/
    92109static struct option long_options[] =
    93110{
     
    98115
    99116
    100 static int      do_move(char *, char *);
     117/*********************************************************************************************************************************
     118*   Internal Functions                                                                                                           *
     119*********************************************************************************************************************************/
     120extern void     bsd_strmode(mode_t mode, char *p); /* strmode.c */
     121
     122static int      do_move(PMVINSTANCE, char *, char *);
    101123#ifdef CROSS_DEVICE_MOVE
    102124static int      fastcopy(char *, char *, struct stat *);
    103125static int      copy(char *, char *);
    104126#endif
    105 static int      usage(FILE *);
    106 
    107 extern void bsd_strmode(mode_t mode, char *p);
     127static int      usage(PKMKBUILTINCTX, int);
     128
    108129
    109130#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
     
    132153
    133154int
    134 kmk_builtin_mv(int argc, char *argv[], char **envp)
    135 {
     155kmk_builtin_mv(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
     156{
     157        MVINSTANCE This;
    136158        size_t baselen, len;
    137159        int rval;
     
    141163        char path[PATH_MAX];
    142164
    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;
    145171
    146172        /* kmk: reset getopt and set progname */
    147         g_progname = argv[0];
    148173        opterr = 1;
    149174        optarg = NULL;
     
    154179                switch (ch) {
    155180                case 'i':
    156                         iflg = 1;
    157                         fflg = nflg = 0;
     181                        This.iflg = 1;
     182                        This.fflg = This.nflg = 0;
    158183                        break;
    159184                case 'f':
    160                         fflg = 1;
    161                         iflg = nflg = 0;
     185                        This.fflg = 1;
     186                        This.iflg = This.nflg = 0;
    162187                        break;
    163188                case 'n':
    164                         nflg = 1;
    165                         fflg = iflg = 0;
     189                        This.nflg = 1;
     190                        This.fflg = This.iflg = 0;
    166191                        break;
    167192                case 'v':
    168                         vflg = 1;
     193                        This.vflg = 1;
    169194                        break;
    170195                case 261:
    171                         usage(stdout);
     196                        usage(pCtx, 0);
    172197                        return 0;
    173198                case 262:
    174199                        return kbuild_version(argv[0]);
    175200                default:
    176                         return usage(stderr);
     201                        return usage(pCtx, 1);
    177202                }
    178203        argc -= optind;
     
    180205
    181206        if (argc < 2)
    182                 return usage(stderr);
     207                return usage(pCtx, 1);
    183208
    184209        /*
     
    188213        if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) {
    189214                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]);
    192217        }
    193218
    194219        /* 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);
    199224        endp = &path[baselen];
     225        *endp = '\0';
    200226#if defined(_MSC_VER) || defined(__EMX__)
    201227        if (!baselen || (*(endp - 1) != '/' && *(endp - 1) != '\\' && *(endp - 1) != ':')) {
     
    225251
    226252                if ((baselen + (len = strlen(p))) >= PATH_MAX) {
    227                         warnx("%s: destination pathname too long", *argv);
     253                        warnx(pCtx, "%s: destination pathname too long", *argv);
    228254                        rval = 1;
    229255                } else {
    230256                        memmove(endp, p, (size_t)len + 1);
    231                         if (do_move(*argv, path))
     257                        if (do_move(&This, *argv, path))
    232258                                rval = 1;
    233259                }
     
    236262}
    237263
     264#ifdef KMK_BUILTIN_STANDALONE
     265int 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
    238272static int
    239 do_move(char *from, char *to)
     273do_move(PMVINSTANCE pThis, char *from, char *to)
    240274{
    241275        struct stat sb;
     
    248282         * make sure the user wants to clobber it.
    249283         */
    250         if (!fflg && !access(to, F_OK)) {
     284        if (!pThis->fflg && !access(to, F_OK)) {
    251285
    252286                /* prompt only if source exist */
    253287                if (lstat(from, &sb) == -1) {
    254                         warn("%s", from);
     288                        warn(pThis->pCtx, "%s", from);
    255289                        return (1);
    256290                }
     
    258292#define YESNO "(y/n [n]) "
    259293                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);
    263297                        return (0);
    264                 } else if (iflg) {
     298                } else if (pThis->iflg) {
    265299                        (void)fprintf(stderr, "overwrite %s? %s", to, YESNO);
    266300                        ask = 1;
     
    274308                }
    275309                if (ask) {
     310                        fflush(stderr);
    276311                        first = ch = getchar();
    277312                        while (ch != '\n' && ch != EOF)
    278313                                ch = getchar();
    279314                        if (first != 'y' && first != 'Y') {
    280                                 (void)fprintf(stderr, "not overwritten\n");
     315                                kmk_builtin_ctx_printf(pThis->pCtx, 1, "not overwritten\n");
    281316                                return (0);
    282317                        }
     
    284319        }
    285320        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);
    288323                return (0);
    289324        }
     
    292327                remove(to);
    293328                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);
    296331                        return (0);
    297332                }
     
    301336        if (errno == EXDEV) {
    302337#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);
    304339                return (1);
    305340#else
     
    312347                 */
    313348                if (lstat(from, &sb) == -1) {
    314                         warn("%s", from);
     349                        warn(pThis->pCtx, "%s", from);
    315350                        return (1);
    316351                }
     
    318353                        /* Can't mv(1) a mount point. */
    319354                        if (realpath(from, path) == NULL) {
    320                                 warnx("cannot resolve %s: %s", from, path);
     355                                warnx(pThis->pCtx, "cannot resolve %s: %s", from, path);
    321356                                return (1);
    322357                        }
    323358                        if (!statfs(path, &sfs) &&
    324359                            !strcmp(path, sfs.f_mntonname)) {
    325                                 warnx("cannot rename a mount point");
     360                                warnx(pThis->pCtx, "cannot rename a mount point");
    326361                                return (1);
    327362                        }
     
    329364#endif
    330365        } else {
    331                 warn("rename %s to %s", from, to);
     366                warn(pThis->pCtx, "rename %s to %s", from, to);
    332367                return (1);
    333368        }
     
    340375         */
    341376        if (lstat(from, &sb)) {
    342                 warn("%s", from);
     377                warn(pThis->pCtx, "%s", from);
    343378                return (1);
    344379        }
    345380        return (S_ISREG(sb.st_mode) ?
    346             fastcopy(from, to, &sb) : copy(from, to));
     381            fastcopy(pThis, from, to, &sb) : copy(pThis, from, to));
    347382#endif
    348383}
     
    451486        }
    452487        if (vflg)
    453                 printf("%s -> %s\n", from, to);
     488                kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s -> %s\n", from, to);
    454489        return (0);
    455490}
     
    503538
    504539static 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);
     540usage(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);
    512548        return EX_USAGE;
    513549}
  • trunk/src/kmk/kmkbuiltin/printf.c

    r3188 r3192  
    4646#endif*/ /* not lint */
    4747
    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)
    4953# include "../makeint.h"
    5054# include "../filedef.h"
     
    8387#endif
    8488
    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*********************************************************************************************************************************/
    86104#if 0 /*def __GNUC__ - bird: gcc complains about non-ISO-standard escape. */
    87105#define ESCAPE '\e'
     
    90108#endif
    91109
    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 #endif
    100 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 progprintf
    130 #endif
    131 
    132 #ifdef SHELL            /* sh (aka ash) builtin */
    133 #define kmk_builtin_printf printfcmd
    134 #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 
    141110#define PF(f, func) { \
    142111        if (fieldwidth != -1) { \
    143112                if (precision != -1) \
    144                         (void)wrap_printf(f, fieldwidth, precision, func); \
     113                        (void)wrap_printf(pThis, f, fieldwidth, precision, func); \
    145114                else \
    146                         (void)wrap_printf(f, fieldwidth, func); \
     115                        (void)wrap_printf(pThis, f, fieldwidth, func); \
    147116        } else if (precision != -1) \
    148                 (void)wrap_printf(f, precision, func); \
     117                (void)wrap_printf(pThis, f, precision, func); \
    149118        else \
    150                 (void)wrap_printf(f, func); \
     119                (void)wrap_printf(pThis, f, func); \
    151120}
    152121
     
    163132}
    164133
    165 int kmk_builtin_printf(int argc, char *argv[], char **envp)
    166 {
    167         int rc;
     134
     135/*********************************************************************************************************************************
     136*   Structures and Typedefs                                                                                                      *
     137*********************************************************************************************************************************/
     138typedef 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;
     152typedef PRINTFINSTANCE *PPRINTFINSTANCE;
     153
     154
     155/*********************************************************************************************************************************
     156*   Global Variables                                                                                                             *
     157*********************************************************************************************************************************/
     158static 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*********************************************************************************************************************************/
     169static int       common_printf(PPRINTFINSTANCE pThis, int argc, char *argv[]);
     170static void      conv_escape_str(PPRINTFINSTANCE, char *, void (*)(PPRINTFINSTANCE, int));
     171static char     *conv_escape(PPRINTFINSTANCE, char *, char *);
     172static char     *conv_expand(const char *);
     173static int       getchr(PPRINTFINSTANCE);
     174static double    getdouble(PPRINTFINSTANCE);
     175static int       getwidth(PPRINTFINSTANCE);
     176static intmax_t  getintmax(PPRINTFINSTANCE);
     177static uintmax_t getuintmax(PPRINTFINSTANCE);
     178static char     *getstr(PPRINTFINSTANCE);
     179static char     *mklong(PPRINTFINSTANCE, const char *, int, char[64]);
     180static void      check_conversion(PPRINTFINSTANCE, const char *, const char *);
     181static int       usage(PKMKBUILTINCTX, int);
     182
     183static int      flush_buffer(PPRINTFINSTANCE);
     184static void     b_count(PPRINTFINSTANCE, int);
     185static void     b_output(PPRINTFINSTANCE, int);
     186static int      wrap_putchar(PPRINTFINSTANCE, int ch);
     187static int      wrap_printf(PPRINTFINSTANCE, const char *, ...);
     188
     189
     190
     191int kmk_builtin_printf(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
     192{
    168193        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;
    169204
    170205        /* kmk: reset getopt, set progname and reset buffer. */
    171         g_progname = argv[0];
    172206        opterr = 1;
    173207        optarg = NULL;
     
    175209        optind = 0; /* init */
    176210
    177 #if !defined(SHELL) && !defined(BUILTIN) && !defined(kmk_builtin_printf) /* kmk did this already. */
    178         (void)setlocale (LC_ALL, "");
    179 #endif
    180 
    181211        while ((ch = getopt_long(argc, argv, "", long_options, NULL)) != -1) {
    182212                switch (ch) {
    183213                case 261:
    184                         usage(stdout);
     214                        usage(pCtx, 0);
    185215                        return 0;
    186216                case 262:
     
    188218                case '?':
    189219                default:
    190                         return usage(stderr);
     220                        return usage(pCtx, 1);
    191221                }
    192222        }
     
    194224        argv += optind;
    195225
    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
     232int 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 */
    205239/* entry point used by function.c $(printf ..,..). */
    206240char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname)
    207241{
     242        PRINTFINSTANCE This;
    208243        int rc;
    209244        int argc;
     
    211246        for (argc = 0; argv[argc] != NULL; argc++)
    212247                /* 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;
    218261
    219262        if (rc != 0)
     
    221264        return o;
    222265}
    223 #endif
    224 
    225 static int common_printf(int argc, char *argv[])
     266#endif /* KMK_BUILTIN_STANDALONE */
     267
     268static int common_printf(PPRINTFINSTANCE pThis, int argc, char *argv[])
    226269{
    227270        char *fmt, *start;
     
    230273        char *format;
    231274        int ch;
     275        char longbuf[64];
    232276
    233277        /* 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;
    240283        format = *argv;
    241         gargv = ++argv;
     284        pThis->gargv = ++argv;
    242285
    243286#define SKIP1   "#-+ 0"
     
    257300                        if (ch == '\\') {
    258301                                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);
    261304                                continue;
    262305                        }
    263306                        if (ch != '%' || (*fmt == '%' && ++fmt)) {
    264                                 (void)wrap_putchar(ch);
     307                                (void)wrap_putchar(pThis, ch);
    265308                                continue;
    266309                        }
     
    272315                        /* skip to field width */
    273316                        fmt += strspn(fmt, SKIP1);
    274                         fieldwidth = *fmt == '*' ? getwidth() : -1;
     317                        fieldwidth = *fmt == '*' ? getwidth(pThis) : -1;
    275318
    276319                        /* skip to possible '.', get following precision */
     
    278321                        if (*fmt == '.')
    279322                                ++fmt;
    280                         precision = *fmt == '*' ? getwidth() : -1;
     323                        precision = *fmt == '*' ? getwidth(pThis) : -1;
    281324
    282325                        fmt += strspn(fmt, SKIP2);
     
    284327                        ch = *fmt;
    285328                        if (!ch) {
    286                                 flush_buffer();
    287                                 warnx("missing format character");
     329                                flush_buffer(pThis);
     330                                warnx(pThis->pCtx, "missing format character");
    288331                                return (1);
    289332                        }
     
    295338
    296339                        case 'B': {
    297                                 const char *p = conv_expand(getstr());
     340                                const char *p = conv_expand(getstr(pThis));
    298341                                *fmt = 's';
    299342                                PF(start, p);
     
    305348                                 * embedded nulls. */
    306349                                static char *a, *t;
    307                                 char *cp = getstr();
     350                                char *cp = getstr(pThis);
    308351                                /* Free on entry in case shell longjumped out */
    309352                                if (a != NULL)
     
    314357                                t = NULL;
    315358                                /* 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);
    319362                                if (t == NULL)
    320363                                        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;
    323366                                /* Get printf to calculate the lengths */
    324367                                *fmt = 's';
    325368                                APF(&a, start, t);
    326                                 b_fmt = a;
     369                                pThis->b_fmt = a;
    327370                                /* Output leading spaces and data bytes */
    328                                 conv_escape_str(cp, b_output);
     371                                conv_escape_str(pThis, cp, b_output);
    329372                                /* Add any trailing spaces */
    330                                 wrap_printf("%s", b_fmt);
     373                                wrap_printf(pThis, "%s", pThis->b_fmt);
    331374                                break;
    332375                        }
    333376                        case 'c': {
    334                                 char p = getchr();
     377                                char p = getchr(pThis);
    335378                                PF(start, p);
    336379                                break;
    337380                        }
    338381                        case 's': {
    339                                 char *p = getstr();
     382                                char *p = getstr(pThis);
    340383                                PF(start, p);
    341384                                break;
     
    343386                        case 'd':
    344387                        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);
    347390                                PF(f, p);
    348391                                break;
     
    352395                        case 'x':
    353396                        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);
    356399                                PF(f, p);
    357400                                break;
     
    362405                        case 'g':
    363406                        case 'G': {
    364                                 double p = getdouble();
     407                                double p = getdouble(pThis);
    365408                                PF(start, p);
    366409                                break;
    367410                        }
    368411                        default:
    369                                 flush_buffer();
    370                                 warnx("%s: invalid directive", start);
     412                                flush_buffer(pThis);
     413                                warnx(pThis->pCtx, "%s: invalid directive", start);
    371414                                return 1;
    372415                        }
     
    374417                        *fmt = nextch;
    375418                        /* 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;
    385428}
    386429
     
    390433static void
    391434/*ARGSUSED*/
    392 b_count(int ch)
    393 {
    394         b_length++;
     435b_count(PPRINTFINSTANCE pThis, int ch)
     436{
     437        pThis->b_length++;
    395438        (void)ch;
    396439}
     
    399442
    400443static void
    401 b_output(int ch)
     444b_output(PPRINTFINSTANCE pThis, int ch)
    402445{
    403446        for (;;) {
    404                 switch (*b_fmt++) {
     447                switch (*pThis->b_fmt++) {
    405448                case 0:
    406                         b_fmt--;
     449                        pThis->b_fmt--;
    407450                        return;
    408451                case ' ':
    409                         wrap_putchar(' ');
     452                        wrap_putchar(pThis, ' ');
    410453                        break;
    411454                default:
    412                         wrap_putchar(ch);
     455                        wrap_putchar(pThis, ch);
    413456                        return;
    414457                }
     
    416459}
    417460
    418 static int wrap_putchar(int ch)
    419 {
    420 #ifndef kmk_builtin_printf
    421         if (g_o) {
     461static int wrap_putchar(PPRINTFINSTANCE pThis, int ch)
     462{
     463#ifndef KMK_BUILTIN_STANDALONE
     464        if (pThis->g_o) {
    422465                char sz[2];
    423466                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
    427470#endif
    428471        /* 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;
    431474        } 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;
    434477                if (rc)
    435478                        return -1;
     
    438481}
    439482
    440 static int wrap_printf(const char * fmt, ...)
     483static int wrap_printf(PPRINTFINSTANCE pThis, const char * fmt, ...)
    441484{
    442485        ssize_t cchRet;
     
    448491        va_end(va);
    449492        if (cchRet >= 0) {
    450 #ifndef kmk_builtin_printf
    451                 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);
    453496                } else
    454497#endif
    455498                {
    456                         if (cchRet + g_cchBuf <= sizeof(g_achBuf)) {
     499                        if (cchRet + pThis->g_cchBuf <= sizeof(pThis->g_achBuf)) {
    457500                                /* 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;
    460503                        } else {
    461504                                /* Try write out complete lines. */
     
    466509                                        const char *pchNewLine = strchr(pszLeft, '\n');
    467510                                        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;
    471514                                        } else {
    472                                                 if (flush_buffer() < 0) {
     515                                                if (flush_buffer(pThis) < 0) {
    473516                                                        return -1;
    474517                                                }
    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
    476524                                                        return -1;
    477                                                 }
    478525                                        }
    479526                                        pszLeft += cchLine;
     
    490537 * Flushes the g_abBuf/g_cchBuf.
    491538 */
    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;
     539static 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;
    498549                if (cchWritten >= cchToWrite) {
    499550                        /* likely */
     
    509560
    510561                        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
    512567                                if (cchWritten > 0) {
    513568                                        off += cchWritten;
     
    530585 */
    531586static void
    532 conv_escape_str(char *str, void (*do_putchar)(int))
     587conv_escape_str(PPRINTFINSTANCE pThis, char *str, void (*do_putchar)(PPRINTFINSTANCE, int))
    533588{
    534589        int value;
     
    538593        while ((ch = *str++) != '\0') {
    539594                if (ch != '\\') {
    540                         do_putchar(ch);
     595                        do_putchar(pThis, ch);
    541596                        continue;
    542597                }
     
    545600                if (ch == 'c') {
    546601                        /* \c as in SYSV echo - abort all processing.... */
    547                         rval |= 0x100;
     602                        pThis->rval |= 0x100;
    548603                        break;
    549604                }
     
    561616                                octnum = (octnum << 3) | (*str++ - '0');
    562617                        }
    563                         do_putchar(octnum);
     618                        do_putchar(pThis, octnum);
    564619                        continue;
    565620                }
     
    567622                /* \[M][^|-]C as defined by vis(3) */
    568623                if (ch == 'M' && *str == '-') {
    569                         do_putchar(0200 | str[1]);
     624                        do_putchar(pThis, 0200 | str[1]);
    570625                        str += 2;
    571626                        continue;
     
    583638                        else
    584639                                value |= ch & 037;
    585                         do_putchar(value);
     640                        do_putchar(pThis, value);
    586641                        continue;
    587642                }
    588643
    589644                /* 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);
    592647        }
    593648}
     
    597652 */
    598653static char *
    599 conv_escape(char *str, char *conv_ch)
     654conv_escape(PPRINTFINSTANCE pThis, char *str, char *conv_ch)
    600655{
    601656        int value;
     
    643698
    644699        default:
    645                 warnx("unknown escape sequence `\\%c'", ch);
    646                 rval = 1;
     700                warnx(pThis->pCtx, "unknown escape sequence `\\%c'", ch);
     701                pThis->rval = 1;
    647702                value = ch;
    648703                break;
     
    720775
    721776static char *
    722 mklong(const char *str, int ch)
    723 {
    724         static char copy[64];
     777mklong(PPRINTFINSTANCE pThis, const char *str, int ch, char copy[64])
     778{
    725779        size_t len;
    726780
    727781        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);
    730784                len = 4;
    731785        }
     
    744798
    745799static int
    746 getchr(void)
    747 {
    748         if (!*gargv)
     800getchr(PPRINTFINSTANCE pThis)
     801{
     802        if (!*pThis->gargv)
    749803                return 0;
    750         return (int)**gargv++;
     804        return (int)**pThis->gargv++;
    751805}
    752806
    753807static char *
    754 getstr(void)
     808getstr(PPRINTFINSTANCE pThis)
    755809{
    756810        static char empty[] = "";
    757         if (!*gargv)
     811        if (!*pThis->gargv)
    758812                return empty;
    759         return *gargv++;
     813        return *pThis->gargv++;
    760814}
    761815
    762816static int
    763 getwidth(void)
     817getwidth(PPRINTFINSTANCE pThis)
    764818{
    765819        long val;
    766820        char *s, *ep;
    767821
    768         s = *gargv;
    769         if (!*gargv)
     822        s = *pThis->gargv;
     823        if (!s)
    770824                return (0);
    771         gargv++;
     825        pThis->gargv++;
    772826
    773827        errno = 0;
    774828        val = strtoul(s, &ep, 0);
    775         check_conversion(s, ep);
     829        check_conversion(pThis, s, ep);
    776830
    777831        /* Arbitrarily 'restrict' field widths to 1Mbyte */
    778832        if (val < 0 || val > 1 << 20) {
    779                 warnx("%s: invalid field width", s);
     833                warnx(pThis->pCtx, "%s: invalid field width", s);
    780834                return 0;
    781835        }
     
    785839
    786840static intmax_t
    787 getintmax(void)
     841getintmax(PPRINTFINSTANCE pThis)
    788842{
    789843        intmax_t val;
    790844        char *cp, *ep;
    791845
    792         cp = *gargv;
     846        cp = *pThis->gargv;
    793847        if (cp == NULL)
    794848                return 0;
    795         gargv++;
     849        pThis->gargv++;
    796850
    797851        if (*cp == '\"' || *cp == '\'')
     
    800854        errno = 0;
    801855        val = strtoimax(cp, &ep, 0);
    802         check_conversion(cp, ep);
     856        check_conversion(pThis, cp, ep);
    803857        return val;
    804858}
    805859
    806860static uintmax_t
    807 getuintmax(void)
     861getuintmax(PPRINTFINSTANCE pThis)
    808862{
    809863        uintmax_t val;
    810864        char *cp, *ep;
    811865
    812         cp = *gargv;
     866        cp = *pThis->gargv;
    813867        if (cp == NULL)
    814868                return 0;
    815         gargv++;
     869        pThis->gargv++;
    816870
    817871        if (*cp == '\"' || *cp == '\'')
     
    822876                cp++;
    823877        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;
    826880                return 0;
    827881        }
     
    829883        errno = 0;
    830884        val = strtoumax(cp, &ep, 0);
    831         check_conversion(cp, ep);
     885        check_conversion(pThis, cp, ep);
    832886        return val;
    833887}
    834888
    835889static double
    836 getdouble(void)
     890getdouble(PPRINTFINSTANCE pThis)
    837891{
    838892        double val;
    839893        char *ep;
    840 
    841         if (!*gargv)
     894        char *s;
     895
     896        s = *pThis->gargv;
     897        if (!s)
    842898                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];
    846903
    847904        errno = 0;
    848         val = strtod(*gargv, &ep);
    849         check_conversion(*gargv++, ep);
     905        val = strtod(s, &ep);
     906        check_conversion(pThis, s, ep);
    850907        return val;
    851908}
    852909
    853910static void
    854 check_conversion(const char *s, const char *ep)
     911check_conversion(PPRINTFINSTANCE pThis, const char *s, const char *ep)
    855912{
    856913        if (*ep) {
    857914                if (ep == s)
    858                         warnx("%s: expected numeric value", s);
     915                        warnx(pThis->pCtx, "%s: expected numeric value", s);
    859916                else
    860                         warnx("%s: not completely converted", s);
    861                 rval = 1;
     917                        warnx(pThis->pCtx, "%s: not completely converted", s);
     918                pThis->rval = 1;
    862919        } 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;
    865922        }
    866923}
    867924
    868925static 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);
     926usage(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);
    875933        return 1;
    876934}
     935
  • trunk/src/kmk/kmkbuiltin/redirect.c

    r3179 r3192  
    6969# include "nt/nt_child_inject_standard_handles.h"
    7070#endif
    71 #if defined(__gnu_hurd__) && !defined(kmk_builtin_redirect) /* need constant */
     71#if defined(__gnu_hurd__) && !defined(KMK_BUILTIN_STANDALONE) /* need constant */
    7272# undef GET_PATH_MAX
    7373# undef PATH_MAX
     
    107107
    108108
    109 static const char *name(const char *pszName)
     109static int kmk_redirect_usage(PKMKBUILTINCTX pCtx, int fIsErr)
    110110{
    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);
    165150    return 2;
    166151}
     
    198183
    199184
    200 #ifdef _MSC_VER
    201 
    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 triggering
    209  * 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     else
    283     {
    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 < fdNew
    322                             && 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                     else
    328                     {
    329                         fprintf(pStdErr, "%s: _open_osfhandle(%#x) failed: %u\n", g_progname, hDup, strerror(errno));
    330                         CloseHandle(hDup);
    331                     }
    332                 }
    333                 else
    334                     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         else
    342             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 
    349185static KBOOL kRedirectHasConflict(int fd, unsigned cOrders, REDIRECTORDERS *paOrders)
    350186{
     
    374210 *          unless it matches @a fdTarget
    375211 *
     212 * @param   pCtx                The command execution context.
    376213 * @param   pszFilename         The filename to open.
    377214 * @param   fOpen               The open flags.
     
    382219 * @param   fdTarget            The target descriptor.
    383220 */
    384 static int kRedirectOpenWithoutConflict(const char *pszFilename, int fOpen, mode_t fMode,
     221static int kRedirectOpenWithoutConflict(PKMKBUILTINCTX pCtx, const char *pszFilename, int fOpen, mode_t fMode,
    385222                                        unsigned cOrders, REDIRECTORDERS *paOrders, int fRemoveOnFailure, int fdTarget)
    386223{
     
    407244    fdOpened = open(pszFilename, fOpen | fNoInherit, fMode);
    408245    if (fdOpened < 0)
    409         return err(-1, "open(%s,%#x,) failed", pszFilename, fOpen);
     246        return err(pCtx, -1, "open(%s,%#x,) failed", pszFilename, fOpen);
    410247
    411248    /* Check for conflicts. */
     
    453290        else
    454291        {
    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);
    456293            break;
    457294        }
     
    463300     */
    464301    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);
    466303
    467304    while (cTries-- > 0)
     
    499336
    500337
     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 */
     347static 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
    501369#if !defined(USE_POSIX_SPAWN) && !defined(KBUILD_OS_WINDOWS)
    502370
     
    506374 *
    507375 * @returns 0 on success, non-zero exit code on failure.
     376 * @param   pCtx            The command execution context.
    508377 * @param   pToSave         Pointer to the file order to save the target
    509378 *                          descriptor of.
     
    514383 *                          keep having a working one to report failures to.
    515384 */
    516 static int kRedirectSaveHandle(REDIRECTORDERS *pToSave, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)
     385static int kRedirectSaveHandle(PKMKBUILTINCTX pCtx, REDIRECTORDERS *pToSave, unsigned cOrders,
     386                               REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)
    517387{
    518388    int fdToSave = pToSave->fdTarget;
     
    537407            if (fdDup == -1)
    538408            {
    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));
    540410                break;
    541411            }
     
    550420                    if (*ppWorkingStdErr == NULL)
    551421                    {
    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));
    553423                        *ppWorkingStdErr = stderr;
    554424                        close(fdDup);
     
    585455 * Restores the target file descriptors affected by the file operation orders.
    586456 *
     457 * @param   pCtx            The command execution context.
    587458 * @param   cOrders         Number of file operation orders.
    588459 * @param   paOrders        The file operation orders.
     
    591462 *                          it to stderr.
    592463 */
    593 static void kRedirectRestoreFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)
     464static void kRedirectRestoreFdOrders(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)
    594465{
    595466    int iSavedErrno = errno;
     
    613484            }
    614485            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));
    617488        }
    618489
     
    622493                paOrders[i].fSaved = -1;
    623494            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));
    626498        }
    627499    }
     
    634506 *
    635507 * @returns 0 on success, exit code on failure.
     508 * @param   pCtx            The command execution context.
    636509 * @param   cOrders         Number of file operation orders.
    637510 * @param   paOrders        File operation orders to execute.
     
    639512 *                          kRedirectRestoreFdOrders).
    640513 */
    641 static int kRedirectExecFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)
     514static int kRedirectExecFdOrders(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, FILE **ppWorkingStdErr)
    642515{
    643516    unsigned i;
     
    669542                            rcExit = 0;
    670543                        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));
    673546                    }
    674547                    else if (errno == EBADF)
    675548                        rcExit = 0;
    676549                    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));
    678552                }
    679553                else
    680                     rcExit = kRedirectSaveHandle(&paOrders[i], cOrders, paOrders, ppWorkingStdErr);
     554                    rcExit = kRedirectSaveHandle(pCtx, &paOrders[i], cOrders, paOrders, ppWorkingStdErr);
    681555                break;
    682556            }
     
    684558            case kRedirectOrder_Dup:
    685559            case kRedirectOrder_Open:
    686                 rcExit = kRedirectSaveHandle(&paOrders[i], cOrders, paOrders, ppWorkingStdErr);
     560                rcExit = kRedirectSaveHandle(pCtx, &paOrders[i], cOrders, paOrders, ppWorkingStdErr);
    687561                if (rcExit == 0)
    688562                {
     
    692566                    {
    693567                        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));
    696570                        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));
    699573                        rcExit = 10;
    700574                    }
     
    703577
    704578            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);
    706580                rcExit = 99;
    707581                break;
     
    710584        if (rcExit != 0)
    711585        {
    712             kRedirectRestoreFdOrders(i, paOrders, ppWorkingStdErr);
     586            kRedirectRestoreFdOrders(pCtx, i, paOrders, ppWorkingStdErr);
    713587            return rcExit;
    714588        }
     
    799673 *
    800674 * @returns 0 on success, non-zero on failure to create.
     675 * @param   pCtx                The command execution context.
    801676 * @param   pszExecutable       The child process executable.
    802677 * @param   cArgs               Number of arguments.
     
    808683 * @param   phProcess           Where to return process handle.
    809684 */
    810 static int kRedirectCreateProcessWindows(const char *pszExecutable, int cArgs, char **papszArgs, char **papszEnvVars,
    811                                          const char *pszCwd, unsigned cOrders, REDIRECTORDERS *paOrders, HANDLE *phProcess)
     685static int kRedirectCreateProcessWindows(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs,
     686                                         char **papszEnvVars, const char *pszCwd, unsigned cOrders,
     687                                         REDIRECTORDERS *paOrders, HANDLE *phProcess)
    812688{
    813689    size_t cbArgs;
     
    828704    pszCmdLine = pch = (char *)malloc(cbArgs);
    829705    if (!pszCmdLine)
    830         return errx(9, "out of memory!");
     706        return errx(pCtx, 9, "out of memory!");
    831707    for (i = 0; i < cArgs; i++)
    832708    {
     
    901777            }
    902778            else
    903                 rc = errx(10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError());
     779                rc = errx(pCtx, 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError());
    904780        }
    905781        else
     
    923799                        if (   (paOrders[i].fOpen & O_APPEND)
    924800                            && 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);
    926802                    case kRedirectOrder_Dup:
    927803                        ahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource);
    928804                        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);
    930806                        break;
    931807                    case kRedirectOrder_Close:
     
    949825                    rc = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg));
    950826                    if (rc)
    951                         rc = errx(10, "%s", szErrMsg);
     827                        rc = errx(pCtx, 10, "%s", szErrMsg);
    952828                    else if (!ResumeThread(ProcInfo.hThread))
    953                         rc = errx(10, "ResumeThread failed: %u", GetLastError());
     829                        rc = errx(pCtx, 10, "ResumeThread failed: %u", GetLastError());
    954830
    955831                    /* Kill it if any of that fails. */
     
    962838                }
    963839                else
    964                     rc = errx(10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError());
     840                    rc = errx(pCtx, 10, "CreateProcessA(%s) failed: %u", pszExecutable, GetLastError());
    965841            }
    966842        }
     
    968844    }
    969845    else
    970         rc = errx(9, "out of memory!");
     846        rc = errx(pCtx, 9, "out of memory!");
    971847    free(pszCmdLine);
    972848    return rc;
     
    979855 *
    980856 * @returns Exit code.
     857 * @param   pCtx                The command execution context.
    981858 * @param   pszExecutable       The child process executable.
    982859 * @param   cArgs               Number of arguments.
     
    998875 *                              is from the child or from our setup efforts.
    999876 */
    1000 static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage,
     877static int kRedirectDoSpawn(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage,
    1001878                            char **papszEnvVars, const char *pszCwd, const char *pszSavedCwd,
    1002879                            unsigned cOrders, REDIRECTORDERS *paOrders,
     
    1025902        memcpy(papszArgs, papszArgsOriginal, (cArgs + 1) * sizeof(papszArgs[0]));
    1026903    else
    1027         return errx(9, "out of memory!");
     904        return errx(pCtx, 9, "out of memory!");
    1028905
    1029906    rcExit = quote_argv(cArgs, papszArgs, fWatcomBrainDamage, 0 /*fFreeOrLeak*/);
     
    1037914        {
    1038915            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]);
    1040917            for (i = 0; i < (int)cOrders; i++)
    1041918                switch (paOrders[i].enmOrder)
    1042919                {
    1043920                    case kRedirectOrder_Close:
    1044                         warnx("debug: close %d\n", paOrders[i].fdTarget);
     921                        warnx(pCtx, "debug: close %d\n", paOrders[i].fdTarget);
    1045922                        break;
    1046923                    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);
    1048925                        break;
    1049926                    case kRedirectOrder_Open:
    1050                         warnx("debug: open '%s' (%#x) as [%d ->] %d\n",
     927                        warnx(pCtx, "debug: open '%s' (%#x) as [%d ->] %d\n",
    1051928                              paOrders[i].pszFilename, paOrders[i].fOpen, paOrders[i].fdSource, paOrders[i].fdTarget);
    1052929                        break;
    1053930                    default:
    1054                         warnx("error! invalid enmOrder=%d", paOrders[i].enmOrder);
     931                        warnx(pCtx, "error! invalid enmOrder=%d", paOrders[i].enmOrder);
    1055932                        assert(0);
    1056933                        break;
    1057934                }
    1058935            if (pszSavedCwd)
    1059                 warnx("debug: chdir %s\n", pszCwd);
     936                warnx(pCtx, "debug: chdir %s\n", pszCwd);
    1060937        }
    1061938
     
    1067944        {
    1068945            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);
    1070947        }
    1071948#endif /* KBUILD_OS_WINDOWS */
     
    1077954             */
    1078955            FILE *pWorkingStdErr = NULL;
    1079             rcExit = kRedirectExecFdOrders(cOrders, paOrders, &pWorkingStdErr);
     956            rcExit = kRedirectExecFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr);
    1080957            if (rcExit == 0)
    1081958# endif
     
    1088965                /* Windows is slightly complicated due to handles and winchildren.c. */
    1089966                HANDLE hProcess = INVALID_HANDLE_VALUE;
    1090                 rcExit = kRedirectCreateProcessWindows(pszExecutable, cArgs, papszArgs, papszEnvVars,
     967                rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
    1091968                                                       pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess);
    1092969                if (rcExit == 0)
     
    1100977                    {
    1101978                        if (cVerbosity > 0)
    1102                             warnx("debug: spawned %d", *pPidSpawned);
     979                            warnx(pCtx, "debug: spawned %d", *pPidSpawned);
    1103980                    }
    1104981                    else
     
    1106983                        DWORD dwTmp;
    1107984#  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...");
    1109986#  else
    1110987                        if (pPidSpawned)
    1111                             warn("MkWinChildCreateRedirect failed...");
     988                            warn(pCtx, "MkWinChildCreateRedirect failed...");
    1112989#  endif
    1113990                        dwTmp = WaitForSingleObject(hProcess, INFINITE);
    1114991                        if (dwTmp != WAIT_OBJECT_0)
    1115                             warn("WaitForSingleObject failed: %#x\n", dwTmp);
     992                            warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp);
    1116993
    1117994                        if (GetExitCodeProcess(hProcess, &dwTmp))
     
    1119996                        else
    1120997                        {
    1121                             warn("GetExitCodeProcess failed: %u\n", GetLastError());
     998                            warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError());
    1122999                            TerminateProcess(hProcess, 127);
    11231000                            rcExit = 127;
     
    11331010# elif defined(KBUILD_OS_OS2)
    11341011                *pPidSpawned = _spawnvpe(P_NOWAIT, pszExecutable, papszArgs, papszEnvVars);
    1135                 kRedirectRestoreFdOrders(cOrders, paOrders, &pWorkingStdErr);
     1012                kRedirectRestoreFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr);
    11361013                if (*pPidSpawned != -1)
    11371014                {
    11381015                    if (cVerbosity > 0)
    1139                         warnx("debug: spawned %d", *pPidSpawned);
     1016                        warnx(pCtx, "debug: spawned %d", *pPidSpawned);
    11401017                }
    11411018                else
    11421019                {
    1143                     rcExit = err(10, "_spawnvpe(%s) failed", pszExecutable);
     1020                    rcExit = err(pCtx, 10, "_spawnvpe(%s) failed", pszExecutable);
    11441021                    *pPidSpawned = 0;
    11451022                }
     
    11491026                {
    11501027                    if (cVerbosity > 0)
    1151                         warnx("debug: spawned %d", *pPidSpawned);
     1028                        warnx(pCtx, "debug: spawned %d", *pPidSpawned);
    11521029                }
    11531030                else
    11541031                {
    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));
    11561033                    *pPidSpawned = 0;
    11571034                }
     
    11641041# ifdef KBUILD_OS_WINDOWS
    11651042                HANDLE hProcess = INVALID_HANDLE_VALUE;
    1166                 rcExit = kRedirectCreateProcessWindows(pszExecutable, cArgs, papszArgs, papszEnvVars,
     1043                rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
    11671044                                                       pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess);
    11681045                if (rcExit == 0)
     
    11771054                        rcExit = dwWait;
    11781055                    else
    1179                         rcExit = errx(11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError());
     1056                        rcExit = errx(pCtx, 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError());
    11801057                }
    11811058
     
    11831060                errno  = 0;
    11841061                rcExit = (int)_spawnvpe(P_WAIT, pszExecutable, papszArgs, papszEnvVars);
    1185                 kRedirectRestoreFdOrders(cOrders, paOrders, &pWorkingStdErr);
     1062                kRedirectRestoreFdOrders(pCtx, cOrders, paOrders, &pWorkingStdErr);
    11861063                if (rcExit != -1 || errno == 0)
    11871064                {
    11881065                    *pfIsChildExitCode = K_TRUE;
    11891066                    if (cVerbosity > 0)
    1190                         warnx("debug: exit code: %d", rcExit);
     1067                        warnx(pCtx, "debug: exit code: %d", rcExit);
    11911068                }
    11921069                else
    1193                     rcExit = err(10, "_spawnvpe(%s) failed", pszExecutable);
     1070                    rcExit = err(pCtx, 10, "_spawnvpe(%s) failed", pszExecutable);
    11941071
    11951072# else
     
    12001077                    *pfIsChildExitCode = K_TRUE;
    12011078                    if (cVerbosity > 0)
    1202                         warnx("debug: spawned %d", pidChild);
     1079                        warnx(pCtx, "debug: spawned %d", pidChild);
    12031080
    12041081                    /* Wait for the child. */
     
    12091086                        {
    12101087                            if (cVerbosity > 0)
    1211                                 warnx("debug: %d exit code: %d", pidChild, rcExit);
     1088                                warnx(pCtx, "debug: %d exit code: %d", pidChild, rcExit);
    12121089                            break;
    12131090                        }
     
    12181095                           )
    12191096                        {
    1220                             rcExit = err(11, "waitpid failed");
     1097                            rcExit = err(pCtx, 11, "waitpid failed");
    12211098                            kill(pidChild, SIGKILL);
    12221099                            break;
     
    12251102                }
    12261103                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));
    12281105# endif
    12291106#endif /* !KMK */
     
    12381115        {
    12391116            if (chdir(pszSavedCwd) < 0)
    1240                 warn("Failed to restore directory to '%s'", pszSavedCwd);
     1117                warn(pCtx, "Failed to restore directory to '%s'", pszSavedCwd);
    12411118        }
    12421119#endif
     
    12441121#ifdef _MSC_VER
    12451122    else
    1246         rcExit = errx(9, "quite_argv failed: %u", rcExit);
     1123        rcExit = errx(pCtx, 9, "quite_argv failed: %u", rcExit);
    12471124
    12481125    /* Restore the original argv strings, freeing the quote_argv replacements. */
     
    12601137 * The function that does almost everything here... ugly.
    12611138 */
    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
     1139int kmk_builtin_redirect(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned)
    12671140{
    12681141    int             rcExit = 0;
     
    12901163
    12911164
    1292     g_progname = argv[0];
    1293 
    12941165    if (argc <= 1)
    1295         return usage(stderr, argv[0]);
     1166        return kmk_redirect_usage(pCtx, 1);
    12961167
    12971168    /*
     
    13051176    { /* likely */ }
    13061177    else
    1307         return err(9, "getcwd failed");
     1178        return err(pCtx, 9, "getcwd failed");
    13081179
    13091180    /* We start out with a read-only enviornment from kmk or the crt, and will
     
    13211192    rcExit = posix_spawn_file_actions_init(&FileActions);
    13221193    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));
    13241195#endif
    13251196
     
    13841255                else
    13851256                {
    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);
    13881259                    break;
    13891260                }
     
    13961267            if (chOpt == 'h')
    13971268            {
    1398                 usage(stdout, argv[0]);
     1269                kmk_redirect_usage(pCtx, 0);
    13991270                rcExit = -1;
    14001271                break;
     
    14251296                else
    14261297                {
    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);
    14291300                    break;
    14301301                }
     
    14571328                            if (rc)
    14581329                            {
    1459                                 rcExit = errx(9, "DosQueryExtLIBPATH(,%u) failed: %lu", ulVar, rc);
     1330                                rcExit = errx(pCtx, 9, "DosQueryExtLIBPATH(,%u) failed: %lu", ulVar, rc);
    14601331                                free(apszSavedLibPaths[ulVar]);
    14611332                                apszSavedLibPaths[ulVar] = NULL;
     
    14631334                        }
    14641335                        else
    1465                             rcExit = errx(9, "out of memory!");
     1336                            rcExit = errx(pCtx, 9, "out of memory!");
    14661337                    }
    14671338                    if (rcExit == 0)
     
    14691340                        rc = DosSetExtLIBPATH(pchEqual + 1, ulVar);
    14701341                        if (rc)
    1471                             rcExit = errx(9, "error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu",
     1342                            rcExit = errx(pCtx, 9, "error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu",
    14721343                                          pchEqual, pchEqual - pszValue, pchEqual + 1, ulVar, rc);
    14731344                    }
     
    14801351                {
    14811352                    if (pchEqual[1] != '\0')
    1482                         rcExit = kBuiltinOptEnvSet(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1353                        rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    14831354                    else
    14841355                    {
     
    14871358                        {
    14881359                            pszCopy[pchEqual - pszValue] = '\0';
    1489                             rcExit = kBuiltinOptEnvUnset(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszCopy);
     1360                            rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszCopy);
    14901361                            free(pszCopy);
    14911362                        }
    14921363                        else
    1493                             rcExit = errx(1, "out of memory!");
     1364                            rcExit = errx(pCtx, 1, "out of memory!");
    14941365                    }
    14951366                    continue;
     
    15081379                    || strcmp(pszValue, "ENDLIBPATH") == 0
    15091380                    || 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);
    15111382                else
    15121383#endif
    15131384                if (chOpt == 'A')
    1514                     rcExit = kBuiltinOptEnvAppend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1385                    rcExit = kBuiltinOptEnvAppend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    15151386                else
    1516                     rcExit = kBuiltinOptEnvPrepend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1387                    rcExit = kBuiltinOptEnvPrepend(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    15171388                continue;
    15181389            }
     
    15271398                    || strcmp(pszValue, "ENDLIBPATH") == 0
    15281399                    || 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);
    15301401                else
    15311402#endif
    1532                     rcExit = kBuiltinOptEnvUnset(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
     1403                    rcExit = kBuiltinOptEnvUnset(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
    15331404                continue;
    15341405            }
     
    15401411                || chOpt == 'i' /* GNU env compatibility. */ )
    15411412            {
    1542                 rcExit = kBuiltinOptEnvZap(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity);
     1413                rcExit = kBuiltinOptEnvZap(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity);
    15431414                continue;
    15441415            }
     
    15521423                    pszSavedCwd = strdup(szCwd);
    15531424                if (pszSavedCwd)
    1554                     rcExit = kBuiltinOptChDir(szCwd, cbCwdBuf, pszValue);
     1425                    rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue);
    15551426                else
    1556                     rcExit = err(9, "out of memory!");
     1427                    rcExit = err(pCtx, 9, "out of memory!");
    15571428                continue;
    15581429            }
     
    15931464            else
    15941465            {
    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));
    15961467                break;
    15971468            }
     
    16051476                fd = (int)strtol(pszValue, &pszTmp, 0);
    16061477                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);
    16081479                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);
    16101481#ifdef ONLY_TARGET_STANDARD_HANDLES
    16111482                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);
    16131484#endif
    16141485                else
     
    16201491                    rcExit = posix_spawn_file_actions_addclose(&FileActions, fd);
    16211492                    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));
    16231494#endif
    16241495                }
     
    16321503                fd = (int)strtol(pszValue, &pszEqual, 0);
    16331504                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);
    16351506                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);
    16371508#ifdef ONLY_TARGET_STANDARD_HANDLES
    16381509                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);
    16401511#endif
    16411512                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);
    16431514                else
    16441515                {
     
    16461517                    int fdSource = (int)strtol(++pszEqual, &pszEnd, 0);
    16471518                    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);
    16491520                    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);
    16511522                    else
    16521523                    {
     
    16581529                        rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdSource, fd);
    16591530                        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));
    16611532#endif
    16621533                    }
     
    17131584
    17141585                    case '+':
    1715                         rcExit = errx(2, "syntax error: Unexpected '+' in '%s'", argv[iArg]);
     1586                        rcExit = errx(pCtx, 2, "syntax error: Unexpected '+' in '%s'", argv[iArg]);
    17161587                        continue;
    17171588
     
    17801651                        fd = (int)strtol(pszValue, &pszArg, 0);
    17811652                        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]);
    17831654                        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]);
    17851656#ifdef ONLY_TARGET_STANDARD_HANDLES
    17861657                        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);
    17881659#endif
    17891660                        else
     
    17951666                     */
    17961667                    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]);
    17981669                        continue;
    17991670                }
     
    18061677                    if (*pszArg != ':' && *pszArg != '=')
    18071678                    {
    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')",
    18091680                                      pszArg, argv[iArg]);
    18101681                        break;
     
    18161687                else
    18171688                {
    1818                     rcExit = errx(2, "syntax error: missing filename argument.");
     1689                    rcExit = errx(pCtx, 2, "syntax error: missing filename argument.");
    18191690                    break;
    18201691                }
     
    18251696                 * this for windows anyway, just do it the same way everywhere.
    18261697                 */
    1827                 fdOpened = kRedirectOpenWithoutConflict(pszArg, fOpen, 0666, cOrders, aOrders,
     1698                fdOpened = kRedirectOpenWithoutConflict(pCtx, pszArg, fOpen, 0666, cOrders, aOrders,
    18281699                                                        aOrders[cOrders].fRemoveOnFailure, fd);
    18291700                if (fdOpened >= 0)
     
    18411712                        rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdOpened, fd);
    18421713                        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",
    18441715                                         fdOpened, fd, pszArg, strerror(rcExit));
    18451716                    }
     
    18521723        else
    18531724        {
    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);
    18561727        }
    18571728    }
     
    18671738         * Do the spawning in a separate function (main is far to large as it is by now).
    18681739         */
    1869         rcExit = kRedirectDoSpawn(pszExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage,
     1740        rcExit = kRedirectDoSpawn(pCtx, pszExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage,
    18701741                                  papszEnvVars,
    18711742                                  szCwd, pszSavedCwd,
     
    18821753    else if (rcExit == 0)
    18831754    {
    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);
    18861757    }
    18871758    /* Help and version sets rcExit to -1. Change it to zero. */
     
    19051776            APIRET rc = DosSetExtLIBPATH(apszSavedLibPaths[ulLibPath], ulLibPath);
    19061777            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!",
    19081779                      apszSavedLibPaths[ulLibPath], ulLibPath, rc);
    19091780            free(apszSavedLibPaths[ulLibPath]);
     
    19141785}
    19151786
     1787#ifdef KMK_BUILTIN_STANDALONE
     1788int 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  
    4242#endif
    4343
     44
     45/*********************************************************************************************************************************
     46*   Header Files                                                                                                                 *
     47*********************************************************************************************************************************/
    4448#include "config.h"
    4549#include <sys/stat.h>
     
    9094#include "k/kDefs.h"    /* for K_OS */
    9195
     96
     97/*********************************************************************************************************************************
     98*   Defined Constants And Macros                                                                                                 *
     99*********************************************************************************************************************************/
    92100#if defined(__EMX__) || defined(KBUILD_OS_WINDOWS)
    93101# define IS_SLASH(ch)   ( (ch) == '/' || (ch) == '\\' )
     
    110118#endif
    111119
    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*********************************************************************************************************************************/
     132typedef struct RMINSTANCE
     133{
     134    PKMKBUILTINCTX pCtx;
     135    int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
    115136#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;
     142typedef RMINSTANCE *PRMINSTANCE;
     143
     144
     145/*********************************************************************************************************************************
     146*   Global Variables                                                                                                             *
     147*********************************************************************************************************************************/
    123148static struct option long_options[] =
    124149{
     
    137162
    138163
    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*********************************************************************************************************************************/
     167extern void bsd_strmode(mode_t mode, char *p); /* strmode.c */
     168
     169static int      check(PRMINSTANCE, char *, char *, struct stat *);
     170static void     checkdot(PRMINSTANCE, char **);
     171static int      rm_file(PRMINSTANCE, char **);
     172static int      rm_overwrite(PRMINSTANCE, char *, struct stat *);
     173static int      rm_tree(PRMINSTANCE, char **);
     174static int      usage(PKMKBUILTINCTX, int);
     175
    153176
    154177
     
    161184 */
    162185int
    163 kmk_builtin_rm(int argc, char *argv[], char **envp)
    164 {
     186kmk_builtin_rm(int argc, char *argv[], char **envp, PKMKBUILTINCTX pCtx)
     187{
     188        RMINSTANCE This;
    165189        int ch, rflag;
    166190
    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;
    170201#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);
    175206
    176207        /* kmk: reset getopt and set program name. */
    177         g_progname = argv[0];
    178208        opterr = 1;
    179209        optarg = NULL;
     
    181211        optind = 0; /* init */
    182212
    183         Pflag = rflag = 0;
     213        rflag = 0;
    184214        while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1)
    185                 switch(ch) {
     215                switch (ch) {
    186216                case 'd':
    187                         dflag = 1;
     217                        This.dflag = 1;
    188218                        break;
    189219                case 'f':
    190                         fflag = 1;
    191                         iflag = 0;
     220                        This.fflag = 1;
     221                        This.iflag = 0;
    192222                        break;
    193223                case 'i':
    194                         fflag = 0;
    195                         iflag = 1;
     224                        This.fflag = 0;
     225                        This.iflag = 1;
    196226                        break;
    197227                case 'P':
    198                         Pflag = 1;
     228                        This.Pflag = 1;
    199229                        break;
    200230                case 'R':
     
    205235                        break;
    206236                case 'v':
    207                         vflag = 1;
     237                        This.vflag = 1;
    208238                        break;
    209239#ifdef FTS_WHITEOUT
    210240                case 'W':
    211                         Wflag = 1;
     241                        This.Wflag = 1;
    212242                        break;
    213243#endif
    214244                case 261:
    215                         kBuildProtectionTerm(&g_ProtData);
    216                         usage(stdout);
     245                        kBuildProtectionTerm(&This.g_ProtData);
     246                        usage(pCtx, 0);
    217247                        return 0;
    218248                case 262:
    219                         kBuildProtectionTerm(&g_ProtData);
     249                        kBuildProtectionTerm(&This.g_ProtData);
    220250                        return kbuild_version(argv[0]);
    221251                case 263:
    222                         kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
     252                        kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
    223253                        break;
    224254                case 264:
    225                         kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
     255                        kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
    226256                        break;
    227257                case 265:
    228                         kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
     258                        kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL);
    229259                        break;
    230260                case 266:
    231                         kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
     261                        kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL);
    232262                        break;
    233263                case 267:
    234                         if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
    235                             kBuildProtectionTerm(&g_ProtData);
     264                        if (kBuildProtectionSetDepth(&This.g_ProtData, optarg)) {
     265                            kBuildProtectionTerm(&This.g_ProtData);
    236266                            return 1;
    237267                        }
     
    239269#ifdef KBUILD_OS_WINDOWS
    240270                case 268:
    241                         fUseNtDeleteFile = 1;
     271                        This.fUseNtDeleteFile = 1;
    242272                        break;
    243273#endif
    244274                case '?':
    245275                default:
    246                         kBuildProtectionTerm(&g_ProtData);
    247                         return usage(stderr);
     276                        kBuildProtectionTerm(&This.g_ProtData);
     277                        return usage(pCtx, 1);
    248278                }
    249279        argc -= optind;
     
    251281
    252282        if (argc < 1) {
    253                 kBuildProtectionTerm(&g_ProtData);
    254                 if (fflag)
     283                kBuildProtectionTerm(&This.g_ProtData);
     284                if (This.fflag)
    255285                        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();
    262292
    263293                if (*argv) {
    264                         stdin_ok = isatty(STDIN_FILENO);
     294                        This.stdin_ok = isatty(STDIN_FILENO);
    265295                        if (rflag)
    266                                 eval |= rm_tree(argv);
     296                                This.eval |= rm_tree(&This, argv);
    267297                        else
    268                                 eval |= rm_file(argv);
     298                                This.eval |= rm_file(&This, argv);
    269299                }
    270300        } 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;
    276306}
    277307
     308#ifdef KMK_BUILTIN_STANDALONE
     309int 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
    278316static int
    279 rm_tree(char **argv)
     317rm_tree(PRMINSTANCE pThis, char **argv)
    280318{
    281319        FTS *fts;
     
    291329        int i;
    292330        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])) {
    294332                        return 1;
    295333                }
     
    300338         * (-i) or can't ask anyway (stdin_ok), don't stat the file.
    301339         */
    302         needstat = !uid || (!fflag && !iflag && stdin_ok);
     340        needstat = !pThis->uid || (!pThis->fflag && !pThis->iflag && pThis->stdin_ok);
    303341
    304342        /*
     
    312350                flags |= FTS_NOSTAT;
    313351#ifdef FTS_WHITEOUT
    314         if (Wflag)
     352        if (pThis->Wflag)
    315353                flags |= FTS_WHITEOUT;
    316354#endif
    317355        if (!(fts = fts_open(argv, flags, NULL))) {
    318                 return err(1, "fts_open");
     356                return err(pThis->pCtx, 1, "fts_open");
    319357        }
    320358        while ((p = fts_read(fts)) != NULL) {
     
    322360                switch (p->fts_info) {
    323361                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));
    329365                        continue;
    330366                case FTS_ERR:
    331367                        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));
    333369                case FTS_NS:
    334370                        /*
     
    338374                        if (!needstat)
    339375                                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));
    345379                        continue;
    346380                case FTS_D:
    347381                        /* 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)) {
    350383                                (void)fts_set(fts, p, FTS_SKIP);
    351384                                p->fts_number = SKIPPED;
    352385                        }
    353386#ifdef UF_APPEND
    354                         else if (!uid &&
     387                        else if (!pThis->uid &&
    355388                                 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
    356389                                 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
     
    366399                        break;
    367400                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))
    370402                                continue;
    371403                }
     
    374406                 * Protect against deleting root files and directories.
    375407                 */
    376                 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {
     408                if (kBuildProtectionEnforce(&pThis->g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {
    377409                        fts_close(fts);
    378410                        return 1;
     
    381413                rval = 0;
    382414#ifdef UF_APPEND
    383                 if (!uid &&
     415                if (!pThis->uid &&
    384416                    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
    385417                    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
     
    405437                                rval = rmdir(p->fts_accpath);
    406438#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);
    411442#if defined(KMK) && defined(KBUILD_OS_WINDOWS)
    412443                                        if (rval == 0) {
     
    423454                        case FTS_W:
    424455                                rval = undelete(p->fts_accpath);
    425                                 if (rval == 0 && (fflag && errno == ENOENT)) {
     456                                if (rval == 0 && (pThis->fflag && errno == ENOENT)) {
    426457                                        if (vflag)
    427                                                 (void)printf("%s\n",
    428                                                     p->fts_path);
     458                                                kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", p->fts_path);
    429459                                        continue;
    430460                                }
     
    438468                                 * the file, it can't be unlinked.
    439469                                 */
    440                                 if (fflag)
     470                                if (pThis->fflag)
    441471                                        continue;
    442472                                /* FALLTHROUGH */
    443473                        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))
    446476                                                continue;
    447477#ifdef KBUILD_OS_WINDOWS
     
    455485#endif
    456486
    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);
    461490                                        continue;
    462491                                }
     
    468497err:
    469498#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));
    472500        }
    473501        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));
    476503        }
    477504        fts_close(fts);
    478         return eval;
     505        return pThis->eval;
    479506}
    480507
    481508static int
    482 rm_file(char **argv)
     509rm_file(PRMINSTANCE pThis, char **argv)
    483510{
    484511        struct stat sb;
     
    491518        int i;
    492519        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]))
    494521                        return 1;
    495522        }
     
    504531                if (lstat(f, &sb)) {
    505532#ifdef FTS_WHITEOUT
    506                         if (Wflag) {
     533                        if (pThis->Wflag) {
    507534                                sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
    508535                        } else {
     
    510537                        {
    511538#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));
    516542                                continue;
    517543                        }
    518544#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;
    522548                        continue;
    523549#endif
    524550                }
    525551
    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);
    529554                        continue;
    530555                }
    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))
    532557                        continue;
    533558                rval = 0;
     
    546571                                operation = "rmdir";
    547572                        } else {
    548                                 if (Pflag)
    549                                         if (!rm_overwrite(f, &sb))
     573                                if (pThis->Pflag)
     574                                        if (!rm_overwrite(pThis, f, &sb))
    550575                                                continue;
    551576#ifndef KBUILD_OS_WINDOWS
     
    553578                                operation = "unlink";
    554579#else
    555                                 if (fUseNtDeleteFile) {
     580                                if (pThis->fUseNtDeleteFile) {
    556581                                        rval = birdUnlinkForcedFast(f);
    557582                                        operation = "NtDeleteFile";
     
    563588                        }
    564589                }
    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;
    573596}
    574597
     
    585608 */
    586609static int
    587 rm_overwrite(char *file, struct stat *sbp)
     610rm_overwrite(PRMINSTANCE pThis, char *file, struct stat *sbp)
    588611{
    589612        struct stat sb;
     
    595618        char *buf = NULL;
    596619        const char *operation = "lstat";
     620        int error;
    597621
    598622        fd = -1;
     
    605629                return (1);
    606630        operation = "open";
    607         if ((fd = open(file, O_WRONLY, 0)) == -1)
     631        if ((fd = open(file, O_WRONLY | KMK_OPEN_NO_INHERIT, 0)) == -1)
    608632                goto err;
    609633#ifdef HAVE_FSTATFS
     
    616640        bsize = 1024;
    617641#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        }
    620647
    621648#define PASS(byte) {                                                    \
     
    643670        operation = "fsync/close";
    644671
    645 err:    eval = 1;
     672err:    pThis->eval = 1;
     673        error = errno;
    646674        if (buf)
    647675                free(buf);
    648676        if (fd != -1)
    649677                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));
    651679        return (0);
    652680}
     
    654682
    655683static int
    656 check(char *path, char *name, struct stat *sp)
     684check(PRMINSTANCE pThis, char *path, char *name, struct stat *sp)
    657685{
    658686        int ch, first;
     
    660688
    661689        /* 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);
    664692        else {
    665693                /*
     
    672700                 * barf later.
    673701                 */
    674                 if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
     702                if (!pThis->stdin_ok || S_ISLNK(sp->st_mode) || pThis->Pflag ||
    675703                    (!access(name, W_OK) &&
    676704#ifdef SF_APPEND
    677705                    !(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))
    679707#else
    680708                    1)
     
    684712                bsd_strmode(sp->st_mode, modep);
    685713#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                }
    688718                (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
    689719                              modep + 1, modep[9] == ' ' ? "" : " ",
     
    710740#define ISDOT(a)        ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
    711741static void
    712 checkdot(char **argv)
     742checkdot(PRMINSTANCE pThis, char **argv)
    713743{
    714744        char *p, **save, **t;
     
    737767                if (ISDOT(p)) {
    738768                        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;
    741771                        for (save = t; (t[0] = t[1]) != NULL; ++t)
    742772                                continue;
     
    748778
    749779static int
    750 usage(FILE *pf)
    751 {
    752         fprintf(pf,
    753                 "usage: %s [options] file ...\n"
    754                 "   or: %s --help\n"
    755                 "   or: %s --version\n"
    756                 "\n"
    757                 "Options:\n"
    758                 "   -f\n"
    759                 "       Attempt to remove files without prompting, regardless of the file\n"
    760                 "       permission. Ignore non-existing files. Overrides previous -i's.\n"
    761                 "   -i\n"
    762                 "       Prompt for each file. Always.\n"
    763                 "   -d\n"
    764                 "       Attempt to remove directories as well as other kinds of files.\n"
    765                 "   -P\n"
    766                 "       Overwrite regular files before deleting; three passes: ff,0,ff\n"
    767                 "   -R\n"
    768                 "       Attempt to remove the file hierachy rooted in each file argument.\n"
    769                 "       This option implies -d and file protection.\n"
    770                 "   -v\n"
    771                 "       Be verbose, show files as they are removed.\n"
    772                 "   -W\n"
    773                 "       Undelete without files.\n"
    774                 "   --disable-protection\n"
    775                 "       Will disable the protection file protection applied with -R.\n"
    776                 "   --enable-protection\n"
    777                 "       Will enable the protection file protection applied with -R.\n"
    778                 "   --enable-full-protection\n"
    779                 "       Will enable the protection file protection for all operations.\n"
    780                 "   --disable-full-protection\n"
    781                 "       Will disable the protection file protection for all operations.\n"
    782                 "   --protection-depth\n"
    783                 "       Number or path indicating the file protection depth. Default: %d\n"
    784                 "\n"
    785                 "Environment:\n"
    786                 "    KMK_RM_DISABLE_PROTECTION\n"
    787                 "       Same as --disable-protection. Overrides command line.\n"
    788                 "    KMK_RM_ENABLE_PROTECTION\n"
    789                 "       Same as --enable-protection. Overrides everyone else.\n"
    790                 "    KMK_RM_ENABLE_FULL_PROTECTION\n"
    791                 "       Same as --enable-full-protection. Overrides everyone else.\n"
    792                 "    KMK_RM_DISABLE_FULL_PROTECTION\n"
    793                 "       Same as --disable-full-protection. Overrides command line.\n"
    794                 "    KMK_RM_PROTECTION_DEPTH\n"
    795                 "       Same as --protection-depth. Overrides command line.\n"
    796                 "\n"
    797                 "The file protection of the top %d layers of the file hierarchy is there\n"
    798                 "to try prevent makefiles from doing bad things to your system. This\n"
    799                 "protection is not bulletproof, but should help prevent you from shooting\n"
    800                 "yourself in the foot.\n"
    801                 ,
    802                 g_progname, g_progname, g_progname,
    803                 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
     780usage(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());
    804834        return EX_USAGE;
    805835}
     836
  • trunk/src/kmk/kmkbuiltin/rmdir.c

    r2912 r3192  
    4444#endif
    4545
     46
     47/*********************************************************************************************************************************
     48*   Header Files                                                                                                                 *
     49*********************************************************************************************************************************/
    4650#include "config.h"
    4751#include "err.h"
     
    6064# include "mscfakes.h"
    6165#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*********************************************************************************************************************************/
     71typedef 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;
     79typedef RMDIRINSTANCE *PRMDIRINSTANCE;
     80
     81
     82/*********************************************************************************************************************************
     83*   Global Variables                                                                                                             *
     84*********************************************************************************************************************************/
    7485static struct option long_options[] =
    7586{
     
    8495
    8596
     97
     98/*********************************************************************************************************************************
     99*   Internal Functions                                                                                                           *
     100*********************************************************************************************************************************/
     101#if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS)
     102extern int dir_cache_deleted_directory(const char *pszDir);
     103#endif
     104static int rm_path(PRMDIRINSTANCE, char *);
     105static int usage(PKMKBUILTINCTX, int);
     106
     107
    86108int
    87 kmk_builtin_rmdir(int argc, char *argv[], char **envp)
    88 {
     109kmk_builtin_rmdir(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
     110{
     111        RMDIRINSTANCE This;
    89112        int ch, errors;
    90113
    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;
    93120
    94121        /* kmk: reset getopt and set progname */
    95         g_progname = argv[0];
    96122        opterr = 1;
    97123        optarg = NULL;
     
    101127                switch(ch) {
    102128                case 'p':
    103                         pflag = 1;
     129                        This.pflag = 1;
    104130                        break;
    105131                case 'v':
    106                         vflag = 1;
     132                        This.vflag = 1;
    107133                        break;
    108134                case 260:
    109                         ignore_fail_on_non_empty = 1;
     135                        This.ignore_fail_on_non_empty = 1;
    110136                        break;
    111137                case 261:
    112                         ignore_fail_on_not_exist = 1;
     138                        This.ignore_fail_on_not_exist = 1;
    113139                        break;
    114140                case 262:
    115                         usage(stdout);
     141                        usage(pCtx, 0);
    116142                        return 0;
    117143                case 263:
     
    119145                case '?':
    120146                default:
    121                         return usage(stderr);
     147                        return usage(pCtx, 1);
    122148                }
    123149        argc -= optind;
     
    129155        for (errors = 0; *argv; argv++) {
    130156                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);
    134162                                errors = 1;
    135163                                continue;
    136164                        }
    137                         if (!ignore_fail_on_not_exist || errno != ENOENT)
     165                        if (!This.ignore_fail_on_not_exist || errno != ENOENT)
    138166                                continue;
    139167                        /* (only ignored doesn't exist errors fall thru) */
    140168                } else {
    141 #if defined(KMK) && defined(KBUILD_OS_WINDOWS)
     169#if !defined(KMK_BUILTIN_STANDALONE) && defined(KBUILD_OS_WINDOWS)
    142170                        dir_cache_deleted_directory(*argv);
    143171#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);
    150177        }
    151178
     
    153180}
    154181
     182#ifdef KMK_BUILTIN_STANDALONE
     183int 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
    155190static int
    156 rm_path(char *path)
     191rm_path(PRMDIRINSTANCE pThis, char *path)
    157192{
    158193        char *p;
     
    186221
    187222                if (rmdir(path) < 0) {
    188                         if (   ignore_fail_on_non_empty
     223                        if (   pThis->ignore_fail_on_non_empty
    189224                            && (   errno == ENOTEMPTY || errno == EPERM || errno == EACCES || errno == EINVAL || errno == EEXIST))
    190225                                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);
    193228                                return (1);
    194229                        }
     
    199234                }
    200235#endif
    201                 if (vflag)
    202                         printf("%s\n", path);
     236                if (pThis->vflag)
     237                        kmk_builtin_ctx_printf(pThis->pCtx, 0, "%s\n", path);
    203238        }
    204239
     
    207242
    208243static 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);
     244usage(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);
    215251        return 1;
    216252}
     253
  • trunk/src/kmk/kmkbuiltin/sleep.c

    r2413 r3192  
    4040#endif
    4141
     42#include "err.h"
    4243#include "../kmkbuiltin.h"
    4344
    4445
    45 static const char *name(const char *pszName)
     46static int kmk_builtin_sleep_usage(PKMKBUILTINCTX pCtx, int fIsErr)
    4647{
    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);
    7461    return 1;
    7562}
    7663
    7764
    78 int kmk_builtin_sleep(int argc, char **argv, char **envp)
     65int kmk_builtin_sleep(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    7966{
    8067    long cMsToSleep;
     
    8875     */
    8976    if (argc != 2)
    90         return usage(stderr, argv[0]);
     77        return kmk_builtin_sleep_usage(pCtx, 1);
    9178
    9279    /* help request */
     
    9683        || !strcmp(argv[1], "--help"))
    9784    {
    98         usage(stdout, argv[0]);
     85        kmk_builtin_sleep_usage(pCtx, 0);
    9986        return 0;
    10087    }
     
    121108    cMsToSleep = strtol(pszInterval, &pszSuff, 0);
    122109    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);
    127111
    128112    while (isspace(*pszSuff))
     
    142126        {
    143127            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);
    148129            i++;
    149130        }
     
    160141            ulFactor = 24*60*60*1000;
    161142        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);
    166144    }
    167145
     
    169147    cMsToSleep *= ulFactor;
    170148    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");
    175150
    176151    /*
     
    195170}
    196171
     172#ifdef KMK_BUILTIN_STANDALONE
     173int 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  
    1616#endif*/
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include "config.h"
    1923#include <sys/stat.h>
     
    3236# include <process.h>
    3337# include "mscfakes.h"
     38# include "quote_argv.h"
    3439#else
    3540# include <unistd.h>
     
    4045#include "kmkbuiltin.h"
    4146
     47
     48/*********************************************************************************************************************************
     49*   Defined Constants And Macros                                                                                                 *
     50*********************************************************************************************************************************/
    4251#ifndef __arraycount
    4352# define __arraycount(a)        ( sizeof(a) / sizeof(a[0]) )
     
    4554
    4655
     56/*********************************************************************************************************************************
     57*   Structures and Typedefs                                                                                                      *
     58*********************************************************************************************************************************/
    4759/* test(1) accepts the following grammar:
    4860        oexpr   ::= aexpr | aexpr "-o" oexpr ;
     
    118130};
    119131
     132/** kmk_test instance data.   */
     133typedef struct TESTINSTANCE
     134{
     135    PKMKBUILTINCTX pCtx;
     136    char **t_wp;
     137    struct t_op const *t_wp_op;
     138} TESTINSTANCE;
     139typedef TESTINSTANCE *PTESTINSTANCE;
     140
     141
     142/*********************************************************************************************************************************
     143*   Global Variables                                                                                                             *
     144*********************************************************************************************************************************/
    120145static const struct t_op cop[] = {
    121146        {"!",   UNOT,   BUNOP},
     
    169194};
    170195
    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*********************************************************************************************************************************/
     200static int syntax(PTESTINSTANCE, const char *, const char *);
     201static int oexpr(PTESTINSTANCE, enum token);
     202static int aexpr(PTESTINSTANCE, enum token);
     203static int nexpr(PTESTINSTANCE, enum token);
     204static int primary(PTESTINSTANCE, enum token);
     205static int binop(PTESTINSTANCE);
    180206static int test_access(struct stat *, mode_t);
    181207static int filstat(char *, enum token);
    182 static enum token t_lex(char *);
    183 static int isoperand(void);
    184 static int getn(const char *);
     208static enum token t_lex(PTESTINSTANCE, char *);
     209static int isoperand(PTESTINSTANCE);
     210static int getn(PTESTINSTANCE, const char *);
    185211static int newerf(const char *, const char *);
    186212static int olderf(const char *, const char *);
    187213static int equalf(const char *, const char *);
    188 static int usage(const char *);
    189 
    190 #if !defined(kmk_builtin_test) || defined(ELECTRIC_HEAP)
     214static int usage(PKMKBUILTINCTX, int);
     215
     216#if !defined(KMK_BUILTIN_STANDALONE) || defined(ELECTRIC_HEAP)
    191217extern void *xmalloc(unsigned int);
    192218#else
     
    195221    void *p = malloc(sz);
    196222    if (!p) {
    197             fprintf(stderr, "%s: malloc(%u) failed\n", g_progname, sz);
     223            fprintf(stderr, "kmk_test: malloc(%u) failed\n", sz);
    198224            exit(1);
    199225    }
     
    202228#endif
    203229
    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
     232int kmk_builtin_test(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, char ***ppapszArgvSpawn)
     233{
     234        TESTINSTANCE This;
    210235        int res;
    211236        char **argv_spawn;
    212237        int i;
    213238
    214         g_progname = argv[0];
     239        This.pCtx = pCtx;
     240        This.t_wp = NULL;
     241        This.t_wp_op = NULL;
    215242
    216243        /* look for the '--', '--help' and '--version'. */
     
    235262                        }
    236263                        if (!strcmp(argv[i], "--help"))
    237                                 return usage(argv[0]);
     264                                return usage(pCtx, 0);
    238265                        if (!strcmp(argv[i], "--version"))
    239266                                return kbuild_version(argv[0]);
     
    242269
    243270        /* 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 */
    245272                if (strcmp(argv[--argc], "]"))
    246                         return errx(1, "missing ]");
     273                        return errx(pCtx, 1, "missing ]");
    247274                argv[argc] = NULL;
    248275        }
     
    252279                res = 1;
    253280        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");
    258285                if (res == -42)
    259286                        return 1; /* don't mix syntax errors with the argv_spawn ignore */
     
    266293                        res = 0; /* ignored */
    267294                else {
    268 #ifdef kmk_builtin_test
     295#ifdef KMK_BUILTIN_STANDALONE
    269296                        /* try exec the specified process */
    270297# 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");
    274309# else
    275310                        execvp(argv_spawn[0], argv_spawn);
     
    305340}
    306341
    307 static int
    308 syntax(const char *op, const char *msg)
     342#ifdef KMK_BUILTIN_STANDALONE
     343int 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
     350static int
     351syntax(PTESTINSTANCE pThis, const char *op, const char *msg)
    309352{
    310353
    311354        if (op && *op)
    312                 errx(1, "%s: %s", op, msg);
     355                errx(pThis->pCtx, 1, "%s: %s", op, msg);
    313356        else
    314                 errx(1, "%s", msg);
     357                errx(pThis->pCtx, 1, "%s", msg);
    315358        return -42;
    316359}
    317360
    318361static int
    319 oexpr(enum token n)
     362oexpr(PTESTINSTANCE pThis, enum token n)
    320363{
    321364        int res;
    322365
    323         res = aexpr(n);
    324         if (res == -42 || *t_wp == NULL)
     366        res = aexpr(pThis, n);
     367        if (res == -42 || *pThis->t_wp == NULL)
    325368                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)));
    328371                return res2 != -42 ? res2 || res : res2;
    329372        }
    330         t_wp--;
     373        pThis->t_wp--;
    331374        return res;
    332375}
    333376
    334377static int
    335 aexpr(enum token n)
     378aexpr(PTESTINSTANCE pThis, enum token n)
    336379{
    337380        int res;
    338381
    339         res = nexpr(n);
    340         if (res == -42 || *t_wp == NULL)
     382        res = nexpr(pThis, n);
     383        if (res == -42 || *pThis->t_wp == NULL)
    341384                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)));
    344387                return res2 != -42 ? res2 && res : res2;
    345388        }
    346         t_wp--;
     389        pThis->t_wp--;
    347390        return res;
    348391}
    349392
    350393static int
    351 nexpr(enum token n)
     394nexpr(PTESTINSTANCE pThis, enum token n)
    352395{
    353396        if (n == UNOT) {
    354                 int res = nexpr(t_lex(*++t_wp));
     397                int res = nexpr(pThis, t_lex(pThis, *++(pThis->t_wp)));
    355398                return res != -42 ? !res : res;
    356399        }
    357         return primary(n);
    358 }
    359 
    360 static int
    361 primary(enum token n)
     400        return primary(pThis, n);
     401}
     402
     403static int
     404primary(PTESTINSTANCE pThis, enum token n)
    362405{
    363406        enum token nn;
     
    367410                return 0;               /* missing expression */
    368411        if (n == LPAREN) {
    369                 if ((nn = t_lex(*++t_wp)) == RPAREN)
     412                if ((nn = t_lex(pThis, *++(pThis->t_wp))) == RPAREN)
    370413                        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");
    374417                return res;
    375418        }
    376         if (t_wp_op && t_wp_op->op_type == UNOP) {
     419        if (pThis->t_wp_op && pThis->t_wp_op->op_type == UNOP) {
    377420                /* 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");
    380423                switch (n) {
    381424                case STREZ:
    382                         return strlen(*t_wp) == 0;
     425                        return strlen(*pThis->t_wp) == 0;
    383426                case STRNZ:
    384                         return strlen(*t_wp) != 0;
     427                        return strlen(*pThis->t_wp) != 0;
    385428                case FILTT:
    386                         return isatty(getn(*t_wp));
     429                        return isatty(getn(pThis, *pThis->t_wp));
    387430                default:
    388                         return filstat(*t_wp, n);
     431                        return filstat(*pThis->t_wp, n);
    389432                }
    390433        }
    391434
    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
     442static int
     443binop(PTESTINSTANCE pThis)
    401444{
    402445        const char *opnd1, *opnd2;
    403446        struct t_op const *op;
    404447
    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");
    411454
    412455        switch (op->op_num) {
     
    420463                return strcmp(opnd1, opnd2) > 0;
    421464        case INTEQ:
    422                 return getn(opnd1) == getn(opnd2);
     465                return getn(pThis, opnd1) == getn(pThis, opnd2);
    423466        case INTNE:
    424                 return getn(opnd1) != getn(opnd2);
     467                return getn(pThis, opnd1) != getn(pThis, opnd2);
    425468        case INTGE:
    426                 return getn(opnd1) >= getn(opnd2);
     469                return getn(pThis, opnd1) >= getn(pThis, opnd2);
    427470        case INTGT:
    428                 return getn(opnd1) > getn(opnd2);
     471                return getn(pThis, opnd1) > getn(pThis, opnd2);
    429472        case INTLE:
    430                 return getn(opnd1) <= getn(opnd2);
     473                return getn(pThis, opnd1) <= getn(pThis, opnd2);
    431474        case INTLT:
    432                 return getn(opnd1) < getn(opnd2);
     475                return getn(pThis, opnd1) < getn(pThis, opnd2);
    433476        case FILNT:
    434477                return newerf(opnd1, opnd2);
     
    714757                        return NULL;
    715758                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);
    718760                else if (s[3] != '\0')
    719761                        return NULL;
    720762                else
    721                         return bsearch(s + 1, mop3, __arraycount(mop3),
    722                             sizeof(*mop3), compare2);
     763                        return bsearch(s + 1, mop3, __arraycount(mop3), sizeof(*mop3), compare2);
    723764        } else {
    724765                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);
    727767                else if (strcmp(s, cop2[0].op_text) == 0)
    728768                        return cop2;
     
    733773
    734774static enum token
    735 t_lex(char *s)
     775t_lex(PTESTINSTANCE pThis, char *s)
    736776{
    737777        struct t_op const *op;
    738778
    739779        if (s == NULL) {
    740                 t_wp_op = NULL;
     780                pThis->t_wp_op = NULL;
    741781                return EOI;
    742782        }
    743783
    744784        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;
    748788                        return op->op_num;
    749789                }
    750790        }
    751         t_wp_op = NULL;
     791        pThis->t_wp_op = NULL;
    752792        return OPERAND;
    753793}
    754794
    755795static int
    756 isoperand(void)
     796isoperand(PTESTINSTANCE pThis)
    757797{
    758798        struct t_op const *op;
    759799        char *s, *t;
    760800
    761         if ((s  = *(t_wp+1)) == 0)
     801        if ((s  = *(pThis->t_wp+1)) == 0)
    762802                return 1;
    763         if ((t = *(t_wp+2)) == 0)
     803        if ((t = *(pThis->t_wp+2)) == 0)
    764804                return 0;
    765805        if ((op = findop(s)) != NULL)
     
    770810/* atoi with error detection */
    771811static int
    772 getn(const char *s)
     812getn(PTESTINSTANCE pThis, const char *s)
    773813{
    774814        char *p;
     
    779819
    780820        if (errno != 0)
    781               return errx(-42, "%s: out of range", s);
     821              return errx(pThis->pCtx, -42, "%s: out of range", s);
    782822
    783823        while (isspace((unsigned char)*p))
     
    785825
    786826        if (*p)
    787               return errx(-42, "%s: bad number", s);
     827              return errx(pThis->pCtx, -42, "%s: bad number", s);
    788828
    789829        return (int) r;
     
    822862
    823863static int
    824 usage(const char *argv0)
    825 {
    826         fprintf(stdout,
    827                 "usage: %s expression [-- <prog> [args]]\n", argv0);
     864usage(PKMKBUILTINCTX pCtx, int fIsErr)
     865{
     866        kmk_builtin_ctx_printf(pCtx, fIsErr, "usage: %s expression [-- <prog> [args]]\n", pCtx->pszProgName);
    828867        return 0; /* only used in --help. */
    829868}
     869
  • trunk/src/kmk/kmkbuiltin/touch.c

    r3140 r3192  
    9191typedef struct KMKTOUCHOPTS
    9292{
     93    /** Command execution context. */
     94    PKMKBUILTINCTX  pCtx;
    9395    /** What timestamps to modify on the files. */
    9496    KMKTOUCHTARGET  enmWhatToTouch;
     
    111113typedef KMKTOUCHOPTS *PKMKTOUCHOPTS;
    112114
    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 }
    136115
    137116static int touch_usage(void)
     
    189168 * Parses adjustment value: [-][[hh]mm]SS
    190169 */
    191 static int touch_parse_adjust(const char *pszValue, int *piAdjustValue)
     170static int touch_parse_adjust(PKMKBUILTINCTX pCtx, const char *pszValue, int *piAdjustValue)
    192171{
    193172    const char * const  pszInValue = pszValue;
     
    210189            if (   !IS_DIGIT(pszValue[0], 9)
    211190                || !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);
    213192            *piAdjustValue = TWO_CHARS_TO_INT(pszValue[0], pszValue[1]) * 60 * 60;
    214193            /* fall thru */
     
    216195            if (   !IS_DIGIT(pszValue[cchValue - 4], 9) /* don't bother limit to 60 minutes */
    217196                || !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);
    219198            *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 4], pszValue[cchValue - 3]) * 60;
    220199            /* fall thru */
     
    222201            if (   !IS_DIGIT(pszValue[cchValue - 2], 9) /* don't bother limit to 60 seconds */
    223202                || !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);
    225204            *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 2], pszValue[cchValue - 1]);
    226205            break;
    227206
    228207        default:
    229             return touch_syntax("Invalid -A value (length): %s", pszInValue);
     208            return errx(pCtx, 2, "Invalid -A value (length): %s", pszInValue);
    230209    }
    231210
     
    241220 * Parse -d timestamp: YYYY-MM-DDThh:mm:SS[.frac][tz]
    242221 */
    243 static int touch_parse_d_ts(const char *pszTs, struct timeval *pDst)
     222static int touch_parse_d_ts(PKMKBUILTINCTX pCtx, const char *pszTs, struct timeval *pDst)
    244223{
    245224    const char * const  pszTsIn = pszTs;
     
    257236        || !IS_DIGIT(pszTs[3], 9)
    258237        || pszTs[4] != '-')
    259         return touch_error("Malformed timestamp '%s' given to -d: expected to start with 4 digit year followed by a dash",
    260                            pszTsIn);
     238        return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to start with 4 digit year followed by a dash",
     239                    pszTsIn);
    261240    ExpTime.tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) * 100
    262241                    + TWO_CHARS_TO_INT(pszTs[2], pszTs[3])
     
    268247        || !IS_DIGIT(pszTs[1], 9)
    269248        || 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                            pszTsIn);
     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);
    272251    ExpTime.tm_mon = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) - 1;
    273252    pszTs += 3;
     
    277256        || !IS_DIGIT(pszTs[1], 9)
    278257        || (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                            pszTsIn);
     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);
    281260    ExpTime.tm_mday = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
    282261    pszTs += 3;
     
    286265        || !IS_DIGIT(pszTs[1], 9)
    287266        || pszTs[2] != ':')
    288         return touch_error("Malformed timestamp '%s' given to -d: expected to two digit hour at position 12 followed by colon",
    289                            pszTsIn);
     267        return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit hour at position 12 followed by colon",
     268                    pszTsIn);
    290269    ExpTime.tm_hour = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
    291270    pszTs += 3;
     
    295274        || !IS_DIGIT(pszTs[1], 9)
    296275        || pszTs[2] != ':')
    297         return touch_error("Malformed timestamp '%s' given to -d: expected to two digit minute at position 15 followed by colon",
    298                            pszTsIn);
     276        return errx(pCtx, 2, "Malformed timestamp '%s' given to -d: expected to two digit minute at position 15 followed by colon",
     277                    pszTsIn);
    299278    ExpTime.tm_min = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
    300279    pszTs += 3;
     
    303282    if (   !IS_DIGIT(pszTs[0], 5)
    304283        || !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);
    306285    ExpTime.tm_sec = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
    307286    pszTs += 2;
     
    315294        pszTs++;
    316295        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);
    318297
    319298        iFactor = 100000;
     
    333312        pszTs++;
    334313        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);
    337317    }
    338318    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);
    340320
    341321    /*
     
    352332#endif
    353333        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));
    355335    }
    356336    else
     
    358338        pDst->tv_sec = mktime(&ExpTime);
    359339        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));
    361341    }
    362342    return 0;
     
    367347 * Parse -t timestamp: [[CC]YY]MMDDhhmm[.SS]
    368348 */
    369 static int touch_parse_ts(const char *pszTs, struct timeval *pDst)
     349static int touch_parse_ts(PKMKBUILTINCTX pCtx, const char *pszTs, struct timeval *pDst)
    370350{
    371351    size_t const    cchTs = strlen(pszTs);
     
    380360     */
    381361    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);
    383363    switch (cchTs)
    384364    {
     
    392372        case 8 + 3 + 2 + 2: /* CCYYMMDDhhmm.SS */
    393373            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);
    395375            if (   !IS_DIGIT(pszTs[cchTs - 2], 5)
    396376                || !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);
    398378            cchTsNoSec = cchTs - 3;
    399379            break;
    400380        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);
    402382    }
    403383
     
    407387            if (   !IS_DIGIT(pszTs[cchTsNoSec - 12], 9)
    408388                || !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);
    410390            /* fall thru */
    411391        case 8 + 2:         /*   YYMMDDhhmm */
    412392            if (   !IS_DIGIT(pszTs[cchTsNoSec - 10], 9)
    413393                || !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);
    415395            /* fall thru */
    416396        case 8:             /*     MMDDhhmm */
    417397            if (   !IS_DIGIT(pszTs[cchTsNoSec - 8], 1)
    418398                || !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);
    420400            if (   !IS_DIGIT(pszTs[cchTsNoSec - 6], 3)
    421401                || !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);
    423403            if (   !IS_DIGIT(pszTs[cchTsNoSec - 4], 2)
    424404                || !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);
    426406            if (   !IS_DIGIT(pszTs[cchTsNoSec - 2], 5)
    427407                || !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);
    429409            break;
    430410    }
     
    435415    rc = gettimeofday(&Now, NULL);
    436416    if (rc != 0)
    437         return touch_error("gettimeofday failed: %s", strerror(errno));
     417        return errx(pCtx, 1, "gettimeofday failed: %s", strerror(errno));
    438418
    439419    pExpTime = localtime_r(&Now.tv_sec, &ExpTime);
    440420    if (pExpTime == NULL)
    441         return touch_error("localtime_r failed: %s", strerror(errno));
     421        return errx(pCtx, 1, "localtime_r failed: %s", strerror(errno));
    442422
    443423    /*
     
    475455    if (pDst->tv_sec != -1)
    476456        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));
    478458}
    479459
     
    482462 * Check for old timestamp: MMDDhhmm[YY]
    483463 */
    484 static int touch_parse_old_ts(const char *pszOldTs, time_t Now, struct timeval *pDst)
     464static int touch_parse_old_ts(PKMKBUILTINCTX pCtx, const char *pszOldTs, time_t Now, struct timeval *pDst)
    485465{
    486466    /*
     
    509489        pExpTime = localtime_r(&Now, &ExpTime);
    510490        if (pExpTime == NULL)
    511             return touch_error("localtime_r failed: %s", strerror(errno));
     491            return errx(pCtx, 1, "localtime_r failed: %s", strerror(errno));
    512492
    513493        /*
     
    535515        if (pDst->tv_sec != -1)
    536516            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));
    538518    }
    539519
     
    544524
    545525/**
    546  * Parses the arguments into pOpts.
     526 * Parses the arguments into pThis.
    547527 *
    548528 * @returns exit code.
    549  * @param   pOpts               Options structure to return the parsed info in.
     529 * @param   pThis               Options structure to return the parsed info in.
    550530 *                              Caller initalizes this with defaults.
    551531 * @param   cArgs               The number of arguments.
     
    554534 *                              files.
    555535 */
    556 static int touch_parse_args(PKMKTOUCHOPTS pOpts, int cArgs, char **papszArgs, KBOOL *pfExit)
     536static int touch_parse_args(PKMKTOUCHOPTS pThis, int cArgs, char **papszArgs, KBOOL *pfExit)
    557537{
    558538    int iAdjustValue = 0;
     
    583563                {
    584564                    while (++iArg < cArgs)
    585                         pOpts->papszFiles[pOpts->cFiles++] = papszArgs[iArg];
     565                        pThis->papszFiles[pThis->cFiles++] = papszArgs[iArg];
    586566                    break; /* '--' */
    587567                }
     
    626606                    return kbuild_version(papszArgs[0]);
    627607                else
    628                     return touch_syntax("Unknown option: --%s", pszLong);
     608                    return errx(pThis->pCtx, 2, "Unknown option: --%s", pszLong);
    629609            }
    630610
     
    651631                            pszValue = papszArgs[++iArg];
    652632                        else
    653                             return touch_syntax("Option -%c requires a value", ch);
     633                            return errx(pThis->pCtx, 2, "Option -%c requires a value", ch);
    654634                        break;
    655635
     
    663643                    /* -A [-][[HH]MM]SS */
    664644                    case 'A':
    665                         rc = touch_parse_adjust(pszValue, &iAdjustValue);
     645                        rc = touch_parse_adjust(pThis->pCtx, pszValue, &iAdjustValue);
    666646                        if (rc != 0)
    667647                            return rc;
    668                         if (pOpts->enmAction != kTouchActionSet)
     648                        if (pThis->enmAction != kTouchActionSet)
    669649                        {
    670                             pOpts->enmAction = kTouchActionAdjust;
    671                             pOpts->NewATime.tv_sec  = iAdjustValue;
    672                             pOpts->NewATime.tv_usec = 0;
    673                             pOpts->NewMTime = pOpts->NewATime;
     650                            pThis->enmAction = kTouchActionAdjust;
     651                            pThis->NewATime.tv_sec  = iAdjustValue;
     652                            pThis->NewATime.tv_usec = 0;
     653                            pThis->NewMTime = pThis->NewATime;
    674654                        }
    675655                        /* else: applied after parsing everything. */
     
    677657
    678658                    case 'a':
    679                         pOpts->enmWhatToTouch = kTouchAccessOnly;
     659                        pThis->enmWhatToTouch = kTouchAccessOnly;
    680660                        break;
    681661
    682662                    case 'c':
    683                         pOpts->fCreate = K_FALSE;
     663                        pThis->fCreate = K_FALSE;
    684664                        break;
    685665
    686666                    case 'd':
    687                         rc = touch_parse_d_ts(pszValue, &pOpts->NewATime);
     667                        rc = touch_parse_d_ts(pThis->pCtx, pszValue, &pThis->NewATime);
    688668                        if (rc != 0)
    689669                            return rc;
    690                         pOpts->enmAction = kTouchActionSet;
    691                         pOpts->NewMTime  = pOpts->NewATime;
     670                        pThis->enmAction = kTouchActionSet;
     671                        pThis->NewMTime  = pThis->NewATime;
    692672                        break;
    693673
     
    697677
    698678                    case 'h':
    699                         pOpts->fDereference = K_FALSE;
     679                        pThis->fDereference = K_FALSE;
    700680                        break;
    701681
    702682                    case 'm':
    703                         pOpts->enmWhatToTouch = kTouchModifyOnly;
     683                        pThis->enmWhatToTouch = kTouchModifyOnly;
    704684                        break;
    705685
     
    708688                        struct stat St;
    709689                        if (stat(pszValue, &St) != 0)
    710                             return touch_error("Failed to stat '%s' (-r option): %s", pszValue, strerror(errno));
    711 
    712                         pOpts->enmAction = kTouchActionSet;
    713                         pOpts->NewATime.tv_sec  = St.st_atime;
    714                         pOpts->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;
    715695#if FILE_TIMESTAMP_HI_RES
    716                         pOpts->NewATime.tv_usec = St.st_atim.tv_nsec / 1000;
    717                         pOpts->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;
    718698#else
    719                         pOpts->NewATime.tv_usec = 0;
    720                         pOpts->NewMTime.tv_usec = 0;
     699                        pThis->NewATime.tv_usec = 0;
     700                        pThis->NewMTime.tv_usec = 0;
    721701#endif
    722702                        break;
     
    724704
    725705                    case 't':
    726                         rc = touch_parse_ts(pszValue, &pOpts->NewATime);
     706                        rc = touch_parse_ts(pThis->pCtx, pszValue, &pThis->NewATime);
    727707                        if (rc != 0)
    728708                            return rc;
    729                         pOpts->enmAction = kTouchActionSet;
    730                         pOpts->NewMTime  = pOpts->NewATime;
     709                        pThis->enmAction = kTouchActionSet;
     710                        pThis->NewMTime  = pThis->NewATime;
    731711                        break;
    732712
     
    734714                        if (   strcmp(pszValue, "atime") == 0
    735715                            || strcmp(pszValue, "access") == 0)
    736                             pOpts->enmWhatToTouch = kTouchAccessOnly;
     716                            pThis->enmWhatToTouch = kTouchAccessOnly;
    737717                        else if (   strcmp(pszValue, "mtime") == 0
    738718                                 || strcmp(pszValue, "modify") == 0)
    739                             pOpts->enmWhatToTouch = kTouchModifyOnly;
     719                            pThis->enmWhatToTouch = kTouchModifyOnly;
    740720                        else
    741                             return touch_syntax("Unknown --time value: %s", pszValue);
     721                            return errx(pThis->pCtx, 2, "Unknown --time value: %s", pszValue);
    742722                        break;
    743723
     
    746726
    747727                    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);
    749729                }
    750730
     
    752732        }
    753733        else
    754             pOpts->papszFiles[pOpts->cFiles++] = papszArgs[iArg];
     734            pThis->papszFiles[pThis->cFiles++] = papszArgs[iArg];
    755735    }
    756736
     
    758738     * Allow adjusting specified timestamps too like BSD does.
    759739     */
    760     if (   pOpts->enmAction == kTouchActionSet
     740    if (   pThis->enmAction == kTouchActionSet
    761741        && iAdjustValue != 0)
    762742    {
    763         if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
    764             || pOpts->enmWhatToTouch == kTouchAccessOnly)
    765             pOpts->NewATime.tv_sec += iAdjustValue;
    766         if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
    767             || pOpts->enmWhatToTouch == kTouchModifyOnly)
    768             pOpts->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;
    769749    }
    770750
     
    772752     * Check for old timestamp: MMDDhhmm[YY]
    773753     */
    774     if (   pOpts->enmAction == kTouchActionCurrent
    775         && pOpts->cFiles >= 2)
     754    if (   pThis->enmAction == kTouchActionCurrent
     755        && pThis->cFiles >= 2)
    776756    {
    777757        struct timeval OldTs;
    778         rc = touch_parse_old_ts(pOpts->papszFiles[0], pOpts->NewATime.tv_sec, &OldTs);
     758        rc = touch_parse_old_ts(pThis->pCtx, pThis->papszFiles[0], pThis->NewATime.tv_sec, &OldTs);
    779759        if (rc == 0)
    780760        {
    781761            int iFile;
    782762
    783             pOpts->NewATime = OldTs;
    784             pOpts->NewMTime = OldTs;
    785             pOpts->enmAction = kTouchActionSet;
    786 
    787             for (iFile = 1; iFile < pOpts->cFiles; iFile++)
    788                 pOpts->papszFiles[iFile - 1] = pOpts->papszFiles[iFile];
    789             pOpts->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--;
    790770        }
    791771        else if (rc > 0)
     
    796776     * Check that we've found at least one file argument.
    797777     */
    798     if (pOpts->cFiles > 0)
     778    if (pThis->cFiles > 0)
    799779    {
    800780        *pfExit = K_FALSE;
    801781        return 0;
    802782    }
    803     return touch_syntax("No file specified");
     783    return errx(pThis->pCtx, 2, "No file specified");
    804784}
    805785
     
    809789 *
    810790 * @returns exit code.
    811  * @param   pOpts               The options.
     791 * @param   pThis               The options.
    812792 * @param   pszFile             The file to touch.
    813793 */
    814 static int touch_process_file(PKMKTOUCHOPTS pOpts, const char *pszFile)
     794static int touch_process_file(PKMKTOUCHOPTS pThis, const char *pszFile)
    815795{
    816796    int             fd;
     
    823803     * in effect, we silently skip the file if it doesn't already exist.
    824804     */
    825     if (pOpts->fDereference)
     805    if (pThis->fDereference)
    826806        rc = stat(pszFile, &St);
    827807    else
     
    830810    {
    831811        if (errno != ENOENT)
    832             return touch_error("Failed to stat '%s': %s", pszFile, strerror(errno));
    833 
    834         if (!pOpts->fCreate)
     812            return errx(pThis->pCtx, 1, "Failed to stat '%s': %s", pszFile, strerror(errno));
     813
     814        if (!pThis->fCreate)
    835815            return 0;
    836         fd = open(pszFile, O_WRONLY | O_CREAT, 0666);
     816        fd = open(pszFile, O_WRONLY | O_CREAT | KMK_OPEN_NO_INHERIT, 0666);
    837817        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));
    839819
    840820        /* If we're not setting the current time, we may need value stat info
    841821           on the file, so get it thru the file descriptor before closing it. */
    842         if (pOpts->enmAction == kTouchActionCurrent)
     822        if (pThis->enmAction == kTouchActionCurrent)
    843823            rc = 0;
    844824        else
    845825            rc = fstat(fd, &St);
    846826        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));
    848828        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));
    850830
    851831        /* We're done now if we're setting the current time. */
    852         if (pOpts->enmAction == kTouchActionCurrent)
     832        if (pThis->enmAction == kTouchActionCurrent)
    853833            return 0;
    854834    }
     
    866846    aTimes[1].tv_usec = 0;
    867847#endif
    868     if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
    869         || pOpts->enmWhatToTouch == kTouchAccessOnly)
    870     {
    871         if (   pOpts->enmAction == kTouchActionCurrent
    872             || pOpts->enmAction == kTouchActionSet)
    873             aTimes[0] = pOpts->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;
    874854        else
    875             aTimes[0].tv_sec += pOpts->NewATime.tv_sec;
    876     }
    877     if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
    878         || pOpts->enmWhatToTouch == kTouchModifyOnly)
    879     {
    880         if (   pOpts->enmAction == kTouchActionCurrent
    881             || pOpts->enmAction == kTouchActionSet)
    882             aTimes[1] = pOpts->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;
    883863        else
    884             aTimes[1].tv_sec += pOpts->NewMTime.tv_sec;
     864            aTimes[1].tv_sec += pThis->NewMTime.tv_sec;
    885865    }
    886866
     
    891871     * may do more than what we want (st_ctime).)
    892872     */
    893     if (pOpts->fDereference)
     873    if (pThis->fDereference)
    894874        rc = utimes(pszFile, aTimes);
    895875    else
     
    897877    if (rc != 0)
    898878    {
    899         if (pOpts->enmAction == kTouchActionCurrent)
     879        if (pThis->enmAction == kTouchActionCurrent)
    900880        {
    901             if (pOpts->fDereference)
     881            if (pThis->fDereference)
    902882                rc = utimes(pszFile, NULL);
    903883            else
     
    905885        }
    906886        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));
    908888    }
    909889
     
    913893
    914894/**
    915  * The function that does almost everything here... ugly.
     895 * Actual main function for the touch command.
    916896 */
    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
     897int kmk_builtin_touch(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx)
    922898{
    923899    int             rc;
    924     KMKTOUCHOPTS    Opts;
     900    KMKTOUCHOPTS    This;
    925901    K_NOREF(envp);
    926902
     
    928904     * Initialize options with defaults and parse them.
    929905     */
    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);
    939916        if (rc == 0)
    940917        {
    941918            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);
    945922            if (rc == 0 && !fExit)
    946923            {
     
    949926                 */
    950927                int iFile;
    951                 for (iFile = 0; iFile < Opts.cFiles; iFile++)
     928                for (iFile = 0; iFile < This.cFiles; iFile++)
    952929                {
    953                     int rc2 = touch_process_file(&Opts, Opts.papszFiles[iFile]);
     930                    int rc2 = touch_process_file(&This, This.papszFiles[iFile]);
    954931                    if (rc2 != 0 && rc == 0)
    955932                        rc = rc2;
     
    958935        }
    959936        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);
    962939    }
    963940    else
    964         rc = touch_error("calloc failed");
     941        rc = errx(pCtx, 2, "calloc failed");
    965942    return rc;
    966943}
    967944
     945#ifdef KMK_BUILTIN_STANDALONE
     946int 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  
    373373
    374374/* write/fwrite like function, binary mode. */
    375 void
     375ssize_t
    376376output_write_bin (struct output *out, int is_err, const char *src, size_t len)
    377377{
     378  size_t ret = len;
    378379  if (!out || !out->syncout)
    379380    {
    380381      FILE *f = is_err ? stderr : stdout;
    381382# ifdef KBUILD_OS_WINDOWS
    382       /* On windows we need to disable \n -> \r\n convers that is common on
     383      /* On windows we need to disable \n -> \r\n converts that is common on
    383384         standard output/error.  Also optimize for console output. */
     385      int saved_errno;
    384386      int fd = fileno (f);
    385387      int prev_mode = _setmode (fd, _O_BINARY);
    386388      maybe_con_fwrite (src, len, 1, f);
    387       fflush (f);
     389      if (fflush (f) == EOF)
     390        ret = -1;
     391      saved_errno = errno;
    388392      _setmode (fd, prev_mode);
     393      errno = saved_errno;
    389394# else
    390395      fwrite (src, len, 1, f);
    391       fflush (f);
     396      if (fflush (f) == EOF)
     397        ret = -1;
    392398# endif
    393399    }
     
    410416        }
    411417    }
     418  return ret;
    412419}
    413420
    414421/* write/fwrite like function, text mode. */
    415 void
     422ssize_t
    416423output_write_text (struct output *out, int is_err, const char *src, size_t len)
    417424{
    418425# 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)
    420428    {
    421429      /* ASSUME fwrite does the desired conversion. */
    422430      FILE *f = is_err ? stderr : stdout;
    423431# 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;
    425434# else
    426435      fwrite (src, len, 1, f);
    427436# endif
    428       fflush (f);
     437      if (fflush (f) == EOF)
     438        ret = -1;
    429439    }
    430440  else
     
    443453        }
    444454    }
     455  return len;
    445456# else
    446   output_write_bin (out, is_err, src, len);
     457  return output_write_bin (out, is_err, src, len);
    447458# endif
    448459}
  • trunk/src/kmk/output.h

    r3190 r3192  
    1414You should have received a copy of the GNU General Public License along with
    1515this program.  If not, see <http://www.gnu.org/licenses/>.  */
     16
     17#ifndef INCLUDED_MAKE_OUTPUT_H
     18#define INCLUDED_MAKE_OUTPUT_H
    1619
    1720#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
     
    8184void outputs (int is_err, const char *msg);
    8285#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
    83 void output_write_bin (struct output *out, int is_err, const char *src, size_t len);
    84 void output_write_text (struct output *out, int is_err, const char *src, size_t len);
     86ssize_t output_write_bin (struct output *out, int is_err, const char *src, size_t len);
     87ssize_t output_write_text (struct output *out, int is_err, const char *src, size_t len);
    8588#endif
    8689
     
    9093void output_dump (struct output *out);
    9194#endif
     95
     96#endif /* INLCUDED_MAKE_OUTPUT_H */
     97
  • trunk/src/kmk/w32/winchildren.c

    r3191 r3192  
    19581958{
    19591959    PCKMKBUILTINENTRY pBuiltIn = pChild->u.BuiltIn.pBuiltIn;
     1960    KMKBUILTINCTX Ctx = { pBuiltIn->uName.s.sz, pChild->pMkChild ? &pChild->pMkChild->output : NULL };
    19601961    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);
    19621964    else if (pBuiltIn->uFnSignature == FN_SIG_MAIN_SPAWNS)
    19631965        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);
    19651967    else
    19661968    {
Note: See TracChangeset for help on using the changeset viewer.

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