/* GetPrivateProfileString() -- approximate implementation of */ /* Windows NT System Services version of GetPrivateProfileString() */ /* probably doesn't handle the NULL key for section name or value key */ /* correctly also, doesn't provide Microsoft backwards compatability */ /* wrt TAB characters in the value string -- Microsoft terminates value */ /* at the first TAB, but I couldn't discover what the behavior should */ /* be regarding TABS in quoted strings so, I treat tabs like any other */ /* characters -- NO comments following value string separated by a TAB */ /* are allowed (that is an anachronism anyway) */ /* Added code to search for ODBC_INI file in users home directory on */ /* Unix */ #ifndef WIN32 #if HAVE_CONFIG_H #include "config.h" /* produced by configure */ #endif #include #include #include #if HAVE_PWD_H #include #endif #include #include #include "misc.h" #include "gpps.h" #ifndef TRUE #define TRUE ((BOOL)1) #endif #ifndef FALSE #define FALSE ((BOOL)0) #endif DWORD GetPrivateProfileString(char *theSection, /* section name */ char *theKey, /* search key name */ char *theDefault, /* default value if not found */ char *theReturnBuffer, /* return value stored here */ size_t theReturnBufferLength, /* byte length of return buffer */ char *theIniFileName) /* pathname of ini file to search */ { char buf[MAXPGPATH]; char* ptr = 0; FILE* aFile = 0; size_t aLength; char aLine[2048]; char *aValue; char *aStart; char *aString; size_t aLineLength; size_t aReturnLength = 0; BOOL aSectionFound = FALSE; BOOL aKeyFound = FALSE; int j = 0; j = strlen(theIniFileName) + 1; ptr = (char*)getpwuid(getuid()); /* get user info */ if( ptr == NULL) { if( MAXPGPATH-1 < j ) theIniFileName[MAXPGPATH-1] = '\0'; sprintf(buf,"%s",theIniFileName); } ptr = ((struct passwd*)ptr)->pw_dir; /* get user home dir */ if( ptr == NULL || *ptr == '\0' ) ptr = "/home"; /* This doesn't make it so we find an ini file but allows normal * processing to continue further on down. The likelihood is that * the file won't be found and thus the default value will be * returned. */ if( MAXPGPATH-1 < strlen(ptr) + j ) { if( MAXPGPATH-1 < strlen(ptr) ) ptr[MAXPGPATH-1] = '\0'; else theIniFileName[MAXPGPATH-1-strlen(ptr)] = '\0'; } sprintf( buf, "%s/%s",ptr,theIniFileName ); /* This code makes it so that a file in the users home dir * overrides a the "default" file as passed in */ aFile = (FILE*)(buf ? fopen(buf, PG_BINARY_R) : NULL); if(!aFile) { sprintf(buf,"%s",theIniFileName); aFile = (FILE*)(buf ? fopen(buf, PG_BINARY_R) : NULL); } aLength = (theDefault == NULL) ? 0 : strlen(theDefault); if(theReturnBufferLength == 0 || theReturnBuffer == NULL) { if(aFile) { fclose(aFile); } return 0; } if(aFile == NULL) { /* no ini file specified, return the default */ ++aLength; /* room for NULL char */ aLength = theReturnBufferLength < aLength ? theReturnBufferLength : aLength; strncpy(theReturnBuffer, theDefault, aLength); theReturnBuffer[aLength - 1] = '\0'; return aLength - 1; } while(fgets(aLine, sizeof(aLine), aFile) != NULL) { aLineLength = strlen(aLine); /* strip final '\n' */ if(aLineLength > 0 && aLine[aLineLength - 1] == '\n') { aLine[aLineLength - 1] = '\0'; } switch(*aLine) { case ' ': /* blank line */ case ';': /* comment line */ continue; break; case '[': /* section marker */ if( (aString = strchr(aLine, ']')) ) { aStart = aLine + 1; aString--; while (isspace(*aStart)) aStart++; while (isspace(*aString)) aString--; *(aString+1) = '\0'; /* accept as matched if NULL key or exact match */ if(!theSection || !strcmp(aStart, theSection)) { aSectionFound = TRUE; } } break; default: /* try to match value keys if in proper section */ if(aSectionFound) { /* try to match requested key */ if( (aString = aValue = strchr(aLine, '=')) ) { *aValue = '\0'; ++aValue; /* strip leading blanks in value field */ while(*aValue == ' ' && aValue < aLine + sizeof(aLine)) { *aValue++ = '\0'; } if(aValue >= aLine + sizeof(aLine)) { aValue = ""; } } else { aValue = ""; } aStart = aLine; while(isspace(*aStart)) aStart++; /* strip trailing blanks from key */ if(aString) { while(--aString >= aStart && *aString == ' ') { *aString = '\0'; } } /* see if key is matched */ if(theKey == NULL || !strcmp(theKey, aStart)) { /* matched -- first, terminate value part */ aKeyFound = TRUE; aLength = strlen(aValue); /* remove trailing blanks from aValue if any */ aString = aValue + aLength - 1; while(--aString > aValue && *aString == ' ') { *aString = '\0'; --aLength; } /* unquote value if quoted */ if(aLength >= 2 && aValue[0] == '"' && aValue[aLength - 1] == '"') { /* string quoted with double quotes */ aValue[aLength - 1] = '\0'; ++aValue; aLength -= 2; } else { /* single quotes allowed also... */ if(aLength >= 2 && aValue[0] == '\'' && aValue[aLength - 1] == '\'') { aValue[aLength - 1] = '\0'; ++aValue; aLength -= 2; } } /* compute maximum length copyable */ aLineLength = (aLength < theReturnBufferLength - aReturnLength) ? aLength : theReturnBufferLength - aReturnLength; /* do the copy to return buffer */ if(aLineLength) { strncpy(&theReturnBuffer[aReturnLength], aValue, aLineLength); aReturnLength += aLineLength; if(aReturnLength < theReturnBufferLength) { theReturnBuffer[aReturnLength] = '\0'; ++aReturnLength; } } if(aFile) { fclose(aFile); aFile = NULL; } return aReturnLength > 0 ? aReturnLength - 1 : 0; } } break; } } if(aFile) { fclose(aFile); } if(!aKeyFound) { /* key wasn't found return default */ ++aLength; /* room for NULL char */ aLength = theReturnBufferLength < aLength ? theReturnBufferLength : aLength; strncpy(theReturnBuffer, theDefault, aLength); theReturnBuffer[aLength - 1] = '\0'; aReturnLength = aLength - 1; } return aReturnLength > 0 ? aReturnLength - 1 : 0; } DWORD WritePrivateProfileString(char *theSection, /* section name */ char *theKey, /* write key name */ char *theBuffer, /* input buffer */ char *theIniFileName) /* pathname of ini file to write */ { return 0; } #if 0 /* Ok. What the hell's the default behaviour for a null input buffer, and null * section name. For now if either are null I ignore the request, until * I find out different. */ DWORD WritePrivateProfileString(char *theSection, /* section name */ char *theKey, /* write key name */ char *theBuffer, /* input buffer */ char *theIniFileName) /* pathname of ini file to write */ { char buf[MAXPGPATH]; char* ptr = 0; FILE* aFile = 0; size_t aLength; char aLine[2048]; char *aValue; char *aString; size_t aLineLength; size_t aReturnLength = 0; BOOL aSectionFound = FALSE; BOOL keyFound = FALSE; int j = 0; /* If this isn't correct processing we'll change it later */ if(theSection == NULL || theKey == NULL || theBuffer == NULL || theIniFileName == NULL) return 0; aLength = strlen(theBuffer); if(aLength == 0) return 0; j = strlen(theIniFileName) + 1; ptr = (char*)getpwuid(getuid()); /* get user info */ if( ptr == NULL) { if( MAXPGPATH-1 < j ) theIniFileName[MAXPGPATH-1] = '\0'; sprintf(buf,"%s",theIniFileName); } ptr = ((struct passwd*)ptr)->pw_dir; /* get user home dir */ if( ptr == NULL || *ptr == '\0' ) ptr = "/home"; /* This doesn't make it so we find an ini file but allows normal */ /* processing to continue further on down. The likelihood is that */ /* the file won't be found and thus the default value will be */ /* returned. */ /* */ if( MAXPGPATH-1 < strlen(ptr) + j ) { if( MAXPGPATH-1 < strlen(ptr) ) ptr[MAXPGPATH-1] = '\0'; else theIniFileName[MAXPGPATH-1-strlen(ptr)] = '\0'; } sprintf( buf, "%s/%s",ptr,theIniFileName ); /* This code makes it so that a file in the users home dir */ /* overrides a the "default" file as passed in */ /* */ aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL); if(!aFile) { sprintf(buf,"%s",theIniFileName); aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL); if(!aFile) return 0; } aLength = strlen(theBuffer); /* We have to search for theKey, because if it already */ /* exists we have to overwrite it. If it doesn't exist */ /* we just write a new line to the file. */ /* */ while(fgets(aLine, sizeof(aLine), aFile) != NULL) { aLineLength = strlen(aLine); /* strip final '\n' */ if(aLineLength > 0 && aLine[aLineLength - 1] == '\n') { aLine[aLineLength - 1] = '\0'; } switch(*aLine) { case ' ': /* blank line */ case ';': /* comment line */ continue; break; case '[': /* section marker */ if( (aString = strchr(aLine, ']')) ) { *aString = '\0'; /* accept as matched if key exact match */ if(!strcmp(aLine + 1, theSection)) { aSectionFound = TRUE; } } break; default: /* try to match value keys if in proper section */ if(aSectionFound) { /* try to match requested key */ if( (aString = aValue = strchr(aLine, '=')) ) { *aValue = '\0'; ++aValue; /* strip leading blanks in value field */ while(*aValue == ' ' && aValue < aLine + sizeof(aLine)) { *aValue++ = '\0'; } if(aValue >= aLine + sizeof(aLine)) { aValue = ""; } } else { aValue = ""; } /* strip trailing blanks from key */ if(aString) { while(--aString >= aLine && *aString == ' ') { *aString = '\0'; } } /* see if key is matched */ if(!strcmp(theKey, aLine)) { keyFound = TRUE; /* matched -- first, terminate value part */ /* overwrite current value */ fseek(aFile,-aLineLength,SEEK_CUR); /* overwrite key and value */ sprintf(aLine,"%s = %s\n",theKey,theBuffer); fputs(aLine,aFile); } } } break; } } if(!keyFound) { /* theKey wasn't in file so */ if(aFile) { fclose(aFile); } return aReturnLength > 0 ? aReturnLength - 1 : 0; } #endif #endif