Index: trunk/src/kmk/kmkbuiltin/redirect.c
===================================================================
--- trunk/src/kmk/kmkbuiltin/redirect.c	(revision 3682)
+++ trunk/src/kmk/kmkbuiltin/redirect.c	(revision 3685)
@@ -119,4 +119,5 @@
                            "Usage: %s [-[rwa+tb]<fd> <file>] [-d<fd>=<src-fd>] [-c<fd>] [--stdin-pipe]\n"
                            "           [-Z] [-E <var=val>] [-A <var=val>] [-P <var=val>] [-D <var>]\n"
+                           "           [-X <from-exitcode>[=<to>]\n"
                            "           [-C <dir>] [--wcc-brain-damage] [-v] -- <program> [args]\n"
                            "   or: %s --help\n"
@@ -153,4 +154,6 @@
     /*                      0         1         2         3         4         5         6         7         8 */
     /*                      012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
+                           "-X <from-exitcode>[=<to>], --translate-exitcode <from-exitcode>[=<to>]\n"
+                           "    Translates exit codes.  The '<to>' value defaults to zero.\n"
                            "-C <dir>, --chdir <dir>\n"
                            "    The -C switch is for changing the current directory.  Please specify an\n"
@@ -164,5 +167,5 @@
                            "\n"
                            "On OS/2 the kernel variables BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT can be\n"
-                           "accessed as-if they were regular enviornment variables.\n"
+                           "accessed as-if they were regular environment variables.\n"
                            "\n"
                            "This command was originally just a quick hack to avoid invoking the shell\n"
@@ -1377,4 +1380,10 @@
     REDIRECTORDERS  aOrders[32];
 
+    unsigned        cExitCodeTranslations = 0;
+    struct
+    {
+        int         rcExitFrom, rcExitTo;
+    }               aExitCodeTranslations[8];
+
     int             iArg;
     const char     *pszExecutable      = NULL;
@@ -1408,5 +1417,5 @@
         return err(pCtx, 9, "getcwd failed");
 
-    /* We start out with a read-only enviornment from kmk or the crt, and will
+    /* We start out with a read-only environment from kmk or the crt, and will
        duplicate it if we make changes to it. */
     cAllocatedEnvVars = 0;
@@ -1502,4 +1511,6 @@
                 else if (strcmp(pszArg, "stdin-pipe") == 0)
                     chOpt = 'I';
+                else if (strcmp(pszArg, "translate-exitcode") == 0)
+                    chOpt = 'X';
                 else
                 {
@@ -1537,5 +1548,6 @@
                 || chOpt == 'c'
                 || chOpt == 'd'
-                || chOpt == 'e')
+                || chOpt == 'e'
+                || chOpt == 'X')
             {
                 if (*pszArg != '\0')
@@ -1697,4 +1709,41 @@
 
             /*
+             * Exit code translation: from[=to]
+             */
+            if (chOpt == 'X')
+            {
+                int   rcExitTo = 0;
+                char *pszEqual;
+                int   rcExitFrom = (int)strtol(pszValue, &pszEqual, 0);
+                if (pszEqual == pszValue)
+                    rcExit = errx(pCtx, 2, "error: failed to convert 1st part of '--translate-exitcode %s' to a number",
+                                  pszValue);
+                else if (!pszEqual || !*pszEqual)
+                    rcExitTo = 0;
+                else if (*pszEqual != '=')
+                    rcExit = errx(pCtx, 2, "syntax error: expected '=' to separate the two values in: '--translate-exitcode %s'",
+                                  pszValue);
+                else
+                {
+                    char *pszEnd = 0;
+                    rcExitTo = (int)strtol(++pszEqual, &pszEnd, 0);
+                    if (pszEnd == pszEqual)
+                        rcExit = errx(pCtx, 2, "error: failed to convert 2nd half of '--translate-exitcode %s' to a number",
+                                      pszValue);
+                    else if (pszEnd && *pszEnd != '\0')
+                        rcExit = errx(pCtx, 2, "error: unexpected trailing chars in: '--translate-exitcode %s'", pszValue);
+                }
+                if (cExitCodeTranslations >= K_ELEMENTS(aExitCodeTranslations))
+                    rcExit = errx(pCtx, 2, "error: too many exit code translations");
+                else if (rcExit == 0)
+                {
+                    aExitCodeTranslations[cExitCodeTranslations].rcExitFrom = rcExitFrom;
+                    aExitCodeTranslations[cExitCodeTranslations].rcExitTo   = rcExitTo;
+                    cExitCodeTranslations++;
+                }
+                continue;
+            }
+
+            /*
              * Okay, it is some file descriptor operation.  Make sure we've got room for it.
              */
@@ -2021,4 +2070,16 @@
 #endif
                                   &fChildExitCode);
+
+        /* Do exit code translations if rcExit is a child exit code. */
+        if (fChildExitCode)
+            while (cExitCodeTranslations-- > 0)
+                if (aExitCodeTranslations[cExitCodeTranslations].rcExitFrom == rcExit)
+                {
+                    if (cVerbosity > 0)
+                        warnx(pCtx, "info: translating exit code %d to %d",
+                              rcExit, aExitCodeTranslations[cExitCodeTranslations].rcExitTo);
+                    rcExit = aExitCodeTranslations[cExitCodeTranslations].rcExitTo;
+                    break;
+                }
     }
     else if (rcExit == 0)
