Index: /trunk/src/gdllshell/Makefile.OS2.libc
===================================================================
--- /trunk/src/gdllshell/Makefile.OS2.libc	(revision 199)
+++ /trunk/src/gdllshell/Makefile.OS2.libc	(revision 199)
@@ -0,0 +1,24 @@
+# $Id$
+
+OBJDIR = objdir/OS2.libc
+OBJDIR = .
+SRC    = gdllshell.c
+OBJS   = $(addprefix $(OBJDIR)/, $(SRC:.c=.obj))
+
+CFLAGS = -Zomf -g -DMAKE_DLLSHELL -Wall
+ifndef DEBUG
+CFLAGS += -O3
+endif
+
+all: $(OBJDIR) gdllshl.dll
+
+
+gdllshl.dll:  $(OBJS) gdllshl.os2.def
+	gcc -g $(CFLAGS) -Zdll -Zhigh-mem -o $@ $(OBJS) gdllshl.os2.def
+
+.c.obj:
+	gcc -c $(CFLAGS) -o $@ -DHAVE_CONFIG_H  $<
+
+$(OBJDIR):
+	mkdir -p $@
+
Index: /trunk/src/gdllshell/gdllshell.c
===================================================================
--- /trunk/src/gdllshell/gdllshell.c	(revision 199)
+++ /trunk/src/gdllshell/gdllshell.c	(revision 199)
@@ -0,0 +1,55 @@
+/* $Id$ */
+/** @file
+ *
+ * dllshell://reference implementation.
+ *
+ * Copyright (c) 2003 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <process.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+/**
+ * Asynchronusly execute a command. The argument argv and envp together
+ * with the current filehandle configuration is what the command should
+ * should work within.
+ *
+ * @returns pid or fake pid of the command.
+ *          Fake pid means a pid number out of the normal pid range, but
+ *          still unique for sometime.
+ * @param   argv    Argument vector.
+ * @param   envp    Environment vector.
+ * @param   status  Where to store the status.
+ * @param   done    Where to flag that the command is completed in one
+ *                  or another manner.
+ */
+pid_t _System spawn_command(char **argv, char **envp, int *status, char *done)
+{
+    printf("gdllshell: hello\n");
+    return 0;
+}
Index: /trunk/src/gdllshell/gdllshl.OS2.def
===================================================================
--- /trunk/src/gdllshell/gdllshl.OS2.def	(revision 199)
+++ /trunk/src/gdllshell/gdllshl.OS2.def	(revision 199)
@@ -0,0 +1,4 @@
+LIBRARY gdllshl INITINSTANCE TERMINSTANCE
+DATA MULTIPLE
+EXPORTS
+    spawn_command
Index: /trunk/src/kShell/kShell.c
===================================================================
--- /trunk/src/kShell/kShell.c	(revision 198)
+++ /trunk/src/kShell/kShell.c	(revision 199)
@@ -158,13 +158,4 @@
  *
  * <b>Syntax: chdir <directory> </b>
- *
- *
- *
- * @subsubsection       mkdir
- * Create directory.
- *
- * <b>Syntax:  mkdir <directory> </b>
- *
- * Specify one directory to create.
  *
  *
@@ -311,4 +302,6 @@
 int             kshellError(const char *pszCmd, const char *pszMessage, ...);
 
+int             kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords);
+int             kshellCmd_log(const char *pszCmd, PKSHELLWORDS pWords);
 int             kshellCmd_copy(const char *pszCmd, PKSHELLWORDS pWords);
 int             kshellCmd_copytree(const char *pszCmd, PKSHELLWORDS pWords);
@@ -324,5 +317,4 @@
 int             kshellCmd_pushenv(const char *pszCmd, PKSHELLWORDS pWords);
 int             kshellCmd_popenv(const char *pszCmd, PKSHELLWORDS pWords);
-int             kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords);
 int             kshellCmd_write(const char *pszCmd, PKSHELLWORDS pWords);
 int             kshellCmd_ExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords);
@@ -410,4 +402,6 @@
     } aCmds[] =
     {
+        {"echo",        MAX_WORDS,  kshellCmd_echo},
+        {"log",         2,          kshellCmd_log},
         {"copy",        MAX_WORDS,  kshellCmd_copy},
         {"copytree",    3,          kshellCmd_copytree},
@@ -423,5 +417,4 @@
         {"pushenv",     MAX_WORDS,  kshellCmd_pushenv},
         {"popenv",      1,          kshellCmd_popenv},
-        {"echo",        2,          kshellCmd_echo},
         {"write",       2,          kshellCmd_write},
 
@@ -698,4 +691,5 @@
 
 
+
 /*
  *
@@ -704,4 +698,91 @@
  *
  */
+
+
+/** @subsubsection      echo
+ * Prints a message to stdout.
+ *
+ * <b>Syntax: echo <level> <message>
+ *
+ * The message is printed word for word normalize with a single space between
+ * the words. It's therefore a good thing to quote the message.
+ *
+ * The message can be empty. Then a blank line will be printed.
+ */
+int             kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords)
+{
+    int         i;
+
+    /* output all the words forcing one space separation */
+    for (i = 2; i < pWords->cWords; i++)
+    {
+        if (i != 2)
+            fputc(' ', stdout);
+        fwrite(pWords->aWords[i].pszWord, pWords->aWords[i].cchWord, 1, stdout);
+    }
+
+    /* new line */
+    fputc('\n', stdout);
+    fflush(stdout);
+
+    return 0;
+}
+
+
+/** @subsubsection      log
+ * Prints a message to stdout.
+ *
+ * <b>Syntax: log <level> <message>
+ *
+ * Level is verbosity level of the message. This is compared with the
+ * KBUILD_MSG_LEVEL environment variable. The message is suppressed if the
+ * level is lower that KBUILD_MSG_LEVEL.
+ *
+ * The message is printed word for word normalize with a single space between
+ * the words. It's therefore a good thing to quote the message.
+ *
+ * The message can be empty. Then a blank line will be printed.
+ */
+int             kshellCmd_log(const char *pszCmd, PKSHELLWORDS pWords)
+{
+    int         rc = KSHELL_ERROR_SYNTAX_ERROR;
+
+    /*
+     * Get the message level from the message.
+     */
+    if (pWords->cWords >= 2)
+    {
+        unsigned uMsgLevel = kStrToUDef(pWords->aWords[1].pszWord, -2, 0);
+        if (uMsgLevel != -2)
+        {
+            if (uMsgLevel <= kEnvGetUDef("KBUILD_MSG_LEVEL", 0, 0))
+            {
+                /* output all the words forcing one space separation */
+                pWords = kshellWordsParse(pszCmd, -1, pWords);
+                if (pWords)
+                {
+                    int i;
+                    for (i = 2; i < pWords->cWords; i++)
+                    {
+                        if (i != 2)
+                            fputc(' ', stdout);
+                        fwrite(pWords->aWords[i].pszWord, pWords->aWords[i].cchWord, 1, stdout);
+                    }
+                }
+
+                /* new line */
+                fputc('\n', stdout);
+                fflush(stdout);
+            }
+        }
+        else
+            kshellSyntaxError("log", "invalid message level!");
+    }
+    else
+        kshellSyntaxError("log", "requires at least one argument!");
+
+    return -1;
+}
+
 
 
@@ -820,8 +901,53 @@
 }
 
-
+/** @subsubsection      mkdir
+ * Create directory.
+ *
+ * <b>Syntax:  mkdir <directory> [directory2[..]] </b>
+ *
+ * Specify zero or more directories to create. Necessary parent directories
+ * will be created.
+ *
+ * If the directory exist no error is reported.
+ * The command fails on the first failure, processing directories left to right.
+ *
+ * Mkdir is hence not suitable for making locks. Should such be needed a
+ * dedicated command should be created for that purpose.
+ *
+ */
 int             kshellCmd_mkdir(const char *pszCmd, PKSHELLWORDS pWords)
 {
-    return -1;
+    int     rc = 0;
+    int     i;
+
+    for (i = 1; i < pWords->cWords; i++)
+    {
+        /*
+         * Allocate a buffer for canonizing the directory name and work in.
+         */
+        char *pszDir = kHeapAlloc(pWords->aWords[i].cchWord + KFILE_LENGTH);
+        if (pszDir)
+        {
+            /*
+             * Canonify the path to local default slash etc.
+             */
+            rc = kPathCanonifyEx(pWords->aWords[i].pszWord, NULL, KSHELL_SLASH, 0, psz);
+            if (!rc)
+            {
+                kFileState
+                /*
+                 * Now we will enumerate the path towards the root and
+                 * find the first existing directory. We need the mode
+                 * of that directory.
+                 */
+
+                char *psz =
+            }
+        }
+
+        rc = kDirCreate(
+    }
+
+    return rc;
 }
 
@@ -857,54 +983,4 @@
 
 
-/** @subsubsection      echo
- * Prints a message to stdout.
- *
- * <b>Syntax: echo <level> <message>
- *
- * Level is verbosity level of the message. This is compared with the
- * KBUILD_MSG_LEVEL environment variable. The message is suppressed if the
- * level is lower that KBUILD_MSG_LEVEL.
- *
- * The message is printed word for word normalize with a single space between
- * the words. It's therefore a good thing to quote the message.
- *
- * The message can be empty. Then a blank line will be printed.
- */
-int             kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords)
-{
-    int         rc = KSHELL_ERROR_SYNTAX_ERROR;
-
-    /*
-     * Get the message level from the message.
-     */
-    if (pWords->cWords >= 2)
-    {
-        unsigned uMsgLevel = kStrToUDef(pWords->aWords[1].pszWord, -2, 0);
-        if (uMsgLevel != -2)
-        {
-            if (uMsgLevel <= kEnvGetUDef("KBUILD_MSG_LEVEL", 0, 0))
-            {
-                /* output all the words forcing one space separation */
-                pWords = kshellWordsParse(pszCmd, -1, pWords);
-                if (pWords)
-                {
-                    int i;
-                    for (i = 2; i < pWords->cWords; i++)
-                        fwrite(pWords->aWords[i].pszWord, pWords->aWords[i].cchWord, 1, stdout);
-                }
-
-                /* new line */
-                fputc('\n', stdout);
-                fflush(stdout);
-            }
-        }
-        else
-            kshellSyntaxError("echo", "invalid message level!");
-    }
-    else
-        kshellSyntaxError("echo", "requires at least one argument!");
-
-    return -1;
-}
 
 
