00001 /*---------------------------------------------------------------------------- 00002 Name: Properties.c 00003 Project: xmlBlaster.org 00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 00005 Comment: A tiny helper to encapsulate command line and environment properties 00006 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info> 00007 Compile: gcc -DPropertiesMain -D_ENABLE_STACK_TRACE_ -rdynamic -export-dynamic -Wall -pedantic -g -D_REENTRANT -I.. -o PropertiesMain Properties.c 00008 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.socket.html 00009 -----------------------------------------------------------------------------*/ 00010 00011 #include <stdio.h> 00012 #include <stdlib.h> 00013 #include <string.h> 00014 /*#include <errno.h>*/ 00015 /*#include <sys/types.h>*/ 00016 #include "helper.h" 00017 #include "Properties.h" 00018 00019 static const char *getString(Properties *props, const char *key, const char *defaultValue); 00020 static bool getBool(Properties *props, const char *key, bool defaultValue); 00021 static int getInt(Properties *props, const char *key, int defaultValue); 00022 static long getLong(Properties *props, const char *key, long defaultValue); 00023 static int64_t getInt64(Properties *props, const char *key, int64_t defaultValue); 00024 00035 Properties *createProperties(int argc, const char* const* argv) { 00036 int iarg; 00037 Properties *props = (Properties *)calloc(1, sizeof(Properties)); 00038 props->argc = 0; 00039 props->argv = 0; 00040 props->execName = (argv != 0) ? argv[0] : __FILE__; 00041 props->getString = getString; 00042 props->getBool = getBool; 00043 props->getInt = getInt; 00044 props->getLong = getLong; 00045 props->getInt64 = getInt64; 00046 00047 if (argc > 1) { 00048 /* strip the executable name and the dash '-' */ 00049 props->argc = argc-1; 00050 props->argv = (char **)calloc(props->argc, sizeof(char *)); 00051 for (iarg=1; iarg < argc; iarg++) { 00052 if (argv[iarg] == 0 || strlen(argv[iarg]) == 0) 00053 props->argv[iarg-1] = (char *)argv[iarg]; 00054 else if ((iarg % 2) == 1 && *argv[iarg] == '-') 00055 props->argv[iarg-1] = (char *)argv[iarg]+1; 00056 else 00057 props->argv[iarg-1] = (char *)argv[iarg]; 00058 } 00059 } 00060 return props; 00061 } 00062 00063 void freeProperties(Properties *props) 00064 { 00065 if (props == 0) return; 00066 00067 if (props->argc > 0) { 00068 free(props->argv); 00069 props->argc = 0; 00070 props->argv = 0; 00071 } 00072 free(props); 00073 } 00074 00078 void dumpProperties(Properties *props) 00079 { 00080 int iarg; 00081 if (props == 0) return; 00082 00083 for (iarg=0; iarg < props->argc-1; iarg++) { 00084 printf("#%d, %s=%s\n", iarg, props->argv[iarg], props->argv[iarg+1]); 00085 iarg++; 00086 } 00087 } 00088 00092 static const char *getString(Properties *props, const char *key, const char *defaultValue) 00093 { 00094 int iarg; 00095 00096 if (key == 0) return defaultValue; 00097 00098 for (iarg=0; iarg < props->argc-1; iarg++) { 00099 if (strcmp(props->argv[iarg], key) == 0) 00100 return props->argv[++iarg]; 00101 } 00102 00103 /* 00104 WIN32 00105 char *pValue; 00106 size_t len; 00107 errno_t err = _dupenv_s( &pValue, &len, "pathext" ); 00108 // returns 0 if not found! 00109 if ( err ) return -1; 00110 printf( "pathext = %s\n", pValue ); 00111 free( pValue ); 00112 err = _dupenv_s( &pValue, &len, "nonexistentvariable" ); 00113 if ( err ) return -1; 00114 printf( "nonexistentvariable = %s\n", pValue ); 00115 free( pValue ); // It's OK to call free with NULL 00116 00117 // not thread save as putenv could change 00118 errno_t getenv_s(size_t *pReturnValue, char* buffer, size_t sizeInBytes, const char *varname); 00119 00120 00121 UNIX: int getenv_r(const char *name, char *buf, size_t len); 00122 returns -1 if not found 00123 */ 00124 #if !defined(WINCE) /* Where is the getenv() for Windows CE? */ 00125 { 00126 const char *p = getenv(key); 00127 if (p != 0) return p; 00128 } 00129 #endif 00130 00131 return defaultValue; 00132 } 00133 00134 static bool getBool(Properties *props, const char *key, bool defaultValue) 00135 { 00136 const char *valP = getString(props, key, 0); 00137 if (valP != 0) { 00138 if (!strcmp(valP, "false") || !strcmp(valP, "FALSE") || !strcmp(valP, "0")) 00139 return false; 00140 else 00141 return true; 00142 } 00143 return defaultValue; 00144 } 00145 00146 static int getInt(Properties *props, const char *key, int defaultValue) 00147 { 00148 return (int)getLong(props, key, defaultValue); 00149 } 00150 00151 static long getLong(Properties *props, const char *key, long defaultValue) 00152 { 00153 const char *valP = getString(props, key, 0); 00154 if (valP != 0) { 00155 long val; 00156 if (strToLong(&val, valP) == true) 00157 return val; 00158 } 00159 return defaultValue; 00160 } 00161 00162 static int64_t getInt64(Properties *props, const char *key, int64_t defaultValue) 00163 { 00164 const char *valP = getString(props, key, 0); 00165 if (valP != 0) { 00166 int64_t val; 00167 if (strToInt64(&val, valP) == true) 00168 return val; 00169 } 00170 return defaultValue; 00171 } 00172 00173 #ifdef PropertiesMain /* compile a standalone test program */ 00174 00175 Dll_Export bool strToInt64(int64_t *val, const char * const str) { 00176 if (str == 0 || val == 0) return false; 00177 return (SSCANF(str, PRINTF_PREFIX_INT64_T, val) == 1) ? true : false; 00178 } 00179 00186 int main(int argc, char** argv) 00187 { 00188 Properties *props = createProperties(argc, (const char* const*)argv); 00189 printf("MY_SETTING=%s\n", props->getString(props, "MY_SETTING", "DUMMY")); 00190 printf("logLevel=%s\n", props->getString(props, "logLevel", "DUMMY")); 00191 printf("isPersistent=%d\n", props->getBool(props, "isPersistent", false)); 00192 printf("isDurable=%d\n", props->getBool(props, "isDurable", true)); 00193 printf("numTests=%d\n", props->getInt(props, "numTests", -1)); 00194 printf("timeout=%ld\n", props->getLong(props, "timeout", -1l)); 00195 printf("timeout="PRINTF_PREFIX_INT64_T"\n", props->getInt64(props, "lonLong", -1LL)); /* "%I64d", "%ld", "%lld" */ 00196 freeProperties(props); 00197 return 0; 00198 } 00199 #endif /* #ifdef PropertiesMain */ 00200