VirtualBox

Changeset 3192 in kBuild for trunk/src/kmk/kmkbuiltin/redirect.c


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).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.

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