postgresql/src/interfaces/odbc/gpps.c

484 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 "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