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 240
openout(int append)
71
{
72
73 240
        AN(LOG.w_arg);
74 240
        if (LOG.A_opt) {
75 80
                if (!strcmp(LOG.w_arg, "-"))
76 40
                        LOG.fo = stdout;
77
                else
78 40
                        LOG.fo = fopen(LOG.w_arg, append ? "a" : "w");
79 80
        } else
80 160
                LOG.fo = VSL_WriteOpen(vut->vsl, LOG.w_arg, append, LOG.u_opt);
81 240
        if (LOG.fo == NULL)
82 80
                VUT_Error(vut, 2, "Cannot open output file (%s)",
83 40
                    LOG.A_opt ? strerror(errno) : VSL_Error(vut->vsl));
84 200
        vut->dispatch_priv = LOG.fo;
85 200
}
86
87
static int v_matchproto_(VUT_cb_f)
88 40
rotateout(struct VUT *v)
89
{
90
91 40
        assert(v == vut);
92 40
        AN(LOG.w_arg);
93 40
        AN(LOG.fo);
94 40
        (void)fclose(LOG.fo);
95 40
        openout(1);
96 40
        AN(LOG.fo);
97 40
        return (0);
98
}
99
100
static int v_matchproto_(VUT_cb_f)
101 91728
flushout(struct VUT *v)
102
{
103
104 91728
        assert(v == vut);
105 91728
        AN(LOG.fo);
106 91728
        if (fflush(LOG.fo))
107 0
                return (-5);
108 91728
        return (0);
109 91728
}
110
111
int
112 2360
main(int argc, char * const *argv)
113
{
114
        int opt;
115
116 2360
        vut = VUT_InitProg(argc, argv, &vopt_spec);
117 2360
        AN(vut);
118 2360
        memset(&LOG, 0, sizeof LOG);
119
120 7840
        while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) {
121 5520
                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 80
                        LOG.A_opt = 1;
129 80
                        break;
130
                case 'h':
131
                        /* Usage help */
132 40
                        VUT_Usage(vut, &vopt_spec, 0);
133
                case 'u':
134
                        /* Unbuffered output */
135 40
                        LOG.u_opt = 1;
136 40
                        break;
137
                case 'w':
138
                        /* Write to file */
139 280
                        REPLACE(LOG.w_arg, optarg);
140 280
                        break;
141
                default:
142 5080
                        if (!VUT_Arg(vut, opt, optarg))
143 0
                                VUT_Usage(vut, &vopt_spec, 1);
144 5080
                }
145
        }
146
147 2320
        if (optind != argc)
148 40
                VUT_Usage(vut, &vopt_spec, 1);
149
150 2280
        if (vut->D_opt && !LOG.w_arg)
151 40
                VUT_Error(vut, 1, "Missing -w option");
152
153 2240
        if (vut->D_opt && !strcmp(LOG.w_arg, "-"))
154 80
                VUT_Error(vut, 1, "Daemon cannot write to stdout");
155
156
        /* Setup output */
157 2160
        if (LOG.A_opt || !LOG.w_arg) {
158 2040
                vut->dispatch_f = VSL_PrintTransactions;
159 2040
        } else {
160 120
                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 120
                AN(VUT_Arg(vut, 'x', "Link"));
166 120
                AN(VUT_Arg(vut, 'i', "Link"));
167 120
                AN(VUT_Arg(vut, 'i', "Begin"));
168 120
                AN(VUT_Arg(vut, 'i', "End"));
169
        }
170 2160
        if (LOG.w_arg) {
171 160
                openout(LOG.a_opt);
172 160
                AN(LOG.fo);
173 160
                if (vut->D_opt)
174 40
                        vut->sighup_f = rotateout;
175 160
        } else
176 2000
                LOG.fo = stdout;
177 2160
        vut->idle_f = flushout;
178
179 2160
        VUT_Setup(vut);
180 2160
        (void)VUT_Main(vut);
181 2160
        VUT_Fini(&vut);
182
183 2160
        (void)flushout(NULL);
184
185 2160
        exit(0);
186
}