/* $Id: kLdrHlp.c 2944 2007-01-13 15:55:40Z bird $ */ /** @file * * kLdr - The Dynamic Loader, Misc Helper Functions. * * Copyright (c) 2006 knut st. osmundsen * * * This file is part of kLdr. * * kLdr 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. * * kLdr 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 kLdr; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifdef __OS2__ # define INCL_BASE # define INCL_ERRORS # include #elif defined(__WIN__) # include #else # error "port me" #endif #include #include "kLdrHlp.h" /** * Get an environment variable. * * @returns 0 on success. * @returns KLDR_ERR_BUFFER_OVERFLOW on if the buffer is too small. * @returns KLDR_ERR_SYMBOL_NOT_FOUND if not found. (Yeah, abusing the status code, but it's only internally...) * @returns OS specfic status code on other error. * @param pszVar The variable name. * @param pszVal Where to store the value. * @param cchVal The size of the buffer pointed to by pszVal. */ int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t cchVal) { #ifdef __OS2__ PSZ pszValue = NULL; int rc; *pszVal = '\0'; rc = DosScanEnv((PCSZ)pszVar, &pszValue); if (!rc) { size_t cch = kLdrHlpStrLen((const char *)pszValue); if (cchVal > cch) kLdrHlpMemCopy(pszVal, pszValue, cch + 1); else rc = KLDR_ERR_BUFFER_OVERFLOW; } else rc = KLDR_ERR_SYMBOL_NOT_FOUND; return rc; #elif defined(__WIN__) DWORD cch; SetLastError(0); cch = GetEnvironmentVariable(pszVar, pszVal, cchVal); if (cch > 0 && cch < cchVal) return 0; *pszVal = '\0'; if (cch >= cchVal) return KLDR_ERR_BUFFER_OVERFLOW; if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) return KLDR_ERR_SYMBOL_NOT_FOUND; return GetLastError(); #else # error "Port me" #endif } /** * Gets an environment variable and converts it to a size_t. * * @returns 0 and *pcb on success. * @returns On failure see kldrHlpGetEnv. * @param pszVar The name of the variable. * @param pcb Where to put the value. */ int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb) { size_t cb; unsigned uBase; char szVal[64]; size_t cchVal = sizeof(szVal); const char *psz; int rc; *pcb = 0; rc = kldrHlpGetEnv(pszVar, szVal, cchVal); if (rc) return rc; /* figure out the base. */ uBase = 10; psz = szVal; if ( *psz == '0' && (psz[1] == 'x' || psz[1] == 'X')) { uBase = 16; psz += 2; } /* convert it up to the first unknown char. */ cb = 0; for(;;) { const char ch = *psz; unsigned uDigit; if (!ch) break; else if (ch >= '0' && ch <= '9') uDigit = ch - '0'; else if (ch >= 'a' && ch <= 'z') uDigit = ch - 'a' + 10; else if (ch >= 'A' && ch <= 'Z') uDigit = ch - 'A' + 10; else break; if (uDigit >= uBase) break; /* add the digit */ cb *= uBase; cb += uDigit; psz++; } /* check for unit */ if (*psz == 'm' || *psz == 'M') cb *= 1024*1024; else if (*psz == 'k' ||*psz == 'K') cb *= 1024; else if (*psz == 'g' || *psz == 'G') cb *= 1024*1024*1024; *pcb = cb; return 0; } /** * Terminate the process. * * @param rc The exit status. */ void kldrHlpExit(int rc) { for (;;) { #ifdef __OS2__ DosExit(EXIT_PROCESS, rc); #elif defined(__WIN__) TerminateProcess(GetCurrentProcess(), rc); #else # error "Port me" #endif kldrHlpAssert(!"Impossible"); } } /** * Sleep for a number of milliseconds. * @param cMillies Number of milliseconds to sleep. */ void kldrHlpSleep(unsigned cMillies) { #ifdef __OS2__ DosSleep(cMillies); #elif defined(__WIN__) Sleep(cMillies); #else usleep(cMillies * 1000); #endif } /** * Writes a assert string with unix lineendings. * * @param pszMsg The string. */ static void kldrHlpAssertWrite(const char *pszMsg) { #if defined(__OS2__) || defined(__WIN__) /* * Line by line. */ ULONG cbWritten; const char *pszNl = kLdrHlpStrChr(pszMsg, '\n'); while (pszNl) { cbWritten = pszNl - pszMsg; #ifdef __OS2__ if (cbWritten) DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten); DosWrite((HFILE)2, "\r\n", 2, &cbWritten); #else /* __WIN32__ */ if (cbWritten) WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL); WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL); #endif /* next */ pszMsg = pszNl + 1; pszNl = kLdrHlpStrChr(pszMsg, '\n'); } /* * Remaining incomplete line. */ if (*pszMsg) { cbWritten = kLdrHlpStrLen(pszMsg); #ifdef __OS2__ DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten); #else /* __WIN32__ */ WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL); #endif } #else # error "port me" #endif } /** * Internal worker for the kLdrHlpAssert() macro. * * @param pszExpr The assert expression. * @param pszFile The filename. * @param iLine The line number. * @param pszFunction The function name. */ void kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction) { char szLine[16]; kldrHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: "); kldrHlpAssertWrite(pszExpr); kldrHlpAssertWrite("\nAt: "); kldrHlpAssertWrite(pszFile); kldrHlpAssertWrite("("); kldrHlpAssertWrite(kldrHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10)); kldrHlpAssertWrite(") "); kldrHlpAssertWrite(pszFunction); kldrHlpAssertWrite("\n"); }