| 1 | /* $Id: kLdrHlp.c 2944 2007-01-13 15:55:40Z bird $ */
 | 
|---|
| 2 | /** @file
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  * kLdr - The Dynamic Loader, Misc Helper Functions.
 | 
|---|
| 5 |  *
 | 
|---|
| 6 |  * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
 | 
|---|
| 7 |  *
 | 
|---|
| 8 |  *
 | 
|---|
| 9 |  * This file is part of kLdr.
 | 
|---|
| 10 |  *
 | 
|---|
| 11 |  * kLdr is free software; you can redistribute it and/or modify
 | 
|---|
| 12 |  * it under the terms of the GNU General Public License as published by
 | 
|---|
| 13 |  * the Free Software Foundation; either version 2 of the License, or
 | 
|---|
| 14 |  * (at your option) any later version.
 | 
|---|
| 15 |  *
 | 
|---|
| 16 |  * kLdr is distributed in the hope that it will be useful,
 | 
|---|
| 17 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 18 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 19 |  * GNU General Public License for more details.
 | 
|---|
| 20 |  *
 | 
|---|
| 21 |  * You should have received a copy of the GNU General Public License
 | 
|---|
| 22 |  * along with kLdr; if not, write to the Free Software
 | 
|---|
| 23 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|---|
| 24 |  *
 | 
|---|
| 25 |  */
 | 
|---|
| 26 | 
 | 
|---|
| 27 | 
 | 
|---|
| 28 | /*******************************************************************************
 | 
|---|
| 29 | *   Header Files                                                               *
 | 
|---|
| 30 | *******************************************************************************/
 | 
|---|
| 31 | #ifdef __OS2__
 | 
|---|
| 32 | # define INCL_BASE
 | 
|---|
| 33 | # define INCL_ERRORS
 | 
|---|
| 34 | # include <os2.h>
 | 
|---|
| 35 | #elif defined(__WIN__)
 | 
|---|
| 36 | # include <Windows.h>
 | 
|---|
| 37 | #else
 | 
|---|
| 38 | # error "port me"
 | 
|---|
| 39 | #endif
 | 
|---|
| 40 | 
 | 
|---|
| 41 | #include <kLdr.h>
 | 
|---|
| 42 | #include "kLdrHlp.h"
 | 
|---|
| 43 | 
 | 
|---|
| 44 | 
 | 
|---|
| 45 | /**
 | 
|---|
| 46 |  * Get an environment variable.
 | 
|---|
| 47 |  *
 | 
|---|
| 48 |  * @returns 0 on success.
 | 
|---|
| 49 |  * @returns KLDR_ERR_BUFFER_OVERFLOW on if the buffer is too small.
 | 
|---|
| 50 |  * @returns KLDR_ERR_SYMBOL_NOT_FOUND if not found. (Yeah, abusing the status code, but it's only internally...)
 | 
|---|
| 51 |  * @returns OS specfic status code on other error.
 | 
|---|
| 52 |  * @param   pszVar      The variable name.
 | 
|---|
| 53 |  * @param   pszVal      Where to store the value.
 | 
|---|
| 54 |  * @param   cchVal      The size of the buffer pointed to by pszVal.
 | 
|---|
| 55 |  */
 | 
|---|
| 56 | int     kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t cchVal)
 | 
|---|
| 57 | {
 | 
|---|
| 58 | #ifdef __OS2__
 | 
|---|
| 59 |     PSZ pszValue = NULL;
 | 
|---|
| 60 |     int rc;
 | 
|---|
| 61 | 
 | 
|---|
| 62 |     *pszVal = '\0';
 | 
|---|
| 63 |     rc = DosScanEnv((PCSZ)pszVar, &pszValue);
 | 
|---|
| 64 |     if (!rc)
 | 
|---|
| 65 |     {
 | 
|---|
| 66 |         size_t cch = kLdrHlpStrLen((const char *)pszValue);
 | 
|---|
| 67 |         if (cchVal > cch)
 | 
|---|
| 68 |             kLdrHlpMemCopy(pszVal, pszValue, cch + 1);
 | 
|---|
| 69 |         else
 | 
|---|
| 70 |             rc = KLDR_ERR_BUFFER_OVERFLOW;
 | 
|---|
| 71 |     }
 | 
|---|
| 72 |     else
 | 
|---|
| 73 |         rc = KLDR_ERR_SYMBOL_NOT_FOUND;
 | 
|---|
| 74 |     return rc;
 | 
|---|
| 75 | 
 | 
|---|
| 76 | #elif defined(__WIN__)
 | 
|---|
| 77 |     DWORD cch;
 | 
|---|
| 78 | 
 | 
|---|
| 79 |     SetLastError(0);
 | 
|---|
| 80 |     cch = GetEnvironmentVariable(pszVar, pszVal, cchVal);
 | 
|---|
| 81 |     if (cch > 0 && cch < cchVal)
 | 
|---|
| 82 |         return 0;
 | 
|---|
| 83 | 
 | 
|---|
| 84 |     *pszVal = '\0';
 | 
|---|
| 85 |     if (cch >= cchVal)
 | 
|---|
| 86 |         return KLDR_ERR_BUFFER_OVERFLOW;
 | 
|---|
| 87 |     if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
 | 
|---|
| 88 |         return KLDR_ERR_SYMBOL_NOT_FOUND;
 | 
|---|
| 89 |     return GetLastError();
 | 
|---|
| 90 | 
 | 
|---|
| 91 | #else
 | 
|---|
| 92 | # error "Port me"
 | 
|---|
| 93 | #endif
 | 
|---|
| 94 | }
 | 
|---|
| 95 | 
 | 
|---|
| 96 | 
 | 
|---|
| 97 | /**
 | 
|---|
| 98 |  * Gets an environment variable and converts it to a size_t.
 | 
|---|
| 99 |  *
 | 
|---|
| 100 |  * @returns 0 and *pcb on success.
 | 
|---|
| 101 |  * @returns On failure see kldrHlpGetEnv.
 | 
|---|
| 102 |  * @param   pszVar  The name of the variable.
 | 
|---|
| 103 |  * @param   pcb     Where to put the value.
 | 
|---|
| 104 |  */
 | 
|---|
| 105 | int     kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb)
 | 
|---|
| 106 | {
 | 
|---|
| 107 |     size_t      cb;
 | 
|---|
| 108 |     unsigned    uBase;
 | 
|---|
| 109 |     char        szVal[64];
 | 
|---|
| 110 |     size_t      cchVal = sizeof(szVal);
 | 
|---|
| 111 |     const char *psz;
 | 
|---|
| 112 |     int         rc;
 | 
|---|
| 113 | 
 | 
|---|
| 114 |     *pcb = 0;
 | 
|---|
| 115 |     rc = kldrHlpGetEnv(pszVar, szVal, cchVal);
 | 
|---|
| 116 |     if (rc)
 | 
|---|
| 117 |         return rc;
 | 
|---|
| 118 | 
 | 
|---|
| 119 |     /* figure out the base. */
 | 
|---|
| 120 |     uBase = 10;
 | 
|---|
| 121 |     psz = szVal;
 | 
|---|
| 122 |     if (    *psz == '0'
 | 
|---|
| 123 |         &&  (psz[1] == 'x' || psz[1] == 'X'))
 | 
|---|
| 124 |     {
 | 
|---|
| 125 |         uBase = 16;
 | 
|---|
| 126 |         psz += 2;
 | 
|---|
| 127 |     }
 | 
|---|
| 128 | 
 | 
|---|
| 129 |     /* convert it up to the first unknown char. */
 | 
|---|
| 130 |     cb = 0;
 | 
|---|
| 131 |     for(;;)
 | 
|---|
| 132 |     {
 | 
|---|
| 133 |         const char ch = *psz;
 | 
|---|
| 134 |         unsigned uDigit;
 | 
|---|
| 135 |         if (!ch)
 | 
|---|
| 136 |             break;
 | 
|---|
| 137 |         else if (ch >= '0' && ch <= '9')
 | 
|---|
| 138 |             uDigit = ch - '0';
 | 
|---|
| 139 |         else if (ch >= 'a' && ch <= 'z')
 | 
|---|
| 140 |             uDigit = ch - 'a' + 10;
 | 
|---|
| 141 |         else if (ch >= 'A' && ch <= 'Z')
 | 
|---|
| 142 |             uDigit = ch - 'A' + 10;
 | 
|---|
| 143 |         else
 | 
|---|
| 144 |             break;
 | 
|---|
| 145 |         if (uDigit >= uBase)
 | 
|---|
| 146 |             break;
 | 
|---|
| 147 | 
 | 
|---|
| 148 |         /* add the digit */
 | 
|---|
| 149 |         cb *= uBase;
 | 
|---|
| 150 |         cb += uDigit;
 | 
|---|
| 151 | 
 | 
|---|
| 152 |         psz++;
 | 
|---|
| 153 |     }
 | 
|---|
| 154 | 
 | 
|---|
| 155 |     /* check for unit */
 | 
|---|
| 156 |     if (*psz == 'm' || *psz == 'M')
 | 
|---|
| 157 |         cb *= 1024*1024;
 | 
|---|
| 158 |     else if (*psz == 'k' ||*psz == 'K')
 | 
|---|
| 159 |         cb *= 1024;
 | 
|---|
| 160 |     else if (*psz == 'g' || *psz == 'G')
 | 
|---|
| 161 |         cb *= 1024*1024*1024;
 | 
|---|
| 162 | 
 | 
|---|
| 163 |     *pcb = cb;
 | 
|---|
| 164 |     return 0;
 | 
|---|
| 165 | }
 | 
|---|
| 166 | 
 | 
|---|
| 167 | 
 | 
|---|
| 168 | /**
 | 
|---|
| 169 |  * Terminate the process.
 | 
|---|
| 170 |  *
 | 
|---|
| 171 |  * @param   rc      The exit status.
 | 
|---|
| 172 |  */
 | 
|---|
| 173 | void    kldrHlpExit(int rc)
 | 
|---|
| 174 | {
 | 
|---|
| 175 |     for (;;)
 | 
|---|
| 176 |     {
 | 
|---|
| 177 | #ifdef __OS2__
 | 
|---|
| 178 |         DosExit(EXIT_PROCESS, rc);
 | 
|---|
| 179 | 
 | 
|---|
| 180 | #elif defined(__WIN__)
 | 
|---|
| 181 |         TerminateProcess(GetCurrentProcess(), rc);
 | 
|---|
| 182 | 
 | 
|---|
| 183 | #else
 | 
|---|
| 184 | # error "Port me"
 | 
|---|
| 185 | #endif
 | 
|---|
| 186 |         kldrHlpAssert(!"Impossible");
 | 
|---|
| 187 |     }
 | 
|---|
| 188 | }
 | 
|---|
| 189 | 
 | 
|---|
| 190 | 
 | 
|---|
| 191 | /**
 | 
|---|
| 192 |  * Sleep for a number of milliseconds.
 | 
|---|
| 193 |  * @param   cMillies    Number of milliseconds to sleep.
 | 
|---|
| 194 |  */
 | 
|---|
| 195 | void kldrHlpSleep(unsigned cMillies)
 | 
|---|
| 196 | {
 | 
|---|
| 197 | #ifdef __OS2__
 | 
|---|
| 198 |     DosSleep(cMillies);
 | 
|---|
| 199 | #elif defined(__WIN__)
 | 
|---|
| 200 |     Sleep(cMillies);
 | 
|---|
| 201 | #else
 | 
|---|
| 202 |     usleep(cMillies * 1000);
 | 
|---|
| 203 | #endif
 | 
|---|
| 204 | }
 | 
|---|
| 205 | 
 | 
|---|
| 206 | 
 | 
|---|
| 207 | /**
 | 
|---|
| 208 |  * Writes a assert string with unix lineendings.
 | 
|---|
| 209 |  *
 | 
|---|
| 210 |  * @param   pszMsg  The string.
 | 
|---|
| 211 |  */
 | 
|---|
| 212 | static void kldrHlpAssertWrite(const char *pszMsg)
 | 
|---|
| 213 | {
 | 
|---|
| 214 | #if defined(__OS2__) || defined(__WIN__)
 | 
|---|
| 215 |     /*
 | 
|---|
| 216 |      * Line by line.
 | 
|---|
| 217 |      */
 | 
|---|
| 218 |     ULONG       cbWritten;
 | 
|---|
| 219 |     const char *pszNl = kLdrHlpStrChr(pszMsg, '\n');
 | 
|---|
| 220 |     while (pszNl)
 | 
|---|
| 221 |     {
 | 
|---|
| 222 |         cbWritten = pszNl - pszMsg;
 | 
|---|
| 223 | 
 | 
|---|
| 224 | #ifdef __OS2__
 | 
|---|
| 225 |         if (cbWritten)
 | 
|---|
| 226 |             DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
 | 
|---|
| 227 |         DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
 | 
|---|
| 228 | #else /* __WIN32__ */
 | 
|---|
| 229 |         if (cbWritten)
 | 
|---|
| 230 |             WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
 | 
|---|
| 231 |         WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
 | 
|---|
| 232 | #endif
 | 
|---|
| 233 | 
 | 
|---|
| 234 |         /* next */
 | 
|---|
| 235 |         pszMsg = pszNl + 1;
 | 
|---|
| 236 |         pszNl = kLdrHlpStrChr(pszMsg, '\n');
 | 
|---|
| 237 |     }
 | 
|---|
| 238 | 
 | 
|---|
| 239 |     /*
 | 
|---|
| 240 |      * Remaining incomplete line.
 | 
|---|
| 241 |      */
 | 
|---|
| 242 |     if (*pszMsg)
 | 
|---|
| 243 |     {
 | 
|---|
| 244 |         cbWritten = kLdrHlpStrLen(pszMsg);
 | 
|---|
| 245 | #ifdef __OS2__
 | 
|---|
| 246 |         DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
 | 
|---|
| 247 | #else /* __WIN32__ */
 | 
|---|
| 248 |         WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
 | 
|---|
| 249 | #endif
 | 
|---|
| 250 |     }
 | 
|---|
| 251 | 
 | 
|---|
| 252 | #else
 | 
|---|
| 253 | # error "port me"
 | 
|---|
| 254 | #endif
 | 
|---|
| 255 | }
 | 
|---|
| 256 | 
 | 
|---|
| 257 | 
 | 
|---|
| 258 | /**
 | 
|---|
| 259 |  * Internal worker for the kLdrHlpAssert() macro.
 | 
|---|
| 260 |  *
 | 
|---|
| 261 |  * @param   pszExpr         The assert expression.
 | 
|---|
| 262 |  * @param   pszFile         The filename.
 | 
|---|
| 263 |  * @param   iLine           The line number.
 | 
|---|
| 264 |  * @param   pszFunction     The function name.
 | 
|---|
| 265 |  */
 | 
|---|
| 266 | void    kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
 | 
|---|
| 267 | {
 | 
|---|
| 268 |     char szLine[16];
 | 
|---|
| 269 | 
 | 
|---|
| 270 |     kldrHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
 | 
|---|
| 271 |     kldrHlpAssertWrite(pszExpr);
 | 
|---|
| 272 |     kldrHlpAssertWrite("\nAt: ");
 | 
|---|
| 273 |     kldrHlpAssertWrite(pszFile);
 | 
|---|
| 274 |     kldrHlpAssertWrite("(");
 | 
|---|
| 275 |     kldrHlpAssertWrite(kldrHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
 | 
|---|
| 276 |     kldrHlpAssertWrite(") ");
 | 
|---|
| 277 |     kldrHlpAssertWrite(pszFunction);
 | 
|---|
| 278 |     kldrHlpAssertWrite("\n");
 | 
|---|
| 279 | }
 | 
|---|
| 280 | 
 | 
|---|