/*********************************************************************
This file is part of Siworin. Copyright © 2021 by Ruud Harmsen.
Siworin is a simple word indexer and local search engine. See
https://rudhar.com/sfreview/siworin/#siw04 and
https://rudhar.com/sfreview/siworin/toolsrc/siworin .
Siworin 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 3 of the License,
or (at your option) any later version.
Siworin 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 Siworin. If not, see .
********************************************************************/
#include
#include
#include
#include "siworin-config.h"
#include "siworin.h"
static int config_already_filled = 0;
static struct siworin_config_pair_s
{
char *key;
char *value;
} siworin_configdata[] =
{
{"word_max_occur" , NULL},
{"write_words_freq" , NULL},
{"files_prefix" , NULL},
{"filepath_replace_this" , NULL},
{"filepath_replace_by" , NULL},
{"head_html_file" , NULL},
{"minim_match" , NULL},
{"maxim_dista" , NULL},
{"show_context_befor" , NULL},
{"show_context_after" , NULL},
{"dont_remove_tags_wordsep", NULL},
{"dont_remove_tags_context", NULL},
{"include_digits_initial" , NULL},
{"include_digits_subsequ" , NULL},
{"ranking_numwords" , NULL},
{"ranking_wordfreq" , NULL},
{"ranking_worddist" , NULL},
};
#define SIWORIN_CONFIG_NUMELTS \
(sizeof siworin_configdata / sizeof siworin_configdata[0])
/* Can be allocated and set by calling function
siworin_set_explicit_config_path() . */
static char *explicit_config_path = NULL;
static void check_config_read (void);
static void alloc_and_set_string (char **dest, const char *src);
static void init_config (void);
static void read_config (void);
static void read_config_values_from_configfile (FILE *fp);
/* Searches a program's invocation parameters, passed as argv.
As soon as any of
-cconfigpath
-c configpath
--config configpath
is found, siworin_set_explicit_config_path is called with
configpath. */
int siworin_args_to_config_path (char **argv)
{
char *opt1 = "-c";
char *opt2 = "--config";
int number_of_arguments_handled = 0;
for (; argv[0]; argv++)
{
if (strncmp(argv[0], opt1, strlen(opt1)) == 0)
{
if (argv[0][strlen(opt1)])
{
siworin_set_explicit_config_path(argv[0] + strlen(opt1));
number_of_arguments_handled = 1;
break;
}
else if (argv[1])
{
siworin_set_explicit_config_path(argv[1]);
number_of_arguments_handled = 2;
break;
}
}
else if (strcmp(argv[0], opt2) == 0 && argv[1])
{
siworin_set_explicit_config_path(argv[1]);
number_of_arguments_handled = 2;
break;
}
}
return number_of_arguments_handled;
}
/* Sets path for the siworin config file. If it exists,
it takes precedence over all default paths to find
a config file. */
void siworin_set_explicit_config_path (char *path)
{
alloc_and_set_string(&explicit_config_path, path);
}
char *siworin_get_explicit_config_path (void)
{
return explicit_config_path;
}
char *siworin_config_value (enum siworin_configindex_e index)
{
check_config_read();
if (index < 0 || index >= SIWORIN_CONFIG_NUMELTS)
{
SIWORIN_FAIL("config index");
return NULL;
}
return siworin_configdata[index].value;
}
/* Free all malloc'ed memory areas (including realloc and calloc)
internally allocated by siworin-config.c */
void siworin_config_freeall (void)
{
unsigned int i;
free(explicit_config_path);
explicit_config_path = NULL;
for (i = 0; i < SIWORIN_CONFIG_NUMELTS; i++)
free(siworin_configdata[i].value);
config_already_filled = 0;
}
static void check_config_read (void)
{
if (!config_already_filled)
{
init_config();
read_config();
config_already_filled = 1;
}
}
static void alloc_and_set_string (char **dest, const char *src)
{
char *newdest;
if (!(newdest = realloc(*dest, strlen(src) + 1)))
SIWORIN_FAIL("realloc");
strcpy(newdest, src);
*dest = newdest;
}
static void init_config (void)
{
alloc_and_set_string(
&siworin_configdata[SIWORIN_CONFIG_INDEX_WORD_MAX_OCCUR].value, "3000");
alloc_and_set_string(
&siworin_configdata[SIWORIN_CONFIG_WRITE_WORDS_FREQ].value, "0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_CONFIG_INDEX_FILES_PREFIX].value,
"/var/www/cgi-bin/siworin/siworin");
alloc_and_set_string(
&siworin_configdata[SIWORIN_FILEPATH_REPLACE_THIS].value,
"/var/www/html/");
alloc_and_set_string(
&siworin_configdata[SIWORIN_FILEPATH_REPLACE_BY].value,
"https://rudhar.com/");
alloc_and_set_string(
&siworin_configdata[SIWORIN_HEAD_HTML_FILE].value,
"/var/www/cgi-bin/siworin/siworin-head-html.htm");
alloc_and_set_string(
&siworin_configdata[SIWORIN_MINIM_MATCH].value, "3");
alloc_and_set_string(
&siworin_configdata[SIWORIN_MAXIM_DISTA].value, "100");
alloc_and_set_string(
&siworin_configdata[SIWORIN_SHOW_CONTEXT_BEFOR].value, "80");
alloc_and_set_string(
&siworin_configdata[SIWORIN_SHOW_CONTEXT_AFTER].value, "80");
alloc_and_set_string(
&siworin_configdata[SIWORIN_DONT_REMOVE_TAGS_WORDSEP].value, "0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_DONT_REMOVE_TAGS_CONTEXT].value, "0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_INCLUDE_DIGITS_INITIAL].value, "0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_INCLUDE_DIGITS_SUBSEQU].value, "0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_RANKING_NUMWORDS].value, "1.0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_RANKING_WORDFREQ].value, "20.0");
alloc_and_set_string(
&siworin_configdata[SIWORIN_RANKING_WORDDIST].value, "10.0");
}
static char *config_paths[] =
{
"./siworin.conf",
"/usr/local/siworin.conf",
"/usr/local/siworin/siworin.conf",
"/var/www/cgi-bin/siworin.conf",
"/var/www/cgi-bin/siworin/siworin.conf",
NULL
};
static void read_config (void)
{
FILE *fp = NULL;
char **path;
/* The first successful attempt at opening a config file
holds. All other paths are then ignored. */
if (explicit_config_path)
fp = fopen(explicit_config_path, "r");
for (path = config_paths; !fp && *path; path++)
fp = fopen(*path, "r");
/* There is no error checking on whether a config file
has been opened. If all attempts failed, the default
values that were already set by function init_config()
remain in force.
If a file was opened, anything it specifies overrides
the default, for that data item only. What is not in
the config file keeps it preset value. */
if (fp)
read_config_values_from_configfile(fp);
}
static void read_config_values_from_configfile (FILE *fp)
{
char line[256];
char *cp;
unsigned int i;
/* Examine the config file line by line. */
while (fgets(line, sizeof line, fp))
{
/* Shortcut to skip lines that consist entirely of a comment,
and empty lines. This is an optimisation. It would also
work without these tests, but more slowly, because then
all the keywords have would to be checked against the empty
line (either originally empty, or meanwhile made empty). */
if (line[0] == '#' || line[0] == '\n')
continue;
/* Wipe out any comments. */
if ((cp = strchr(line, '#')))
*cp = '\0';
/* Skip initial whitespace. */
cp = line + strspn(line, " \t");
/* Check for any known keyword. */
for (i = 0; i < SIWORIN_CONFIG_NUMELTS; i++)
{
if (strncmp(cp, siworin_configdata[i].key,
strlen(siworin_configdata[i].key)) == 0)
{
/* Skip over the keyword. */
cp += strlen(siworin_configdata[i].key);
/* Skip over any white space and/of ':' or '=',
which separates the keyword from the config data
string. */
cp += strspn(cp, " \t:=");
/* Find the end of the string. The string is supposed to
contain only non-whitespace. Also remove end-of-line. */
cp[strcspn(cp, " \t\r\n")] = '\0';
/* Store the found value for later use. */
alloc_and_set_string(&siworin_configdata[i].value, cp);
}
}
}
}