[experimental-ims] 5c0eee3 rename varnishd.c to mgt/mgt_main.c

Geoff Simmons geoff at varnish-cache.org
Mon Jan 9 21:52:32 CET 2012


commit 5c0eee322b6ad646781f66f40d26f01dd7e0079d
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Sun Nov 13 10:09:28 2011 +0000

    rename varnishd.c to mgt/mgt_main.c

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 002447f..94b52a5 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -58,6 +58,7 @@ varnishd_SOURCES = \
 	hash/hash_simple_list.c \
 	mgt/mgt_child.c \
 	mgt/mgt_cli.c \
+	mgt/mgt_main.c \
 	mgt/mgt_param.c \
 	mgt/mgt_pool.c \
 	mgt/mgt_sandbox.c \
@@ -75,7 +76,6 @@ varnishd_SOURCES = \
 	storage/storage_persistent_subr.c \
 	storage/storage_synth.c \
 	storage/storage_umem.c \
-	varnishd.c \
 	vsm.c
 
 noinst_HEADERS = \
diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c
new file mode 100644
index 0000000..ccda130
--- /dev/null
+++ b/bin/varnishd/mgt/mgt_main.c
@@ -0,0 +1,652 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * 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.
+ *
+ * The management process and CLI handling
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mgt/mgt.h"
+#include "heritage.h"
+#include "params.h"
+
+#include "hash/hash_slinger.h"
+#include "vav.h"
+#include "vcli.h"
+#include "vcli_common.h"
+#include "vev.h"
+#include "vfil.h"
+#include "vin.h"
+#include "vpf.h"
+#include "vsha256.h"
+#include "vtim.h"
+
+#include "compat/daemon.h"
+
+#ifndef HAVE_SRANDOMDEV
+#include "compat/srandomdev.h"
+#endif
+
+struct heritage		heritage;
+unsigned		d_flag = 0;
+pid_t			mgt_pid;
+struct vev_base		*mgt_evb;
+int			exit_status = 0;
+struct vsb		*vident;
+
+static void
+build_vident(void)
+{
+	struct utsname uts;
+
+	vident = VSB_new_auto();
+	AN(vident);
+	if (!uname(&uts)) {
+		VSB_printf(vident, ",%s", uts.sysname);
+		VSB_printf(vident, ",%s", uts.release);
+		VSB_printf(vident, ",%s", uts.machine);
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+const void *
+pick(const struct choice *cp, const char *which, const char *kind)
+{
+
+	for(; cp->name != NULL; cp++) {
+		if (!strcmp(cp->name, which))
+			return (cp->ptr);
+	}
+	ARGV_ERR("Unknown %s method \"%s\"\n", kind, which);
+}
+
+/*--------------------------------------------------------------------*/
+
+static unsigned long
+arg_ul(const char *p)
+{
+	char *q;
+	unsigned long ul;
+
+	ul = strtoul(p, &q, 0);
+	if (*q != '\0')
+		ARGV_ERR("Invalid number: \"%s\"\n", p);
+	return (ul);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+usage(void)
+{
+#define FMT "    %-28s # %s\n"
+
+	fprintf(stderr, "usage: varnishd [options]\n");
+	fprintf(stderr, FMT, "-a address:port", "HTTP listen address and port");
+	fprintf(stderr, FMT, "-b address:port", "backend address and port");
+	fprintf(stderr, FMT, "", "   -b <hostname_or_IP>");
+	fprintf(stderr, FMT, "", "   -b '<hostname_or_IP>:<port_or_service>'");
+	fprintf(stderr, FMT, "-C", "print VCL code compiled to C language");
+	fprintf(stderr, FMT, "-d", "debug");
+	fprintf(stderr, FMT, "-f file", "VCL script");
+	fprintf(stderr, FMT, "-F", "Run in foreground");
+	fprintf(stderr, FMT, "-h kind[,hashoptions]", "Hash specification");
+	fprintf(stderr, FMT, "", "  -h critbit [default]");
+	fprintf(stderr, FMT, "", "  -h simple_list");
+	fprintf(stderr, FMT, "", "  -h classic");
+	fprintf(stderr, FMT, "", "  -h classic,<buckets>");
+	fprintf(stderr, FMT, "-i identity", "Identity of varnish instance");
+	fprintf(stderr, FMT, "-l shl,free,fill", "Size of shared memory file");
+	fprintf(stderr, FMT, "", "  shl: space for SHL records [80m]");
+	fprintf(stderr, FMT, "", "  free: space for other allocations [1m]");
+	fprintf(stderr, FMT, "", "  fill: prefill new file [+]");
+	fprintf(stderr, FMT, "-M address:port", "Reverse CLI destination.");
+	fprintf(stderr, FMT, "-n dir", "varnishd working directory");
+	fprintf(stderr, FMT, "-P file", "PID file");
+	fprintf(stderr, FMT, "-p param=value", "set parameter");
+	fprintf(stderr, FMT,
+	    "-s kind[,storageoptions]", "Backend storage specification");
+	fprintf(stderr, FMT, "", "  -s malloc");
+#ifdef HAVE_LIBUMEM
+	fprintf(stderr, FMT, "", "  -s umem");
+#endif
+	fprintf(stderr, FMT, "", "  -s file  [default: use /tmp]");
+	fprintf(stderr, FMT, "", "  -s file,<dir_or_file>");
+	fprintf(stderr, FMT, "", "  -s file,<dir_or_file>,<size>");
+	fprintf(stderr, FMT, "", "  -s persist{experimenta}");
+	fprintf(stderr, FMT, "",
+	    "  -s file,<dir_or_file>,<size>,<granularity>");
+	fprintf(stderr, FMT, "-t", "Default TTL");
+	fprintf(stderr, FMT, "-S secret-file",
+	    "Secret file for CLI authentication");
+	fprintf(stderr, FMT, "-T address:port",
+	    "Telnet listen address and port");
+	fprintf(stderr, FMT, "-V", "version");
+	fprintf(stderr, FMT, "-w int[,int[,int]]", "Number of worker threads");
+	fprintf(stderr, FMT, "", "  -w <fixed_count>");
+	fprintf(stderr, FMT, "", "  -w min,max");
+	fprintf(stderr, FMT, "", "  -w min,max,timeout [default: -w2,500,300]");
+	fprintf(stderr, FMT, "-u user", "Priviledge separation user id");
+#undef FMT
+	exit(1);
+}
+
+
+/*--------------------------------------------------------------------*/
+
+static void
+tackle_warg(const char *argv)
+{
+	char **av;
+	unsigned int u;
+
+	av = VAV_Parse(argv, NULL, ARGV_COMMA);
+	AN(av);
+
+	if (av[0] != NULL)
+		ARGV_ERR("%s\n", av[0]);
+
+	if (av[1] == NULL)
+		usage();
+
+	u = arg_ul(av[1]);
+	if (u < 1)
+		usage();
+	mgt_param.wthread_max = mgt_param.wthread_min = u;
+
+	if (av[2] != NULL) {
+		u = arg_ul(av[2]);
+		if (u < mgt_param.wthread_min)
+			usage();
+		mgt_param.wthread_max = u;
+
+		if (av[3] != NULL) {
+			u = arg_ul(av[3]);
+			mgt_param.wthread_timeout = u;
+		}
+	}
+	VAV_Free(av);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+cli_check(const struct cli *cli)
+{
+	if (cli->result == CLIS_OK) {
+		VSB_clear(cli->sb);
+		return;
+	}
+	AZ(VSB_finish(cli->sb));
+	fprintf(stderr, "Error:\n%s\n", VSB_data(cli->sb));
+	exit (2);
+}
+
+/*--------------------------------------------------------------------
+ * All praise POSIX!  Thanks to our glorious standards there are no
+ * standard way to get a back-trace of the stack, and even if we hack
+ * that together from spit and pieces of string, there is no way no
+ * standard way to translate a pointer to a symbol, which returns anything
+ * usable.  (See for instance FreeBSD PR-134391).
+ *
+ * Attempt to run nm(1) on our binary during startup, hoping it will
+ * give us a usable list of symbols.
+ */
+
+struct symbols {
+	uintptr_t		a;
+	char			*n;
+	VTAILQ_ENTRY(symbols)	list;
+};
+
+static VTAILQ_HEAD(,symbols) symbols = VTAILQ_HEAD_INITIALIZER(symbols);
+
+int
+Symbol_Lookup(struct vsb *vsb, void *ptr)
+{
+	struct symbols *s, *s0;
+	uintptr_t pp;
+
+	pp = (uintptr_t)ptr;
+	s0 = NULL;
+	VTAILQ_FOREACH(s, &symbols, list) {
+		if (s->a > pp)
+			continue;
+		if (s0 == NULL || s->a > s0->a)
+			s0 = s;
+	}
+	if (s0 == NULL)
+		return (-1);
+	VSB_printf(vsb, "%p: %s+%jx", ptr, s0->n, (uintmax_t)pp - s0->a);
+	return (0);
+}
+
+static void
+Symbol_hack(const char *a0)
+{
+	char buf[BUFSIZ], *p, *e;
+	FILE *fi;
+	uintptr_t a;
+	struct symbols *s;
+
+	bprintf(buf, "nm -an %s 2>/dev/null", a0);
+	fi = popen(buf, "r");
+	if (fi == NULL)
+		return;
+	while (fgets(buf, sizeof buf, fi)) {
+		if (buf[0] == ' ')
+			continue;
+		p = NULL;
+		a = strtoul(buf, &p, 16);
+		if (p == NULL)
+			continue;
+		if (a == 0)
+			continue;
+		if (*p++ != ' ')
+			continue;
+		p++;
+		if (*p++ != ' ')
+			continue;
+		if (*p <= ' ')
+			continue;
+		e = strchr(p, '\0');
+		AN(e);
+		while (e > p && isspace(e[-1]))
+			e--;
+		*e = '\0';
+		s = malloc(sizeof *s + strlen(p) + 1);
+		AN(s);
+		s->a = a;
+		s->n = (void*)(s + 1);
+		strcpy(s->n, p);
+		VTAILQ_INSERT_TAIL(&symbols, s, list);
+	}
+	(void)pclose(fi);
+}
+
+/*--------------------------------------------------------------------
+ * This function is called when the CLI on stdin is closed.
+ */
+
+static void
+cli_stdin_close(void *priv)
+{
+
+	(void)priv;
+	(void)close(0);
+	(void)close(1);
+	(void)close(2);
+	assert(open("/dev/null", O_RDONLY) == 0);
+	assert(open("/dev/null", O_WRONLY) == 1);
+	assert(open("/dev/null", O_WRONLY) == 2);
+
+	if (d_flag) {
+		mgt_stop_child();
+		mgt_cli_close_all();
+		exit(0);
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+int
+main(int argc, char * const *argv)
+{
+	int o;
+	unsigned C_flag = 0;
+	unsigned F_flag = 0;
+	const char *b_arg = NULL;
+	const char *f_arg = NULL;
+	const char *i_arg = NULL;
+	const char *l_arg = NULL;	/* default in mgt_shmem.c */
+	const char *h_arg = "critbit";
+	const char *M_arg = NULL;
+	const char *n_arg = NULL;
+	const char *P_arg = NULL;
+	const char *S_arg = NULL;
+	const char *s_arg = "file";
+	int s_arg_given = 0;
+	const char *T_arg = NULL;
+	char *p, *vcl = NULL;
+	struct cli cli[1];
+	struct vpf_fh *pfh = NULL;
+	char *dirname;
+
+	/*
+	 * Start out by closing all unwanted file descriptors we might
+	 * have inherited from sloppy process control daemons.
+	 */
+	for (o = getdtablesize(); o > STDERR_FILENO; o--)
+		(void)close(o);
+
+	srandomdev();
+
+	mgt_got_fd(STDERR_FILENO);
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+	build_vident();
+
+	Symbol_hack(argv[0]);
+
+	/* for ASSERT_MGT() */
+	mgt_pid = getpid();
+
+	/*
+	 * Run in UTC timezone, on the off-chance that this operating
+	 * system does not have a timegm() function, and translates
+	 * timestamps on the local timescale.
+	 * See lib/libvarnish/time.c
+	 */
+	AZ(setenv("TZ", "UTC", 1));
+	tzset();
+	assert(VTIM_parse("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777);
+	assert(VTIM_parse("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777);
+	assert(VTIM_parse("Sun Nov  6 08:49:37 1994") == 784111777);
+
+	/*
+	 * Check that our SHA256 works
+	 */
+	SHA256_Test();
+
+	memset(cli, 0, sizeof cli);
+	cli[0].sb = VSB_new_auto();
+	XXXAN(cli[0].sb);
+	cli[0].result = CLIS_OK;
+
+	VTAILQ_INIT(&heritage.socks);
+
+	MCF_ParamInit(cli);
+
+	if (sizeof(void *) < 8) {
+		/*
+		 * Adjust default parameters for 32 bit systems to conserve
+		 * VM space.
+		 */
+		MCF_ParamSet(cli, "sess_workspace", "16384");
+		cli_check(cli);
+
+		MCF_ParamSet(cli, "thread_pool_workspace", "16384");
+		cli_check(cli);
+
+		MCF_ParamSet(cli, "http_resp_size", "8192");
+		cli_check(cli);
+
+		MCF_ParamSet(cli, "http_req_size", "12288");
+		cli_check(cli);
+
+		MCF_ParamSet(cli, "thread_pool_stack", "32bit");
+		cli_check(cli);
+
+		MCF_ParamSet(cli, "gzip_stack_buffer", "4096");
+		cli_check(cli);
+	}
+
+	cli_check(cli);
+
+	while ((o = getopt(argc, argv,
+	    "a:b:Cdf:Fg:h:i:l:L:M:n:P:p:S:s:T:t:u:Vx:w:")) != -1)
+		switch (o) {
+		case 'a':
+			MCF_ParamSet(cli, "listen_address", optarg);
+			cli_check(cli);
+			break;
+		case 'b':
+			b_arg = optarg;
+			break;
+		case 'C':
+			C_flag = 1 - C_flag;
+			break;
+		case 'd':
+			d_flag++;
+			break;
+		case 'f':
+			f_arg = optarg;
+			break;
+		case 'F':
+			F_flag = 1 - F_flag;
+			break;
+		case 'g':
+			MCF_ParamSet(cli, "group", optarg);
+			break;
+		case 'h':
+			h_arg = optarg;
+			break;
+		case 'i':
+			i_arg = optarg;
+			break;
+		case 'l':
+			l_arg = optarg;
+			break;
+		case 'M':
+			M_arg = optarg;
+			break;
+		case 'n':
+			n_arg = optarg;
+			break;
+		case 'P':
+			P_arg = optarg;
+			break;
+		case 'p':
+			p = strchr(optarg, '=');
+			if (p == NULL)
+				usage();
+			AN(p);
+			*p++ = '\0';
+			MCF_ParamSet(cli, optarg, p);
+			cli_check(cli);
+			break;
+		case 's':
+			s_arg_given = 1;
+			STV_Config(optarg);
+			break;
+		case 't':
+			MCF_ParamSet(cli, "default_ttl", optarg);
+			break;
+		case 'S':
+			S_arg = optarg;
+			break;
+		case 'T':
+			T_arg = optarg;
+			break;
+		case 'u':
+			MCF_ParamSet(cli, "user", optarg);
+			break;
+		case 'V':
+			/* XXX: we should print the ident here */
+			VCS_Message("varnishd");
+			exit(0);
+		case 'x':
+			if (!strcmp(optarg, "dumprst")) {
+				MCF_DumpRst();
+				exit (0);
+			}
+			usage();
+			break;
+		case 'w':
+			tackle_warg(optarg);
+			break;
+		default:
+			usage();
+		}
+
+	argc -= optind;
+	argv += optind;
+
+	mgt_vcc_init();
+
+	if (argc != 0) {
+		fprintf(stderr, "Too many arguments (%s...)\n", argv[0]);
+		usage();
+	}
+
+	/* XXX: we can have multiple CLI actions above, is this enough ? */
+	if (cli[0].result != CLIS_OK) {
+		fprintf(stderr, "Parameter errors:\n");
+		AZ(VSB_finish(cli[0].sb));
+		fprintf(stderr, "%s\n", VSB_data(cli[0].sb));
+		exit(1);
+	}
+
+	if (d_flag && F_flag) {
+		fprintf(stderr, "Only one of -d or -F can be specified\n");
+		usage();
+	}
+
+	if (b_arg != NULL && f_arg != NULL) {
+		fprintf(stderr, "Only one of -b or -f can be specified\n");
+		usage();
+	}
+	if (S_arg == NULL && T_arg == NULL && d_flag == 0 && b_arg == NULL &&
+	    f_arg == NULL && M_arg == NULL) {
+		fprintf(stderr,
+		    "At least one of -d, -b, -f, -M, -S or -T "
+		    "must be specified\n");
+		usage();
+	}
+
+	if (f_arg != NULL) {
+		vcl = VFIL_readfile(NULL, f_arg, NULL);
+		if (vcl == NULL) {
+			fprintf(stderr, "Cannot read '%s': %s\n",
+			    f_arg, strerror(errno));
+			exit(1);
+		}
+	}
+
+	if (VIN_N_Arg(n_arg, &heritage.name, &dirname, NULL) != 0) {
+		fprintf(stderr, "Invalid instance name: %s\n",
+		    strerror(errno));
+		exit(1);
+	}
+
+	if (i_arg != NULL) {
+		if (snprintf(heritage.identity, sizeof heritage.identity,
+		    "%s", i_arg) > sizeof heritage.identity) {
+			fprintf(stderr, "Invalid identity name: %s\n",
+			    strerror(ENAMETOOLONG));
+			exit(1);
+		}
+	}
+
+	if (n_arg != NULL)
+		openlog(n_arg, LOG_PID, LOG_LOCAL0);
+	else
+		openlog("varnishd", LOG_PID, LOG_LOCAL0);
+
+	if (mkdir(dirname, 0755) < 0 && errno != EEXIST) {
+		fprintf(stderr, "Cannot create working directory '%s': %s\n",
+		    dirname, strerror(errno));
+		exit(1);
+	}
+
+	if (chdir(dirname) < 0) {
+		fprintf(stderr, "Cannot change to working directory '%s': %s\n",
+		    dirname, strerror(errno));
+		exit(1);
+	}
+
+	/* XXX: should this be relative to the -n arg ? */
+	if (P_arg && (pfh = VPF_Open(P_arg, 0644, NULL)) == NULL) {
+		perror(P_arg);
+		exit(1);
+	}
+
+	if (b_arg != NULL || f_arg != NULL)
+		if (mgt_vcc_default(b_arg, f_arg, vcl, C_flag))
+			exit (2);
+
+	if (C_flag)
+		exit (0);
+
+	/* If no -s argument specified, process default -s argument */
+	if (!s_arg_given)
+		STV_Config(s_arg);
+
+	/* Configure Transient storage, if user did not */
+	STV_Config_Transient();
+
+	HSH_config(h_arg);
+
+	mgt_SHM_Init(l_arg);
+
+	AZ(VSB_finish(vident));
+
+	if (!d_flag && !F_flag)
+		AZ(varnish_daemon(1, 0));
+
+	mgt_SHM_Pid();
+
+	if (pfh != NULL && VPF_Write(pfh))
+		fprintf(stderr, "NOTE: Could not write PID file\n");
+
+	if (d_flag)
+		fprintf(stderr, "Platform: %s\n", VSB_data(vident) + 1);
+	syslog(LOG_NOTICE, "Platform: %s\n", VSB_data(vident) + 1);
+
+	/* Do this again after debugstunt and daemon has run */
+	mgt_pid = getpid();
+
+	mgt_evb = vev_new_base();
+	XXXAN(mgt_evb);
+
+	if (d_flag)
+		mgt_cli_setup(0, 1, 1, "debug", cli_stdin_close, NULL);
+	if (S_arg != NULL)
+		mgt_cli_secret(S_arg);
+	if (M_arg != NULL)
+		mgt_cli_master(M_arg);
+	if (T_arg != NULL)
+		mgt_cli_telnet(T_arg);
+
+	AN(VSM_Alloc(0, VSM_CLASS_MARK, "", ""));
+
+	MGT_Run();
+
+	if (pfh != NULL)
+		(void)VPF_Remove(pfh);
+	exit(exit_status);
+}
+
+#if defined(PTHREAD_CANCELED) || defined(PTHREAD_MUTEX_DEFAULT)
+#error "Keep pthreads out of in manager process"
+#endif
diff --git a/bin/varnishd/varnishd.c b/bin/varnishd/varnishd.c
deleted file mode 100644
index ccda130..0000000
--- a/bin/varnishd/varnishd.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * 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.
- *
- * The management process and CLI handling
- */
-
-#include "config.h"
-
-#include <sys/stat.h>
-#include <sys/utsname.h>
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "mgt/mgt.h"
-#include "heritage.h"
-#include "params.h"
-
-#include "hash/hash_slinger.h"
-#include "vav.h"
-#include "vcli.h"
-#include "vcli_common.h"
-#include "vev.h"
-#include "vfil.h"
-#include "vin.h"
-#include "vpf.h"
-#include "vsha256.h"
-#include "vtim.h"
-
-#include "compat/daemon.h"
-
-#ifndef HAVE_SRANDOMDEV
-#include "compat/srandomdev.h"
-#endif
-
-struct heritage		heritage;
-unsigned		d_flag = 0;
-pid_t			mgt_pid;
-struct vev_base		*mgt_evb;
-int			exit_status = 0;
-struct vsb		*vident;
-
-static void
-build_vident(void)
-{
-	struct utsname uts;
-
-	vident = VSB_new_auto();
-	AN(vident);
-	if (!uname(&uts)) {
-		VSB_printf(vident, ",%s", uts.sysname);
-		VSB_printf(vident, ",%s", uts.release);
-		VSB_printf(vident, ",%s", uts.machine);
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-const void *
-pick(const struct choice *cp, const char *which, const char *kind)
-{
-
-	for(; cp->name != NULL; cp++) {
-		if (!strcmp(cp->name, which))
-			return (cp->ptr);
-	}
-	ARGV_ERR("Unknown %s method \"%s\"\n", kind, which);
-}
-
-/*--------------------------------------------------------------------*/
-
-static unsigned long
-arg_ul(const char *p)
-{
-	char *q;
-	unsigned long ul;
-
-	ul = strtoul(p, &q, 0);
-	if (*q != '\0')
-		ARGV_ERR("Invalid number: \"%s\"\n", p);
-	return (ul);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-usage(void)
-{
-#define FMT "    %-28s # %s\n"
-
-	fprintf(stderr, "usage: varnishd [options]\n");
-	fprintf(stderr, FMT, "-a address:port", "HTTP listen address and port");
-	fprintf(stderr, FMT, "-b address:port", "backend address and port");
-	fprintf(stderr, FMT, "", "   -b <hostname_or_IP>");
-	fprintf(stderr, FMT, "", "   -b '<hostname_or_IP>:<port_or_service>'");
-	fprintf(stderr, FMT, "-C", "print VCL code compiled to C language");
-	fprintf(stderr, FMT, "-d", "debug");
-	fprintf(stderr, FMT, "-f file", "VCL script");
-	fprintf(stderr, FMT, "-F", "Run in foreground");
-	fprintf(stderr, FMT, "-h kind[,hashoptions]", "Hash specification");
-	fprintf(stderr, FMT, "", "  -h critbit [default]");
-	fprintf(stderr, FMT, "", "  -h simple_list");
-	fprintf(stderr, FMT, "", "  -h classic");
-	fprintf(stderr, FMT, "", "  -h classic,<buckets>");
-	fprintf(stderr, FMT, "-i identity", "Identity of varnish instance");
-	fprintf(stderr, FMT, "-l shl,free,fill", "Size of shared memory file");
-	fprintf(stderr, FMT, "", "  shl: space for SHL records [80m]");
-	fprintf(stderr, FMT, "", "  free: space for other allocations [1m]");
-	fprintf(stderr, FMT, "", "  fill: prefill new file [+]");
-	fprintf(stderr, FMT, "-M address:port", "Reverse CLI destination.");
-	fprintf(stderr, FMT, "-n dir", "varnishd working directory");
-	fprintf(stderr, FMT, "-P file", "PID file");
-	fprintf(stderr, FMT, "-p param=value", "set parameter");
-	fprintf(stderr, FMT,
-	    "-s kind[,storageoptions]", "Backend storage specification");
-	fprintf(stderr, FMT, "", "  -s malloc");
-#ifdef HAVE_LIBUMEM
-	fprintf(stderr, FMT, "", "  -s umem");
-#endif
-	fprintf(stderr, FMT, "", "  -s file  [default: use /tmp]");
-	fprintf(stderr, FMT, "", "  -s file,<dir_or_file>");
-	fprintf(stderr, FMT, "", "  -s file,<dir_or_file>,<size>");
-	fprintf(stderr, FMT, "", "  -s persist{experimenta}");
-	fprintf(stderr, FMT, "",
-	    "  -s file,<dir_or_file>,<size>,<granularity>");
-	fprintf(stderr, FMT, "-t", "Default TTL");
-	fprintf(stderr, FMT, "-S secret-file",
-	    "Secret file for CLI authentication");
-	fprintf(stderr, FMT, "-T address:port",
-	    "Telnet listen address and port");
-	fprintf(stderr, FMT, "-V", "version");
-	fprintf(stderr, FMT, "-w int[,int[,int]]", "Number of worker threads");
-	fprintf(stderr, FMT, "", "  -w <fixed_count>");
-	fprintf(stderr, FMT, "", "  -w min,max");
-	fprintf(stderr, FMT, "", "  -w min,max,timeout [default: -w2,500,300]");
-	fprintf(stderr, FMT, "-u user", "Priviledge separation user id");
-#undef FMT
-	exit(1);
-}
-
-
-/*--------------------------------------------------------------------*/
-
-static void
-tackle_warg(const char *argv)
-{
-	char **av;
-	unsigned int u;
-
-	av = VAV_Parse(argv, NULL, ARGV_COMMA);
-	AN(av);
-
-	if (av[0] != NULL)
-		ARGV_ERR("%s\n", av[0]);
-
-	if (av[1] == NULL)
-		usage();
-
-	u = arg_ul(av[1]);
-	if (u < 1)
-		usage();
-	mgt_param.wthread_max = mgt_param.wthread_min = u;
-
-	if (av[2] != NULL) {
-		u = arg_ul(av[2]);
-		if (u < mgt_param.wthread_min)
-			usage();
-		mgt_param.wthread_max = u;
-
-		if (av[3] != NULL) {
-			u = arg_ul(av[3]);
-			mgt_param.wthread_timeout = u;
-		}
-	}
-	VAV_Free(av);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-cli_check(const struct cli *cli)
-{
-	if (cli->result == CLIS_OK) {
-		VSB_clear(cli->sb);
-		return;
-	}
-	AZ(VSB_finish(cli->sb));
-	fprintf(stderr, "Error:\n%s\n", VSB_data(cli->sb));
-	exit (2);
-}
-
-/*--------------------------------------------------------------------
- * All praise POSIX!  Thanks to our glorious standards there are no
- * standard way to get a back-trace of the stack, and even if we hack
- * that together from spit and pieces of string, there is no way no
- * standard way to translate a pointer to a symbol, which returns anything
- * usable.  (See for instance FreeBSD PR-134391).
- *
- * Attempt to run nm(1) on our binary during startup, hoping it will
- * give us a usable list of symbols.
- */
-
-struct symbols {
-	uintptr_t		a;
-	char			*n;
-	VTAILQ_ENTRY(symbols)	list;
-};
-
-static VTAILQ_HEAD(,symbols) symbols = VTAILQ_HEAD_INITIALIZER(symbols);
-
-int
-Symbol_Lookup(struct vsb *vsb, void *ptr)
-{
-	struct symbols *s, *s0;
-	uintptr_t pp;
-
-	pp = (uintptr_t)ptr;
-	s0 = NULL;
-	VTAILQ_FOREACH(s, &symbols, list) {
-		if (s->a > pp)
-			continue;
-		if (s0 == NULL || s->a > s0->a)
-			s0 = s;
-	}
-	if (s0 == NULL)
-		return (-1);
-	VSB_printf(vsb, "%p: %s+%jx", ptr, s0->n, (uintmax_t)pp - s0->a);
-	return (0);
-}
-
-static void
-Symbol_hack(const char *a0)
-{
-	char buf[BUFSIZ], *p, *e;
-	FILE *fi;
-	uintptr_t a;
-	struct symbols *s;
-
-	bprintf(buf, "nm -an %s 2>/dev/null", a0);
-	fi = popen(buf, "r");
-	if (fi == NULL)
-		return;
-	while (fgets(buf, sizeof buf, fi)) {
-		if (buf[0] == ' ')
-			continue;
-		p = NULL;
-		a = strtoul(buf, &p, 16);
-		if (p == NULL)
-			continue;
-		if (a == 0)
-			continue;
-		if (*p++ != ' ')
-			continue;
-		p++;
-		if (*p++ != ' ')
-			continue;
-		if (*p <= ' ')
-			continue;
-		e = strchr(p, '\0');
-		AN(e);
-		while (e > p && isspace(e[-1]))
-			e--;
-		*e = '\0';
-		s = malloc(sizeof *s + strlen(p) + 1);
-		AN(s);
-		s->a = a;
-		s->n = (void*)(s + 1);
-		strcpy(s->n, p);
-		VTAILQ_INSERT_TAIL(&symbols, s, list);
-	}
-	(void)pclose(fi);
-}
-
-/*--------------------------------------------------------------------
- * This function is called when the CLI on stdin is closed.
- */
-
-static void
-cli_stdin_close(void *priv)
-{
-
-	(void)priv;
-	(void)close(0);
-	(void)close(1);
-	(void)close(2);
-	assert(open("/dev/null", O_RDONLY) == 0);
-	assert(open("/dev/null", O_WRONLY) == 1);
-	assert(open("/dev/null", O_WRONLY) == 2);
-
-	if (d_flag) {
-		mgt_stop_child();
-		mgt_cli_close_all();
-		exit(0);
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-int
-main(int argc, char * const *argv)
-{
-	int o;
-	unsigned C_flag = 0;
-	unsigned F_flag = 0;
-	const char *b_arg = NULL;
-	const char *f_arg = NULL;
-	const char *i_arg = NULL;
-	const char *l_arg = NULL;	/* default in mgt_shmem.c */
-	const char *h_arg = "critbit";
-	const char *M_arg = NULL;
-	const char *n_arg = NULL;
-	const char *P_arg = NULL;
-	const char *S_arg = NULL;
-	const char *s_arg = "file";
-	int s_arg_given = 0;
-	const char *T_arg = NULL;
-	char *p, *vcl = NULL;
-	struct cli cli[1];
-	struct vpf_fh *pfh = NULL;
-	char *dirname;
-
-	/*
-	 * Start out by closing all unwanted file descriptors we might
-	 * have inherited from sloppy process control daemons.
-	 */
-	for (o = getdtablesize(); o > STDERR_FILENO; o--)
-		(void)close(o);
-
-	srandomdev();
-
-	mgt_got_fd(STDERR_FILENO);
-
-	setbuf(stdout, NULL);
-	setbuf(stderr, NULL);
-
-	build_vident();
-
-	Symbol_hack(argv[0]);
-
-	/* for ASSERT_MGT() */
-	mgt_pid = getpid();
-
-	/*
-	 * Run in UTC timezone, on the off-chance that this operating
-	 * system does not have a timegm() function, and translates
-	 * timestamps on the local timescale.
-	 * See lib/libvarnish/time.c
-	 */
-	AZ(setenv("TZ", "UTC", 1));
-	tzset();
-	assert(VTIM_parse("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777);
-	assert(VTIM_parse("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777);
-	assert(VTIM_parse("Sun Nov  6 08:49:37 1994") == 784111777);
-
-	/*
-	 * Check that our SHA256 works
-	 */
-	SHA256_Test();
-
-	memset(cli, 0, sizeof cli);
-	cli[0].sb = VSB_new_auto();
-	XXXAN(cli[0].sb);
-	cli[0].result = CLIS_OK;
-
-	VTAILQ_INIT(&heritage.socks);
-
-	MCF_ParamInit(cli);
-
-	if (sizeof(void *) < 8) {
-		/*
-		 * Adjust default parameters for 32 bit systems to conserve
-		 * VM space.
-		 */
-		MCF_ParamSet(cli, "sess_workspace", "16384");
-		cli_check(cli);
-
-		MCF_ParamSet(cli, "thread_pool_workspace", "16384");
-		cli_check(cli);
-
-		MCF_ParamSet(cli, "http_resp_size", "8192");
-		cli_check(cli);
-
-		MCF_ParamSet(cli, "http_req_size", "12288");
-		cli_check(cli);
-
-		MCF_ParamSet(cli, "thread_pool_stack", "32bit");
-		cli_check(cli);
-
-		MCF_ParamSet(cli, "gzip_stack_buffer", "4096");
-		cli_check(cli);
-	}
-
-	cli_check(cli);
-
-	while ((o = getopt(argc, argv,
-	    "a:b:Cdf:Fg:h:i:l:L:M:n:P:p:S:s:T:t:u:Vx:w:")) != -1)
-		switch (o) {
-		case 'a':
-			MCF_ParamSet(cli, "listen_address", optarg);
-			cli_check(cli);
-			break;
-		case 'b':
-			b_arg = optarg;
-			break;
-		case 'C':
-			C_flag = 1 - C_flag;
-			break;
-		case 'd':
-			d_flag++;
-			break;
-		case 'f':
-			f_arg = optarg;
-			break;
-		case 'F':
-			F_flag = 1 - F_flag;
-			break;
-		case 'g':
-			MCF_ParamSet(cli, "group", optarg);
-			break;
-		case 'h':
-			h_arg = optarg;
-			break;
-		case 'i':
-			i_arg = optarg;
-			break;
-		case 'l':
-			l_arg = optarg;
-			break;
-		case 'M':
-			M_arg = optarg;
-			break;
-		case 'n':
-			n_arg = optarg;
-			break;
-		case 'P':
-			P_arg = optarg;
-			break;
-		case 'p':
-			p = strchr(optarg, '=');
-			if (p == NULL)
-				usage();
-			AN(p);
-			*p++ = '\0';
-			MCF_ParamSet(cli, optarg, p);
-			cli_check(cli);
-			break;
-		case 's':
-			s_arg_given = 1;
-			STV_Config(optarg);
-			break;
-		case 't':
-			MCF_ParamSet(cli, "default_ttl", optarg);
-			break;
-		case 'S':
-			S_arg = optarg;
-			break;
-		case 'T':
-			T_arg = optarg;
-			break;
-		case 'u':
-			MCF_ParamSet(cli, "user", optarg);
-			break;
-		case 'V':
-			/* XXX: we should print the ident here */
-			VCS_Message("varnishd");
-			exit(0);
-		case 'x':
-			if (!strcmp(optarg, "dumprst")) {
-				MCF_DumpRst();
-				exit (0);
-			}
-			usage();
-			break;
-		case 'w':
-			tackle_warg(optarg);
-			break;
-		default:
-			usage();
-		}
-
-	argc -= optind;
-	argv += optind;
-
-	mgt_vcc_init();
-
-	if (argc != 0) {
-		fprintf(stderr, "Too many arguments (%s...)\n", argv[0]);
-		usage();
-	}
-
-	/* XXX: we can have multiple CLI actions above, is this enough ? */
-	if (cli[0].result != CLIS_OK) {
-		fprintf(stderr, "Parameter errors:\n");
-		AZ(VSB_finish(cli[0].sb));
-		fprintf(stderr, "%s\n", VSB_data(cli[0].sb));
-		exit(1);
-	}
-
-	if (d_flag && F_flag) {
-		fprintf(stderr, "Only one of -d or -F can be specified\n");
-		usage();
-	}
-
-	if (b_arg != NULL && f_arg != NULL) {
-		fprintf(stderr, "Only one of -b or -f can be specified\n");
-		usage();
-	}
-	if (S_arg == NULL && T_arg == NULL && d_flag == 0 && b_arg == NULL &&
-	    f_arg == NULL && M_arg == NULL) {
-		fprintf(stderr,
-		    "At least one of -d, -b, -f, -M, -S or -T "
-		    "must be specified\n");
-		usage();
-	}
-
-	if (f_arg != NULL) {
-		vcl = VFIL_readfile(NULL, f_arg, NULL);
-		if (vcl == NULL) {
-			fprintf(stderr, "Cannot read '%s': %s\n",
-			    f_arg, strerror(errno));
-			exit(1);
-		}
-	}
-
-	if (VIN_N_Arg(n_arg, &heritage.name, &dirname, NULL) != 0) {
-		fprintf(stderr, "Invalid instance name: %s\n",
-		    strerror(errno));
-		exit(1);
-	}
-
-	if (i_arg != NULL) {
-		if (snprintf(heritage.identity, sizeof heritage.identity,
-		    "%s", i_arg) > sizeof heritage.identity) {
-			fprintf(stderr, "Invalid identity name: %s\n",
-			    strerror(ENAMETOOLONG));
-			exit(1);
-		}
-	}
-
-	if (n_arg != NULL)
-		openlog(n_arg, LOG_PID, LOG_LOCAL0);
-	else
-		openlog("varnishd", LOG_PID, LOG_LOCAL0);
-
-	if (mkdir(dirname, 0755) < 0 && errno != EEXIST) {
-		fprintf(stderr, "Cannot create working directory '%s': %s\n",
-		    dirname, strerror(errno));
-		exit(1);
-	}
-
-	if (chdir(dirname) < 0) {
-		fprintf(stderr, "Cannot change to working directory '%s': %s\n",
-		    dirname, strerror(errno));
-		exit(1);
-	}
-
-	/* XXX: should this be relative to the -n arg ? */
-	if (P_arg && (pfh = VPF_Open(P_arg, 0644, NULL)) == NULL) {
-		perror(P_arg);
-		exit(1);
-	}
-
-	if (b_arg != NULL || f_arg != NULL)
-		if (mgt_vcc_default(b_arg, f_arg, vcl, C_flag))
-			exit (2);
-
-	if (C_flag)
-		exit (0);
-
-	/* If no -s argument specified, process default -s argument */
-	if (!s_arg_given)
-		STV_Config(s_arg);
-
-	/* Configure Transient storage, if user did not */
-	STV_Config_Transient();
-
-	HSH_config(h_arg);
-
-	mgt_SHM_Init(l_arg);
-
-	AZ(VSB_finish(vident));
-
-	if (!d_flag && !F_flag)
-		AZ(varnish_daemon(1, 0));
-
-	mgt_SHM_Pid();
-
-	if (pfh != NULL && VPF_Write(pfh))
-		fprintf(stderr, "NOTE: Could not write PID file\n");
-
-	if (d_flag)
-		fprintf(stderr, "Platform: %s\n", VSB_data(vident) + 1);
-	syslog(LOG_NOTICE, "Platform: %s\n", VSB_data(vident) + 1);
-
-	/* Do this again after debugstunt and daemon has run */
-	mgt_pid = getpid();
-
-	mgt_evb = vev_new_base();
-	XXXAN(mgt_evb);
-
-	if (d_flag)
-		mgt_cli_setup(0, 1, 1, "debug", cli_stdin_close, NULL);
-	if (S_arg != NULL)
-		mgt_cli_secret(S_arg);
-	if (M_arg != NULL)
-		mgt_cli_master(M_arg);
-	if (T_arg != NULL)
-		mgt_cli_telnet(T_arg);
-
-	AN(VSM_Alloc(0, VSM_CLASS_MARK, "", ""));
-
-	MGT_Run();
-
-	if (pfh != NULL)
-		(void)VPF_Remove(pfh);
-	exit(exit_status);
-}
-
-#if defined(PTHREAD_CANCELED) || defined(PTHREAD_MUTEX_DEFAULT)
-#error "Keep pthreads out of in manager process"
-#endif



More information about the varnish-commit mailing list