mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 03:12:53 +00:00
406 lines
12 KiB
C++
406 lines
12 KiB
C++
/* -*- mode: c; indent-tabs-mode: nil; -*-
|
|
* $Id: config.c,v 1.3 2003/12/28 20:59:21 chrish Exp $
|
|
*
|
|
* config -- read and parse the Plucker config files
|
|
* Copyright (c) 2002, Bill Janssen
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#if !defined(WIN32)
|
|
#include <unistd.h> /* for lseek, etc. */
|
|
#else
|
|
#include <io.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h> /* for fstat() */
|
|
#include <string.h> /* for strndup() */
|
|
#include <errno.h> /* for errno */
|
|
#include <fcntl.h> /* for O_RDONLY */
|
|
#include <assert.h> /* for assert() */
|
|
|
|
#include "unpluck.h"
|
|
#include "unpluckint.h"
|
|
|
|
#define STRINGIFY(s) STRINGIFY2 (s)
|
|
#define STRINGIFY2(s) #s
|
|
|
|
#define MAX_LINE_SIZE 1023
|
|
|
|
#define COMMENT_CHARS "#;"
|
|
#define SEGMENT_LEAD_CHAR '['
|
|
#define SEGMENT_END_CHAR ']'
|
|
#define OPTION_SEPARATOR_CHARS "=:"
|
|
|
|
HashTable *SectionsTable = NULL;
|
|
|
|
static HashTable* GetOrCreateSegment
|
|
(
|
|
char* name
|
|
)
|
|
{
|
|
HashTable* target;
|
|
|
|
if (SectionsTable == NULL)
|
|
SectionsTable = _plkr_NewHashTable (23);
|
|
|
|
if ((target = (HashTable*)_plkr_FindInTable (SectionsTable, name)) == NULL) {
|
|
target = _plkr_NewHashTable (53);
|
|
_plkr_AddToTable (SectionsTable, name, target);
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
static int ReadConfigFile
|
|
(
|
|
char* filename
|
|
)
|
|
{
|
|
HashTable* current_segment = NULL;
|
|
FILE* fp = fopen (filename, "r");
|
|
char* ptr;
|
|
char* str_end;
|
|
char* str_begin;
|
|
char* charptr;
|
|
char* current_option;
|
|
char* option_value;
|
|
char linebuf[MAX_LINE_SIZE + 1];
|
|
int linelen;
|
|
int len2;
|
|
int buf_index;
|
|
int status;
|
|
int line_number;
|
|
|
|
if (fp == NULL) {
|
|
_plkr_message ("Can't open config file %s", filename);
|
|
return 0;
|
|
}
|
|
|
|
current_segment = GetOrCreateSegment ("default");
|
|
current_option = NULL;
|
|
|
|
status = 1; /* optimistic */
|
|
line_number = 0;
|
|
|
|
while (1) {
|
|
|
|
ptr = fgets (linebuf, sizeof (linebuf) - 1, fp);
|
|
if (ptr == NULL)
|
|
break;
|
|
|
|
line_number += 1;
|
|
linebuf[strlen (linebuf) - 1] = 0; /* strip newline */
|
|
if (linebuf[strlen (linebuf) - 1] == '\r')
|
|
linebuf[strlen (linebuf) - 1] = 0; /* strip carriage return */
|
|
|
|
/* fprintf (stderr, "%s:%d: line is '%s'\n", filename, line_number, linebuf); */
|
|
|
|
linelen = strlen (linebuf);
|
|
for (buf_index = 0; linebuf[buf_index] != 0; buf_index++)
|
|
if (!isspace (linebuf[buf_index]))
|
|
break;
|
|
|
|
if (linebuf[buf_index] == 0)
|
|
/* blank line */
|
|
continue;
|
|
|
|
if ((strchr (COMMENT_CHARS, linebuf[0]) != NULL) ||
|
|
(strncmp (linebuf, "rem", 3) == 0) ||
|
|
(strncmp (linebuf, "REM", 3) == 0))
|
|
/* comment */
|
|
continue;
|
|
|
|
/* At this point we have a valid thing */
|
|
|
|
if (linebuf[buf_index] == SEGMENT_LEAD_CHAR) {
|
|
if ((str_end =
|
|
strchr (linebuf + buf_index + 1,
|
|
SEGMENT_END_CHAR)) == NULL) {
|
|
/* invalid segment line */
|
|
_plkr_message ("%s:%d: Invalid segment line '%s'",
|
|
filename, line_number, linebuf);
|
|
goto error_exit;
|
|
}
|
|
str_begin = linebuf + buf_index + 1;
|
|
for (charptr = str_begin; charptr < str_end; charptr++)
|
|
*charptr = tolower (*charptr);
|
|
*str_end = 0;
|
|
current_segment = GetOrCreateSegment (str_begin);
|
|
/* fprintf (stderr, "Current segment is now %p (%s)\n", current_segment, str_begin); */
|
|
if (current_option)
|
|
free (current_option);
|
|
current_option = NULL;
|
|
|
|
}
|
|
else if ((linebuf[0] == ' ' || linebuf[0] == '\t')
|
|
&& current_option != NULL) {
|
|
/* continuation line */
|
|
str_begin =
|
|
(char *) _plkr_RemoveFromTable (current_segment,
|
|
current_option);
|
|
for (str_end = linebuf + strlen (linebuf) - 1;
|
|
str_end > linebuf && isspace (*str_end); str_end--);
|
|
charptr =
|
|
(char *) malloc (strlen (str_begin) +
|
|
(str_end - (linebuf + buf_index)) + 2);
|
|
strcpy (charptr, str_begin);
|
|
len2 = strlen (charptr);
|
|
charptr[len2] = '\n';
|
|
strncpy (charptr + len2 + 1, linebuf + buf_index,
|
|
str_end - (linebuf + buf_index));
|
|
charptr[len2 + (str_end - (linebuf + buf_index)) + 1] = '\0';
|
|
_plkr_AddToTable (current_segment, current_option, charptr);
|
|
free (str_begin);
|
|
|
|
}
|
|
else if ((int)strcspn (linebuf, OPTION_SEPARATOR_CHARS) < linelen) {
|
|
/* possible option line */
|
|
|
|
for (str_begin = linebuf + buf_index, ptr = str_begin;
|
|
isalnum (*ptr) || (*ptr == '.') || (*ptr == '_')
|
|
|| (*ptr == '-'); ptr++);
|
|
if (ptr == str_begin) {
|
|
_plkr_message ("%s:%d: Invalid option line '%s'",
|
|
filename, line_number, linebuf);
|
|
goto error_exit;
|
|
}
|
|
|
|
for (charptr = str_begin; charptr < ptr; charptr++)
|
|
*charptr = tolower (*charptr);
|
|
str_end = ptr;
|
|
|
|
while (isspace (*ptr) && (*ptr != '\0'))
|
|
ptr++;
|
|
|
|
if (strchr (OPTION_SEPARATOR_CHARS, *ptr) != NULL)
|
|
ptr++;
|
|
else {
|
|
_plkr_message ("%s:%d: Invalid option line '%s'",
|
|
filename, line_number, linebuf);
|
|
goto error_exit;
|
|
}
|
|
|
|
while (isspace (*ptr) && (*ptr != '\0'))
|
|
ptr++;
|
|
|
|
if (*ptr == 0) {
|
|
_plkr_message ("%s:%d: Invalid option line '%s'",
|
|
filename, line_number, linebuf);
|
|
goto error_exit;
|
|
}
|
|
|
|
if (current_option)
|
|
free (current_option);
|
|
current_option =
|
|
_plkr_strndup (str_begin, str_end - str_begin);
|
|
|
|
option_value = _plkr_strndup (ptr, strlen (ptr));
|
|
|
|
ptr =
|
|
(char *) _plkr_RemoveFromTable (current_segment,
|
|
current_option);
|
|
if (ptr)
|
|
free (ptr);
|
|
_plkr_AddToTable (current_segment, current_option,
|
|
option_value);
|
|
/* fprintf (stderr, "Added value '%s' for option '%p:%s'\n", option_value, current_segment, current_option); */
|
|
|
|
}
|
|
else {
|
|
_plkr_message ("%s:%d: Bad line '%s'", filename, line_number,
|
|
linebuf);
|
|
goto error_exit;
|
|
}
|
|
}
|
|
|
|
good_exit:
|
|
|
|
if (current_option)
|
|
free (current_option);
|
|
fclose (fp);
|
|
return status;
|
|
|
|
error_exit:
|
|
status = 0;
|
|
goto good_exit;
|
|
}
|
|
|
|
static void TryReadConfigFile
|
|
(
|
|
char* dir,
|
|
char* name
|
|
)
|
|
{
|
|
char* filename;
|
|
|
|
if (dir == NULL || name == NULL)
|
|
return;
|
|
|
|
filename = (char *) malloc (strlen (dir) + strlen (name) + 2);
|
|
strcpy (filename, dir);
|
|
strcpy (filename + strlen (filename),
|
|
STRINGIFY (FILE_SEPARATOR_CHAR_S));
|
|
strcpy (filename + strlen (filename), name);
|
|
if (!ReadConfigFile (filename))
|
|
_plkr_message ("Error reading config file %s", filename);
|
|
free (filename);
|
|
}
|
|
|
|
static void InitializeConfigInfo ()
|
|
{
|
|
char *config_dir = STRINGIFY (PLUCKER_CONFIG_DIR);
|
|
char *system_config_file_name = STRINGIFY (SYS_CONFIG_FILE_NAME);
|
|
char *user_config_filename = STRINGIFY (USER_CONFIG_FILE_NAME);
|
|
char *home = getenv ("HOME");
|
|
|
|
TryReadConfigFile (config_dir, system_config_file_name);
|
|
if (home != NULL)
|
|
TryReadConfigFile (home, user_config_filename);
|
|
}
|
|
|
|
char* plkr_GetConfigString
|
|
(
|
|
char* section_name,
|
|
char* option_name,
|
|
char* default_value
|
|
)
|
|
{
|
|
char* value = NULL;
|
|
HashTable* section;
|
|
|
|
if (SectionsTable == NULL)
|
|
InitializeConfigInfo ();
|
|
|
|
if (SectionsTable == NULL)
|
|
return default_value;
|
|
|
|
if (section_name != NULL) {
|
|
if ((section =
|
|
(HashTable *) _plkr_FindInTable (SectionsTable,
|
|
section_name)) != NULL)
|
|
value = (char *) _plkr_FindInTable (section, option_name);
|
|
}
|
|
if (value == NULL && ((section_name == NULL)
|
|
|| (strcmp (section_name, "default") != 0))) {
|
|
if ((section =
|
|
(HashTable *) _plkr_FindInTable (SectionsTable,
|
|
STRINGIFY (OS_SECTION_NAME)))
|
|
!= NULL)
|
|
value = (char *) _plkr_FindInTable (section, option_name);
|
|
}
|
|
if (value == NULL && ((section_name == NULL)
|
|
|| (strcmp (section_name, "default") != 0))) {
|
|
if ((section =
|
|
(HashTable *) _plkr_FindInTable (SectionsTable,
|
|
"default")) != NULL)
|
|
value = (char *) _plkr_FindInTable (section, option_name);
|
|
}
|
|
|
|
return ((value == NULL) ? default_value : value);
|
|
}
|
|
|
|
long int plkr_GetConfigInt
|
|
(
|
|
char* section_name,
|
|
char* option_name,
|
|
long int default_value
|
|
)
|
|
{
|
|
char* svalue = plkr_GetConfigString (section_name, option_name, NULL);
|
|
char* endptr;
|
|
long int value;
|
|
|
|
if (svalue == NULL)
|
|
return default_value;
|
|
|
|
value = strtol (svalue, &endptr, 0);
|
|
if (*endptr != 0) {
|
|
_plkr_message ("Bad int value string '%s' for option %s:%s",
|
|
svalue, (section_name ? section_name : "default"),
|
|
option_name);
|
|
return default_value;
|
|
}
|
|
else {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
double plkr_GetConfigFloat
|
|
(
|
|
char* section_name,
|
|
char* option_name,
|
|
double default_value
|
|
)
|
|
{
|
|
char* svalue = plkr_GetConfigString (section_name, option_name, NULL);
|
|
char* endptr;
|
|
double value;
|
|
|
|
if (svalue == NULL)
|
|
return default_value;
|
|
|
|
value = strtod (svalue, &endptr);
|
|
if (*endptr != 0) {
|
|
_plkr_message ("Bad float value string '%s' for option %s:%s",
|
|
svalue, (section_name ? section_name : "default"),
|
|
option_name);
|
|
return default_value;
|
|
}
|
|
else {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
int plkr_GetConfigBoolean
|
|
(
|
|
char* section_name,
|
|
char* option_name,
|
|
int default_value
|
|
)
|
|
{
|
|
char* svalue = plkr_GetConfigString (section_name, option_name, NULL);
|
|
|
|
if (svalue == NULL)
|
|
return default_value;
|
|
|
|
if ((strcmp (svalue, "1") == 0) ||
|
|
(strcmp (svalue, "true") == 0) || (strcmp (svalue, "TRUE") == 0) ||
|
|
(strcmp (svalue, "on") == 0) || (strcmp (svalue, "ON") == 0) ||
|
|
(strcmp (svalue, "t") == 0) || (strcmp (svalue, "T") == 0)
|
|
|| (strcmp (svalue, "True") == 0))
|
|
return 1;
|
|
|
|
else if ((strcmp (svalue, "0") == 0) || (strcmp (svalue, "false") == 0)
|
|
|| (strcmp (svalue, "FALSE") == 0)
|
|
|| (strcmp (svalue, "off") == 0)
|
|
|| (strcmp (svalue, "OFF") == 0)
|
|
|| (strcmp (svalue, "F") == 0)
|
|
|| (strcmp (svalue, "F") == 0)
|
|
|| (strcmp (svalue, "False") == 0))
|
|
return 0;
|
|
|
|
else {
|
|
_plkr_message ("Bad boolean value string '%s' for option %s:%s",
|
|
svalue, (section_name ? section_name : "default"),
|
|
option_name);
|
|
return default_value;
|
|
}
|
|
}
|