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