Index: trunk/src/kmk/kmkbuiltin.h
===================================================================
--- trunk/src/kmk/kmkbuiltin.h	(revision 3038)
+++ trunk/src/kmk/kmkbuiltin.h	(revision 3039)
@@ -78,4 +78,8 @@
 extern int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
                              int cVerbosity, const char *pszValue);
+extern int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                int cVerbosity, const char *pszValue);
+extern int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                 int cVerbosity, const char *pszValue);
 extern int kBuiltinOptEnvUnset(char **papszEnv, unsigned *pcEnvVars, int cVerbosity, const char *pszVarToRemove);
 extern int kBuiltinOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue);
Index: trunk/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c
===================================================================
--- trunk/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c	(revision 3038)
+++ trunk/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c	(revision 3039)
@@ -46,8 +46,78 @@
 
 /**
+ * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that adds
+ * a new variable to the environment.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   papszEnv            The environment vector.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+static int kBuiltinOptEnvAddVar(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                int cVerbosity, const char *pszValue)
+{
+    /* Append new variable. We probably need to resize the vector. */
+    char   **papszEnv = *ppapszEnv;
+    unsigned cEnvVars = *pcEnvVars;
+    if ((cEnvVars + 2) > *pcAllocatedEnvVars)
+    {
+        *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
+        papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
+        if (!papszEnv)
+            return errx(1, "out of memory!");
+        *ppapszEnv = papszEnv;
+    }
+    papszEnv[cEnvVars] = strdup(pszValue);
+    if (!papszEnv[cEnvVars])
+        return errx(1, "out of memory!");
+    papszEnv[++cEnvVars]   = NULL;
+    *pcEnvVars = cEnvVars;
+    if (cVerbosity > 0)
+        warnx("added '%s'", papszEnv[cEnvVars - 1]);
+    return 0;
+}
+
+
+/**
+ * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that
+ * remove duplicates.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   papszEnv            The environment vector.
+ * @param   cEnvVars            Number of environment variables.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ * @param   cchVar              The length of the variable part of @a pszValue.
+ * @param   iEnvVar             Where to start searching after.
+ */
+static int kBuiltinOptEnvRemoveDuplicates(char **papszEnv, unsigned cEnvVars, int cVerbosity,
+                                          const char *pszValue, size_t cchVar, unsigned iEnvVar)
+{
+    for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
+        if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
+            && papszEnv[iEnvVar][cchVar] == '=')
+        {
+            if (cVerbosity > 0)
+                warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
+            free(papszEnv[iEnvVar]);
+            cEnvVars--;
+            if (iEnvVar != cEnvVars)
+                papszEnv[iEnvVar] = papszEnv[cEnvVars];
+            papszEnv[cEnvVars] = NULL;
+            iEnvVar--;
+        }
+    return 0;
+}
+
+
+/**
  * Handles the --set var=value option.
  *
  * @returns 0 on success, non-zero exit code on error.
- * @param   papszEnv            The environment vector.
+ * @param   ppapszEnv           The environment vector pointer.
  * @param   pcEnvVars           Pointer to the variable holding the number of
  *                              environment variables held by @a papszEnv.
@@ -78,48 +148,106 @@
                 if (!papszEnv[iEnvVar])
                     return errx(1, "out of memory!");
-                break;
-            }
-        }
-        if (iEnvVar == cEnvVars)
-        {
-            /* Append new variable. We probably need to resize the vector. */
-            if ((cEnvVars + 2) > *pcAllocatedEnvVars)
-            {
-                *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
-                papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
-                if (!papszEnv)
+
+                return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
+            }
+        }
+        return kBuiltinOptEnvAddVar(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);
+    }
+    return errx(1, "Missing '=': -E %s", pszValue);
+}
+
+
+/**
+ * Common worker for kBuiltinOptEnvAppend and kBuiltinOptEnvPrepend.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+static int kBuiltinOptEnvAppendPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                       int cVerbosity, const char *pszValue, int fAppend)
+{
+    const char *pszEqual = strchr(pszValue, '=');
+    if (pszEqual)
+    {
+        char   **papszEnv = *ppapszEnv;
+        unsigned iEnvVar;
+        unsigned cEnvVars = *pcEnvVars;
+        size_t const cchVar = pszEqual - pszValue;
+        for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
+        {
+            char *pszCur = papszEnv[iEnvVar];
+            if (   KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 0
+                && pszCur[cchVar] == '=')
+            {
+                size_t cchOldValue = strlen(papszEnv[iEnvVar]) - cchVar - 1;
+                size_t cchNewValue = strlen(pszValue)          - cchVar - 1;
+                char *pszNew = malloc(cchVar + 1 + cchOldValue + cchNewValue);
+                if (!papszEnv[iEnvVar])
                     return errx(1, "out of memory!");
-                *ppapszEnv = papszEnv;
-            }
-            papszEnv[cEnvVars] = strdup(pszValue);
-            if (!papszEnv[cEnvVars])
-                return errx(1, "out of memory!");
-            papszEnv[++cEnvVars]   = NULL;
-            *pcEnvVars = cEnvVars;
-            if (cVerbosity > 0)
-                warnx("added '%s'", papszEnv[iEnvVar]);
-        }
-        else
-        {
-            /* Check for duplicates. */
-            for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
-                if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
-                    && papszEnv[iEnvVar][cchVar] == '=')
+                if (fAppend)
                 {
-                    if (cVerbosity > 0)
-                        warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
-                    free(papszEnv[iEnvVar]);
-                    cEnvVars--;
-                    if (iEnvVar != cEnvVars)
-                        papszEnv[iEnvVar] = papszEnv[cEnvVars];
-                    papszEnv[cEnvVars] = NULL;
-                    iEnvVar--;
+                    memcpy(pszNew, papszEnv[iEnvVar], cchVar + 1 + cchOldValue);
+                    memcpy(&pszNew[cchVar + 1 + cchOldValue], &pszValue[cchVar + 1], cchNewValue + 1);
                 }
-        }
-    }
-    else
-        return errx(1, "Missing '=': -E %s", pszValue);
-
-    return 0;
+                else
+                {
+                    memcpy(pszNew, papszEnv[iEnvVar], cchVar + 1); /* preserve variable name case  */
+                    memcpy(&pszNew[cchVar + 1], &pszValue[cchVar + 1], cchNewValue);
+                    memcpy(&pszNew[cchVar + 1 + cchNewValue], &papszEnv[iEnvVar][cchVar + 1], cchOldValue + 1);
+                }
+
+                if (cVerbosity > 0)
+                    warnx("replacing '%s' with '%s'", papszEnv[iEnvVar], pszNew);
+                free(papszEnv[iEnvVar]);
+                papszEnv[iEnvVar] = pszNew;
+
+                return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
+            }
+        }
+        return kBuiltinOptEnvAddVar(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);
+    }
+    return errx(1, "Missing '=': -E %s", pszValue);
+}
+
+
+/**
+ * Handles the --append var=value option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
+{
+    return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 1 /*fAppend*/);
+}
+
+
+/**
+ * Handles the --prepend var=value option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
+{
+    return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 0 /*fAppend*/);
 }
 
Index: trunk/src/kmk/kmkbuiltin/kSubmit.c
===================================================================
--- trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 3038)
+++ trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 3039)
@@ -1169,4 +1169,5 @@
     fprintf(pOut,
             "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"
+            "           [-A|--append <var=val>] [-D|--prepend <var=val>]\n"
             "           [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n"
             "           [-3|--32-bit] [-6|--64-bit] [-v]\n"
@@ -1182,4 +1183,8 @@
             "  -U, --unset <var>\n"
             "    Removes an environment variable. Position dependent.\n"
+            "  -A, --append <var>=<value>\n"
+            "    Appends the given value to the environment variable.\n"
+            "  -D,--prepend <var>=<value>\n"
+            "    Prepends the given value to the environment variable.\n"
             "  -C, --chdir <dir>\n"
             "    Specifies the current directory for the program.  Relative paths\n"
@@ -1296,4 +1301,8 @@
                 else if (strcmp(pszArg, "set") == 0)
                     chOpt = 'E';
+                else if (strcmp(pszArg, "append") == 0)
+                    chOpt = 'A';
+                else if (strcmp(pszArg, "prepend") == 0)
+                    chOpt = 'D';
                 else if (strcmp(pszArg, "unset") == 0)
                     chOpt = 'U';
@@ -1327,7 +1336,9 @@
                 switch (chOpt)
                 {
+                    case 'A':
+                    case 'C':
                     case 'E':
                     case 'U':
-                    case 'C':
+                    case 'D':
                     case 'e':
                         if (*pszArg != '\0')
@@ -1355,4 +1366,18 @@
                     case 'E':
                         rcExit = kBuiltinOptEnvSet(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                        pChild->environment = papszEnv;
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
+                    case 'A':
+                        rcExit = kBuiltinOptEnvAppend(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                        pChild->environment = papszEnv;
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
+                    case 'D':
+                        rcExit = kBuiltinOptEnvPrepend(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
                         pChild->environment = papszEnv;
                         if (rcExit == 0)
Index: trunk/src/kmk/kmkbuiltin/redirect.c
===================================================================
--- trunk/src/kmk/kmkbuiltin/redirect.c	(revision 3038)
+++ trunk/src/kmk/kmkbuiltin/redirect.c	(revision 3039)
@@ -1139,4 +1139,8 @@
                          || strcmp(pszArg, "env") == 0)
                     chOpt = 'E';
+                else if (strcmp(pszArg, "append") == 0)
+                    chOpt = 'A';
+                else if (strcmp(pszArg, "prepend") == 0)
+                    chOpt = 'D';
                 else if (strcmp(pszArg, "unset") == 0)
                     chOpt = 'U';
@@ -1179,4 +1183,6 @@
              */
             if (   chOpt == 'E'
+                || chOpt == 'A'
+                || chOpt == 'D'
                 || chOpt == 'U'
                 || chOpt == 'C'
@@ -1271,4 +1277,23 @@
 
             /*
+             * Append or prepend value to and environment variable.
+             */
+            if (chOpt == 'A' || chOpt == 'D')
+            {
+#ifdef KBUILD_OS_OS2
+                if (   strcmp(pszValue, "BEGINLIBPATH") == 0
+                    || strcmp(pszValue, "ENDLIBPATH") == 0
+                    || strcmp(pszValue, "LIBPATHSTRICT") == 0)
+                    rcExit = errx(2, "error: '%s' cannot currently be appended or prepended to. Please use -E/--set for now.", pszValue);
+                else
+#endif
+                if (chOpt == 'A')
+                    rcExit = kBuiltinOptEnvAppend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                else
+                    rcExit = kBuiltinOptEnvPrepend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                continue;
+            }
+
+            /*
              * Unset environment variable.
              */
