varnish-cache/bin/varnishd/mgt/mgt_main.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2017 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * The management process and CLI handling
31
 */
32
33
#include "config.h"
34
35
#include <ctype.h>
36
#include <fcntl.h>
37
#include <signal.h>
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <syslog.h>
43
#include <unistd.h>
44
#include <sys/stat.h>
45
#include <sys/socket.h>
46
47
#include "mgt/mgt.h"
48
#include "common/heritage.h"
49
50
#include "hash/hash_slinger.h"
51
#include "libvcc.h"
52
#include "vcli_serve.h"
53
#include "vct.h"
54
#include "vev.h"
55
#include "vfil.h"
56
#include "vin.h"
57
#include "vpf.h"
58
#include "vrnd.h"
59
#include "vsha256.h"
60
#include "vsub.h"
61
#include "vtim.h"
62
#include "waiter/mgt_waiter.h"
63
#include "vsa.h"
64
#include "vus.h"
65
66
struct heritage         heritage;
67
unsigned                d_flag = 0;
68
struct vev_root         *mgt_evb;
69
int                     exit_status = 0;
70
struct vsb              *vident;
71
struct VSC_mgt          *VSC_C_mgt;
72
static int              I_fd = -1;
73
static char             *workdir;
74
75
static struct vfil_path *vcl_path = NULL;
76
77
static const char opt_spec[] = "?a:b:CdE:f:Fh:i:I:j:l:M:n:P:p:r:S:s:T:t:VW:x:";
78
79
/*--------------------------------------------------------------------*/
80
81
static void
82 50
usage(void)
83
{
84
        char *p;
85
86
#define FMT_NONL "  %-28s # %s"
87
#define FMT FMT_NONL "\n"
88
89 50
        printf( "Usage: varnishd [options]\n");
90
91 50
        printf("\nBasic options:\n");
92
93 50
        printf(FMT, "-a [<name>=]address[:port][,proto]",
94
            "HTTP listen address and port");
95 50
        printf(FMT, "   [,user=<u>][,group=<g>]",
96
            "Can be specified multiple times.");
97 50
        printf(FMT, "   [,mode=<m>]", "  default: \":80,HTTP\"");
98 50
        printf(FMT, "", "Proto can be \"PROXY\" or \"HTTP\" (default)");
99 50
        printf(FMT, "", "user, group and mode set permissions for");
100 50
        printf(FMT, "", "  a Unix domain socket.");
101 50
        printf(FMT, "-b none", "No backend");
102 50
        printf(FMT, "-b [addr[:port]|path]", "Backend address and port");
103 50
        printf(FMT, "", "  or socket file path");
104 50
        printf(FMT, "", "  default: \":80\"");
105 50
        printf(FMT, "-f vclfile", "VCL program");
106 50
        printf(FMT, "", "Can be specified multiple times.");
107 50
        printf(FMT, "-n dir", "Working directory");
108
109 50
        p = VIN_n_Arg(NULL);
110 50
        AN(p);
111 50
        printf(FMT_NONL "  default: %s\n", "", "", p);
112 50
        free(p);
113
114 50
        printf("\n-b can be used only once, and not together with -f\n");
115
116 50
        printf("\nDocumentation options:\n");
117 50
        printf(FMT, "-?", "Prints this usage message");
118 50
        printf(FMT, "-x parameter", "Parameter documentation");
119 50
        printf(FMT, "-x vsl", "VSL record documentation");
120 50
        printf(FMT, "-x cli", "CLI command documentation");
121 50
        printf(FMT, "-x builtin", "Builtin VCL program");
122 50
        printf(FMT, "-x optstring", "List of getopt options");
123
124 50
        printf("\nOperations options:\n");
125
126 50
        printf(FMT, "-F", "Run in foreground");
127 50
        printf(FMT, "-T address[:port]", "CLI address");
128 50
        printf(FMT, "", "Can be specified multiple times.");
129 50
        printf(FMT, "-M address:port", "Reverse CLI destination");
130 50
        printf(FMT, "", "Can be specified multiple times.");
131 50
        printf(FMT, "-P file", "PID file");
132 50
        printf(FMT, "-i identity", "Identity of varnish instance");
133 50
        printf(FMT, "-I clifile", "Initialization CLI commands");
134 50
        printf(FMT, "-E extension", "Load extension");
135
136 50
        printf("\nTuning options:\n");
137
138 50
        printf(FMT, "-t TTL", "Default TTL");
139 50
        printf(FMT, "-p param=value", "set parameter");
140 50
        printf(FMT, "", "Can be specified multiple times.");
141
142 50
        printf(FMT, "-s [name=]kind[,options]", "Storage specification");
143 50
        printf(FMT, "", "Can be specified multiple times.");
144
#ifdef HAVE_UMEM_H
145
        printf(FMT, "", "  -s default (=umem)");
146
        printf(FMT, "", "  -s umem");
147
#else
148 50
        printf(FMT, "", "  -s default (=malloc)");
149
#endif
150 50
        printf(FMT, "", "  -s malloc");
151 50
        printf(FMT, "", "  -s file");
152
153 50
        printf(FMT, "-l vsl", "Size of shared memory log");
154 50
        printf(FMT, "", "  vsl: space for VSL records [80m]");
155
156 50
        printf("\nSecurity options:\n");
157
158 50
        printf(FMT, "-r param[,param...]", "Set parameters read-only from CLI");
159 50
        printf(FMT, "", "Can be specified multiple times.");
160 50
        printf(FMT, "-S secret-file", "Secret file for CLI authentication");
161 50
        printf(FMT, "-j jail[,options]", "Jail specification");
162
#ifdef HAVE_SETPPRIV
163
        printf(FMT, "", "  -j solaris");
164
#endif
165 50
        printf(FMT, "", "  -j unix");
166 50
        printf(FMT, "", "  -j none");
167
168 50
        printf("\nAdvanced/Dev/Debug options:\n");
169
170 50
        printf(FMT, "-d", "debug mode");
171 50
        printf(FMT, "", "Stay in foreground, CLI on stdin.");
172 50
        printf(FMT, "-C", "Output VCL code compiled to C language");
173 50
        printf(FMT, "-V", "version");
174 50
        printf(FMT, "-h kind[,options]", "Hash specification");
175 50
        printf(FMT, "-W waiter", "Waiter implementation");
176 50
}
177
178
/*--------------------------------------------------------------------*/
179
180
struct arg_list {
181
        unsigned                magic;
182
#define ARG_LIST_MAGIC          0x7b0d1bc4
183
        char                    arg[2];
184
        char                    *val;
185
        VTAILQ_ENTRY(arg_list)  list;
186
        void                    *priv;
187
};
188
189
static VTAILQ_HEAD(, arg_list) arglist = VTAILQ_HEAD_INITIALIZER(arglist);
190
191
static struct arg_list *
192 329000
arg_list_add(const char arg, const char *val)
193
{
194
        struct arg_list *alp;
195
196 329000
        ALLOC_OBJ(alp, ARG_LIST_MAGIC);
197 329000
        AN(alp);
198 329000
        alp->arg[0] = arg;
199 329000
        alp->arg[1] = '\0';
200 329000
        REPLACE(alp->val, val);
201 329000
        VTAILQ_INSERT_TAIL(&arglist, alp, list);
202 329000
        return (alp);
203
}
204
205
static unsigned
206 97425
arg_list_count(const char *arg)
207
{
208 97425
        unsigned retval = 0;
209
        struct arg_list *alp;
210
211 1280100
        VTAILQ_FOREACH(alp, &arglist, list) {
212 1182675
                if (!strcmp(alp->arg, arg))
213 3900
                        retval++;
214 1182675
        }
215 97425
        return (retval);
216
}
217
218
/*--------------------------------------------------------------------*/
219
220
static void
221 329000
cli_check(const struct cli *cli)
222
{
223 329000
        if (cli->result == CLIS_OK || cli->result == CLIS_TRUNCATED) {
224 328975
                AZ(VSB_finish(cli->sb));
225 328975
                if (VSB_len(cli->sb) > 0)
226 50
                        fprintf(stderr, "Warnings:\n%s\n", VSB_data(cli->sb));
227 328975
                VSB_clear(cli->sb);
228 328975
                return;
229
        }
230 25
        AZ(VSB_finish(cli->sb));
231 25
        fprintf(stderr, "Error:\n%s\n", VSB_data(cli->sb));
232 25
        exit(2);
233
}
234
235
/*--------------------------------------------------------------------
236
 * This function is called when the CLI on stdin is closed.
237
 */
238
239
static int v_matchproto_(mgt_cli_close_f)
240 22650
mgt_stdin_close(void *priv)
241
{
242
243 22650
        (void)priv;
244 22650
        return (-42);
245
}
246
247
/*--------------------------------------------------------------------
248
 * Autogenerate a -S file using strong random bits from the kernel.
249
 */
250
251
static void
252 109025
mgt_secret_atexit(void)
253
{
254
255
        /* Only master process */
256 109025
        if (getpid() != heritage.mgt_pid)
257 86125
                return;
258 22900
        VJ_master(JAIL_MASTER_FILE);
259 22900
        (void)unlink("_.secret");
260 22900
        VJ_master(JAIL_MASTER_LOW);
261 109025
}
262
263
static const char *
264 22925
make_secret(const char *dirname)
265
{
266
        char *fn;
267
        int fdo;
268
        int i;
269
        unsigned char b;
270
271 22925
        assert(asprintf(&fn, "%s/_.secret", dirname) > 0);
272
273 22925
        VJ_master(JAIL_MASTER_FILE);
274 22925
        fdo = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0640);
275 22925
        if (fdo < 0)
276 25
                ARGV_ERR("Cannot create secret-file in %s (%s)\n",
277
                    dirname, VAS_errtxt(errno));
278
279 5885300
        for (i = 0; i < 256; i++) {
280 5862400
                AZ(VRND_RandomCrypto(&b, 1));
281 5862400
                assert(1 == write(fdo, &b, 1));
282 5862400
        }
283 22900
        closefd(&fdo);
284 22900
        VJ_master(JAIL_MASTER_LOW);
285 22900
        AZ(atexit(mgt_secret_atexit));
286 22900
        return (fn);
287
}
288
289
static void
290 300
mgt_Cflag_atexit(void)
291
{
292
293
        /* Only master process */
294 300
        if (getpid() != heritage.mgt_pid)
295 200
                return;
296 100
        if (arg_list_count("E")) {
297 0
                vext_cleanup(1);
298 0
                VJ_rmdir("vext_cache");
299 0
        }
300 100
        VJ_rmdir("vmod_cache");
301 100
        (void)chdir("/");
302 100
        VJ_rmdir(workdir);
303 300
}
304
305
/*--------------------------------------------------------------------*/
306
307
static void
308 24800
mgt_tests(void)
309
{
310 24800
        assert(VTIM_parse("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777);
311 24800
        assert(VTIM_parse("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777);
312 24800
        assert(VTIM_parse("Sun Nov  6 08:49:37 1994") == 784111777);
313
314
        /* Check that our VSHA256 works */
315 24800
        VSHA256_Test();
316 24800
}
317
318
static void
319 24800
mgt_initialize(struct cli *cli)
320
{
321
        static unsigned clilim = 32768;
322
323
        /* for ASSERT_MGT() */
324 24800
        heritage.mgt_pid = getpid();
325
326
        /* Create a cli for convenience in otherwise CLI functions */
327 24800
        INIT_OBJ(cli, CLI_MAGIC);
328 24800
        cli[0].sb = VSB_new_auto();
329 24800
        AN(cli[0].sb);
330 24800
        cli[0].result = CLIS_OK;
331 24800
        cli[0].limit = &clilim;
332
333 24800
        mgt_cli_init_cls();             // CLI commands can be registered
334
335 24800
        MCF_InitParams(cli);
336
337 24800
        VCC_VCL_Range(&heritage.min_vcl_version, &heritage.max_vcl_version);
338
339 24800
        cli_check(cli);
340 24800
}
341
342
static void
343 200
mgt_x_arg(const char *x_arg)
344
{
345 200
        if (!strcmp(x_arg, "parameter"))
346 50
                MCF_DumpRstParam();
347 150
        else if (!strcmp(x_arg, "vsl"))
348 25
                mgt_DumpRstVsl();
349 125
        else if (!strcmp(x_arg, "cli"))
350 50
                mgt_DumpRstCli();
351 75
        else if (!strcmp(x_arg, "builtin"))
352 25
                mgt_DumpBuiltin();
353 50
        else if (!strcmp(x_arg, "optstring"))
354 25
                (void)printf("%s\n", opt_spec);
355
        else
356 25
                ARGV_ERR("Invalid -x argument\n");
357 175
}
358
359
/*--------------------------------------------------------------------*/
360
361
#define ERIC_MAGIC 0x2246988a           /* Eric is not random */
362
363
static int
364 500
mgt_eric(void)
365
{
366
        int eric_pipes[2];
367
        unsigned u;
368
        ssize_t sz;
369
370 500
        AZ(pipe(eric_pipes));
371
372 500
        switch (fork()) {
373
        case -1:
374 0
                fprintf(stderr, "Fork() failed: %s\n", VAS_errtxt(errno));
375 0
                exit(-1);
376
        case 0:
377 500
                closefd(&eric_pipes[0]);
378 500
                assert(setsid() > 1);
379
380 500
                VFIL_null_fd(STDIN_FILENO);
381 500
                return (eric_pipes[1]);
382
        default:
383 500
                break;
384
        }
385 500
        closefd(&eric_pipes[1]);
386 500
        sz = read(eric_pipes[0], &u, sizeof u);
387 500
        if (sz == sizeof u && u == ERIC_MAGIC)
388 0
                exit(0);
389 125
        else if (sz == sizeof u && u != 0)
390 125
                exit(u);
391
        else
392 375
                exit(-1);
393
}
394
395
static void
396 125
mgt_eric_im_done(int eric_fd, unsigned u)
397
{
398
399 125
        if (u == 0)
400 0
                u = ERIC_MAGIC;
401
402 125
        VFIL_null_fd(STDIN_FILENO);
403 125
        VFIL_null_fd(STDOUT_FILENO);
404 125
        VFIL_null_fd(STDERR_FILENO);
405
406 125
        assert(write(eric_fd, &u, sizeof u) == sizeof u);
407 125
        closefd(&eric_fd);
408 125
}
409
410
/*--------------------------------------------------------------------*/
411
412
static int v_matchproto_(vev_cb_f)
413 75
mgt_sigint(const struct vev *e, int what)
414
{
415
416 75
        (void)e;
417 75
        (void)what;
418 75
        MGT_Complain(C_ERR, "Manager got %s", e->name);
419 75
        (void)fflush(stdout);
420 75
        if (MCH_Running())
421 75
                MCH_Stop_Child();
422 75
        return (-42);
423
}
424
425
/*--------------------------------------------------------------------*/
426
427
static int v_matchproto_(vev_cb_f)
428 42647
mgt_uptime(const struct vev *e, int what)
429
{
430
        static double mgt_uptime_t0 = 0;
431
432 42647
        (void)e;
433 42647
        (void)what;
434 42647
        AN(VSC_C_mgt);
435 42647
        if (mgt_uptime_t0 == 0)
436 21862
                mgt_uptime_t0 = VTIM_real();
437 42647
        VSC_C_mgt->uptime = (uint64_t)(VTIM_real() - mgt_uptime_t0);
438 42647
        return (0);
439
}
440
441
/*--------------------------------------------------------------------*/
442
443
static int v_matchproto_(mgt_cli_close_f)
444 25
mgt_I_close(void *priv)
445
{
446 25
        (void)priv;
447 25
        fprintf(stderr, "END of -I file processing\n");
448 25
        I_fd = -1;
449 25
        return (0);
450
}
451
452
/*--------------------------------------------------------------------*/
453
454
struct f_arg {
455
        unsigned                magic;
456
#define F_ARG_MAGIC             0x840649a8
457
        char                    *farg;
458
        char                    *src;
459
};
460
461
static struct f_arg *
462 325
mgt_f_read(const char *fn)
463
{
464
        struct f_arg *fa;
465
        char *f, *fnp;
466
467 325
        ALLOC_OBJ(fa, F_ARG_MAGIC);
468 325
        AN(fa);
469 325
        REPLACE(fa->farg, fn);
470 325
        VFIL_setpath(&vcl_path, mgt_vcl_path);
471 325
        if (VFIL_searchpath(vcl_path, NULL, &f, fn, &fnp) || f == NULL) {
472 75
                ARGV_ERR("Cannot read -f file '%s' (%s)\n",
473
                    fnp != NULL ? fnp : fn, VAS_errtxt(errno));
474 0
        }
475 250
        free(fa->farg);
476 250
        fa->farg = fnp;
477 250
        fa->src = f;
478 250
        return (fa);
479
}
480
481
static void
482 600
mgt_b_conv(const char *b_arg)
483
{
484
        struct f_arg *fa;
485
        struct vsb *vsb;
486
487 600
        ALLOC_OBJ(fa, F_ARG_MAGIC);
488 600
        AN(fa);
489 600
        REPLACE(fa->farg, "<-b argument>");
490 600
        vsb = VSB_new_auto();
491 600
        AN(vsb);
492 600
        VSB_cat(vsb, "vcl 4.1;\n");
493 600
        VSB_cat(vsb, "backend default ");
494 600
        if (!strcasecmp(b_arg, "none"))
495 300
                VSB_cat(vsb, "none;\n");
496 300
        else if (VUS_is(b_arg))
497 25
                VSB_printf(vsb, "{\n    .path = \"%s\";\n}\n", b_arg);
498
        else
499 275
                VSB_printf(vsb, "{\n    .host = \"%s\";\n}\n", b_arg);
500 600
        AZ(VSB_finish(vsb));
501 600
        fa->src = strdup(VSB_data(vsb));
502 600
        AN(fa->src);
503 600
        VSB_destroy(&vsb);
504 600
        AZ(arg_list_count("f"));
505 600
        arg_list_add('f', "")->priv = fa;
506 600
}
507
508
static int
509 675
mgt_process_f_arg(struct cli *cli, unsigned C_flag, void **fap)
510
{
511 675
        int retval = 0;
512
        struct f_arg *fa;
513 675
        const char *name = NULL;
514
515 675
        TAKE_OBJ_NOTNULL(fa, fap, F_ARG_MAGIC);
516 675
        if (arg_list_count("f") == 1)
517 625
                name = "boot";
518 675
        mgt_vcl_startup(cli, fa->src, name, fa->farg, C_flag);
519 675
        if (C_flag) {
520 100
                if (cli->result != CLIS_OK &&
521 0
                    cli->result != CLIS_TRUNCATED)
522 0
                        retval = 2;
523 100
                AZ(VSB_finish(cli->sb));
524 100
                fprintf(stderr, "%s\n", VSB_data(cli->sb));
525 100
                VSB_clear(cli->sb);
526 100
        } else {
527 575
                cli_check(cli);
528
        }
529 675
        free(fa->farg);
530 675
        free(fa->src);
531 675
        FREE_OBJ(fa);
532 650
        return (retval);
533
}
534
535
static const char *
536 50
create_bogo_n_arg(void)
537
{
538
        struct vsb *vsb;
539
        char *p;
540
541 50
        vsb = VSB_new_auto();
542 50
        AN(vsb);
543 50
        if (getenv("TMPDIR") != NULL)
544 50
                VSB_printf(vsb, "%s", getenv("TMPDIR"));
545
        else
546 0
                VSB_cat(vsb, "/tmp");
547 50
        VSB_cat(vsb, "/varnishd_C_XXXXXXX");
548 50
        AZ(VSB_finish(vsb));
549 50
        p = strdup(VSB_data(vsb));
550 50
        AN(p);
551 50
        VSB_destroy(&vsb);
552 50
        AN(mkdtemp(p));
553 50
        AZ(chmod(p, 0750));
554 50
        return (p);
555
}
556
557
static struct vpf_fh *
558 45625
create_pid_file(pid_t *ppid, const char *fmt, ...)
559
{
560
        struct vsb *vsb;
561
        va_list ap;
562
        struct vpf_fh *pfh;
563
564 45625
        va_start(ap, fmt);
565 45625
        vsb = VSB_new_auto();
566 45625
        AN(vsb);
567 45625
        VSB_vprintf(vsb, fmt, ap);
568 45625
        AZ(VSB_finish(vsb));
569 45625
        VJ_master(JAIL_MASTER_FILE);
570 45625
        pfh = VPF_Open(VSB_data(vsb), 0644, ppid);
571 45625
        if (pfh == NULL && errno == EEXIST)
572 50
                ARGV_ERR(
573
                    "Varnishd is already running (pid=%jd) (pidfile=%s)\n",
574
                    (intmax_t)*ppid, VSB_data(vsb));
575 25
        if (pfh == NULL)
576 25
                ARGV_ERR("Could not open pid-file (%s): %s\n",
577
                    VSB_data(vsb), VAS_errtxt(errno));
578 45550
        VJ_master(JAIL_MASTER_LOW);
579 45550
        VSB_destroy(&vsb);
580 45550
        va_end(ap);
581 45550
        return (pfh);
582
}
583
584
int
585 24825
main(int argc, char * const *argv)
586
{
587 24825
        int o, eric_fd = -1;
588 24825
        unsigned C_flag = 0;
589 24825
        unsigned F_flag = 0;
590 24825
        const char *b_arg = NULL;
591 24825
        const char *i_arg = NULL;
592 24825
        const char *j_arg = NULL;
593 24825
        const char *h_arg = "critbit";
594 24825
        const char *n_arg = NULL;
595 24825
        const char *S_arg = NULL;
596 24825
        const char *s_arg = "default,100m";
597 24825
        const char *W_arg = NULL;
598
        const char *c;
599
        char *p;
600
        struct cli cli[1];
601
        const char *err;
602
        unsigned u;
603
        struct sigaction sac;
604
        struct vev *e;
605
        pid_t pid;
606
        struct arg_list *alp;
607 24825
        int first_arg = 1;
608
609 24825
        if (argc == 2 && !strcmp(argv[1], "--optstring")) {
610 25
                printf("%s\n", opt_spec);
611 25
                exit(0);
612
        }
613
614 24800
        heritage.argc = argc;
615 24800
        heritage.argv = argv;
616
617 24800
        setbuf(stdout, NULL);
618 24800
        setbuf(stderr, NULL);
619
620 24800
        mgt_tests();
621
622 24800
        mgt_initialize(cli);
623
624 377300
        for (; (o = getopt(argc, argv, opt_spec)) != -1; first_arg = 0) {
625 352875
                switch (o) {
626
                case 'V':
627 75
                        if (!first_arg)
628 25
                                ARGV_ERR("-V must be the first argument\n");
629 25
                        if (argc != 2)
630 25
                                ARGV_ERR("Too many arguments for -V\n");
631 25
                        VCS_Message("varnishd");
632 25
                        exit(0);
633
                case 'x':
634 250
                        if (!first_arg)
635 25
                                ARGV_ERR("-x must be the first argument\n");
636 25
                        if (argc != 3)
637 25
                                ARGV_ERR("Too many arguments for -x\n");
638 200
                        mgt_x_arg(optarg);
639 200
                        exit(0);
640
                case 'b':
641 675
                        b_arg = optarg;
642 675
                        break;
643
                case 'C':
644 175
                        C_flag = 1;
645 175
                        break;
646
                case 'd':
647 23475
                        d_flag++;
648 23475
                        break;
649
                case 'F':
650 300
                        F_flag = 1;
651 300
                        break;
652
                case 'j':
653 250
                        j_arg = optarg;
654 250
                        break;
655
                case 'h':
656 100
                        h_arg = optarg;
657 100
                        break;
658
                case 'i':
659 22700
                        i_arg = optarg;
660 22700
                        break;
661
                case 'l':
662 22750
                        arg_list_add('p', "vsl_space")->priv = optarg;
663 22750
                        break;
664
                case 'n':
665 23425
                        n_arg = optarg;
666 23425
                        break;
667
                case 'S':
668 25
                        S_arg = optarg;
669 25
                        break;
670
                case 't':
671 25
                        arg_list_add('p', "default_ttl")->priv = optarg;
672 25
                        break;
673
                case 'W':
674 150
                        W_arg = optarg;
675 150
                        break;
676
                case 'a':
677
                case 'E':
678
                case 'f':
679
                case 'I':
680
                case 'p':
681
                case 'P':
682
                case 'M':
683
                case 'r':
684
                case 's':
685
                case 'T':
686 258450
                        (void)arg_list_add(o, optarg);
687 258450
                        break;
688
                default:
689 50
                        usage();
690 50
                        exit(2);
691
                }
692 352500
        }
693
694 24425
        if (argc != optind)
695 25
                ARGV_ERR("Too many arguments (%s...)\n", argv[optind]);
696
697 675
        if (b_arg != NULL && arg_list_count("f"))
698 25
                ARGV_ERR("Only one of -b or -f can be specified\n");
699
700 23425
        if (d_flag && F_flag)
701 25
                ARGV_ERR("Only one of -d or -F can be specified\n");
702
703 175
        if (C_flag && b_arg == NULL && !arg_list_count("f"))
704 25
                ARGV_ERR("-C needs either -b <backend> or -f <vcl_file>\n");
705
706 23400
        if (d_flag && C_flag)
707 25
                ARGV_ERR("-d makes no sense with -C\n");
708
709 275
        if (F_flag && C_flag)
710 25
                ARGV_ERR("-F makes no sense with -C\n");
711
712 900
        if (!d_flag && b_arg == NULL && !arg_list_count("f"))
713 25
                ARGV_ERR("Neither -b nor -f given. (use -f '' to override)\n");
714
715 25
        if (arg_list_count("I") > 1)
716 25
                ARGV_ERR("\tOnly one -I allowed\n");
717
718 850
        if (d_flag || F_flag)
719 23625
                complain_to_stderr = 1;
720
721 24225
        if (!arg_list_count("T"))
722 24225
                (void)arg_list_add('T', "localhost:0");
723
724
        /*
725
         * Start out by closing all unwanted file descriptors we might
726
         * have inherited from sloppy process control daemons.
727
         */
728 24325
        VSUB_closefrom(STDERR_FILENO + 1);
729 24325
        MCH_TrackHighFd(STDERR_FILENO);
730
731
        /*
732
         * Have Eric Daemonize us if need be
733
         */
734 24325
        if (!C_flag && !d_flag && !F_flag) {
735 500
                eric_fd = mgt_eric();
736 500
                MCH_TrackHighFd(eric_fd);
737 500
                heritage.mgt_pid = getpid();
738 500
        }
739
740 24225
        VRND_SeedAll();
741
742 24225
        vident = mgt_BuildVident();
743
744
        /* Various initializations */
745 24225
        VTAILQ_INIT(&heritage.socks);
746 24225
        mgt_evb = VEV_New();
747 24225
        AN(mgt_evb);
748
749
        /* Initialize transport protocols */
750 24225
        XPORT_Init();
751
752 24225
        VJ_Init(j_arg);
753
754
        /* Initialize the bogo-IP VSA */
755 24225
        VSA_Init();
756
757 24225
        if (b_arg != NULL)
758 600
                mgt_b_conv(b_arg);
759
760
        /* Process delayed arguments */
761 327700
        VTAILQ_FOREACH(alp, &arglist, list) {
762 304550
                switch(alp->arg[0]) {
763
                case 'a':
764 24075
                        MAC_Arg(alp->val);
765 24075
                        break;
766
                case 'f':
767 1050
                        if (*alp->val != '\0')
768 325
                                alp->priv = mgt_f_read(alp->val);
769 975
                        break;
770
                case 'E':
771 25
                        vext_argument(alp->val);
772 25
                        break;
773
                case 'I':
774 125
                        VJ_master(JAIL_MASTER_FILE);
775 125
                        I_fd = open(alp->val, O_RDONLY);
776 125
                        if (I_fd < 0)
777 25
                                ARGV_ERR("\tCan't open %s: %s\n",
778
                                    alp->val, VAS_errtxt(errno));
779 100
                        VJ_master(JAIL_MASTER_LOW);
780 100
                        break;
781
                case 'p':
782 208350
                        if (alp->priv) {
783 22775
                                MCF_ParamSet(cli, alp->val, alp->priv);
784 22775
                        } else {
785 185575
                                p = strchr(alp->val, '=');
786 185575
                                if (p == NULL)
787 0
                                        ARGV_ERR("\t-p lacks '='\n");
788 185575
                                AN(p);
789 185575
                                *p++ = '\0';
790 185575
                                MCF_ParamSet(cli, alp->val, p);
791
                        }
792 208350
                        break;
793
                case 'r':
794 25
                        MCF_ParamProtect(cli, alp->val);
795 25
                        break;
796
                case 's':
797 2450
                        STV_Config(alp->val);
798 2450
                        break;
799
                default:
800 68450
                        break;
801
                }
802 304450
                cli_check(cli);
803 304450
        }
804
805 23150
        VCLS_SetLimit(mgt_cls, &mgt_param.cli_limit);
806
807 23150
        assert(d_flag == 0 || F_flag == 0);
808
809 23150
        if (C_flag && n_arg == NULL)
810 50
                n_arg = create_bogo_n_arg();
811
812 75
        if (S_arg != NULL && !strcmp(S_arg, "none")) {
813 0
                fprintf(stderr,
814
                    "Warning: CLI authentication disabled.\n");
815 25
        } else if (S_arg != NULL) {
816 25
                VJ_master(JAIL_MASTER_FILE);
817 25
                o = open(S_arg, O_RDONLY, 0);
818 25
                if (o < 0)
819 25
                        ARGV_ERR("Cannot open -S file (%s): %s\n",
820
                            S_arg, VAS_errtxt(errno));
821 0
                closefd(&o);
822 0
                VJ_master(JAIL_MASTER_LOW);
823 0
        }
824
825 23125
        workdir = VIN_n_Arg(n_arg);
826 23125
        AN(workdir);
827
828 23125
        if (i_arg == NULL || *i_arg == '\0')
829 500
                i_arg = mgt_HostName();
830 68325
        else for (c = i_arg; *c != '\0'; c++) {
831 45700
                if (!vct_istchar(*c))
832 0
                        ARGV_ERR("Invalid character '%c' for -i\n", *c);
833 45700
        }
834 23125
        heritage.identity = i_arg;
835
836 23125
        mgt_ProcTitle("Mgt");
837
838 23125
        openlog("varnishd", LOG_PID, LOG_LOCAL0);
839
840 23125
        if (VJ_make_workdir(workdir))
841 0
                ARGV_ERR("Cannot create working directory (%s): %s\n",
842
                    workdir, VAS_errtxt(errno));
843
844 23125
        VJ_master(JAIL_MASTER_SYSTEM);
845 23125
        AZ(system("rm -rf vmod_cache"));
846 23125
        AZ(system("rm -rf vext_cache"));
847 23125
        VJ_master(JAIL_MASTER_LOW);
848
849 23125
        if (VJ_make_subdir("vmod_cache", "VMOD cache", NULL)) {
850 0
                ARGV_ERR(
851
                    "Cannot create vmod directory (%s/vmod_cache): %s\n",
852
                    workdir, VAS_errtxt(errno));
853 0
        }
854
855 25
        if (arg_list_count("E") &&
856 25
            VJ_make_subdir("vext_cache", "VMOD cache", NULL)) {
857 0
                ARGV_ERR(
858
                    "Cannot create vmod directory (%s/vext_cache): %s\n",
859
                    workdir, VAS_errtxt(errno));
860 0
        }
861
862 100
        if (C_flag)
863 100
                AZ(atexit(mgt_Cflag_atexit));
864
865
        /* If no -s argument specified, process default -s argument */
866 21450
        if (!arg_list_count("s"))
867 21450
                STV_Config(s_arg);
868
869
        /* Configure CLI and Transient storage, if user did not */
870 23125
        STV_Config_Final();
871
872 23125
        mgt_vcl_init();
873
874 23125
        vext_copyin(vident);
875
876 23125
        u = 0;
877 326050
        VTAILQ_FOREACH(alp, &arglist, list) {
878 302950
                if (!strcmp(alp->arg, "f") && alp->priv != NULL)
879 675
                        u |= mgt_process_f_arg(cli, C_flag, &alp->priv);
880 302925
        }
881 23100
        if (C_flag)
882 100
                exit(u);
883
884 325475
        VTAILQ_FOREACH(alp, &arglist, list) {
885 302525
                if (!strcmp(alp->arg, "P"))
886 22675
                        alp->priv = create_pid_file(&pid, "%s", alp->val);
887 302475
        }
888
889
        /* Implict -P argument */
890 22950
        alp = arg_list_add('P', NULL);
891 22950
        alp->priv = create_pid_file(&pid, "%s/_.pid", workdir);
892
893 22950
        if (VTAILQ_EMPTY(&heritage.socks))
894 0
                MAC_Arg(":80\0");       // XXX: extra NUL for FlexeLint
895
896 22925
        assert(!VTAILQ_EMPTY(&heritage.socks));
897
898 22925
        HSH_config(h_arg);
899
900 22925
        Wait_config(W_arg);
901
902 22925
        mgt_SHM_Init();
903
904 22925
        mgt_SHM_static_alloc(i_arg, strlen(i_arg) + 1L, "Arg", "-i");
905 22925
        VSC_C_mgt = VSC_mgt_New(NULL, NULL, "");
906
907 348250
        VTAILQ_FOREACH(alp, &arglist, list) {
908 325325
                if (!strcmp(alp->arg, "M"))
909 22625
                        mgt_cli_master(alp->val);
910 302700
                else if (!strcmp(alp->arg, "T") && strcmp(alp->val, "none"))
911 22925
                        mgt_cli_telnet(alp->val);
912 45550
                else if (!strcmp(alp->arg, "P"))
913 45550
                        VPF_Write(alp->priv);
914 325325
        }
915
916 22925
        AZ(VSB_finish(vident));
917
918 22925
        if (S_arg == NULL)
919 22925
                S_arg = make_secret(workdir);
920 22950
        AN(S_arg);
921
922 22900
        MGT_Complain(C_DEBUG, "Version: %s", VCS_String("V"));
923 22900
        MGT_Complain(C_DEBUG, "Platform: %s", VSB_data(vident) + 1);
924
925 22900
        if (d_flag)
926 22700
                mgt_cli_setup(0, 1, 1, "debug", mgt_stdin_close, NULL);
927
928 22900
        if (strcmp(S_arg, "none"))
929 22900
                mgt_cli_secret(S_arg);
930
931 22900
        memset(&sac, 0, sizeof sac);
932 22900
        sac.sa_handler = SIG_IGN;
933 22900
        sac.sa_flags = SA_RESTART;
934
935 22900
        AZ(sigaction(SIGPIPE, &sac, NULL));
936 22900
        AZ(sigaction(SIGHUP, &sac, NULL));
937
938 22900
        MCH_Init();
939
940 22900
        if (I_fd >= 0) {
941 100
                fprintf(stderr, "BEGIN of -I file processing\n");
942
                /* We must dup stderr, because VCLS closes the output fd */
943 100
                mgt_cli_setup(I_fd, dup(2), 1, "-I file", mgt_I_close, stderr);
944 200
                while (I_fd >= 0) {
945 175
                        o = VEV_Once(mgt_evb);
946 175
                        if (o != 1)
947 0
                                MGT_Complain(C_ERR,
948 0
                                    "VEV_Once() = %d", o);
949
                }
950 25
        }
951 22825
        assert(I_fd == -1);
952
953 22825
        err = mgt_has_vcl();
954 22825
        if (!d_flag && err != NULL && !arg_list_count("f"))
955 0
                MGT_Complain(C_ERR, "%s", err);
956
957 450
        if (err == NULL && !d_flag)
958 150
                u = MCH_Start_Child();
959
        else
960 22675
                u = 0;
961
962 22825
        if (eric_fd >= 0)
963 125
                mgt_eric_im_done(eric_fd, u);
964
965 22825
        if (u)
966 125
                exit(u);
967
968
        /* Failure is no longer an option */
969
970 22700
        if (F_flag)
971 50
                VFIL_null_fd(STDIN_FILENO);
972
973 22700
        e = VEV_Alloc();
974 22700
        AN(e);
975 22700
        e->callback = mgt_uptime;
976 22700
        e->timeout = 1.0;
977 22700
        e->name = "mgt_uptime";
978 22700
        AZ(VEV_Start(mgt_evb, e));
979
980 22700
        e = VEV_Alloc();
981 22700
        AN(e);
982 22700
        e->sig = SIGTERM;
983 22700
        e->callback = mgt_sigint;
984 22700
        e->name = "SIGTERM";
985 22700
        AZ(VEV_Start(mgt_evb, e));
986
987 22700
        e = VEV_Alloc();
988 22700
        AN(e);
989 22700
        e->sig = SIGINT;
990 22700
        e->callback = mgt_sigint;
991 22700
        e->name = "SIGINT";
992 22700
        AZ(VEV_Start(mgt_evb, e));
993
994 22700
        o = VEV_Loop(mgt_evb);
995 22700
        if (o != 0 && o != -42)
996 0
                MGT_Complain(C_ERR, "VEV_Loop() = %d", o);
997
998 22700
        MGT_Complain(C_INFO, "manager stopping child");
999 22700
        MCH_Stop_Child();
1000 22700
        MGT_Complain(C_INFO, "manager dies");
1001 22700
        mgt_cli_close_all();
1002 22700
        VEV_Destroy(&mgt_evb);
1003 22700
        VJ_master(JAIL_MASTER_SYSTEM);
1004
        /*lint -e(730)*/
1005 22700
        vext_cleanup(! MGT_DO_DEBUG(DBG_VMOD_SO_KEEP));
1006 22700
        (void)rmdir("vext_cache");
1007 22700
        VJ_master(JAIL_MASTER_LOW);
1008 346875
        VTAILQ_FOREACH(alp, &arglist, list) {
1009 324175
                if (!strcmp(alp->arg, "P"))
1010 45325
                        VPF_Remove(alp->priv);
1011 324175
        }
1012 22700
        exit(exit_status);
1013
}