[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