Index: __initdll.c
===================================================================
--- __initdll.c	(revision 3657)
+++ __initdll.c	(working copy)
@@ -17,6 +17,7 @@
 #include "libc-alias.h"
 #define INCL_DOS
 #define INCL_FSMACROS
+#define INCL_WINSHELLDATA
 #include <os2emx.h>
 #define _osmajor __osminor
 #define _osminor __osminor
@@ -79,8 +80,161 @@
 static int initdllForkChild1(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
 static int initdllForkTLM(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg);
 
+/**
+ * Reads new variables from appkey and adds to environment.
+ * Supports macro expansion (only for current key name).
+ * Handles also special cases for BEGINLIBPATH and ENDLIBPATH.
+ *
+ * @returns  0 always.
+ * @param   appkey Name of application key in USER_INI.
+ * @param   ulSize size of application key data.
+ */
+int __sys_init_environ_ini(char* appkey, ULONG ulSize) {
 
+    PBYTE pData, pValue;
+    PBYTE pKey, pMacro;
+    PBYTE pSubst, pPrevious;
+    ULONG ulApp, ulValue;
+    ULONG ulPrevious;
+    ULONG ulMacro;
+    APIRET rc;
+
+    // query enumeration data
+    pData = malloc( ulSize);
+    ulApp = PrfQueryProfileString( HINI_USERPROFILE, appkey, NULL, "", pData, ulSize);
+    // size includes also 0-terminator
+    if (ulApp == 0 || ulApp == 1) {
+        free( pData);
+        return 0;
+    }
+
+    // allocate for macro expansion
+    pMacro = malloc( ulSize + 2); 
+
+    // data buffer is a null terminated array (double null at end)
+    pKey = pData;
+    while (*pKey) {
+
+        // query key value
+        if (PrfQueryProfileSize( HINI_USERPROFILE, appkey, pKey, &ulValue) && ulValue) {
+            pValue = malloc( ulValue);
+            PrfQueryProfileString( HINI_USERPROFILE, appkey, pKey, "", pValue, ulValue);
+
+	    // check for variable expansion
+	    if (strchr( pValue, '%')) {
+                strcpy( pMacro, "%");
+                strcat( pMacro, pKey);
+                strcat( pMacro, "%");
+                // check if current variable expansion required
+                if (pSubst = strstr( pValue, pMacro)) {
+                    char        libPath[1024];
+
+                    // handle special cases for BEGINLIBPATH/ENDLIBPATH
+                    memset( libPath, 0, sizeof(libPath));
+                    if (!strcmp( pKey, "BEGINLIBPATH")) {
+                        rc = DosQueryExtLIBPATH( libPath, BEGIN_LIBPATH);
+                        pPrevious = libPath;
+                    } else if (!strcmp( pKey, "ENDLIBPATH")) {
+                        rc = DosQueryExtLIBPATH( libPath, END_LIBPATH);
+                        pPrevious = libPath;
+                    } else
+                        pPrevious = getenv( pKey);
+                    
+                    ulPrevious = strlen( pPrevious);
+                    ulMacro = strlen( pMacro);
+                    
+                    PBYTE pNew = malloc( ulValue + ulPrevious);
+                    // copy left lpart
+                    memcpy( pNew, pValue, pSubst - pValue);
+                    // add old value
+                    memcpy( pNew + (pSubst - pValue), pPrevious, ulPrevious);
+                    // add right part with 0-terminator
+                    strcpy( pNew + (pSubst - pValue) + ulPrevious, pSubst + ulMacro);
+                    // exchange data
+                    free( pValue);
+                    pValue = pNew;
+                }
+	    }
+
+            // handle special cases for BEGINLIBPATH/ENDLIBPATH
+            if (!strcmp( pKey, "BEGINLIBPATH"))
+                rc = DosSetExtLIBPATH( pValue, BEGIN_LIBPATH);
+            else if (!strcmp( pKey, "ENDLIBPATH"))
+                rc = DosSetExtLIBPATH( pValue, END_LIBPATH);
+            else if (*pValue == 0)
+                // if empty value, remove from environment
+                unsetenv( pKey);
+            else
+                // add/overwrite to current environment
+                setenv( pKey, pValue, 1);
+            free( pValue);
+        }
+
+        // get next variable
+        while(*pKey)
+            pKey++;
+        pKey++;
+    }
+
+    free( pMacro);
+    free( pData);
+
+    //done
+    return 0;
+}
+
 /**
+ * Initialized environment reading USER_INI variables.
+ * Reads USER_INI for following keys in sequence:
+ * KLIBC
+ * KLIBC_MYPROGRAM.EXE
+ * KLIBC_X:\PATH\MYPROGRAM.EXE
+ *
+ * For every key adds new variables to current environment (or replaces variables)
+ *
+ * @returns  0 always.
+ */
+int _sys_init_environ_ini(void) {
+    HAB        hab;
+    ULONG    ulSize = 0L;
+    APIRET    rc;
+    PPIB        pib;
+    CHAR      Buff[_MAX_PATH];
+    CHAR      AppKey[_MAX_PATH+10];
+    char        fname[_MAX_FNAME], ext[_MAX_EXT];
+
+    // enumerate LIBC global key
+    if (PrfQueryProfileSize( HINI_USERPROFILE, "KLIBC", NULL, &ulSize) && ulSize) {
+        rc = __sys_init_environ_ini( "KLIBC", ulSize);
+    }
+    
+    // get executable fullpath
+    rc = DosGetInfoBlocks( NULL, &pib);
+    rc = DosQueryModuleName( pib->pib_hmte, sizeof(Buff), Buff);
+    // extract path info
+    _splitpath( Buff, NULL, NULL, fname, ext);
+
+    // enumerate LIBC process key
+    strcpy( AppKey, "KLIBC_");
+    strcat( AppKey, fname);
+    strcat( AppKey, ext);
+    if (PrfQueryProfileSize( HINI_USERPROFILE, AppKey, NULL, &ulSize) && ulSize) {
+        rc = __sys_init_environ_ini( AppKey, ulSize);
+    }
+
+    // enumerate LIBC process full path key
+    strcpy( AppKey, "KLIBC_");
+    strcat( AppKey, Buff);
+    if (PrfQueryProfileSize( HINI_USERPROFILE, AppKey, NULL, &ulSize) && ulSize) {
+        rc = __sys_init_environ_ini( AppKey, ulSize);
+    }
+
+    // done
+    return 0;
+}
+
+
+/**
  * Common init code for crt0 and dll0.
  * This should perhaps be a part of _CRT_init.
  *
@@ -178,6 +332,16 @@
     }
 
     /*
+     * Setup environment using INI values
+     */
+    rc = _sys_init_environ_ini();
+    if (rc)
+    {
+        LIBC_ASSERTM_FAILED("_sys_init_environ_ini() failed\n");
+        return -1;
+    }
+
+    /*
      * Get the current process.
      */
     pSelf = __libc_spmSelf();
