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