1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2005-2008 Poul-Henning Kamp
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: stable/11/usr.sbin/fifolog/fifolog_reader/fifolog_reader.c 330449 2018-03-05 07:26:05Z eadler $
29 */
30
31#include <stdio.h>
32#include <assert.h>
33#include <unistd.h>
34#include <err.h>
35#include <time.h>
36#include <string.h>
37#include <stdlib.h>
38#include <sysexits.h>
39#include <regex.h>
40
41#include "libfifolog.h"
42
43static time_t opt_B;
44static time_t opt_E;
45static const char *opt_T;
46static const char *opt_o;
47static const char *opt_R;
48static regex_t R;
49
50static FILE *fo;
51
52static void
53Render(void *priv __unused, time_t now, unsigned flag __unused, const unsigned char *p, unsigned l __unused)
54{
55	static struct tm utc;
56	char buf[128];
57	int i;
58
59	if (now < opt_B || now > opt_E)
60		return;
61
62	if (opt_R != NULL && regexec(&R, (const char *)p, 0, NULL, 0))
63		return;
64
65	if (opt_T != NULL && *opt_T == '\0') {
66		fprintf(fo, "%s\n", p);
67	} else if (opt_T != NULL) {
68		(void)gmtime_r(&now, &utc);
69		i = strftime(buf, sizeof buf, opt_T, &utc);
70		assert(i > 0);
71		fprintf(fo, "%s %s\n", buf, p);
72	} else {
73		fprintf(fo, "%12ld %s\n", (long)now, p);
74	}
75}
76
77/*--------------------------------------------------------------------*/
78
79static void
80Usage(void)
81{
82	fprintf(stderr,
83		"Usage: fiforead [options] fifofile\n"
84		"\t-b <start time integer>\n"
85		"\t-B <start time>\n"
86		"\t-e <end time integer>\n"
87		"\t-E <end time>\n"
88		"\t-o <output file>\n"
89		"\t-R <regexp> # match regexp\n"
90		"\t-t # format timestamps as %%Y%%m%%d%%H%%M%%S\n"
91		"\t-T <timestamp format>\n"
92	);
93	exit (EX_USAGE);
94}
95
96int
97main(int argc, char * const *argv)
98{
99	int ch, i;
100	off_t o;
101	struct fifolog_reader *fl;
102
103	time(&opt_E);
104	opt_o = "-";
105	while ((ch = getopt(argc, argv, "b:B:e:E:o:R:tT:")) != -1) {
106		switch (ch) {
107		case 'b':
108			opt_B = strtoul(optarg, NULL, 0);
109			break;
110		case 'B':
111			opt_B = get_date(optarg);
112			if (opt_B == -1)
113				errx(1, "Didn't understand \"%s\"", optarg);
114			break;
115		case 'e':
116			opt_E = strtoul(optarg, NULL, 0);
117			break;
118		case 'E':
119			opt_E = get_date(optarg);
120			if (opt_E == -1)
121				errx(1, "Didn't understand \"%s\"", optarg);
122			break;
123		case 'o':
124			opt_o = optarg;
125			break;
126		case 'R':
127			opt_R = optarg;
128			break;
129		case 't':
130			opt_T = "%Y%m%d%H%M%S";
131			break;
132		case 'T':
133			opt_T = optarg;
134			break;
135		default:
136			Usage();
137		}
138	}
139	argc -= optind;
140	argv += optind;
141
142	if (opt_R != NULL) {
143		i = regcomp(&R, opt_R, REG_NOSUB);
144		if (i != 0) {
145			char buf[BUFSIZ];
146			(void)regerror(i, &R, buf, sizeof buf);
147			fprintf(stderr, "-R argument: %s\n", buf);
148			exit (1);
149		}
150	}
151
152	if (argv[0] == NULL)
153		Usage();
154
155	fprintf(stderr, "From\t%jd %s", (intmax_t)opt_B, ctime(&opt_B));
156	fprintf(stderr, "To\t%jd %s", (intmax_t)opt_E, ctime(&opt_E));
157	if (opt_B >= opt_E)
158		errx(1, "Begin time not before End time");
159
160	fl = fifolog_reader_open(argv[0]);
161
162	if (!strcmp(opt_o, "-"))
163		fo = stdout;
164	else {
165		fo = fopen(opt_o, "w");
166		if (fo == NULL)
167			err(1, "Cannot open: %s", argv[1]);
168	}
169
170	o = fifolog_reader_seek(fl, opt_B);
171	fifolog_reader_process(fl, o, Render, NULL, opt_E);
172	return (0);
173}
174