forked from Telodendria/Telodendria
Prototype the configuration file parser.
Right now there's a nasty memory bug I need to fix. Will have to run this through valgrind.
This commit is contained in:
parent
0a101f0853
commit
cdd7808642
9 changed files with 515 additions and 32 deletions
|
@ -1,2 +1,4 @@
|
|||
build
|
||||
.env
|
||||
*.log
|
||||
vgcore.*
|
||||
|
|
13
contrib/development.conf
Normal file
13
contrib/development.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
server-name "example.com";
|
||||
chroot "/var/telodendria";
|
||||
id "_telodendria" "_telodendria";
|
||||
data-dir "./data";
|
||||
federation "true";
|
||||
registration "false";
|
||||
log "stdout" {
|
||||
level "debug";
|
||||
timestampFormat "none";
|
||||
color "true";
|
||||
};
|
||||
threads "4";
|
||||
|
|
@ -13,18 +13,20 @@
|
|||
# should go through and check.
|
||||
#
|
||||
|
||||
# The address to listen on. You can specify multiple addresses by
|
||||
# simply adding more values to this directive. It is recommended
|
||||
# to only listen on localhost, and then configure a reverse proxy
|
||||
# such as relayd(8) in front of it, because the server does not
|
||||
# implement TLS.
|
||||
# The address to listen on. It is recommended to listen on localhost,
|
||||
# and then configure a reverse proxy # such as relayd(8) in front of
|
||||
# it, because the server does not implement TLS.
|
||||
#
|
||||
# Also note that Telodendria doesn't provide multiple ports for
|
||||
# different things. All APIs are made available over the same port.
|
||||
# This works because Matrix allows the port configuration to be
|
||||
# shared via .well-known/matrix/, which this server does properly
|
||||
# serve.
|
||||
listen "localhost:8008";
|
||||
#
|
||||
# The first parameter is the host name or IP address to listen on,
|
||||
# and the second parameter is the port name or number. See the
|
||||
# getaddrinfo() manual page for more information.
|
||||
listen "localhost" "8008";
|
||||
|
||||
# Configure the domain name of your homeserver. Note that Matrix
|
||||
# servers cannot be migrated to other domains, so once this is set,
|
||||
|
@ -55,7 +57,7 @@ id "_telodendria" "_telodendria";
|
|||
# event information. Telodendria doesn't use a database; it uses a
|
||||
# flat-file directory structure, sort of like how most SMTP servers
|
||||
# use Maildirs or mbox files.
|
||||
data-dir "/data";
|
||||
data-dir "./data";
|
||||
|
||||
# Whether to enable federation or not. Matrix is by default
|
||||
# a federated protocol, but if you just want your own internal chat
|
||||
|
@ -90,8 +92,8 @@ registration "false";
|
|||
# configures the log file. If you're going to be running Telodendria
|
||||
# in a chroot, the log file will have to live inside the chroot.
|
||||
#
|
||||
# Acceptable values here are "stdout", "stderr", or a log file.
|
||||
log "/telodendria.log" {
|
||||
# Acceptable values here are "stdout" or a log file.
|
||||
log "./telodendria.log" {
|
||||
# The level to log. This can be one of "error", "warning",
|
||||
# "task", "message", or "debug", with each level showing all
|
||||
# the levels above it as well. For example, "error" shows
|
14
src/Log.c
14
src/Log.c
|
@ -100,6 +100,12 @@ LogConfigFlagSet(LogConfig * config, int flags)
|
|||
void
|
||||
LogConfigFree(LogConfig * config)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(config->out);
|
||||
free(config);
|
||||
}
|
||||
|
||||
|
@ -218,10 +224,6 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
|||
|
||||
pthread_mutex_lock(&config->lock);
|
||||
|
||||
for (i = 0; i < config->indent; i++)
|
||||
{
|
||||
fputc(' ', config->out);
|
||||
}
|
||||
|
||||
doColor = LogConfigFlagGet(config, LOG_FLAG_COLOR)
|
||||
&& isatty(fileno(config->out));
|
||||
|
@ -312,6 +314,10 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
|||
}
|
||||
|
||||
fputc(' ', config->out);
|
||||
for (i = 0; i < config->indent; i++)
|
||||
{
|
||||
fputc(' ', config->out);
|
||||
}
|
||||
|
||||
va_start(argp, msg);
|
||||
vfprintf(config->out, msg, argp);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <TelodendriaConfig.h>
|
||||
|
||||
#include <Log.h>
|
||||
#include <HashMap.h>
|
||||
#include <Config.h>
|
||||
|
@ -83,10 +85,10 @@ main(int argc, char **argv)
|
|||
ConfigParseResult *configParseResult = NULL;
|
||||
HashMap *config = NULL;
|
||||
|
||||
lc = LogConfigCreate();
|
||||
/* Program configuration */
|
||||
TelodendriaConfig *tConfig = NULL;
|
||||
|
||||
/* TODO: Remove */
|
||||
LogConfigLevelSet(lc, LOG_DEBUG);
|
||||
lc = LogConfigCreate();
|
||||
|
||||
if (!lc)
|
||||
{
|
||||
|
@ -147,15 +149,9 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
Log(lc, LOG_MESSAGE, "Using configuration file '%s'.", configArg);
|
||||
Log(lc, LOG_TASK, "Processing configuration file '%s'.", configArg);
|
||||
|
||||
Log(lc, LOG_DEBUG, "Executing ConfigParse()");
|
||||
|
||||
/* Read config here */
|
||||
configParseResult = ConfigParse(configFile);
|
||||
|
||||
Log(lc, LOG_DEBUG, "Exitting ConfigParse()");
|
||||
|
||||
if (!ConfigParseResultOk(configParseResult))
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Syntax error on line %d.",
|
||||
|
@ -167,18 +163,30 @@ main(int argc, char **argv)
|
|||
config = ConfigParseResultGet(configParseResult);
|
||||
ConfigParseResultFree(configParseResult);
|
||||
|
||||
Log(lc, LOG_DEBUG, "Closing configuration file.");
|
||||
fclose(configFile);
|
||||
|
||||
/* Configure log file */
|
||||
tConfig = TelodendriaConfigParse(config, lc);
|
||||
if (!tConfig)
|
||||
{
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ConfigFree(config);
|
||||
|
||||
Log(lc, LOG_DEBUG, "Configuration:");
|
||||
LogConfigIndent(lc);
|
||||
Log(lc, LOG_DEBUG, "Listen On: %s:%s", tConfig->listenHost, tConfig->listenPort);
|
||||
Log(lc, LOG_DEBUG, "Server Name: %s", tConfig->serverName);
|
||||
Log(lc, LOG_DEBUG, "Chroot: %s", tConfig->chroot);
|
||||
Log(lc, LOG_DEBUG, "Run As: %s:%s", tConfig->uid, tConfig->gid);
|
||||
Log(lc, LOG_DEBUG, "Data Directory: %s", tConfig->dataDir);
|
||||
Log(lc, LOG_DEBUG, "Threads: %d", tConfig->threads);
|
||||
Log(lc, LOG_DEBUG, "Flags: %x", tConfig->flags);
|
||||
LogConfigUnindent(lc);
|
||||
|
||||
finish:
|
||||
if (config)
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "Freeing configuration structure.");
|
||||
ConfigFree(config);
|
||||
}
|
||||
Log(lc, LOG_DEBUG, "Freeing log configuration and exiting with code '%d'.", exit);
|
||||
LogConfigFree(lc);
|
||||
Log(lc, LOG_DEBUG, "Exiting with code '%d'.", exit);
|
||||
TelodendriaConfigFree(tConfig);
|
||||
return exit;
|
||||
}
|
||||
|
|
317
src/TelodendriaConfig.c
Normal file
317
src/TelodendriaConfig.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Jordan Bancino <@jordan:bancino.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <TelodendriaConfig.h>
|
||||
#include <Config.h>
|
||||
#include <HashMap.h>
|
||||
#include <Log.h>
|
||||
#include <Array.h>
|
||||
#include <Util.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
static int
|
||||
IsInteger(char *str)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
if (!isdigit(*str))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define GET_DIRECTIVE(name) \
|
||||
directive = (ConfigDirective *) HashMapGet(config, name); \
|
||||
if (!directive) { \
|
||||
Log(lc, LOG_ERROR, "Missing required configuration directive: '%s'.", name); \
|
||||
goto error; \
|
||||
} \
|
||||
children = ConfigChildrenGet(directive); \
|
||||
value = ConfigValuesGet(directive); \
|
||||
|
||||
#define ASSERT_NO_CHILDREN(name) if (children) { \
|
||||
Log(lc, LOG_ERROR, "Unexpected child values in directive: '%s'.", name); \
|
||||
goto error; \
|
||||
}
|
||||
|
||||
#define ASSERT_VALUES(name, expected) if (ArraySize(value) != expected) { \
|
||||
Log(lc, LOG_ERROR, \
|
||||
"Wrong value count in directive '%s': got '%d', but expected '%d'.", \
|
||||
name, ArraySize(value), expected); \
|
||||
goto error; \
|
||||
}
|
||||
|
||||
#define COPY_VALUE(into, index) into = UtilStringDuplicate(ArrayGet(value, index))
|
||||
|
||||
TelodendriaConfig *
|
||||
TelodendriaConfigParse(HashMap * config, LogConfig * lc)
|
||||
{
|
||||
TelodendriaConfig *tConfig;
|
||||
|
||||
ConfigDirective *directive;
|
||||
Array *value;
|
||||
HashMap *children;
|
||||
|
||||
if (!config || !lc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tConfig = calloc(1, sizeof(tConfig));
|
||||
if (!tConfig)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
directive = (ConfigDirective *) HashMapGet(config, "listen");
|
||||
children = ConfigChildrenGet(directive);
|
||||
value = ConfigValuesGet(directive);
|
||||
|
||||
if (!directive)
|
||||
{
|
||||
Log(lc, LOG_WARNING, "No 'listen' directive specified; using defaults, which may change.");
|
||||
tConfig->listenHost = UtilStringDuplicate("localhost");
|
||||
tConfig->listenPort = UtilStringDuplicate("8008");
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_NO_CHILDREN("listen");
|
||||
ASSERT_VALUES("listen", 2);
|
||||
COPY_VALUE(tConfig->listenHost, 0);
|
||||
COPY_VALUE(tConfig->listenPort, 1);
|
||||
}
|
||||
|
||||
GET_DIRECTIVE("server-name");
|
||||
ASSERT_NO_CHILDREN("server-name");
|
||||
ASSERT_VALUES("server-name", 1);
|
||||
COPY_VALUE(tConfig->serverName, 0);
|
||||
|
||||
GET_DIRECTIVE("chroot");
|
||||
ASSERT_NO_CHILDREN("chroot");
|
||||
ASSERT_VALUES("chroot", 1);
|
||||
COPY_VALUE(tConfig->chroot, 0);
|
||||
|
||||
GET_DIRECTIVE("id");
|
||||
ASSERT_NO_CHILDREN("id");
|
||||
ASSERT_VALUES("id", 2);
|
||||
COPY_VALUE(tConfig->uid, 0);
|
||||
COPY_VALUE(tConfig->gid, 1);
|
||||
|
||||
GET_DIRECTIVE("data-dir");
|
||||
ASSERT_NO_CHILDREN("data-dir");
|
||||
ASSERT_VALUES("data-dir", 1);
|
||||
COPY_VALUE(tConfig->dataDir, 0);
|
||||
|
||||
GET_DIRECTIVE("threads");
|
||||
ASSERT_NO_CHILDREN("threads");
|
||||
ASSERT_VALUES("threads", 1);
|
||||
|
||||
if (IsInteger(ArrayGet(value, 0)))
|
||||
{
|
||||
tConfig->threads = atoi(ArrayGet(value, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_ERROR,
|
||||
"Expected integer for directive 'threads', "
|
||||
"but got '%s'.", ArrayGet(value, 0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
GET_DIRECTIVE("federation");
|
||||
ASSERT_NO_CHILDREN("federation");
|
||||
ASSERT_VALUES("federation", 1);
|
||||
|
||||
if (strcmp(ArrayGet(value, 0), "true") == 0)
|
||||
{
|
||||
tConfig->flags |= TELODENDRIA_FEDERATION;
|
||||
}
|
||||
else if (strcmp(ArrayGet(value, 0), "false") != 0)
|
||||
{
|
||||
Log(lc, LOG_ERROR,
|
||||
"Expected boolean value for directive 'federation', "
|
||||
"but got '%s'.", ArrayGet(value, 0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
GET_DIRECTIVE("registration");
|
||||
ASSERT_NO_CHILDREN("registration");
|
||||
ASSERT_VALUES("registration", 1);
|
||||
if (strcmp(ArrayGet(value, 0), "true") == 0)
|
||||
{
|
||||
tConfig->flags |= TELODENDRIA_REGISTRATION;
|
||||
}
|
||||
else if (strcmp(ArrayGet(value, 0), "false") != 0)
|
||||
{
|
||||
Log(lc, LOG_ERROR,
|
||||
"Expected boolean value for directive 'registration', "
|
||||
"but got '%s'.", ArrayGet(value, 0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
GET_DIRECTIVE("log");
|
||||
ASSERT_VALUES("log", 1);
|
||||
|
||||
if (children)
|
||||
{
|
||||
ConfigDirective *cDirective;
|
||||
char *cVal;
|
||||
size_t size;
|
||||
|
||||
cDirective = HashMapGet(children, "level");
|
||||
if (cDirective)
|
||||
{
|
||||
size = ArraySize(ConfigValuesGet(cDirective));
|
||||
if (size > 1)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Expected 1 value for log.level, got %d.", size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
cVal = ArrayGet(ConfigValuesGet(cDirective), 0);
|
||||
if (strcmp(cVal, "message") == 0)
|
||||
{
|
||||
LogConfigLevelSet(lc, LOG_MESSAGE);
|
||||
}
|
||||
else if (strcmp(cVal, "debug") == 0)
|
||||
{
|
||||
LogConfigLevelSet(lc, LOG_DEBUG);
|
||||
}
|
||||
else if (strcmp(cVal, "task") == 0)
|
||||
{
|
||||
LogConfigLevelSet(lc, LOG_TASK);
|
||||
}
|
||||
else if (strcmp(cVal, "warning") == 0)
|
||||
{
|
||||
LogConfigLevelSet(lc, LOG_WARNING);
|
||||
}
|
||||
else if (strcmp(cVal, "error") == 0)
|
||||
{
|
||||
LogConfigLevelSet(lc, LOG_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Invalid value for log.level: '%s'.", cVal);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
cDirective = HashMapGet(children, "timestampFormat");
|
||||
if (cDirective)
|
||||
{
|
||||
size = ArraySize(ConfigValuesGet(cDirective));
|
||||
if (size > 1)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Expected 1 value for log.level, got %d.", size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
cVal = ArrayGet(ConfigValuesGet(cDirective), 0);
|
||||
|
||||
if (strcmp(cVal, "none") == 0)
|
||||
{
|
||||
LogConfigTimeStampFormatSet(lc, NULL);
|
||||
}
|
||||
else if (strcmp(cVal, "default") != 0)
|
||||
{
|
||||
LogConfigTimeStampFormatSet(lc, UtilStringDuplicate(cVal));
|
||||
}
|
||||
}
|
||||
|
||||
cDirective = HashMapGet(children, "color");
|
||||
if (cDirective)
|
||||
{
|
||||
size = ArraySize(ConfigValuesGet(cDirective));
|
||||
if (size > 1)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Expected 1 value for log.level, got %d.", size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
cVal = ArrayGet(ConfigValuesGet(cDirective), 0);
|
||||
|
||||
if (strcmp(cVal, "false") == 0)
|
||||
{
|
||||
LogConfigFlagClear(lc, LOG_FLAG_COLOR);
|
||||
}
|
||||
else if (strcmp(cVal, "true") != 0)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Expected boolean value for log.color, got '%s'.", cVal);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the actual log output file last */
|
||||
if (strcmp(ArrayGet(value, 0), "stdout") != 0)
|
||||
{
|
||||
FILE *out = fopen(ArrayGet(value, 0), "w");
|
||||
|
||||
if (!out)
|
||||
{
|
||||
Log(lc, LOG_ERROR, "Unable to open log file '%s' for writing.",
|
||||
ArrayGet(value, 0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
Log(lc, LOG_DEBUG, "Redirecting output to '%s'.", ArrayGet(value, 0));
|
||||
LogConfigOutputSet(lc, out);
|
||||
}
|
||||
|
||||
tConfig->logConfig = lc;
|
||||
return tConfig;
|
||||
error:
|
||||
TelodendriaConfigFree(tConfig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef GET_DIRECTIVE
|
||||
#undef ASSERT_NO_CHILDREN
|
||||
#undef ASSERT_VALUES
|
||||
|
||||
void
|
||||
TelodendriaConfigFree(TelodendriaConfig * tConfig)
|
||||
{
|
||||
if (!tConfig)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
free(tConfig->listenHost);
|
||||
free(tConfig->listenPort);
|
||||
free(tConfig->serverName);
|
||||
free(tConfig->chroot);
|
||||
free(tConfig->uid);
|
||||
free(tConfig->gid);
|
||||
free(tConfig->dataDir);
|
||||
|
||||
LogConfigFree(tConfig->logConfig);
|
||||
|
||||
free(tConfig);
|
||||
}
|
19
src/Util.c
19
src/Util.c
|
@ -24,6 +24,7 @@
|
|||
#include <Util.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
long
|
||||
|
@ -86,3 +87,21 @@ UtilUtf8Encode(unsigned long utf8)
|
|||
|
||||
return str;
|
||||
}
|
||||
|
||||
char *
|
||||
UtilStringDuplicate(char *inStr)
|
||||
{
|
||||
size_t len;
|
||||
char *outStr;
|
||||
|
||||
len = strlen(inStr);
|
||||
outStr = malloc(len + 1); /* For the null terminator */
|
||||
if (!outStr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(outStr, inStr);
|
||||
|
||||
return outStr;
|
||||
}
|
||||
|
|
100
src/include/TelodendriaConfig.h
Normal file
100
src/include/TelodendriaConfig.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Jordan Bancino <@jordan:bancino.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TelodendriaConfig.h: Validate and maintain the Telodendria server's
|
||||
* configuration data. This API builds on the Config API to add
|
||||
* Telodendria-specific parsing. It takes a fully parsed Config, and
|
||||
* converts it into a TelodendriaConfig, which is more structured.
|
||||
*/
|
||||
#ifndef TELODENDRIA_TELODENDRIACONFIG_H
|
||||
#define TELODENDRIA_TELODENDRIACONFIG_H
|
||||
|
||||
#include <Log.h>
|
||||
#include <HashMap.h>
|
||||
|
||||
typedef enum TelodendriaConfigFlag
|
||||
{
|
||||
TELODENDRIA_FEDERATION = (1 << 0),
|
||||
TELODENDRIA_REGISTRATION = (1 << 1)
|
||||
} TelodendriaConfigFlag;
|
||||
|
||||
/*
|
||||
* Since this configuration will live in memory for a long time, it is
|
||||
* important that unused values are freed as soon as possible. Therefore,
|
||||
* the TelodendriaConfig structure is not opaque; values are accessed
|
||||
* directly, and they can be freed as the program wishes.
|
||||
*
|
||||
* NOTE: If you're going to free a value, make sure you set the pointer
|
||||
* to NULL. TelodendriaConfigFree() will call free() on all values.
|
||||
*/
|
||||
typedef struct TelodendriaConfig
|
||||
{
|
||||
char *listenHost;
|
||||
char *listenPort;
|
||||
char *serverName;
|
||||
char *chroot;
|
||||
char *uid;
|
||||
char *gid;
|
||||
char *dataDir;
|
||||
|
||||
unsigned int flags;
|
||||
unsigned int threads;
|
||||
|
||||
LogConfig *logConfig;
|
||||
} TelodendriaConfig;
|
||||
|
||||
/*
|
||||
* Parse a Config map, extracting the necessary values, validating them,
|
||||
* and then adding them to a new TelodendriaConfig for future use by the
|
||||
* program. All values are copied, so the Config hash map can be safely
|
||||
* freed if this function succeeds.
|
||||
*
|
||||
* Params:
|
||||
* (HashMap *) A hash map from ConfigParse(). This should be a map of
|
||||
* ConfigDirectives.
|
||||
* (LogConfig *) A working log configuration. Messages are written to
|
||||
* this log as the parsing progresses, and this log is
|
||||
* copied into the resulting TelodendriaConfig. It is
|
||||
* also potentially modified by the configuration file's
|
||||
* "log" block.
|
||||
*
|
||||
* Return: A TelodendriaConfig that is completely independent of the passed
|
||||
* configuration hash map, or NULL if one or more required values is missing.
|
||||
*/
|
||||
extern TelodendriaConfig *
|
||||
TelodendriaConfigParse(HashMap *, LogConfig *);
|
||||
|
||||
/*
|
||||
* Free all of the memory allocated to the given configuration. This
|
||||
* function unconditionally calls free() on all items in the structure,
|
||||
* so make sure items that were already freed are NULL.
|
||||
*
|
||||
* Params:
|
||||
* (TelodendriaConfig *) The configuration to free all the values for.
|
||||
*/
|
||||
extern void
|
||||
TelodendriaConfigFree(TelodendriaConfig *);
|
||||
|
||||
#endif
|
|
@ -68,4 +68,20 @@ extern long
|
|||
extern char *
|
||||
UtilUtf8Encode(unsigned long);
|
||||
|
||||
|
||||
/*
|
||||
* Duplicate a null-terminated string, and return a new string on the
|
||||
* heap.
|
||||
*
|
||||
* Params:
|
||||
* (char *) The string to duplicate. It can be located anywhere on
|
||||
* the heap or the stack.
|
||||
*
|
||||
* Return: A pointer to a null-terminated string on the heap. You must
|
||||
* free() it when you're done with it. This may also return NULL if the
|
||||
* call to malloc() fails.
|
||||
*/
|
||||
extern char *
|
||||
UtilStringDuplicate(char *);
|
||||
|
||||
#endif /* TELODENDRIA_UTIL_H */
|
||||
|
|
Loading…
Reference in a new issue