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