mirror of
https://github.com/postgres/postgres.git
synced 2025-05-31 00:01:57 -04:00
eliminating some wildly inconsistent coding in various parts of the system. I set MAXPGPATH = 1024 in config.h.in. If anyone is really convinced that there ought to be a configure-time test to set the value, go right ahead ... but I think it's a waste of time.
489 lines
10 KiB
C
489 lines
10 KiB
C
// 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 <stdio.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
|
|
#if HAVE_PWD_H
|
|
#include <pwd.h>
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <string.h>
|
|
#include "gpps.h"
|
|
#include "misc.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
|
|
*/
|
|
#ifndef __CYGWIN32__
|
|
aFile = (FILE*)(buf ? fopen(buf, "r") : NULL);
|
|
#else
|
|
aFile = (FILE*)(buf ? fopen(buf, "rb") : NULL);
|
|
#endif
|
|
if(!aFile) {
|
|
sprintf(buf,"%s",theIniFileName);
|
|
#ifndef __CYGWIN32__
|
|
aFile = (FILE*)(buf ? fopen(buf, "r") : NULL);
|
|
#else
|
|
aFile = (FILE*)(buf ? fopen(buf, "rb") : NULL);
|
|
#endif
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
/* 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
|