Commit 94cea4ee authored by Geoff Simmons's avatar Geoff Simmons

Merge updates from internal repo

parents bb465fcc 3272860d
;; Code style for this project:
;; * Indentation with 4 spaces (tabs are evil)
;; * 80 column limit
;; * otherwise BSD C style
(((nil . ((indent-tabs-mode . f)
(tab-width . 4)
(fill-column . 80))))
(c-mode . ((c-file-style . "BSD")
(c-basic-offset . 4))))
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src src/test
SUBDIRS = src src/test src/mq/activemq src/mq/activemq/test \
src/mq/kafka src/mq/kafka/test
if HAVE_RST2MAN
dist_man_MANS = trackrdrd.3
MAINTAINERCLEANFILES = $(dist_man_MANS)
MAINTAINERCLEANFILES = $(dist_man_MANS) *~
endif
trackrdrd.3: README.rst
......
This diff is collapsed.
......@@ -5,11 +5,11 @@ Parameter CLI Option Description
shared memory segment for the Varnish log. This parameter and ``varnish.bindump`` are
mutually exclusive.
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``mq.uri`` URIs for the message broker. This is the only parameter that can appear more than once in None, this parameter is required.
the configuration; if more than one MQ URIs are specified, than worker threads
distribute their connections to the different message brokers.
``mq.module`` Name of the shared object implementing the MQ interface. May be an absolute path, or the None, this parameter is required.
name of a library that the dynamic linker finds according to the rules described in
ld.so(8).
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``mq.qname`` Name of the queue (destination) to which messages are sent at the message broker(s). None, this parameter is required.
``mq.config_file`` Path of a configuration file used by the MQ implementation None, this parameter is optional.
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``nworkers`` Number of worker threads used to send messages to the message broker(s). 1
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
......@@ -50,6 +50,14 @@ Parameter CLI Option Description
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``restarts`` Maximum number of restarts of the child process by the management process 1
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``restart.pause`` Seconds to pause before restarting a child process 1
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``thread.restarts`` Maximum number of restarts of a worker thread by the child process. A thread is restarted 1
after a message send, message system reconnect and message resend have all failed. If the
restart limit for a thread is reached, then the thread goes into the state ``abandoned``
and no more restarts are attempted. If all worker threads are abandoned, then the child
process stops.
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
``monitor.interval`` Interval in seconds at which monitoring statistics are emitted to the log. If set to 0, 30
then no statistics are logged.
-------------------- ---------- ----------------------------------------------------------------------------------------- -------
......
AC_PREREQ(2.59)
AC_COPYRIGHT([Copyright (c) 2012 Otto Gmbh & Co KG])
AC_INIT([trackrdrd], [2.0])
AC_PREREQ(2.63)
AC_COPYRIGHT([Copyright (c) 2012-2014 Otto Gmbh & Co KG])
AC_INIT([trackrdrd], [3.0])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src/trackrdrd.c)
AM_CONFIG_HEADER(config.h)
......@@ -9,6 +9,10 @@ AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AC_USE_SYSTEM_EXTENSIONS
LT_PREREQ(2.2)
LT_INIT
AC_GNU_SOURCE
AC_PROG_CC
......@@ -83,8 +87,8 @@ DEVELOPER_CFLAGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith
# Added for compiling C++ for ActiveMQ.
# -Wstrict-prototypes, -Wmissing-prototypes & -Wnested-externs invalid for C++
# activemq-cpp fails on -Wshadow
DEVELOPER_CXXFLAGS="-Wall -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline -Wredundant-decls -Wformat"
# activemq-cpp fails on -Wshadow and -Wcast-qual
DEVELOPER_CXXFLAGS="-Wall -Wpointer-arith -Wreturn-type -Wwrite-strings -Wswitch -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline -Wredundant-decls -Wformat"
# Additional flags for GCC 4
EXTRA_DEVELOPER_CFLAGS="-Wextra -Wno-missing-field-initializers -Wno-sign-compare"
......@@ -139,5 +143,9 @@ AC_CONFIG_FILES([
Makefile
src/Makefile
src/test/Makefile
src/mq/activemq/Makefile
src/mq/activemq/test/Makefile
src/mq/kafka/Makefile
src/mq/kafka/test/Makefile
])
AC_OUTPUT
......@@ -20,6 +20,11 @@ Field Description
``data_overflows`` How often the accumulated length of a record exceeded
``maxdata``
------------------ ------------------------------------------------------------
``data_truncated`` How often data from the Varnish log was truncated due to
the presence of a null byte. This can happen if the data was
already truncated in the log, due to exceeding
``shm_reclen``.
------------------ ------------------------------------------------------------
``done`` Current number of records in state "done"
------------------ ------------------------------------------------------------
``open`` Current number of open records in the table
......@@ -32,6 +37,12 @@ Field Description
``reconnects`` How often worker threads reconnected to a message broker
after an unsuccessful send
------------------ ------------------------------------------------------------
``restarts`` How often worker threads were restarted after a message
send, reconnect and resend all failed
------------------ ------------------------------------------------------------
``abandoned`` Number of worker threads that have been abandoned due to
reaching the restart limit (``thread.restarts``)
------------------ ------------------------------------------------------------
``failed`` Number of failed sends (failure after reconnect)
------------------ ------------------------------------------------------------
``occ_hi`` Occupancy high watermark -- highest number of records (open
......
# Ignore everything in this directory
*
# Except this file
!.gitignore
......@@ -552,7 +552,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = $(SRCDIR)/src
INPUT = $(SRCDIR)/src $(SRCDIR)/include
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
......
# Sample configuration for the varnish log tracking reader
pid.file = /var/run/trackrdrd.pid
maxdata.scale = 2
maxopen.scale = 3
monitor.interval = 10
nworkers = 20
mq.uri = tcp://localhost:61616?wireFormat.maxInactivityDuration=0
mq.qname = lhotse/tracking/rdr2proc
#!/bin/bash
### BEGIN INIT INFO
# Provides: trackrdrd
# Required-Start: $syslog $remote_fs
# Should-Start: $time ypbind smtp
# Required-Stop: $syslog $remote_fs
# Should-Stop: ypbind smtp
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Short-Description: Varnish log tracking reader demon
# Description: This is the Varnish log tracking reader demon,
# which reads data intended for tracking from the Varnish
# shared memory log, collects all data for each XID, and
# sends each data record to an ActiveMQ message broker.
### END INIT INFO
PIDFILE=/var/run/trackrdrd.pid
TRACKRDRD_BIN=/var/opt/varnish_tracking/bin/trackrdrd
# We use the default config /etc/trackrdrd.conf, no -c option needed
#CONFIG=/var/opt/varnish_tracking/etc/run.conf
#CMD="${TRACKRDRD_BIN} -c ${CONFIG}"
CMD="${TRACKRDRD_BIN}"
# Child process stops after receiving a request
CURL=/usr/bin/curl
VARNISH_PORT=81
URL=http://localhost:${VARNISH_PORT}/ts-rcv?testSession=true
START_RETRIES=10
if [ ! -e ${TRACKRDRD_BIN} ]; then
echo "${TRACKRDRD_BIN} not installed"
fi
function start_trackrdrd {
START_CHECKS=0
echo -n "Checking if trackrdrd is running ..."
while [ ${START_CHECKS} -lt ${START_RETRIES} ]; do
checkproc ${TRACKRDRD_BIN}
if [ $? -ne 0 ]; then
break
fi
echo -n "."
START_CHECKS=$(( $START_CHECKS + 1 ))
sleep 1
continue
done
if [ ${START_CHECKS} -eq ${START_RETRIES} ]; then
echo " trackrdrd still running, giving up"
logger "trackrdrd still running, start FAILED"
exit 1
fi
echo ""
echo -n "Starting trackrdrd ... "
startproc -q ${CMD}
if [ $? -ne 0 ]; then
echo "FAILED (startproc returned $?)"
logger "trackrdrd start FAILED (startproc returned $?)"
exit 1
fi
echo "done."
}
function stop_trackrdrd {
echo -n "Shutting down trackrdrd ... "
killproc ${TRACKRDRD_BIN}
if [ $? -ne 0 ]; then
echo "FAILED (killproc returned $?)"
logger "trackrdrd stop FAILED (killproc returned $?)"
exit 1
fi
${CURL} ${URL} >/dev/null 2&>1
echo "done."
}
function getstatus_trackrdrd {
checkproc ${TRACKRDRD_BIN}
if [ $? -ne 0 ]; then
echo "trackrdrd NOT RUNNING (checkproc returned $?)"
exit 1
fi
echo "trackrdrd running"
}
function check_varnishd {
pgrep -f varnishd.*pa_proxy >/dev/null
if [ $? -ne 0 ]; then
echo "varnishd not running"
exit 1
fi
}
case "$1" in
start)
check_varnishd
start_trackrdrd
exit 0
;;
stop)
stop_trackrdrd
exit 0
;;
restart)
check_varnishd
echo "Restarting trackrdrd"
stop_trackrdrd
start_trackrdrd
sleep 1
getstatus_trackrdrd
exit 0
;;
reload)
check_varnishd
echo -n "Reloading service trackrdrd ... "
checkproc ${TRACKRDRD_BIN}
if [ $? -ne 0 ]; then
echo "FAILED trackrdrd NOT RUNNING"
exit 1
fi
kill -USR1 $(cat ${PIDFILE})
${CURL} ${URL} >/dev/null 2&>1
getstatus_trackrdrd
exit 0
;;
status)
getstatus_trackrdrd
exit 0
;;
*)
echo "Usage: $0 {start|stop|restart|reload|status}"
exit 1
;;
esac
# rc_exit
/*-
* Copyright (c) 2014 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2014 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file config_common.h
* \brief Config handling interface
* \details Common functions to get configuration data
*
* This header defines the functions used to get configuration data.
*
* If the conf_add() callback returns non-zero, CONF_ReadFile() prints
* an error message to `stderr` assuming that the return value is an
* errno value.
*/
/**
* Function type for adding key value pairs to config data.
*
* @param lval key
* @param rval value
* @return 0 on success, an errno value on failure
*/
typedef int conf_add_f(const char *lval, const char *rval);
/**
* Set config values.
*
* @param file config path we are reading
* @param func pointer for config add function.
* @return 0 on success, an value less than zero if we had a problem
* reading from one file, parsing a line or adding a config value.
*/
int CONF_ReadFile(const char *file, conf_add_f *func);
/*
* Written by Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* This file is in the public domain.
*
*/
#define ALLOC_OBJ(to, type_magic) \
do { \
(to) = calloc(sizeof *(to), 1); \
if ((to) != NULL) \
(to)->magic = (type_magic); \
} while (0)
#define FREE_OBJ(to) \
do { \
(to)->magic = (0); \
free(to); \
} while (0)
#define VALID_OBJ(ptr, type_magic) \
((ptr) != NULL && (ptr)->magic == (type_magic))
#define CHECK_OBJ(ptr, type_magic) \
do { \
assert((ptr)->magic == type_magic); \
} while (0)
#define CHECK_OBJ_NOTNULL(ptr, type_magic) \
do { \
assert((ptr) != NULL); \
assert((ptr)->magic == type_magic); \
} while (0)
#define CHECK_OBJ_ORNULL(ptr, type_magic) \
do { \
if ((ptr) != NULL) \
assert((ptr)->magic == type_magic); \
} while (0)
#define CAST_OBJ(to, from, type_magic) \
do { \
(to) = (from); \
if ((to) != NULL) \
CHECK_OBJ((to), (type_magic)); \
} while (0)
#define CAST_OBJ_NOTNULL(to, from, type_magic) \
do { \
(to) = (from); \
assert((to) != NULL); \
CHECK_OBJ((to), (type_magic)); \
} while (0)
#define REPLACE(ptr, val) \
do { \
if ((ptr) != NULL) \
free(ptr); \
if ((val) != NULL) { \
ptr = strdup(val); \
AN((ptr)); \
} else { \
ptr = NULL; \
} \
} while (0)
This diff is collapsed.
INCLUDES = -I$(VARNISHSRC)/include -I$(VARNISHSRC) @AMQ_CFLAGS@ @APR_CFLAGS@ \
@APU_CFLAGS@
INCLUDES = -I$(VARNISHSRC)/include -I$(VARNISHSRC) -I$(top_srcdir)/include
bin_PROGRAMS = trackrdrd
......@@ -10,14 +9,11 @@ trackrdrd_SOURCES = \
trackrdrd.c \
parse.c \
log.c \
config_common.h \
config_common.c \
config.c \
data.c \
monitor.c \
mq.c \
activemq/amq.h \
activemq/amq.cpp \
activemq/amq_connection.h \
activemq/amq_connection.cpp \
spmcq.c \
worker.c \
sandbox.c \
......@@ -29,10 +25,9 @@ trackrdrd_LDADD = \
$(VARNISHSRC)/lib/libvarnishcompat/libvarnishcompat.la \
$(VARNISHSRC)/lib/libvarnishapi/libvarnishapi.la \
$(VARNISHSRC)/lib/libvarnish/libvarnish.la \
${PTHREAD_LIBS} \
@AMQ_LIBS@ \
@APR_LIBS@ \
@APU_LIBS@
${PTHREAD_LIBS}
trackrdrd_LDFLAGS = -ldl
BUILT_SOURCES = revision.h usage.h
MAINTAINERCLEANFILES = revision.h usage.h
......
/*-
* Copyright (c) 2012 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012 Otto Gmbh & Co KG
* Copyright (c) 2012-2014 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012-2014 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
......
This diff is collapsed.
/*-
* Copyright (c) 2012 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012 Otto Gmbh & Co KG
* Copyright (c) 2012-2014 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012-2014 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
......@@ -44,6 +44,7 @@
#include "trackrdrd.h"
#include "libvarnish.h"
#include "config_common.h"
#define DEFAULT_USER "nobody"
......@@ -114,16 +115,20 @@ CONF_Add(const char *lval, const char *rval)
confString("varnish.name", varnish_name);
confString("log.file", log_file);
confString("varnish.bindump", varnish_bindump);
confString("mq.qname", mq_qname);
confString("mq.module", mq_module);
confString("mq.config_file", mq_config_file);
confUnsigned("maxopen.scale", maxopen_scale);
confUnsigned("maxdata", maxdata);
confUnsigned("maxkeylen", maxkeylen);
confUnsigned("qlen.goal", qlen_goal);
confUnsigned("hash.max_probes", hash_max_probes);
confUnsigned("hash.ttl", hash_ttl);
confUnsigned("hash.mlt", hash_mlt);
confUnsigned("nworkers", nworkers);
confUnsigned("restarts", restarts);
confUnsigned("restart.pause", restart_pause);
confUnsigned("thread.restarts", thread_restarts);
confUnsigned("monitor.interval", monitor_interval);
if (strcmp(lval, "maxdone") == 0) {
......@@ -177,46 +182,9 @@ CONF_Add(const char *lval, const char *rval)
return(EINVAL);
}
if (strcmp(lval, "mq.uri") == 0) {
int n = config.n_mq_uris++;
config.mq_uri = (char **) realloc(config.mq_uri,
config.n_mq_uris * sizeof(char **));
if (config.mq_uri == NULL)
return(errno);
config.mq_uri[n] = (char *) malloc(strlen(rval) + 1);
if (config.mq_uri[n] == NULL)
return(errno);
strcpy(config.mq_uri[n], rval);
return(0);
}
return EINVAL;
}
static int
conf_ParseLine(char *ptr, char **lval, char **rval)
{
char *endlval;
*lval = ptr;
while(*++ptr && !isspace(*ptr) && *ptr != '=')
;
if (*ptr == '\0')
return(1);
endlval = ptr;
while(isspace(*ptr) && *++ptr)
;
if (ptr == '\0' || *ptr != '=')
return(1);
while(*++ptr && isspace(*ptr))
;
if (ptr == '\0')
return(1);
*endlval = '\0';
*rval = ptr;
return(0);
}
void
CONF_Init(void)
{
......@@ -232,17 +200,18 @@ CONF_Init(void)
config.maxopen_scale = DEF_MAXOPEN_SCALE;
config.maxdone = DEF_MAXDONE;
config.maxdata = DEF_MAXDATA;
config.maxkeylen = DEF_MAXKEYLEN;
config.qlen_goal = DEF_QLEN_GOAL;
config.hash_max_probes = DEF_HASH_MAX_PROBES;
config.hash_ttl = DEF_HASH_TTL;
config.hash_mlt = DEF_HASH_MLT;
config.n_mq_uris = 0;
config.mq_uri = (char **) malloc (sizeof(char **));
AN(config.mq_uri);
config.mq_qname[0] = '\0';
config.mq_module[0] = '\0';
config.mq_config_file[0] = '\0';
config.nworkers = 1;
config.restarts = 1;
config.restart_pause = 1;
config.thread_restarts = 1;
pw = getpwnam(DEFAULT_USER);
if (pw == NULL)
......@@ -253,56 +222,6 @@ CONF_Init(void)
config.gid = pw->pw_gid;
}
int
CONF_ReadFile(const char *file) {
FILE *in;
char line[BUFSIZ];
int linenum = 0;
in = fopen(file, "r");
if (in == NULL) {
perror(file);
return(-1);
}
while (fgets(line, BUFSIZ, in) != NULL) {
char orig[BUFSIZ];
linenum++;
char *comment = strchr(line, '#');
if (comment != NULL)
*comment = '\0';
if (strlen(line) == 0)
continue;
char *ptr = line + strlen(line) - 1;
while (ptr != line && isspace(*ptr))
--ptr;
ptr[isspace(*ptr) ? 0 : 1] = '\0';
if (strlen(line) == 0)
continue;
ptr = line;
while (isspace(*ptr) && *++ptr)
;
strcpy(orig, ptr);
char *lval, *rval;
if (conf_ParseLine(ptr, &lval, &rval) != 0) {
fprintf(stderr, "Cannot parse %s line %d: '%s'\n", file, linenum,
orig);
return(-1);
}
int ret;
if ((ret = CONF_Add((const char *) lval, (const char *) rval)) != 0) {
fprintf(stderr, "Error in %s line %d (%s): '%s'\n", file, linenum,
strerror(ret), orig);
return(-1);
}
}
return(0);
}
/* XXX: stdout is /dev/null in child process */
int
CONF_ReadDefault(void)
......@@ -311,7 +230,7 @@ CONF_ReadDefault(void)
if (access(DEFAULT_CONFIG, R_OK) != 0)
return(errno);
printf("Reading config from %s\n", DEFAULT_CONFIG);
if (CONF_ReadFile(DEFAULT_CONFIG) != 0)
if (CONF_ReadFile(DEFAULT_CONFIG, CONF_Add) != 0)
return -1;
}
return 0;
......@@ -334,19 +253,17 @@ CONF_Dump(void)
confdump("maxopen.scale = %u", config.maxopen_scale);
confdump("maxdone = %u", config.maxdone);
confdump("maxdata = %u", config.maxdata);
confdump("maxkeylen = %u", config.maxkeylen);
confdump("qlen.goal = %u", config.qlen_goal);
confdump("hash.max_probes = %u", config.hash_max_probes);
confdump("hash.ttl = %u", config.hash_ttl);
confdump("hash.mlt = %u", config.hash_mlt);
if (config.n_mq_uris > 0)
for (int i = 0; i < config.n_mq_uris; i++)
confdump("mq.uri = %s", config.mq_uri[i]);
else
LOG_Log0(LOG_DEBUG, "config: mq.uri = ");
confdump("mq.qname = %s", config.mq_qname);
confdump("mq.module = %s", config.mq_module);
confdump("mq.config_file = %s", config.mq_config_file);
confdump("nworkers = %u", config.nworkers);
confdump("restarts = %u", config.restarts);
confdump("restart.pause = %u", config.restart_pause);
confdump("thread.restarts = %u", config.thread_restarts);
confdump("user = %s", config.user_name);
}
/*-
* Copyright (c) 2012-2014 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012-2014 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "config_common.h"
static int
conf_ParseLine(char *ptr, char **lval, char **rval)
{
char *endlval;
*lval = ptr;
while(*++ptr && !isspace(*ptr) && *ptr != '=')
;
if (*ptr == '\0')
return(1);
endlval = ptr;
while(isspace(*ptr) && *++ptr)
;
if (ptr == '\0' || *ptr != '=')
return(1);
while(*++ptr && isspace(*ptr))
;
if (ptr == '\0')
return(1);
*endlval = '\0';
*rval = ptr;
return(0);
}
int
CONF_ReadFile(const char *file, conf_add_f *conf_add) {
FILE *in;
char line[BUFSIZ];
int linenum = 0;
in = fopen(file, "r");