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