varnish-cache/bin/varnishlog/varnishlog.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
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
 * Log tailer for Varnish
31
 */
32
33
#include "config.h"
34
35
#include <stdarg.h>
36
#include <stdlib.h>
37
#include <stdio.h>
38
#include <unistd.h>
39
#include <string.h>
40
#include <errno.h>
41
#include <stdint.h>
42
43
#define VOPT_DEFINITION
44
#define VOPT_INC "varnishlog_options.h"
45
46
#include "vdef.h"
47
48
#include "vapi/vsm.h"
49
#include "vapi/vsl.h"
50
#include "vapi/voptget.h"
51
#include "vas.h"
52
#include "vut.h"
53
#include "miniobj.h"
54
55
static struct VUT *vut;
56
57
static struct log {
58
        /* Options */
59
        int             a_opt;
60
        int             A_opt;
61
        char            *w_arg;
62
63
        /* State */
64
        FILE            *fo;
65
} LOG;
66
67
static void v_noreturn_
68 2
usage(int status)
69
{
70
        const char **opt;
71 2
        fprintf(stderr, "Usage: %s <options>\n\n", vut->progname);
72 2
        fprintf(stderr, "Options:\n");
73 50
        for (opt = vopt_spec.vopt_usage; *opt != NULL; opt += 2)
74 48
                fprintf(stderr, " %-25s %s\n", *opt, *(opt + 1));
75 2
        exit(status);
76
}
77
78
static void
79 4
openout(int append)
80
{
81
82 4
        AN(LOG.w_arg);
83 4
        if (LOG.A_opt)
84 1
                LOG.fo = fopen(LOG.w_arg, append ? "a" : "w");
85
        else
86 3
                LOG.fo = VSL_WriteOpen(vut->vsl, LOG.w_arg, append, 0);
87 4
        if (LOG.fo == NULL)
88 2
                VUT_Error(vut, 2, "Cannot open output file (%s)",
89 2
                    LOG.A_opt ? strerror(errno) : VSL_Error(vut->vsl));
90 3
        vut->dispatch_priv = LOG.fo;
91 3
}
92
93
static int v_matchproto_(VUT_cb_f)
94 1
rotateout(struct VUT *v)
95
{
96
97 1
        assert(v == vut);
98 1
        AN(LOG.w_arg);
99 1
        AN(LOG.fo);
100 1
        fclose(LOG.fo);
101 1
        openout(1);
102 1
        AN(LOG.fo);
103 1
        return (0);
104
}
105
106
static int v_matchproto_(VUT_cb_f)
107 1140
flushout(struct VUT *v)
108
{
109
110 1140
        assert(v == vut);
111 1140
        AN(LOG.fo);
112 1140
        if (fflush(LOG.fo))
113 0
                return (-5);
114 1140
        return (0);
115
}
116
117
static int v_matchproto_(VUT_cb_f)
118 0
sighup(struct VUT *v)
119
{
120 0
        assert(v == vut);
121 0
        return (1);
122
}
123
124
static void
125 2
vut_sighandler(int sig)
126
{
127 2
        CHECK_OBJ_NOTNULL(vut, VUT_MAGIC);
128 2
        VUT_Signaled(vut, sig);
129 2
}
130
131
int
132 40
main(int argc, char * const *argv)
133
{
134
        int opt;
135
136 40
        vut = VUT_InitProg(argc, argv, &vopt_spec);
137 38
        AN(vut);
138 38
        memset(&LOG, 0, sizeof LOG);
139
140 141
        while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) {
141 79
                switch (opt) {
142
                case 'a':
143
                        /* Append to file */
144 0
                        LOG.a_opt = 1;
145 0
                        break;
146
                case 'A':
147
                        /* Text output */
148 1
                        LOG.A_opt = 1;
149 1
                        break;
150
                case 'h':
151
                        /* Usage help */
152 1
                        usage(0);
153
                case 'w':
154
                        /* Write to file */
155 3
                        REPLACE(LOG.w_arg, optarg);
156 3
                        break;
157
                default:
158 74
                        if (!VUT_Arg(vut, opt, optarg))
159 0
                                usage(1);
160
                }
161
        }
162
163 24
        if (optind != argc)
164 1
                usage(1);
165
166 23
        if (vut->D_opt && !LOG.w_arg)
167 1
                VUT_Error(vut, 1, "Missing -w option");
168
169
        /* Setup output */
170 22
        if (LOG.A_opt || !LOG.w_arg)
171 20
                vut->dispatch_f = VSL_PrintTransactions;
172
        else
173 2
                vut->dispatch_f = VSL_WriteTransactions;
174 22
        vut->sighup_f = sighup;
175 22
        if (LOG.w_arg) {
176 3
                openout(LOG.a_opt);
177 2
                AN(LOG.fo);
178 2
                if (vut->D_opt)
179 1
                        vut->sighup_f = rotateout;
180
        } else
181 19
                LOG.fo = stdout;
182 21
        vut->idle_f = flushout;
183
184 21
        VUT_Signal(vut_sighandler);
185 21
        VUT_Setup(vut);
186 8
        VUT_Main(vut);
187 8
        VUT_Fini(&vut);
188
189 8
        (void)flushout(NULL);
190
191 8
        exit(0);
192
}