[master] a7ee621 Add a syslog-server facility for the benefit of HAproxy testers.
Poul-Henning Kamp
phk at FreeBSD.org
Tue May 29 12:18:24 UTC 2018
commit a7ee62136fe06eae137fb941010d0caeef9647d4
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue May 29 12:11:19 2018 +0000
Add a syslog-server facility for the benefit of HAproxy testers.
Submitted by: Frédéric Lécaille <flecaille at haproxy.com>
Hacked to pieces by: phk
diff --git a/bin/varnishtest/Makefile.am b/bin/varnishtest/Makefile.am
index 392b02a..0deef9c 100644
--- a/bin/varnishtest/Makefile.am
+++ b/bin/varnishtest/Makefile.am
@@ -57,6 +57,7 @@ varnishtest_SOURCES = \
vtc_proxy.c \
vtc_server.c \
vtc_subr.c \
+ vtc_syslog.c \
vtc_varnish.c
varnishtest_LDADD = \
diff --git a/bin/varnishtest/Makefile.phk b/bin/varnishtest/Makefile.phk
index b50535d..b406cce 100644
--- a/bin/varnishtest/Makefile.phk
+++ b/bin/varnishtest/Makefile.phk
@@ -6,6 +6,7 @@ PROG_SRC += vtc_logexp.c
PROG_SRC += vtc_main.c
PROG_SRC += vtc_barrier.c
PROG_SRC += vtc_server.c
+PROG_SRC += vtc_syslog.c
PROG_SRC += vtc_varnish.c
PROG_SRC += vtc_process.c
diff --git a/bin/varnishtest/cmds.h b/bin/varnishtest/cmds.h
index 290237d..e856e60 100644
--- a/bin/varnishtest/cmds.h
+++ b/bin/varnishtest/cmds.h
@@ -40,6 +40,7 @@ CMD(process)
CMD(server)
CMD(setenv)
CMD(shell)
+CMD(syslog)
CMD(varnish)
CMD(varnishtest)
#undef CMD
diff --git a/bin/varnishtest/tests/h00005.vtc b/bin/varnishtest/tests/h00005.vtc
new file mode 100644
index 0000000..44cf902
--- /dev/null
+++ b/bin/varnishtest/tests/h00005.vtc
@@ -0,0 +1,45 @@
+varnishtest "Exercise varnishtest syslog facility"
+
+feature ignore_unknown_macro
+feature cmd {haproxy --version 2>&1 | grep -q 'HA-Proxy version'}
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+syslog sl1 -level notice -bind "127.0.0.1:0" {
+ recv
+ recv
+ recv info
+ expect ~ \"dip\":\"${h1_fe_1_addr}
+} -start
+
+haproxy h1 -conf {
+ global
+ log ${sl1_addr}:${sl1_port} local0
+
+ defaults
+ log global
+ timeout connect 3000
+ timeout client 5
+ timeout server 10000
+
+ frontend fe1
+ bind "fd@${fe_1}"
+ mode tcp
+ log-format {\"dip\":\"%fi\",\"dport\":\"%fp\"}
+ default_backend be1
+
+ backend be1
+ server srv1 ${s1_addr}:${s1_port}
+} -start
+
+client c1 -connect ${h1_fe_1_sock} {
+ txreq -url "/"
+ delay 0.02
+ rxresp
+} -run
+
+syslog sl1 -wait
+
diff --git a/bin/varnishtest/vtc.c b/bin/varnishtest/vtc.c
index c6c5897..69b2d3d 100644
--- a/bin/varnishtest/vtc.c
+++ b/bin/varnishtest/vtc.c
@@ -472,6 +472,7 @@ exec_file(const char *fn, const char *script, const char *tmpdir,
init_macro();
init_server();
+ init_syslog();
vsb = VSB_new_auto();
AN(vsb);
diff --git a/bin/varnishtest/vtc.h b/bin/varnishtest/vtc.h
index 8ad4a5a..6ebff08 100644
--- a/bin/varnishtest/vtc.h
+++ b/bin/varnishtest/vtc.h
@@ -85,6 +85,7 @@ extern int feature_dns;
extern int ign_unknown_macro;
void init_server(void);
+void init_syslog(void);
int http_process(struct vtclog *vl, const char *spec, int sock, int *sfd,
const char *addr);
diff --git a/bin/varnishtest/vtc_syslog.c b/bin/varnishtest/vtc_syslog.c
new file mode 100644
index 0000000..2ef8a85
--- /dev/null
+++ b/bin/varnishtest/vtc_syslog.c
@@ -0,0 +1,649 @@
+/*-
+ * Copyright (c) 2008-2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Frédéric Lécaille <flecaille at haproxy.com>
+ *
+ * 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 "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "vsa.h"
+#include "vss.h"
+#include "vtcp.h"
+#include "vre.h"
+
+#include "vtc.h"
+
+struct syslog_srv {
+ unsigned magic;
+#define SYSLOG_SRV_MAGIC 0xbf28a692
+ char *name;
+ struct vtclog *vl;
+ VTAILQ_ENTRY(syslog_srv) list;
+ char run;
+
+ unsigned repeat;
+ char *spec;
+
+ int sock;
+ char bind[256];
+ int lvl;
+
+ pthread_t tp;
+ ssize_t rxbuf_left;
+ size_t rxbuf_sz;
+ char *rxbuf;
+ double timeout;
+};
+
+static pthread_mutex_t syslog_mtx;
+
+static VTAILQ_HEAD(, syslog_srv) syslogs =
+ VTAILQ_HEAD_INITIALIZER(syslogs);
+
+static const char * const syslog_levels[] = {
+ "emerg",
+ "alert",
+ "crit",
+ "err",
+ "warning",
+ "notice",
+ "info",
+ "debug",
+ NULL,
+};
+
+static int
+get_syslog_level(struct vtclog *vl, const char *lvl)
+{
+ int i;
+
+ for (i = 0; syslog_levels[i]; i++)
+ if (!strcmp(lvl, syslog_levels[i]))
+ return (i);
+ vtc_fatal(vl, "wrong syslog level '%s'\n", lvl);
+}
+
+/*--------------------------------------------------------------------
+ * Check if a UDP syscall return value is fatal
+ * XXX: Largely copied from VTCP, not sure if really applicable
+ */
+
+static int
+VUDP_Check(int a)
+{
+ if (a == 0)
+ return (1);
+ if (errno == ECONNRESET)
+ return (1);
+#if (defined (__SVR4) && defined (__sun)) || defined (__NetBSD__)
+ /*
+ * Solaris returns EINVAL if the other end unexpectedly reset the
+ * connection.
+ * This is a bug in Solaris and documented behaviour on NetBSD.
+ */
+ if (errno == EINVAL || errno == ETIMEDOUT || errno == EPIPE)
+ return (1);
+#elif defined (__APPLE__)
+ /*
+ * MacOS returns EINVAL if the other end unexpectedly reset
+ * the connection.
+ */
+ if (errno == EINVAL)
+ return (1);
+#endif
+ return (0);
+}
+
+/*--------------------------------------------------------------------
+ * When closing a UDP connection, a couple of errno's are legit, we
+ * can't be held responsible for the other end wanting to talk to us.
+ */
+
+static void
+VUDP_close(int *s)
+{
+ int i;
+
+ i = close(*s);
+
+ assert(VUDP_Check(i));
+ *s = -1;
+}
+
+/*--------------------------------------------------------------------
+ * Given a struct suckaddr, open a socket of the appropriate type, and bind
+ * it to the requested address.
+ *
+ * If the address is an IPv6 address, the IPV6_V6ONLY option is set to
+ * avoid conflicts between INADDR_ANY and IN6ADDR_ANY.
+ */
+
+static int
+VUDP_bind(const struct suckaddr *sa, const char **errp)
+{
+ int sd, val, e;
+ socklen_t sl;
+ const struct sockaddr *so;
+ int proto;
+
+ if (errp != NULL)
+ *errp = NULL;
+
+ proto = VSA_Get_Proto(sa);
+ sd = socket(proto, SOCK_DGRAM, 0);
+ if (sd < 0) {
+ if (errp != NULL)
+ *errp = "socket(2)";
+ return (-1);
+ }
+ val = 1;
+ if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val) != 0) {
+ if (errp != NULL)
+ *errp = "setsockopt(SO_REUSEADDR, 1)";
+ e = errno;
+ closefd(&sd);
+ errno = e;
+ return (-1);
+ }
+
+#ifdef IPV6_V6ONLY
+ /* forcibly use separate sockets for IPv4 and IPv6 */
+ val = 1;
+ if (proto == AF_INET6 &&
+ setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof val) != 0) {
+ if (errp != NULL)
+ *errp = "setsockopt(IPV6_V6ONLY, 1)";
+ e = errno;
+ closefd(&sd);
+ errno = e;
+ return (-1);
+ }
+#endif
+ so = VSA_Get_Sockaddr(sa, &sl);
+ if (bind(sd, so, sl) != 0) {
+ if (errp != NULL)
+ *errp = "bind(2)";
+ e = errno;
+ closefd(&sd);
+ errno = e;
+ return (-1);
+ }
+ return (sd);
+}
+
+/*--------------------------------------------------------------------*/
+
+struct udp_helper {
+ const char **errp;
+};
+
+static int v_matchproto_(vss_resolved_f)
+vudp_lo_cb(void *priv, const struct suckaddr *sa)
+{
+ int sock;
+ struct udp_helper *hp = priv;
+
+ sock = VUDP_bind(sa, hp->errp);
+ if (sock > 0) {
+ *hp->errp = NULL;
+ return (sock);
+ }
+ AN(*hp->errp);
+ return (0);
+}
+
+static int
+VUDP_bind_on(const char *addr, const char *def_port, const char **errp)
+{
+ struct udp_helper h;
+ int sock;
+
+ h.errp = errp;
+
+ sock = VSS_resolver_socktype(
+ addr, def_port, vudp_lo_cb, &h, errp, SOCK_DGRAM);
+ if (*errp != NULL)
+ return (-1);
+ return (sock);
+}
+
+/**********************************************************************
+ * Allocate and initialize a syslog
+ */
+
+static struct syslog_srv *
+syslog_new(const char *name, struct vtclog *vl)
+{
+ struct syslog_srv *s;
+
+ VTC_CHECK_NAME(vl, name, "Syslog", 's');
+ ALLOC_OBJ(s, SYSLOG_SRV_MAGIC);
+ AN(s);
+ REPLACE(s->name, name);
+ s->vl = vtc_logopen(s->name);
+ AN(s->vl);
+
+ bprintf(s->bind, "%s", "127.0.0.1 0");
+ s->repeat = 1;
+ s->sock = -1;
+ s->lvl = -1;
+ s->timeout = vtc_maxdur * .5; // XXX
+
+ vl = vtc_logopen(s->name);
+ AN(vl);
+
+ s->rxbuf_sz = s->rxbuf_left = 2048*1024;
+ s->rxbuf = malloc(s->rxbuf_sz); /* XXX */
+ AN(s->rxbuf);
+
+ AZ(pthread_mutex_lock(&syslog_mtx));
+ VTAILQ_INSERT_TAIL(&syslogs, s, list);
+ AZ(pthread_mutex_unlock(&syslog_mtx));
+ return (s);
+}
+
+/**********************************************************************
+ * Clean up a syslog
+ */
+
+static void
+syslog_delete(struct syslog_srv *s)
+{
+
+ CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
+ macro_undef(s->vl, s->name, "addr");
+ macro_undef(s->vl, s->name, "port");
+ macro_undef(s->vl, s->name, "sock");
+ vtc_logclose(s->vl);
+ free(s->name);
+ free(s->rxbuf);
+ /* XXX: MEMLEAK (?) (VSS ??) */
+ FREE_OBJ(s);
+}
+
+static void
+syslog_rx(const struct syslog_srv *s, int lvl)
+{
+ ssize_t ret;
+
+ while (!vtc_error) {
+ /* Pointers to syslog priority value (see <PRIVAL>, rfc5424). */
+ char *prib, *prie, *end;
+ unsigned int prival;
+
+ VTCP_set_read_timeout(s->sock, s->timeout);
+
+ ret = recv(s->sock, s->rxbuf, s->rxbuf_sz - 1, 0);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+
+ vtc_fatal(s->vl,
+ "%s: recv failed (fd: %d read: %s", __func__,
+ s->sock, strerror(errno));
+ }
+ if (ret == 0)
+ vtc_fatal(s->vl,
+ "syslog rx timeout (fd: %d %.3fs ret: %zd)",
+ s->sock, s->timeout, ret);
+
+ s->rxbuf[ret] = '\0';
+ vtc_dump(s->vl, 4, "syslog", s->rxbuf, ret);
+
+ prib = s->rxbuf;
+ if (*prib++ != '<')
+ vtc_fatal(s->vl, "syslog PRI, no '<'");
+ prie = strchr(prib, '>');
+ if (prie == NULL)
+ vtc_fatal(s->vl, "syslog PRI, no '>'");
+
+ prival = strtoul(prib, &end, 10);
+ if (end != prie)
+ vtc_fatal(s->vl, "syslog PRI, bad number");
+
+ if (lvl >= 0 && lvl == (prival & 0x7))
+ return;
+ }
+}
+
+/**********************************************************************
+ * Syslog server bind
+ */
+
+static void
+syslog_bind(struct syslog_srv *s)
+{
+ const char *err;
+ char aaddr[VTCP_ADDRBUFSIZE];
+ char aport[VTCP_PORTBUFSIZE];
+
+ CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
+
+ if (s->sock >= 0)
+ VUDP_close(&s->sock);
+ s->sock = VUDP_bind_on(s->bind, "0", &err);
+ if (err != NULL)
+ vtc_fatal(s->vl,
+ "Syslog server bind address (%s) cannot be resolved: %s",
+ s->bind, err);
+ assert(s->sock > 0);
+ VTCP_myname(s->sock, aaddr, sizeof aaddr, aport, sizeof aport);
+ macro_def(s->vl, s->name, "addr", "%s", aaddr);
+ macro_def(s->vl, s->name, "port", "%s", aport);
+ macro_def(s->vl, s->name, "sock", "%s %s", aaddr, aport);
+ /* Record the actual port, and reuse it on subsequent starts */
+ bprintf(s->bind, "%s %s", aaddr, aport);
+}
+
+static void v_matchproto_(cmd_f)
+cmd_syslog_expect(CMD_ARGS)
+{
+ struct syslog_srv *s;
+ vre_t *vre;
+ const char *error;
+ int erroroffset, i, ret;
+ char *cmp, *spec;
+
+ (void)vl;
+ (void)cmd;
+ CAST_OBJ_NOTNULL(s, priv, SYSLOG_SRV_MAGIC);
+ AZ(strcmp(av[0], "expect"));
+ av++;
+
+ cmp = av[0];
+ spec = av[1];
+ AN(cmp);
+ AN(spec);
+ AZ(av[2]);
+
+ assert(!strcmp(cmp, "~") || !strcmp(cmp, "!~"));
+
+ vre = VRE_compile(spec, 0, &error, &erroroffset);
+ if (!vre)
+ vtc_fatal(s->vl, "REGEXP error: '%s' (@%d) (%s)",
+ error, erroroffset, spec);
+
+ i = VRE_exec(vre, s->rxbuf, strlen(s->rxbuf), 0, 0, NULL, 0, 0);
+
+ VRE_free(&vre);
+
+ ret = (i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!');
+ if (!ret)
+ vtc_fatal(s->vl, "EXPECT FAILED %s \"%s\"", cmp, spec);
+ else
+ vtc_log(s->vl, 4, "EXPECT MATCH %s \"%s\"", cmp, spec);
+}
+
+static void v_matchproto_(cmd_f)
+cmd_syslog_recv(CMD_ARGS)
+{
+ int lvl;
+ struct syslog_srv *s;
+
+ CAST_OBJ_NOTNULL(s, priv, SYSLOG_SRV_MAGIC);
+ (void)cmd;
+ (void)vl;
+ AZ(strcmp(av[0], "recv"));
+ av++;
+ if (av[0] == NULL)
+ lvl = s->lvl;
+ else
+ lvl = get_syslog_level(vl, av[0]);
+
+ syslog_rx(s, lvl);
+}
+
+static const struct cmds syslog_cmds[] = {
+#define CMD_SYSLOG(n) { #n, cmd_syslog_##n },
+ /* session */
+ CMD_SYSLOG(expect)
+ CMD_SYSLOG(recv)
+#undef CMD_SYSLOG
+};
+
+/**********************************************************************
+ * Syslog server thread
+ */
+
+static void *
+syslog_thread(void *priv)
+{
+ struct syslog_srv *s;
+ int i;
+
+ CAST_OBJ_NOTNULL(s, priv, SYSLOG_SRV_MAGIC);
+ assert(s->sock >= 0);
+
+ vtc_log(s->vl, 2, "Started on %s (level: %d)", s->bind, s->lvl);
+ for (i = 0; i < s->repeat; i++) {
+ if (s->repeat > 1)
+ vtc_log(s->vl, 3, "Iteration %d", i);
+ parse_string(s->spec, syslog_cmds, s, s->vl);
+ vtc_log(s->vl, 3, "shutting fd %d", s->sock);
+ }
+ VUDP_close(&s->sock);
+ vtc_log(s->vl, 2, "Ending");
+ return (NULL);
+}
+
+/**********************************************************************
+ * Start the syslog thread
+ */
+
+static void
+syslog_start(struct syslog_srv *s)
+{
+ CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
+ vtc_log(s->vl, 2, "Starting syslog server");
+ if (s->sock == -1)
+ syslog_bind(s);
+ vtc_log(s->vl, 1, "Bound on %s", s->bind);
+ s->run = 1;
+ AZ(pthread_create(&s->tp, NULL, syslog_thread, s));
+}
+
+/**********************************************************************
+ * Force stop the syslog thread
+ */
+
+static void
+syslog_stop(struct syslog_srv *s)
+{
+ void *res;
+
+ CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
+ vtc_log(s->vl, 2, "Stopping for syslog server");
+ (void)pthread_cancel(s->tp);
+ AZ(pthread_join(s->tp, &res));
+ s->tp = 0;
+ s->run = 0;
+}
+
+/**********************************************************************
+ * Wait for syslog thread to stop
+ */
+
+static void
+syslog_wait(struct syslog_srv *s)
+{
+ void *res;
+
+ CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
+ vtc_log(s->vl, 2, "Waiting for syslog server (%d)", s->sock);
+ AZ(pthread_join(s->tp, &res));
+ if (res != NULL && !vtc_stop)
+ vtc_fatal(s->vl, "Syslog server returned \"%p\"",
+ (char *)res);
+ s->tp = 0;
+ s->run = 0;
+}
+
+/* SECTION: syslog syslog
+ *
+ * Define and interact with syslog instances.
+ *
+ * To define a syslog server, you'll use this syntax::
+ *
+ * syslog sNAME
+ *
+ * Arguments:
+ *
+ * sNAME
+ * Identify the syslog server with a string which must start with 's'.
+ *
+ * \-level STRING
+ * Set the default syslog priority level used by any subsequent "recv"
+ * command.
+ * Any syslog dgram with a different level will be skipped by
+ * "recv" command. This default level value may be superseded
+ * by "recv" command if supplied as first argument: "recv <level>".
+ *
+ * \-start
+ * Start the syslog server thread in the background.
+ *
+ * \-repeat
+ * Instead of processing the specification only once, do it
+ * NUMBER times.
+ *
+ * \-bind
+ * Bind the syslog socket to a local address.
+ *
+ * \-wait
+ * Wait for that thread to terminate.
+ *
+ * \-stop
+ * Stop the syslog server thread.
+ */
+
+void v_matchproto_(cmd_f)
+cmd_syslog(CMD_ARGS)
+{
+ struct syslog_srv *s;
+
+ (void)priv;
+ (void)cmd;
+
+ if (av == NULL) {
+ /* Reset and free */
+ do {
+ AZ(pthread_mutex_lock(&syslog_mtx));
+ s = VTAILQ_FIRST(&syslogs);
+ CHECK_OBJ_ORNULL(s, SYSLOG_SRV_MAGIC);
+ if (s != NULL)
+ VTAILQ_REMOVE(&syslogs, s, list);
+ AZ(pthread_mutex_unlock(&syslog_mtx));
+ if (s != NULL) {
+ if (s->run) {
+ (void)pthread_cancel(s->tp);
+ syslog_wait(s);
+ }
+ if (s->sock >= 0)
+ VUDP_close(&s->sock);
+ syslog_delete(s);
+ }
+ } while (s != NULL);
+ return;
+ }
+
+ AZ(strcmp(av[0], "syslog"));
+ av++;
+
+ AZ(pthread_mutex_lock(&syslog_mtx));
+ VTAILQ_FOREACH(s, &syslogs, list)
+ if (!strcmp(s->name, av[0]))
+ break;
+ AZ(pthread_mutex_unlock(&syslog_mtx));
+ if (s == NULL)
+ s = syslog_new(av[0], vl);
+ CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
+ av++;
+
+ for (; *av != NULL; av++) {
+ if (vtc_error)
+ break;
+ if (!strcmp(*av, "-wait")) {
+ if (!s->run)
+ vtc_fatal(s->vl, "Syslog server not -started");
+ syslog_wait(s);
+ continue;
+ }
+
+ if (!strcmp(*av, "-stop")) {
+ syslog_stop(s);
+ continue;
+ }
+
+ /*
+ * We do an implict -wait if people muck about with a
+ * running syslog.
+ * This only works if the previous ->spec has completed
+ */
+ if (s->run)
+ syslog_wait(s);
+
+ AZ(s->run);
+ if (!strcmp(*av, "-repeat")) {
+ AN(av[1]);
+ s->repeat = atoi(av[1]);
+ av++;
+ continue;
+ }
+ if (!strcmp(*av, "-bind")) {
+ AN(av[1]);
+ bprintf(s->bind, "%s", av[1]);
+ av++;
+ syslog_bind(s);
+ continue;
+ }
+ if (!strcmp(*av, "-level")) {
+ AN(av[1]);
+ s->lvl = get_syslog_level(vl, av[1]);
+ av++;
+ continue;
+ }
+ if (!strcmp(*av, "-start")) {
+ syslog_start(s);
+ continue;
+ }
+ if (**av == '-')
+ vtc_fatal(s->vl, "Unknown syslog argument: %s", *av);
+ s->spec = *av;
+ }
+}
+
+void
+init_syslog(void)
+{
+ AZ(pthread_mutex_init(&syslog_mtx, NULL));
+}
More information about the varnish-commit
mailing list