Ticket #225: env_ini_2.patch

File env_ini_2.patch, 6.2 KB (added by ydario, 9 years ago)

macro expansion and beginlibpath/endlibpath support.

  • __initdll.c

     
    1717#include "libc-alias.h"
    1818#define INCL_DOS
    1919#define INCL_FSMACROS
     20#define INCL_WINSHELLDATA
    2021#include <os2emx.h>
    2122#define _osmajor __osminor
    2223#define _osminor __osminor
     
    7980static int initdllForkChild1(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
    8081static int initdllForkTLM(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg);
    8182
     83/**
     84 * Reads new variables from appkey and adds to environment.
     85 * Supports macro expansion (only for current key name).
     86 * Handles also special cases for BEGINLIBPATH and ENDLIBPATH.
     87 *
     88 * @returns  0 always.
     89 * @param   appkey Name of application key in USER_INI.
     90 * @param   ulSize size of application key data.
     91 */
     92int __sys_init_environ_ini(char* appkey, ULONG ulSize) {
    8293
     94    PBYTE pData, pValue;
     95    PBYTE pKey, pMacro;
     96    PBYTE pSubst, pPrevious;
     97    ULONG ulApp, ulValue;
     98    ULONG ulPrevious;
     99    ULONG ulMacro;
     100    APIRET rc;
     101
     102    // query enumeration data
     103    pData = malloc( ulSize);
     104    ulApp = PrfQueryProfileString( HINI_USERPROFILE, appkey, NULL, "", pData, ulSize);
     105    // size includes also 0-terminator
     106    if (ulApp == 0 || ulApp == 1) {
     107        free( pData);
     108        return 0;
     109    }
     110
     111    // allocate for macro expansion
     112    pMacro = malloc( ulSize + 2);
     113
     114    // data buffer is a null terminated array (double null at end)
     115    pKey = pData;
     116    while (*pKey) {
     117
     118        // query key value
     119        if (PrfQueryProfileSize( HINI_USERPROFILE, appkey, pKey, &ulValue) && ulValue) {
     120            pValue = malloc( ulValue);
     121            PrfQueryProfileString( HINI_USERPROFILE, appkey, pKey, "", pValue, ulValue);
     122
     123            // check for variable expansion
     124            if (strchr( pValue, '%')) {
     125                strcpy( pMacro, "%");
     126                strcat( pMacro, pKey);
     127                strcat( pMacro, "%");
     128                // check if current variable expansion required
     129                if (pSubst = strstr( pValue, pMacro)) {
     130                    char        libPath[1024];
     131
     132                    // handle special cases for BEGINLIBPATH/ENDLIBPATH
     133                    memset( libPath, 0, sizeof(libPath));
     134                    if (!strcmp( pKey, "BEGINLIBPATH")) {
     135                        rc = DosQueryExtLIBPATH( libPath, BEGIN_LIBPATH);
     136                        pPrevious = libPath;
     137                    } else if (!strcmp( pKey, "ENDLIBPATH")) {
     138                        rc = DosQueryExtLIBPATH( libPath, END_LIBPATH);
     139                        pPrevious = libPath;
     140                    } else
     141                        pPrevious = getenv( pKey);
     142                   
     143                    ulPrevious = strlen( pPrevious);
     144                    ulMacro = strlen( pMacro);
     145                   
     146                    PBYTE pNew = malloc( ulValue + ulPrevious);
     147                    // copy left lpart
     148                    memcpy( pNew, pValue, pSubst - pValue);
     149                    // add old value
     150                    memcpy( pNew + (pSubst - pValue), pPrevious, ulPrevious);
     151                    // add right part with 0-terminator
     152                    strcpy( pNew + (pSubst - pValue) + ulPrevious, pSubst + ulMacro);
     153                    // exchange data
     154                    free( pValue);
     155                    pValue = pNew;
     156                }
     157            }
     158
     159            // handle special cases for BEGINLIBPATH/ENDLIBPATH
     160            if (!strcmp( pKey, "BEGINLIBPATH"))
     161                rc = DosSetExtLIBPATH( pValue, BEGIN_LIBPATH);
     162            else if (!strcmp( pKey, "ENDLIBPATH"))
     163                rc = DosSetExtLIBPATH( pValue, END_LIBPATH);
     164            else if (*pValue == 0)
     165                // if empty value, remove from environment
     166                unsetenv( pKey);
     167            else
     168                // add/overwrite to current environment
     169                setenv( pKey, pValue, 1);
     170            free( pValue);
     171        }
     172
     173        // get next variable
     174        while(*pKey)
     175            pKey++;
     176        pKey++;
     177    }
     178
     179    free( pMacro);
     180    free( pData);
     181
     182    //done
     183    return 0;
     184}
     185
    83186/**
     187 * Initialized environment reading USER_INI variables.
     188 * Reads USER_INI for following keys in sequence:
     189 * KLIBC
     190 * KLIBC_MYPROGRAM.EXE
     191 * KLIBC_X:\PATH\MYPROGRAM.EXE
     192 *
     193 * For every key adds new variables to current environment (or replaces variables)
     194 *
     195 * @returns  0 always.
     196 */
     197int _sys_init_environ_ini(void) {
     198    HAB        hab;
     199    ULONG    ulSize = 0L;
     200    APIRET    rc;
     201    PPIB        pib;
     202    CHAR      Buff[_MAX_PATH];
     203    CHAR      AppKey[_MAX_PATH+10];
     204    char        fname[_MAX_FNAME], ext[_MAX_EXT];
     205
     206    // enumerate LIBC global key
     207    if (PrfQueryProfileSize( HINI_USERPROFILE, "KLIBC", NULL, &ulSize) && ulSize) {
     208        rc = __sys_init_environ_ini( "KLIBC", ulSize);
     209    }
     210   
     211    // get executable fullpath
     212    rc = DosGetInfoBlocks( NULL, &pib);
     213    rc = DosQueryModuleName( pib->pib_hmte, sizeof(Buff), Buff);
     214    // extract path info
     215    _splitpath( Buff, NULL, NULL, fname, ext);
     216
     217    // enumerate LIBC process key
     218    strcpy( AppKey, "KLIBC_");
     219    strcat( AppKey, fname);
     220    strcat( AppKey, ext);
     221    if (PrfQueryProfileSize( HINI_USERPROFILE, AppKey, NULL, &ulSize) && ulSize) {
     222        rc = __sys_init_environ_ini( AppKey, ulSize);
     223    }
     224
     225    // enumerate LIBC process full path key
     226    strcpy( AppKey, "KLIBC_");
     227    strcat( AppKey, Buff);
     228    if (PrfQueryProfileSize( HINI_USERPROFILE, AppKey, NULL, &ulSize) && ulSize) {
     229        rc = __sys_init_environ_ini( AppKey, ulSize);
     230    }
     231
     232    // done
     233    return 0;
     234}
     235
     236
     237/**
    84238 * Common init code for crt0 and dll0.
    85239 * This should perhaps be a part of _CRT_init.
    86240 *
     
    178332    }
    179333
    180334    /*
     335     * Setup environment using INI values
     336     */
     337    rc = _sys_init_environ_ini();
     338    if (rc)
     339    {
     340        LIBC_ASSERTM_FAILED("_sys_init_environ_ini() failed\n");
     341        return -1;
     342    }
     343
     344    /*
    181345     * Get the current process.
    182346     */
    183347    pSelf = __libc_spmSelf();