varnish-cache/bin/varnishlog/varnishlog.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 * Log tailer for Varnish
32
 */
33
34
#include "config.h"
35
36
#include <signal.h>
37
#include <stdarg.h>
38
#include <stdlib.h>
39
#include <stdio.h>
40
#include <unistd.h>
41
#include <string.h>
42
#include <stdint.h>
43
44
#define VOPT_DEFINITION
45
#define VOPT_INC "varnishlog_options.h"
46
47
#include "vdef.h"
48
49
#include "vapi/vsm.h"
50
#include "vapi/vsl.h"
51
#include "vapi/voptget.h"
52
#include "vas.h"
53
#include "vut.h"
54
#include "miniobj.h"
55
56
static struct VUT *vut;
57
58
static struct log {
59
        /* Options */
60
        int             a_opt;
61
        int             A_opt;
62
        int             u_opt;
63
        char            *w_arg;
64
65
        /* State */
66
        FILE            *fo;
67
} LOG;
68
69
static void
70 150
openout(int append)
71
{
72
73 150
        AN(LOG.w_arg);
74 150
        if (LOG.A_opt) {
75 50
                if (!strcmp(LOG.w_arg, "-"))
76 25
                        LOG.fo = stdout;
77
                else
78 25
                        LOG.fo = fopen(LOG.w_arg, append ? "a" : "w");
79 50
        } else
80 100
                LOG.fo = VSL_WriteOpen(vut->vsl, LOG.w_arg, append, LOG.u_opt);
81 150
        if (LOG.fo == NULL)
82 50
                VUT_Error(vut, 2, "Cannot open output file (%s)",
83 25
                    LOG.A_opt ? strerror(errno) : VSL_Error(vut->vsl));
84 125
        vut->dispatch_priv = LOG.fo;
85 125
}
86
87
static int v_matchproto_(VUT_cb_f)
88 25
rotateout(struct VUT *v)
89
{
90
91 25
        assert(v == vut);
92 25
        AN(LOG.w_arg);
93 25
        AN(LOG.fo);
94 25
        (void)fclose(LOG.fo);
95 25
        openout(1);
96 25
        AN(LOG.fo);
97 25
        return (0);
98
}
99
100
static int v_matchproto_(VUT_cb_f)
101 56380
flushout(struct VUT *v)
102
{
103
104 56380
        assert(v == vut);
105 56380
        AN(LOG.fo);
106 56380
        if (fflush(LOG.fo))
107 0
                return (-5);
108 56380
        return (0);
109 56380
}
110
111
int
112 1450
main(int argc, char * const *argv)
113
{
114
        int opt;
115
116 1450
        vut = VUT_InitProg(argc, argv, &vopt_spec);
117 1450
        AN(vut);
118 1450
        memset(&LOG, 0, sizeof LOG);
119
120 4800
        while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) {
121 3375
                switch (opt) {
122
                case 'a':
123
                        /* Append to file */
124 0
                        LOG.a_opt = 1;
125 0
                        break;
126
                case 'A':
127
                        /* Text output */
128 50
                        LOG.A_opt = 1;
129 50
                        break;
130
                case 'h':
131
                        /* Usage help */
132 25
                        VUT_Usage(vut, &vopt_spec, 0);
133
                case 'u':
134
                        /* Unbuffered output */
135 25
                        LOG.u_opt = 1;
136 25
                        break;
137
                case 'w':
138
                        /* Write to file */
139 175
                        REPLACE(LOG.w_arg, optarg);
140 175
                        break;
141
                default:
142 3100
                        if (!VUT_Arg(vut, opt, optarg))
143 0
                                VUT_Usage(vut, &vopt_spec, 1);
144 3100
                }
145
        }
146
147 1425
        if (optind != argc)
148 25
                VUT_Usage(vut, &vopt_spec, 1);
149
150 1400
        if (vut->D_opt && !LOG.w_arg)
151 25
                VUT_Error(vut, 1, "Missing -w option");
152
153 1375
        if (vut->D_opt && !strcmp(LOG.w_arg, "-"))
154 50
                VUT_Error(vut, 1, "Daemon cannot write to stdout");
155
156
        /* Setup output */
157 1325
        if (LOG.A_opt || !LOG.w_arg) {
158 1250
                vut->dispatch_f = VSL_PrintTransactions;
159 1250
        } else {
160 75
                vut->dispatch_f = VSL_WriteTransactions;
161
                /*
162
                 * inefficient but not crossing API layers
163
                 * first x argument avoids initial suppression of all tags
164
                 */
165 75
                AN(VUT_Arg(vut, 'x', "Link"));
166 75
                AN(VUT_Arg(vut, 'i', "Link"));
167 75
                AN(VUT_Arg(vut, 'i', "Begin"));
168 75
                AN(VUT_Arg(vut, 'i', "End"));
169
        }
170 1325
        if (LOG.w_arg) {
171 100
                openout(LOG.a_opt);
172 100
                AN(LOG.fo);
173 100
                if (vut->D_opt)
174 25
                        vut->sighup_f = rotateout;
175 100
        } else
176 1225
                LOG.fo = stdout;
177 1325
        vut->idle_f = flushout;
178
179 1325
        VUT_Setup(vut);
180 1325
        (void)VUT_Main(vut);
181 1325
        VUT_Fini(&vut);
182
183 1325
        (void)flushout(NULL);
184
185 1325
        exit(0);
186
}