484 lines
10 KiB
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
|