Index: /trunk/src/emx/ChangeLog.LIBC
===================================================================
--- /trunk/src/emx/ChangeLog.LIBC	(revision 2020)
+++ /trunk/src/emx/ChangeLog.LIBC	(revision 2021)
@@ -1,3 +1,8 @@
 /* $Id$ */
+
+2005-06-12: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libc:
+        o Changed the LIBC_PATHREADWRITERS to a generic LIBC_HOOK_DLLS.
+          See src/emx/src/lib/sys/hooks.c for details.
 
 2005-06-11: knut st. osmundsen <bird-gccos2-spam@anduin.net>
Index: /trunk/src/emx/include/InnoTekLIBC/pathrewrite.h
===================================================================
--- /trunk/src/emx/include/InnoTekLIBC/pathrewrite.h	(revision 2020)
+++ /trunk/src/emx/include/InnoTekLIBC/pathrewrite.h	(revision 2021)
@@ -4,5 +4,5 @@
  * InnoTek LIBC - Path Rewrite.
  *
- * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ * Copyright (c) 2004-2005 knut st. osmundsen <bird-srcspam@anduin.net>
  *
  *
@@ -57,4 +57,10 @@
     /** Length of to path. */
     unsigned        cchTo;
+    /** Reserved 0 - intended for function pointer to special open. */
+    unsigned        uReserved0;
+    /** Reserved 1 - intended for function pointer to special parser. */
+    unsigned        uReserved1;
+    /** Reserved 2 - 8 byte alignment*/
+    unsigned        uReserved2;
 } __LIBC_PATHREWRITE, *__LIBC_PPATHREWRITE;
 
Index: /trunk/src/emx/src/lib/startup/386/dll0.s
===================================================================
--- /trunk/src/emx/src/lib/startup/386/dll0.s	(revision 2020)
+++ /trunk/src/emx/src/lib/startup/386/dll0.s	(revision 2021)
@@ -81,7 +81,8 @@
 do_init:
 #endif
+    pushl   4(%esp)
     pushl   $(FLAG_HIGHMEM + FLAG_NOUNIX)
     call    ___init_dll
-    add     $4, %esp
+    add     $8, %esp
     orl     %eax, %eax
     jz      do_initterm
Index: /trunk/src/emx/src/lib/startup/startup.c
===================================================================
--- /trunk/src/emx/src/lib/startup/startup.c	(revision 2020)
+++ /trunk/src/emx/src/lib/startup/startup.c	(revision 2021)
@@ -68,4 +68,6 @@
  *              - __libc_fhInit() will call _hmalloc() and a number of OS/2 APIs
  *                to figure out what handles was inherited.
+ *          - __init_dll checks for LIBC_HOOK_DLLS and calls __libc_back_hooksInit()
+ *                to process it if it is present in the environment.
  *          - __init_dll then intializes _sys_clock0_ms with the current MS count.
  *      - dll0.s calls _DLL_InitTerm in startup/dllinit.c.
Index: /trunk/src/emx/src/lib/sys/__init.c
===================================================================
--- /trunk/src/emx/src/lib/sys/__init.c	(revision 2020)
+++ /trunk/src/emx/src/lib/sys/__init.c	(revision 2021)
@@ -184,5 +184,5 @@
      * Then end the heap voting.
      */
-    if (__init_dll(fFlags))
+    if (__init_dll(fFlags, 0))
         goto failure;
 
Index: /trunk/src/emx/src/lib/sys/__initdll.c
===================================================================
--- /trunk/src/emx/src/lib/sys/__initdll.c	(revision 2020)
+++ /trunk/src/emx/src/lib/sys/__initdll.c	(revision 2021)
@@ -36,4 +36,5 @@
 #include "b_fs.h"
 #include "b_signal.h"
+#include "backend.h"
 #include <InnoTekLIBC/thread.h>
 #include <InnoTekLIBC/libc.h>
@@ -89,6 +90,8 @@
  *                         If clear all unix like features are enabled.
  *                  Passed on to __init_dll().
- */
-int __init_dll(int fFlags)
+ * @param   hmod    The handle of the calling module. This is 0 when we're called from crt0.s.
+ *                  If we're not already initialized, this will be the handle of the libc dll.
+ */
+int __init_dll(int fFlags, unsigned long hmod)
 {
     ULONG               aul[2];
@@ -213,4 +216,11 @@
         return -1;
     }
+
+    /*
+     * Load and call hook DLLs.
+     */
+    const char *psz = getenv("LIBC_HOOK_DLLS");
+    if (psz)
+        __libc_back_hooksInit(psz, hmod);
 
     /*
Index: /trunk/src/emx/src/lib/sys/backend.h
===================================================================
--- /trunk/src/emx/src/lib/sys/backend.h	(revision 2020)
+++ /trunk/src/emx/src/lib/sys/backend.h	(revision 2021)
@@ -47,4 +47,9 @@
 int __libc_native2errno(unsigned long rc);
 
+/**
+ * Initializes the various LIBC hooks using the given
+ * specification string.
+ */
+void __libc_back_hooksInit(const char *pszSpec, unsigned long hmod);
 
 __END_DECLS
Index: /trunk/src/emx/src/lib/sys/hooks.c
===================================================================
--- /trunk/src/emx/src/lib/sys/hooks.c	(revision 2021)
+++ /trunk/src/emx/src/lib/sys/hooks.c	(revision 2021)
@@ -0,0 +1,234 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC SYS Backend - hooks.
+ *
+ * Copyright (c) 2005 knut st. osmundsen <bird@innotek.de>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/** @page pg_hooks  Hooks
+ *
+ * Presently this is a simple feature to load and call dlls as specified in
+ * the LIBC_HOOK_DLLS environment variable.
+ *
+ *
+ * @subsection  LIBC_HOOK_DLLS
+ *
+ * The format is <dllname>@<export>[!<type>]. LIBC will load <dllname>,
+ * resolve <export>and call <export> according to the convention of <type>.
+ * Single of double quotes can be applied to the <dllname>. If multiple hooks
+ * is desired, they shall be separated by the semicolon, space or tab character.
+
+ * Failure to parse this variable, load dlls and resolve functions as specified
+ * bye this variable will not prevent libc processes from starting. So, do NOT
+ * count on it as a security measure.
+ *
+ * @subsubsection   Types
+ *
+ * The default type is 'generic' and means that the libc module handle and
+ * the address of __libc_Back_ldrSymbol will be passed.
+ *
+ * 'pathrewrite' is another type. The parameters here are the three
+ * __libc_PathRewrite functions. The function should
+ *
+ *
+ * @subsubsection   Examples
+ *
+ *  set LIBC_HOOK_DLLS=prwhome.dll@_instprws!pathrewrite
+ *  set LIBC_HOOK_DLLS=/usr/lib/prwhome.dll@_instprws!pathrewrite
+ *  set LIBC_HOOK_DLLS="c:\My Plugins\prwhome.dll"@_instprws!pathrewrite
+ *  set LIBC_HOOK_DLLS=prwhome@_insthomeprws!pathrewrite prwhome@_instetcprws!pathrewrite
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define _GNU_SOURCE
+#include "libc-alias.h"
+#define INCL_BASE
+#define INCL_EXAPIS
+#include <os2emx.h>
+#include "backend.h"
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "syscalls.h"
+#include <InnoTekLIBC/backend.h>
+#include <InnoTekLIBC/pathrewrite.h>
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_INITTERM
+#include <InnoTekLIBC/logstrict.h>
+
+
+
+/**
+ * Initializes the various LIBC hooks using the given
+ * specification string.
+ */
+void __libc_back_hooksInit(const char *pszSpec, unsigned long hmod)
+{
+    LIBCLOG_ENTER("pszSpec=%s\n", pszSpec);
+
+    /*
+     * Parse the variable.
+     */
+    const char *psz = pszSpec;
+    for (;;)
+    {
+        char        chQuote;
+        const char *pszDll;
+        const char *pszDllEnd;
+        const char *pszSym;
+        const char *pszSymEnd;
+        const char *pszType;
+        const char *pszTypeEnd;
+        char        szSym[CCHMAXPATH];
+        char        szDll[CCHMAXPATH];
+        HMODULE     hmod;
+        APIRET      rc;
+
+        /*
+         * Trimming off blanks.
+         */
+        while ((chQuote = *psz) == ' ' || chQuote == '\t' || chQuote == ';')
+            psz++;
+        if (!chQuote)
+            break;
+
+        /*
+         * Check for quotes and find the end of the spec.
+         */
+        if (chQuote != '\'' && chQuote != '"')
+        {
+            pszDll = psz;
+            chQuote = 0;
+            pszDllEnd = strpbrk(psz, " \t;@!");
+            if (!pszDllEnd)
+            {
+                LIBC_ASSERTM_FAILED("missformed dll specification; '%s'\n", psz);
+                LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (1)! stopped parsing!\n");
+            }
+            pszSym = pszDllEnd;
+        }
+        else
+        {   /* quoted */
+            pszDll = psz + 1;
+            pszDllEnd = strchr(pszDll, chQuote);
+            if (!pszDllEnd)
+            {
+                LIBC_ASSERTM_FAILED("mismatching quotes '%s'\n", psz);
+                LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (2)! stopped parsing!\n");
+            }
+            pszSym = pszDllEnd + 1;
+        }
+
+        pszSym++;
+        pszSymEnd = strpbrk(pszSym, " \t;!@'\"");
+        if (!pszSymEnd)
+            pszSymEnd = strchr(pszSym, '\0');
+        if (    pszSymEnd == pszSym
+            || (*pszSymEnd != '!' && *pszSymEnd != ' ' && *pszSymEnd != '\t' && *pszSymEnd != '\0' && *pszSymEnd != ';'))
+        {
+            LIBC_ASSERTM_FAILED("missformed export specification; '%s'\n", psz);
+            LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (3)! stopped parsing!\n");
+        }
+
+        /* type */
+        if (*pszSymEnd == '!')
+        {
+            pszType = pszSymEnd + 1;
+            pszTypeEnd = strpbrk(pszType, " \t;!@'\"");
+            if (!pszTypeEnd)
+                pszTypeEnd = strchr(pszType, '\0');
+            if (    pszTypeEnd == pszType
+                || (*pszTypeEnd != ' ' && *pszTypeEnd != '\t' && *pszTypeEnd != '\0' && *pszTypeEnd != ';'))
+            {
+                LIBC_ASSERTM_FAILED("missformed export specification; '%s'\n", psz);
+                LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (4)! stopped parsing!\n");
+            }
+        }
+        else
+            pszTypeEnd = pszType = NULL;
+
+        /* lengths */
+        if (pszDllEnd - pszDll >= sizeof(szDll))
+        {
+            LIBC_ASSERTM_FAILED("dll name is too long! %d bytes ; '%s'\n", pszDllEnd - pszDll, psz);
+            LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (5)! stopped parsing!\n");
+        }
+
+        if (pszSymEnd - pszSym >= sizeof(szSym))
+        {
+            LIBC_ASSERTM_FAILED("symbol name is too long! %d bytes ; '%s'\n", pszSymEnd - pszSym, psz);
+            LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (6)! stopped parsing!\n");
+        }
+
+        /*
+         * Load the DLL.
+         */
+        memcpy(szDll, pszDll, pszDllEnd - pszDll);
+        szDll[pszDllEnd - pszDll] = '\0';
+        #if defined(DEBUG_LOGGING) || defined(__LIBC_STRICT)
+        rc = DosLoadModuleEx((PSZ)szSym, sizeof(szSym), (PCSZ)szDll, &hmod);
+        #else
+        rc = DosLoadModuleEx(NULL, 0, (PCSZ)szDll, &hmod);
+        #endif
+        if (!rc)
+        {
+            union
+            {
+                PFN pfn;
+                void (*pfnRewriter)(int (*pfnAdd)(), int (*pfnRemove)(), int (*pfnRewrite)(), void *pvHandle);
+                void (*pfnGeneric)(void *pvHandle, int (*pfnLdrSymbol)(void *pvHandle,  const char *pszSymbol, void **ppfn));
+            } u;
+
+            /*
+             * Resolve the symbol.
+             */
+            memcpy(szSym, pszSym, pszSymEnd - pszSym);
+            szSym[pszSymEnd - pszSym] = '\0';
+            rc = DosQueryProcAddr(hmod, 0, (PSZ)szSym, &u.pfn);
+            if (!rc)
+            {
+                LIBCLOG_MSG("Successfully loaded and resolved hook '%s' in '%s' to %p\n",
+                            szSym, szDll, (void *)u.pfn);
+                if (!pszType || !strncmp(pszType, "generic", sizeof("generic") - 1))
+                    u.pfnGeneric((void *)hmod, __libc_Back_ldrSymbol);
+                else if (!strncmp(pszType, "pathrewrite", sizeof("pathrewrite") - 1))
+                    u.pfnRewriter(__libc_PathRewriteAdd, __libc_PathRewriteRemove, __libc_PathRewrite, (void *)hmod);
+
+            }
+            else
+                LIBC_ASSERTM_FAILED("Failed to resolve rewriter '%s' in '%s', rc=%lu\n", szSym, szDll, rc);
+        }
+        else
+            LIBC_ASSERTM_FAILED("Failed to load rewriter '%s', rc=%lu szObj='%s'\n", szDll, rc, szSym);
+
+        /*
+         * Next part.
+         */
+        psz = pszType ? pszTypeEnd : pszSymEnd;
+    }
+
+    LIBCLOG_RETURN_VOID();
+}
+
+/** @todo Term */
Index: /trunk/src/emx/src/lib/sys/pathrewrite.c
===================================================================
--- /trunk/src/emx/src/lib/sys/pathrewrite.c	(revision 2020)
+++ /trunk/src/emx/src/lib/sys/pathrewrite.c	(revision 2021)
@@ -26,27 +26,13 @@
 
 
-/** @page PathRewrite   Path Rewrite Feature
+/** @page pg_pathRewrite   Path Rewrite Feature
  *
  * The Path Rewrite Feature was designed as a replacement for the hardcoded
  * mapping of /dev/null to nul and /dev/tty to con in __open.c. It allows
- * the user of LIBC to automatically rewrite (map) paths given to LIBC APIS.
+ * the user of LIBC to automatically rewrite (map) paths given to LIBC APIs.
  * The user can dynamically add and remove rewrite rules. The environment
- * variable LIBC_PATHREWRITERS can be used to dynamically load DLLs containing
- * rewrite rules and add it to the process.
- *
- *
- * @subsection  LIBC_PATHREWRITERS
- *
- * The format is <dllname>@<export>. LIBC will load <dllname>, resolve <export>
- * and call <export> with pointers to the three __libc_PathRewrite interfaces.
- * The <export> function will then register and remove rules as it pleases it.
- * Single of double quotes can be applied to the <dllname>. Multiple rewriters
- * must be separated by space.
- *
- * Examples:
- *      set LIBC_PATHREWRITERS=prwhome.dll@_instprws
- *      set LIBC_PATHREWRITERS=/usr/lib/prwhome.dll@_instprws
- *      set LIBC_PATHREWRITERS="c:\My Plugins\prwhome.dll"@_instprws
- *      set LIBC_PATHREWRITERS=prwhome@_insthomeprws prwhome@_instetcprws
+ * variable LIBC_HOOK_DLLS can be used to dynamically load DLLs containing
+ * rewrite rules and add it to the process. See \ref pg_hooks for further
+ * details.
  */
 
@@ -207,161 +193,8 @@
 
 
-/** Flag which tells if we're initialized or not. */
-static int gfInited;
-
 /*******************************************************************************
 *   Internal Functions                                                         *
 *******************************************************************************/
 static void __libc_pathRewriteDeleteDir(PDIRECTORY pDir);
-static void __libc_pathRewriteInit(void);
-/* static void __libc_pathRewriteTerm(void); */
-
-_CRT_INIT1(__libc_pathRewriteInit)
-
-/**
- * Init rewriters if LIBC_PATHREWRITERS contains anything useful.
- * @remark  Cannot be static as GCC will optimize it away then.
- */
-static void __libc_pathRewriteInit(void)
-{
-    static void *pfnDummy = __libc_pathRewriteInit;
-    LIBCLOG_ENTER("\n");
-    if (gfInited)
-        LIBCLOG_RETURN_VOID();
-    gfInited = 1;
-
-    /*
-     * Check for the presense of the variable.
-     */
-    const char *psz = getenv("LIBC_PATHREWRITERS");
-    if (!psz || !*psz)
-        LIBCLOG_RETURN_MSG_VOID("no rewriters\n");
-
-    /*
-     * Parse the variable.
-     */
-    for (;;)
-    {
-        char        chQuote;
-        const char *pszDll;
-        const char *pszDllEnd;
-        const char *pszSym;
-        const char *pszSymEnd;
-        char        szSym[CCHMAXPATH];
-        char        szDll[CCHMAXPATH];
-        HMODULE     hmod;
-        APIRET      rc;
-
-        /*
-         * Trimming off blanks.
-         */
-        while ((chQuote = *psz) == ' ' || chQuote == '\t' || chQuote == ';')
-            psz++;
-        if (!chQuote)
-            break;
-
-        /*
-         * Check for quotes and find the end of the spec.
-         */
-        if (chQuote != '\'' && chQuote != '"')
-        {
-            pszDll = psz;
-            chQuote = 0;
-            pszDllEnd = strpbrk(psz, " \t;@");
-            if (!pszDllEnd)
-            {
-                LIBC_ASSERTM_FAILED("missformed dll specification; '%s'\n", psz);
-                LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (1)! stopped parsing!\n");
-            }
-            pszSym = pszDllEnd;
-        }
-        else
-        {   /* quoted */
-            pszDll = psz + 1;
-            pszDllEnd = strchr(pszDll, chQuote);
-            if (!pszDllEnd)
-            {
-                LIBC_ASSERTM_FAILED("mismatching quotes '%s'\n", psz);
-                LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (2)! stopped parsing!\n");
-            }
-            pszSym = pszDllEnd + 1;
-        }
-
-        if (*pszSym != '@' || pszSym[1] == ' ' || pszSym[1] == '\t' || pszSym[1] == '\0')
-        {
-            LIBC_ASSERTM_FAILED("missformed export specification; '%s'\n", psz);
-            LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (3)! stopped parsing!\n");
-        }
-        pszSym++;
-        pszSymEnd = strpbrk(pszSym, " \t;@'\"");
-        if (!pszSymEnd)
-            pszSymEnd = strchr(pszSym, '\0');
-
-        if (pszDllEnd - pszDll >= sizeof(szDll))
-        {
-            LIBC_ASSERTM_FAILED("dll name is too long! %d bytes ; '%s'\n", pszDllEnd - pszDll, psz);
-            LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (4)! stopped parsing!\n");
-        }
-
-        if (pszSymEnd - pszSym >= sizeof(szSym))
-        {
-            LIBC_ASSERTM_FAILED("symbol name is too long! %d bytes ; '%s'\n", pszSymEnd - pszSym, psz);
-            LIBCLOG_RETURN_MSG_VOID("ret void. bad spec (4)! stopped parsing!\n");
-        }
-
-        /*
-         * Load the DLL.
-         */
-        memcpy(szDll, pszDll, pszDllEnd - pszDll);
-        szDll[pszDllEnd - pszDll] = '\0';
-        #if defined(DEBUG_LOGGING) || defined(__LIBC_STRICT)
-        rc = DosLoadModule((PSZ)szSym, sizeof(szSym), (PCSZ)szDll, &hmod);
-        #else
-        rc = DosLoadModule(NULL, 0, (PCSZ)szDll, &hmod);
-        #endif
-        if (!rc)
-        {
-            void (*pfnRewriter)(int (*pfnAdd)(), int (*pfnRemove)(), int (*pfnRewrite)());
-
-            /*
-             * Resolve the symbol.
-             */
-            memcpy(szSym, pszSym, pszSymEnd - pszSym);
-            szSym[pszSymEnd - pszSym] = '\0';
-            rc = DosQueryProcAddr(hmod, 0, (PSZ)szSym, (PFN*)(void *)&pfnRewriter);
-            if (!rc)
-            {
-                LIBCLOG_MSG("Successfully loaded and resolved rewriter '%s' in '%s' to %p\n",
-                            szSym, szDll, (void*)pfnRewriter);
-                pfnRewriter(__libc_PathRewriteAdd, __libc_PathRewriteRemove, __libc_PathRewrite);
-            }
-            else
-                LIBC_ASSERTM_FAILED("Failed to resolve rewriter '%s' in '%s', rc=%lu\n", szSym, szDll, rc);
-        }
-        else
-            LIBC_ASSERTM_FAILED("Failed to load rewriter '%s', rc=%lu szObj='%s'\n", szDll, rc, szSym);
-
-        /*
-         * Next part.
-         */
-        psz = pszSymEnd;
-    }
-
-    LIBCLOG_RETURN_VOID();
-    pfnDummy = pfnDummy;
-}
-
-
-
-/** @todo proper cleanup for non process term. */
-#if 0
-void __libc_pathRewriteTerm(void)
-{
-
-}
-_CRT_TERM1(__libc_pathRewriteTerm);
-#endif
-
-
 
 /**
@@ -553,8 +386,4 @@
     LIBCLOG_ENTER("paRules=%p cRules=%d\n", (void*)paRules, cRules);
     int i;
-
-    /* 'Random' init order forces this. :/ */
-    if (!gfInited)
-         __libc_pathRewriteInit();
 
     /*
@@ -699,8 +528,4 @@
     int i;
 
-    /* 'Random' init order forces this. :/ */
-    if (!gfInited)
-         __libc_pathRewriteInit();
-
     /*
      * Validation.
@@ -842,8 +667,4 @@
     const char         *psz;
     const char         *pszBest;
-
-    /* 'Random' init order forces this. :/ */
-    if (!gfInited)
-         __libc_pathRewriteInit();
 
     /*
Index: /trunk/src/emx/src/lib/sys/syscalls.h
===================================================================
--- /trunk/src/emx/src/lib/sys/syscalls.h	(revision 2020)
+++ /trunk/src/emx/src/lib/sys/syscalls.h	(revision 2021)
@@ -117,5 +117,5 @@
  * @{ */
 extern void             __init(int fFlags);
-extern int              __init_dll(int fFlags);
+extern int              __init_dll(int fFlags, unsigned long hmod);
 extern void /*volatile*/_sys_init_ret(void *stack) __attribute__((__noreturn__));
 extern int              _sys_init_environ(const char *pszEnv);
