1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-20 05:03:10 +03:00
Files
postgres/src/interfaces/odbc/gpps.c
2001-11-05 17:46:40 +00:00

455 lines
11 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
*-------
*/
#if !defined(WIN32) && !defined(WITH_UNIXODBC) && !defined(WITH_IODBC)
#include "gpps.h"
#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 "dlg_specific.h"
#ifndef TRUE
#define TRUE ((BOOL)1)
#endif
#ifndef FALSE
#define FALSE ((BOOL)0)
#endif
#ifndef ODBCINSTDIR
#error "ODBCINSTDIR must be defined to compile this file"
#endif
/*
* theIniFileName is searched for in:
* $HOME/theIniFileName
* theIniFileName
* ODBCINSTDIR/ODBCINST_INI
*/
DWORD
GetPrivateProfileString(const char *theSection, /* section name */
const char *theKey, /* search key name */
const char *theDefault, /* default value if not
* found */
char *theReturnBuffer, /* return value stored
* here */
size_t theReturnBufferLength, /* byte length of return
* buffer */
const 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;
ptr = (char *) getpwuid(getuid()); /* get user info */
if (ptr == NULL || (((struct passwd *) ptr)->pw_dir) == NULL || *(((struct passwd *) ptr)->pw_dir) == '\0')
ptr = "/home";
else
ptr = ((struct passwd *) ptr)->pw_dir; /* get user home dir */
/*
* If it can't be opened because the paths are too long, then skip it,
* don't just truncate the path string... The truncated path might
* accidently be an existing file. The default value will be returned
* instead.
*/
if (MAXPGPATH - 1 >= strlen(ptr) + 1 + strlen(theIniFileName))
{
sprintf(buf, "%s/%s", ptr, theIniFileName);
aFile = (FILE *) fopen(buf, PG_BINARY_R);
}
/*
* This code makes it so that a file in the users home dir overrides a
* the "default" file as passed in
*/
if (!aFile)
{
aFile = (FILE *) fopen(theIniFileName, PG_BINARY_R);
if (!aFile)
aFile = (FILE *) fopen(ODBCINSTDIR "/" ODBCINST_INI, PG_BINARY_R);
}
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((unsigned char) *aStart))
aStart++;
while (isspace((unsigned char) *aString))
aString--;
*(aString + 1) = '\0';
/* accept as matched if NULL key or exact match */
if (!theSection || !strcmp(aStart, theSection))
aSectionFound = TRUE;
else
aSectionFound = FALSE;
}
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((unsigned char) *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(const char *theSection, /* section name */
const char *theKey, /* write key name */
const char *theBuffer, /* input buffer */
const char *theIniFileName) /* pathname of ini file
* to write */
{
return 0;
}
#if NOT_USED
/*
* 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 /* NOT_USED */
#endif /* not WIN32 */