Reformat code in zeek-aux with clang-format/cmake-format

This commit is contained in:
Tim Wojtulewicz 2025-08-07 13:52:45 -07:00
parent a1d0cebca4
commit 7ead295152
12 changed files with 1327 additions and 1459 deletions

View file

@ -27,18 +27,13 @@ include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
# explicitly installed by the user via "make install-aux" # explicitly installed by the user via "make install-aux"
macro (AddAuxInstallTarget _target) macro (AddAuxInstallTarget _target)
add_custom_target( add_custom_target(
install-${_target} COMMAND ${CMAKE_COMMAND} -E make_directory install-${_target} COMMAND ${CMAKE_COMMAND} -E make_directory${CMAKE_INSTALL_PREFIX}/bin
${CMAKE_INSTALL_PREFIX}/bin
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${_target}> ${CMAKE_INSTALL_PREFIX}/bin) COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${_target}> ${CMAKE_INSTALL_PREFIX}/bin)
add_dependencies(install-${_target} ${_target}) add_dependencies(install-${_target} ${_target})
set(AUX_TARGETS install-${_target};${AUX_TARGETS}) set(AUX_TARGETS install-${_target};${AUX_TARGETS})
set(AUX_TARGETS ${AUX_TARGETS} PARENT_SCOPE) set(AUX_TARGETS ${AUX_TARGETS} PARENT_SCOPE)
endmacro (AddAuxInstallTarget) endmacro (AddAuxInstallTarget)
if (NOT ZEEK_MAN_INSTALL_PATH)
set(ZEEK_MAN_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/share/man)
endif ()
add_subdirectory(adtrace) add_subdirectory(adtrace)
add_subdirectory(zeek-archiver) add_subdirectory(zeek-archiver)
add_subdirectory(zeek-cut) add_subdirectory(zeek-cut)

View file

@ -5,4 +5,4 @@ set(adtrace_SRCS adtrace.c)
add_executable(adtrace ${adtrace_SRCS}) add_executable(adtrace ${adtrace_SRCS})
target_include_directories(adtrace BEFORE PRIVATE ${PCAP_INCLUDE_DIR}) target_include_directories(adtrace BEFORE PRIVATE ${PCAP_INCLUDE_DIR})
target_link_libraries(adtrace ${PCAP_LIBRARY}) target_link_libraries(adtrace ${PCAP_LIBRARY})
AddAuxInstallTarget(adtrace) addauxinstalltarget(adtrace)

View file

@ -1,72 +1,73 @@
#include <stdio.h> // See the file "COPYING" in the main distribution directory for copyright.
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h>
#include <pcap.h> #include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "ip.h"
#include "ether.h" #include "ether.h"
#include "ethertype.h" #include "ethertype.h"
#include "ip.h"
pcap_t *p; pcap_t* p;
const u_char* printEAddr(const u_char* pkt, u_char* endp){ const u_char* printEAddr(const u_char* pkt, u_char* endp) {
const struct ether_header *ep; const struct ether_header* ep;
int i=0; int i = 0;
ep = (const struct ether_header*) pkt; ep = (const struct ether_header*)pkt;
if (pkt+ETHER_HDRLEN > endp || if ( pkt + ETHER_HDRLEN > endp || ntohs(ep->ether_type) != ETHERTYPE_IP ) {
ntohs(ep->ether_type) != ETHERTYPE_IP){
return 0; return 0;
} }
for (i = 0; i<ETHER_ADDR_LEN; i++){ for ( i = 0; i < ETHER_ADDR_LEN; i++ ) {
if (i>0) putchar(':'); if ( i > 0 )
putchar(':');
printf("%02x", ep->ether_shost[i]); printf("%02x", ep->ether_shost[i]);
} }
putchar (' '); putchar(' ');
for (i = 0; i<ETHER_ADDR_LEN; i++){ for ( i = 0; i < ETHER_ADDR_LEN; i++ ) {
if (i>0) putchar(':'); if ( i > 0 )
putchar(':');
printf("%02x", ep->ether_dhost[i]); printf("%02x", ep->ether_dhost[i]);
} }
putchar(' '); putchar(' ');
return (pkt+ETHER_HDRLEN); return (pkt + ETHER_HDRLEN);
} }
void printIPAddr(const u_char* pkt, u_char* endp){ void printIPAddr(const u_char* pkt, u_char* endp) {
const struct ip* iph; const struct ip* iph;
if (pkt+sizeof(struct ip) > endp) return; if ( pkt + sizeof(struct ip) > endp )
iph = (const struct ip*) pkt; return;
fputs ((char*) inet_ntoa(iph->ip_src), stdout); iph = (const struct ip*)pkt;
fputs((char*)inet_ntoa(iph->ip_src), stdout);
putchar(' '); putchar(' ');
puts ((char*) inet_ntoa(iph->ip_dst)); puts((char*)inet_ntoa(iph->ip_dst));
} }
void handler(u_char *user, const struct pcap_pkthdr *head, const u_char *packet){ void handler(u_char* user, const struct pcap_pkthdr* head, const u_char* packet) {
u_char* endp; u_char* endp;
endp =(u_char*) packet + head->caplen; endp = (u_char*)packet + head->caplen;
packet = printEAddr(packet, endp); packet = printEAddr(packet, endp);
if (packet) if ( packet )
printIPAddr(packet, endp); printIPAddr(packet, endp);
} }
void usage(char *av[]) void usage(char* av[]) {
{ fprintf(stderr, "usage: %s filename \n", av[0]);
fprintf(stderr,"usage: %s filename \n", av[0]);
exit(1); exit(1);
} }
int main (int argc, char *argv[]) int main(int argc, char* argv[]) {
{ char* file;
char *file;
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
u_char* pkt, endp; u_char *pkt, endp;
struct pcap_pkthdr *head; struct pcap_pkthdr* head;
if ( argc != 2 ) if ( argc != 2 )
usage(argv); usage(argv);
@ -74,18 +75,17 @@ int main (int argc, char *argv[])
file = argv[1]; file = argv[1];
p = pcap_open_offline(file, errbuf); p = pcap_open_offline(file, errbuf);
if(p==NULL){ if ( p == NULL ) {
fprintf (stderr, "cannot open %s: %s\n", file, errbuf); fprintf(stderr, "cannot open %s: %s\n", file, errbuf);
exit(2); exit(2);
} }
if (pcap_datalink(p) != DLT_EN10MB){ if ( pcap_datalink(p) != DLT_EN10MB ) {
fputs ("sorry, currently only ethernet links supported\n", stderr); fputs("sorry, currently only ethernet links supported\n", stderr);
exit(1); //if it is not ethernet we are watching we won't have MACs exit(1); // if it is not ethernet we are watching we won't have MACs
} }
pcap_loop(p, -1, handler, NULL); pcap_loop(p, -1, handler, NULL);
pcap_close(p); pcap_close(p);
return(0); return (0);
} }

View file

@ -61,7 +61,7 @@ struct ip {
u_int8_t ip_ttl; /* time to live */ u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */ u_int8_t ip_p; /* protocol */
u_int16_t ip_sum; /* checksum */ u_int16_t ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */ struct in_addr ip_src, ip_dst; /* source and dest address */
}; };
#define IP_MAXPACKET 65535 /* maximum packet size */ #define IP_MAXPACKET 65535 /* maximum packet size */
@ -88,9 +88,9 @@ struct ip {
/* /*
* Definitions for options. * Definitions for options.
*/ */
#define IPOPT_COPIED(o) ((o)&0x80) #define IPOPT_COPIED(o) ((o) & 0x80)
#define IPOPT_CLASS(o) ((o)&0x60) #define IPOPT_CLASS(o) ((o) & 0x60)
#define IPOPT_NUMBER(o) ((o)&0x1f) #define IPOPT_NUMBER(o) ((o) & 0x1f)
#define IPOPT_CONTROL 0x00 #define IPOPT_CONTROL 0x00
#define IPOPT_RESERVED1 0x20 #define IPOPT_RESERVED1 0x20

View file

@ -5,8 +5,7 @@ namespace plugin { namespace @PLUGIN_NAMESPACE@_@PLUGIN_NAME@ { Plugin plugin; }
using namespace plugin::@PLUGIN_NAMESPACE@_@PLUGIN_NAME@; using namespace plugin::@PLUGIN_NAMESPACE@_@PLUGIN_NAME@;
zeek::plugin::Configuration Plugin::Configure() zeek::plugin::Configuration Plugin::Configure() {
{
zeek::plugin::Configuration config; zeek::plugin::Configuration config;
config.name = "@PLUGIN_NAMESPACE@::@PLUGIN_NAME@"; config.name = "@PLUGIN_NAMESPACE@::@PLUGIN_NAME@";
config.description = "<Insert description>"; config.description = "<Insert description>";
@ -14,4 +13,4 @@ zeek::plugin::Configuration Plugin::Configure()
config.version.minor = 1; config.version.minor = 1;
config.version.patch = 0; config.version.patch = 0;
return config; return config;
} }

View file

@ -2,4 +2,4 @@ set(rst_SRCS rst.c)
add_executable(rst ${rst_SRCS}) add_executable(rst ${rst_SRCS})
AddAuxInstallTarget(rst) addauxinstalltarget(rst)

View file

@ -30,48 +30,45 @@ static const char copyright[] =
#define _BSD_SOURCE /* Deprecated, but still needed by older Linux. */ #define _BSD_SOURCE /* Deprecated, but still needed by older Linux. */
#endif #endif
// clang-format off
// This file needs to come before some of the files below or FreeBSD won't find
// some of the types it needs.
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> // clang-format on
#include <arpa/inet.h>
#include <netinet/in_systm.h> #include <errno.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include "config.h" #include "config.h"
/* Forwards */ /* Forwards */
void gripe(const char *, const char *); void gripe(const char*, const char*);
void pgripe(const char *); void pgripe(const char*);
uint16_t in_cksum(register uint16_t *, register int); uint16_t in_cksum(register uint16_t*, register int);
int ones_complement_checksum(const void *, int, uint32_t); int ones_complement_checksum(const void*, int, uint32_t);
int tcp_checksum(const struct ip *, const struct tcphdr *, int); int tcp_checksum(const struct ip*, const struct tcphdr*, int);
void send_pkt(int, struct in_addr, int, uint32_t, struct in_addr, void send_pkt(int, struct in_addr, int, uint32_t, struct in_addr, int, uint32_t, int, int, int, int, const char*);
int, uint32_t, int, int, int, int, const char *); void terminate(int, const char*, int, uint32_t, const char*, int, uint32_t, int, int, int, int, const char*);
void terminate(int, const char *, int, uint32_t, const char *,
int, uint32_t, int, int, int, int, const char *);
void usage(void); void usage(void);
int main(int, char **); int main(int, char**);
const char *prog_name; const char* prog_name;
void gripe(const char *fmt, const char *arg) void gripe(const char* fmt, const char* arg) {
{
fprintf(stderr, "%s: ", prog_name); fprintf(stderr, "%s: ", prog_name);
fprintf(stderr, fmt, arg); fprintf(stderr, fmt, arg);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
void pgripe(const char *msg) void pgripe(const char* msg) {
{
fprintf(stderr, "%s: %s (%s)\n", prog_name, msg, strerror(errno)); fprintf(stderr, "%s: %s (%s)\n", prog_name, msg, strerror(errno));
exit(1); exit(1);
} }
@ -79,11 +76,9 @@ void pgripe(const char *msg)
/* /*
* Checksum routine for Internet Protocol family headers (C Version) * Checksum routine for Internet Protocol family headers (C Version)
*/ */
uint16_t uint16_t in_cksum(register uint16_t* addr, register int len) {
in_cksum(register uint16_t *addr, register int len)
{
register int nleft = len; register int nleft = len;
register uint16_t *w = addr; register uint16_t* w = addr;
register uint16_t answer; register uint16_t answer;
register int sum = 0; register int sum = 0;
@ -93,14 +88,14 @@ in_cksum(register uint16_t *addr, register int len)
* back all the carry bits from the top 16 bits into the lower * back all the carry bits from the top 16 bits into the lower
* 16 bits. * 16 bits.
*/ */
while (nleft > 1) { while ( nleft > 1 ) {
sum += *w++; sum += *w++;
nleft -= 2; nleft -= 2;
} }
/* mop up an odd byte, if necessary */ /* mop up an odd byte, if necessary */
if (nleft == 1) if ( nleft == 1 )
sum += *(u_char *)w; sum += *(u_char*)w;
/* /*
* add back carry outs from top 16 bits to low 16 bits * add back carry outs from top 16 bits to low 16 bits
@ -113,9 +108,8 @@ in_cksum(register uint16_t *addr, register int len)
// - adapted from tcpdump // - adapted from tcpdump
// Returns the ones-complement checksum of a chunk of b short-aligned bytes. // Returns the ones-complement checksum of a chunk of b short-aligned bytes.
int ones_complement_checksum(const void *p, int b, uint32_t sum) int ones_complement_checksum(const void* p, int b, uint32_t sum) {
{ const uint16_t* sp = (uint16_t*)p; // better be aligned!
const uint16_t *sp = (uint16_t *) p; // better be aligned!
b /= 2; // convert to count of short's b /= 2; // convert to count of short's
@ -129,8 +123,7 @@ int ones_complement_checksum(const void *p, int b, uint32_t sum)
return sum; return sum;
} }
int tcp_checksum(const struct ip *ip, const struct tcphdr *tp, int len) int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len) {
{
int tcp_len = tp->th_off * 4 + len; int tcp_len = tp->th_off * 4 + len;
uint32_t sum = 0; uint32_t sum = 0;
@ -143,32 +136,29 @@ int tcp_checksum(const struct ip *ip, const struct tcphdr *tp, int len)
if ( len % 2 == 1 ) if ( len % 2 == 1 )
// Add in pad byte. // Add in pad byte.
sum = htons(((const u_char*) tp)[tcp_len - 1] << 8); sum = htons(((const u_char*)tp)[tcp_len - 1] << 8);
else else
sum = 0; sum = 0;
sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum); sum = ones_complement_checksum((void*)&ip->ip_src.s_addr, 4, sum);
sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum); sum = ones_complement_checksum((void*)&ip->ip_dst.s_addr, 4, sum);
addl_pseudo = (htons(IPPROTO_TCP) << 16) | htons((unsigned short) tcp_len); addl_pseudo = (htons(IPPROTO_TCP) << 16) | htons((unsigned short)tcp_len);
sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); sum = ones_complement_checksum((void*)&addl_pseudo, 4, sum);
sum = ones_complement_checksum((void*) tp, tcp_len, sum); sum = ones_complement_checksum((void*)tp, tcp_len, sum);
return sum; return sum;
} }
void send_pkt(int s, struct in_addr from, int from_port, uint32_t from_seq, void send_pkt(int s, struct in_addr from, int from_port, uint32_t from_seq, struct in_addr to, int to_port,
struct in_addr to, int to_port, uint32_t to_seq, uint32_t to_seq, int size, int redundancy, int delay, int flags, const char* inject) {
int size, int redundancy, int delay, int flags,
const char *inject)
{
int cc; int cc;
int pktlen = 40 + size; int pktlen = 40 + size;
const int max_injection_size = 4096; const int max_injection_size = 4096;
char *pkt = malloc(pktlen + max_injection_size + 1024 /* slop */); char* pkt = malloc(pktlen + max_injection_size + 1024 /* slop */);
struct ip *ip = (struct ip *) pkt; struct ip* ip = (struct ip*)pkt;
struct tcphdr *tcp = (struct tcphdr *) &pkt[20]; struct tcphdr* tcp = (struct tcphdr*)&pkt[20];
if ( ! pkt ) if ( ! pkt )
pgripe("couldn't malloc memory"); pgripe("couldn't malloc memory");
@ -194,9 +184,9 @@ void send_pkt(int s, struct in_addr from, int from_port, uint32_t from_seq,
ip->ip_ttl = 255; ip->ip_ttl = 255;
ip->ip_id = 0; ip->ip_id = 0;
ip->ip_sum = in_cksum((uint16_t *) ip, sizeof(*ip)); ip->ip_sum = in_cksum((uint16_t*)ip, sizeof(*ip));
if (ip->ip_sum == 0) if ( ip->ip_sum == 0 )
ip->ip_sum = 0xffff; ip->ip_sum = 0xffff;
tcp->th_sport = htons(from_port); tcp->th_sport = htons(from_port);
@ -210,18 +200,15 @@ void send_pkt(int s, struct in_addr from, int from_port, uint32_t from_seq,
tcp->th_sum = 0; tcp->th_sum = 0;
if ( inject && *inject ) { if ( inject && *inject ) {
char *payload = &pkt[40]; char* payload = &pkt[40];
strcpy(payload, inject); strcpy(payload, inject);
}
} else if ( size > 0 ) else if ( size > 0 ) {
{ const char* fill_string = (inject && *inject) ? inject : "BRO-RST\n";
const char *fill_string = char* payload = &pkt[40];
(inject && *inject) ? inject : "BRO-RST\n";
char *payload = &pkt[40];
int n = strlen(fill_string); int n = strlen(fill_string);
int i; int i;
for ( i = size; i > n + 1; i -= n ) for ( i = size; i > n + 1; i -= n ) {
{
strcpy(payload, fill_string); strcpy(payload, fill_string);
payload += n; payload += n;
} }
@ -232,10 +219,9 @@ void send_pkt(int s, struct in_addr from, int from_port, uint32_t from_seq,
tcp->th_sum = ~tcp_checksum(ip, tcp, size); tcp->th_sum = ~tcp_checksum(ip, tcp, size);
while ( redundancy-- > 0 ) while ( redundancy-- > 0 ) {
{ cc = send(s, (char*)ip, pktlen, 0);
cc = send(s, (char *) ip, pktlen, 0); if ( cc < 0 || cc != pktlen )
if (cc < 0 || cc != pktlen)
pgripe("problem in sendto()"); pgripe("problem in sendto()");
usleep(delay * 1000); usleep(delay * 1000);
} }
@ -243,14 +229,11 @@ void send_pkt(int s, struct in_addr from, int from_port, uint32_t from_seq,
free(pkt); free(pkt);
} }
void terminate(int s, const char *from_addr, int from_port, uint32_t from_seq, void terminate(int s, const char* from_addr, int from_port, uint32_t from_seq, const char* to_addr, int to_port,
const char *to_addr, int to_port, uint32_t to_seq, uint32_t to_seq, int num, int redundancy, int stride, int delay, const char* inject) {
int num, int redundancy, int stride, int delay,
const char *inject)
{
struct sockaddr_in where_from, where_to; struct sockaddr_in where_from, where_to;
struct sockaddr_in *from = (struct sockaddr_in *) &where_from; struct sockaddr_in* from = (struct sockaddr_in*)&where_from;
struct sockaddr_in *to = (struct sockaddr_in *) &where_to; struct sockaddr_in* to = (struct sockaddr_in*)&where_to;
memset(from, 0, sizeof(*from)); memset(from, 0, sizeof(*from));
memset(to, 0, sizeof(*to)); memset(to, 0, sizeof(*to));
@ -259,41 +242,42 @@ void terminate(int s, const char *from_addr, int from_port, uint32_t from_seq,
#endif /* SIN_LEN */ #endif /* SIN_LEN */
from->sin_family = to->sin_family = AF_INET; from->sin_family = to->sin_family = AF_INET;
if ( inet_aton(from_addr, (struct in_addr *) &from->sin_addr) == 0 ) if ( inet_aton(from_addr, (struct in_addr*)&from->sin_addr) == 0 )
gripe("bad from address %s", from_addr); gripe("bad from address %s", from_addr);
if ( inet_aton(to_addr, (struct in_addr *) &to->sin_addr) == 0 ) if ( inet_aton(to_addr, (struct in_addr*)&to->sin_addr) == 0 )
gripe("bad to address %s", to_addr); gripe("bad to address %s", to_addr);
if ( connect(s, (struct sockaddr *) &where_to, sizeof(where_to)) < 0 ) if ( connect(s, (struct sockaddr*)&where_to, sizeof(where_to)) < 0 )
pgripe("can't connect"); pgripe("can't connect");
while ( num-- > 0 ) while ( num-- > 0 ) {
{ send_pkt(s, from->sin_addr, from_port, from_seq, to->sin_addr, to_port, to_seq, 0, redundancy, delay,
send_pkt(s, from->sin_addr, from_port, from_seq,
to->sin_addr, to_port, to_seq, 0, redundancy, delay,
(*inject ? 0 : TH_RST) | TH_ACK, inject); (*inject ? 0 : TH_RST) | TH_ACK, inject);
if ( num > 0 && stride > 1 ) if ( num > 0 && stride > 1 )
send_pkt(s, from->sin_addr, from_port, from_seq, send_pkt(s, from->sin_addr, from_port, from_seq, to->sin_addr, to_port, to_seq, stride, redundancy, delay,
to->sin_addr, to_port, to_seq, stride, TH_ACK, inject);
redundancy, delay, TH_ACK, inject);
from_seq += stride; from_seq += stride;
} }
} }
void usage() void usage() {
{
#if defined(__linux__) #if defined(__linux__)
fprintf(stderr, "%s [-R] [-I text-to-inject] [-i interface] [-d delay-msec] [-n num] [-r redundancy] [-s stride] from_addr from_port from_seq to_addr to_port to_seq\n", prog_name); fprintf(stderr,
"%s [-R] [-I text-to-inject] [-i interface] [-d delay-msec] [-n num] [-r redundancy] [-s stride] from_addr "
"from_port from_seq to_addr to_port to_seq\n",
prog_name);
#else #else
fprintf(stderr, "%s [-R] [-I text-to-inject] [-d delay-msec] [-n num] [-r redundancy] [-s stride] from_addr from_port from_seq to_addr to_port to_seq\n", prog_name); fprintf(stderr,
"%s [-R] [-I text-to-inject] [-d delay-msec] [-n num] [-r redundancy] [-s stride] from_addr from_port "
"from_seq to_addr to_port to_seq\n",
prog_name);
#endif #endif
exit(0); exit(0);
} }
int main(int argc, char **argv) int main(int argc, char** argv) {
{
extern char* optarg; extern char* optarg;
extern int optind, opterr; extern int optind, opterr;
const char *from_addr, *to_addr; const char *from_addr, *to_addr;
@ -316,55 +300,39 @@ int main(int argc, char **argv)
inject[0] = 0; inject[0] = 0;
#if defined(__linux__) #if defined(__linux__)
char *interface = NULL; char* interface = NULL;
while ( (op = getopt(argc, argv, "RI:i:d:n:r:s:")) != EOF ) while ( (op = getopt(argc, argv, "RI:i:d:n:r:s:")) != EOF )
#else #else
while ( (op = getopt(argc, argv, "RI:d:n:r:s:")) != EOF ) while ( (op = getopt(argc, argv, "RI:d:n:r:s:")) != EOF )
#endif #endif
switch ( op ) { switch ( op ) {
case 'R': case 'R': reverse = 1; break;
reverse = 1;
break;
case 'I': case 'I': {
{ char* ap = optarg;
char *ap = optarg; char* ip;
char *ip;
for ( ip = inject; *ap; ++ip, ++ap ) { for ( ip = inject; *ap; ++ip, ++ap ) {
if ( ap[0] == '\\' && ap[1] == 'n' ) if ( ap[0] == '\\' && ap[1] == 'n' )
*ip = '\n', ++ap; *ip = '\n', ++ap;
else else
*ip = *ap; *ip = *ap;
} }
} } break;
break;
#if defined(__linux__) #if defined(__linux__)
case 'i': case 'i': interface = optarg; break;
interface = optarg;
break;
#endif #endif
case 'd': case 'd': delay = atoi(optarg); break;
delay = atoi(optarg);
break;
case 'n': case 'n': num = atoi(optarg); break;
num = atoi(optarg);
break;
case 'r': case 'r': redundancy = atoi(optarg); break;
redundancy = atoi(optarg);
break;
case 's': case 's': stride = atoi(optarg); break;
stride = atoi(optarg);
break;
default: default: usage(); break;
usage();
break;
} }
if ( argc - optind != 6 ) if ( argc - optind != 6 )
@ -377,11 +345,11 @@ int main(int argc, char **argv)
if ( setuid(getuid()) ) if ( setuid(getuid()) )
pgripe("couldn't lower privileges"); pgripe("couldn't lower privileges");
if ( setsockopt(s, 0, IP_HDRINCL, (char *) &on, sizeof(on)) < 0 ) if ( setsockopt(s, 0, IP_HDRINCL, (char*)&on, sizeof(on)) < 0 )
pgripe("can't turn on IP_HDRINCL"); pgripe("can't turn on IP_HDRINCL");
#if defined(__linux__) #if defined(__linux__)
if ( interface ){ if ( interface ) {
if ( setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)) < 0 ) if ( setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)) < 0 )
pgripe("can't set interface"); pgripe("can't set interface");
} }
@ -396,13 +364,9 @@ int main(int argc, char **argv)
to_seq = strtoul(argv[optind++], 0, 10); to_seq = strtoul(argv[optind++], 0, 10);
if ( reverse ) if ( reverse )
terminate(s, to_addr, to_port, to_seq, terminate(s, to_addr, to_port, to_seq, from_addr, from_port, from_seq, num, redundancy, stride, delay, inject);
from_addr, from_port, from_seq,
num, redundancy, stride, delay, inject);
else else
terminate(s, from_addr, from_port, from_seq, terminate(s, from_addr, from_port, from_seq, to_addr, to_port, to_seq, num, redundancy, stride, delay, inject);
to_addr, to_port, to_seq,
num, redundancy, stride, delay, inject);
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. ## #BTest baseline data generated by btest - diff.Do not edit.Use "btest -U/-u" to update.Requires BTest >= 0.63.
#define ZEEK_VERSION "1.0.0-2" /* with comment */ #define ZEEK_VERSION "1.0.0-2" /* with comment */
#define ZEEK_VERSION "1.0.0-2" /* with comment */ #define ZEEK_VERSION "1.0.0-2" /* with comment */
#define FOO_VERSION "1.0.0-2" // another comment #define FOO_VERSION "1.0.0-2" // another comment
... ...

View file

@ -1,28 +1,28 @@
#define _XOPEN_SOURCE // See the file "COPYING" in the main distribution directory for copyright.
#include <time.h>
#include <sys/time.h> #define _XOPEN_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <algorithm> #include <algorithm>
#include <cerrno>
#include <chrono>
#include <csignal> #include <csignal>
#include <cstdarg>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstdarg>
#include <cstring> #include <cstring>
#include <cerrno>
#include <fstream> #include <fstream>
#include <chrono> #include <optional>
#include <set>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <optional>
#include <vector> #include <vector>
#include <set>
constexpr auto ZEEK_ARCHIVER_VERSION = "v0.50-174"; constexpr auto ZEEK_ARCHIVER_VERSION = "v0.50-174";
@ -36,7 +36,7 @@ struct Options {
std::string compress_ext = "gz"; std::string compress_ext = "gz";
std::string compress_cmd = "gzip"; std::string compress_cmd = "gzip";
std::string timestamp_fmt = "%Y-%m-%d-%H-%M-%S"; std::string timestamp_fmt = "%Y-%m-%d-%H-%M-%S";
std::vector<std::string> zip_file_extensions = { "gz", "bz2", "lz", "lz4" }; std::vector<std::string> zip_file_extensions = {"gz", "bz2", "lz", "lz4"};
int idle_poll_interval = 30; int idle_poll_interval = 30;
}; };
@ -51,8 +51,7 @@ struct LogFile {
std::string ext; std::string ext;
std::string suffix; std::string suffix;
std::string DestDir() const std::string DestDir() const {
{
char buf[64]; char buf[64];
auto res = strftime(buf, sizeof(buf), "%Y-%m-%d", &open); auto res = strftime(buf, sizeof(buf), "%Y-%m-%d", &open);
@ -62,8 +61,7 @@ struct LogFile {
return buf; return buf;
} }
std::string DestFile() const std::string DestFile() const {
{
constexpr auto time_fmt = "%H:%M:%S"; constexpr auto time_fmt = "%H:%M:%S";
char buf[64]; char buf[64];
auto res = strftime(buf, sizeof(buf), time_fmt, &open); auto res = strftime(buf, sizeof(buf), time_fmt, &open);
@ -88,19 +86,17 @@ struct LogFile {
} }
}; };
static double now() static double now() {
{
struct timeval tv; struct timeval tv;
if ( gettimeofday(&tv, 0) < 0 ) if ( gettimeofday(&tv, 0) < 0 )
return 0; return 0;
return (double)tv.tv_sec + (double)tv.tv_usec / 1e6; return (double)tv.tv_sec + (double)tv.tv_usec / 1e6;
} }
static void debug(const char* format, ...) __attribute__((format (printf, 1, 2))); static void debug(const char* format, ...) __attribute__((format(printf, 1, 2)));
static void debug(const char* format, ...) static void debug(const char* format, ...) {
{
if ( ! options.verbose ) if ( ! options.verbose )
return; return;
@ -113,11 +109,10 @@ static void debug(const char* format, ...)
va_end(args); va_end(args);
fprintf(f, "\n"); fprintf(f, "\n");
} }
static void info(const char* format, ...) __attribute__((format (printf, 1, 2))); static void info(const char* format, ...) __attribute__((format(printf, 1, 2)));
static void info(const char* format, ...) static void info(const char* format, ...) {
{
auto f = stdout; auto f = stdout;
fprintf(f, "[%17.06f] [INFO] ", now()); fprintf(f, "[%17.06f] [INFO] ", now());
@ -127,11 +122,10 @@ static void info(const char* format, ...)
va_end(args); va_end(args);
fprintf(f, "\n"); fprintf(f, "\n");
} }
static void error(const char* format, ...) __attribute__((format (printf, 1, 2))); static void error(const char* format, ...) __attribute__((format(printf, 1, 2)));
static void error(const char* format, ...) static void error(const char* format, ...) {
{
auto f = stderr; auto f = stderr;
fprintf(f, "[%17.06f] [ERROR] ", now()); fprintf(f, "[%17.06f] [ERROR] ", now());
@ -141,11 +135,10 @@ static void error(const char* format, ...)
va_end(args); va_end(args);
fprintf(f, "\n"); fprintf(f, "\n");
} }
static void fatal(const char* format, ...) __attribute__((format (printf, 1, 2))); static void fatal(const char* format, ...) __attribute__((format(printf, 1, 2)));
static void fatal(const char* format, ...) static void fatal(const char* format, ...) {
{
auto f = stderr; auto f = stderr;
fprintf(f, "[%17.06f] [FATAL] ", now()); fprintf(f, "[%17.06f] [FATAL] ", now());
@ -156,15 +149,11 @@ static void fatal(const char* format, ...)
fprintf(f, "\n"); fprintf(f, "\n");
exit(1); exit(1);
} }
static void print_version(FILE* f) static void print_version(FILE* f) { fprintf(f, "zeek-archiver %s\n", ZEEK_ARCHIVER_VERSION); }
{
fprintf(f, "zeek-archiver %s\n", ZEEK_ARCHIVER_VERSION);
}
static void print_usage() static void print_usage() {
{
print_version(stderr); print_version(stderr);
fprintf(stderr, "usage: zeek-archiver [options] <src_dir> <dst_dir>\n"); fprintf(stderr, "usage: zeek-archiver [options] <src_dir> <dst_dir>\n");
fprintf(stderr, " <src_dir> | A directory to monitor for Zeek log files\n"); fprintf(stderr, " <src_dir> | A directory to monitor for Zeek log files\n");
@ -173,21 +162,24 @@ static void print_usage()
fprintf(stderr, " -1 | Archive current logs and exit w/o looping\n"); fprintf(stderr, " -1 | Archive current logs and exit w/o looping\n");
fprintf(stderr, " -h|--help | Show this usage information\n"); fprintf(stderr, " -h|--help | Show this usage information\n");
fprintf(stderr, " -v|--verbose | Print verbose/debug logs to stderr\n"); fprintf(stderr, " -v|--verbose | Print verbose/debug logs to stderr\n");
fprintf(stderr, " -c|--compress <ext,cmd> | File extension and compression command,\n" fprintf(stderr,
" -c|--compress <ext,cmd> | File extension and compression command,\n"
" empty string means \"disable compression\"\n" " empty string means \"disable compression\"\n"
" (default: \"gz,gzip\")\n"); " (default: \"gz,gzip\")\n");
fprintf(stderr, " -d|--delimiter <string> | Delimiter between timestamps in log names\n" fprintf(stderr,
" -d|--delimiter <string> | Delimiter between timestamps in log names\n"
" (default: \"__\")\n"); " (default: \"__\")\n");
fprintf(stderr, " -t|--time-fmt <string> | Format of timestamps within input file names\n" fprintf(stderr,
" -t|--time-fmt <string> | Format of timestamps within input file names\n"
" (default: \"%%Y-%%m-%%d-%%H-%%M-%%S\")\n"); " (default: \"%%Y-%%m-%%d-%%H-%%M-%%S\")\n");
fprintf(stderr, " -z|--zip-extensions <strings> | File extensions for already-zipped logs,\n" fprintf(stderr,
" -z|--zip-extensions <strings> | File extensions for already-zipped logs,\n"
" an empty string disables this feature\n" " an empty string disables this feature\n"
" (default: \"gz,bz2,lz,lz4\")\n"); " (default: \"gz,bz2,lz,lz4\")\n");
} }
static void usage_error(const char* format, ...) __attribute__((format (printf, 1, 2))); static void usage_error(const char* format, ...) __attribute__((format(printf, 1, 2)));
static void usage_error(const char* format, ...) static void usage_error(const char* format, ...) {
{
print_usage(); print_usage();
fprintf(stderr, "ERROR: "); fprintf(stderr, "ERROR: ");
@ -200,49 +192,41 @@ static void usage_error(const char* format, ...)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
exit(1); exit(1);
} }
static std::vector<std::string> static std::vector<std::string> split_string(std::string_view input, std::string_view delim) {
split_string(std::string_view input, std::string_view delim)
{
std::vector<std::string> rval; std::vector<std::string> rval;
size_t pos = 0; size_t pos = 0;
size_t n = 0; size_t n = 0;
while ( (n = input.find(delim, pos)) != std::string::npos ) while ( (n = input.find(delim, pos)) != std::string::npos ) {
{
rval.emplace_back(input.substr(pos, n - pos)); rval.emplace_back(input.substr(pos, n - pos));
pos = n + delim.size(); pos = n + delim.size();
} }
rval.emplace_back(input.substr(pos)); rval.emplace_back(input.substr(pos));
return rval; return rval;
} }
static std::string strip_string(std::string s) static std::string strip_string(std::string s) {
{ auto notspace = [](unsigned char c) { return ! std::isspace(c); };
auto notspace = [](unsigned char c)
{
return ! std::isspace(c);
};
s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace)); s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace));
s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end()); s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end());
return s; return s;
} }
static void consume_option_value(const std::string& flag, std::string arg_value) static void consume_option_value(const std::string& flag, std::string arg_value) {
{ if ( flag == "-c" || flag == "--compress" ) {
if ( flag == "-c" || flag == "--compress" )
{
if ( arg_value.empty() ) if ( arg_value.empty() )
options.compress_cmd = ""; options.compress_cmd = "";
else else {
{
auto parts = split_string(arg_value, ","); auto parts = split_string(arg_value, ",");
if ( parts.size() != 2 ) if ( parts.size() != 2 )
usage_error("--compress must give a 'ext,compress_cmd' formatted " usage_error(
"value, got: %s", arg_value.data()); "--compress must give a 'ext,compress_cmd' formatted "
"value, got: %s",
arg_value.data());
options.compress_ext = parts[0]; options.compress_ext = parts[0];
options.compress_cmd = parts[1]; options.compress_cmd = parts[1];
@ -250,55 +234,45 @@ static void consume_option_value(const std::string& flag, std::string arg_value)
} }
else if ( flag == "-d" || flag == "--delimiter" ) else if ( flag == "-d" || flag == "--delimiter" ) {
{
if ( arg_value.empty() ) if ( arg_value.empty() )
usage_error("flag '%s' is missing a value", flag.data()); usage_error("flag '%s' is missing a value", flag.data());
options.delimiter = std::move(arg_value); options.delimiter = std::move(arg_value);
} }
else if ( flag == "-t" || flag == "--time-fmt" ) else if ( flag == "-t" || flag == "--time-fmt" ) {
{
if ( arg_value.empty() ) if ( arg_value.empty() )
usage_error("flag '%s' is missing a value", flag.data()); usage_error("flag '%s' is missing a value", flag.data());
options.timestamp_fmt = std::move(arg_value); options.timestamp_fmt = std::move(arg_value);
} }
else if ( flag == "-z" || flag == "--zip-extensions" ) else if ( flag == "-z" || flag == "--zip-extensions" ) {
{
options.zip_file_extensions = split_string(arg_value, ","); options.zip_file_extensions = split_string(arg_value, ",");
} }
} }
static void parse_options(int argc, char** argv) static void parse_options(int argc, char** argv) {
{
std::set<std::string> flags = { std::set<std::string> flags = {
"--version", "--version", "-1", "-h", "--help", "-v", "--verbose", "-c",
"-1", "--compress", "-d", "--delimiter", "-t", "--time-fmt", "-z", "--zip-extensions",
"-h", "--help",
"-v", "--verbose",
"-c", "--compress",
"-d", "--delimiter",
"-t", "--time-fmt",
"-z", "--zip-extensions",
}; };
bool in_options = true; bool in_options = true;
for ( auto i = 1; i < argc; ++i ) for ( auto i = 1; i < argc; ++i ) {
{
auto arg = argv[i]; auto arg = argv[i];
if ( ! arg[0] ) if ( ! arg[0] )
continue; continue;
if ( arg[0] == '-' ) if ( arg[0] == '-' ) {
{
if ( ! in_options ) if ( ! in_options )
usage_error("optional flags must precede non-optional arguments: " usage_error(
"'%s'", arg); "optional flags must precede non-optional arguments: "
"'%s'",
arg);
if ( ! arg[1] ) if ( ! arg[1] )
// Has to be something after a '-' // Has to be something after a '-'
@ -313,13 +287,11 @@ static void parse_options(int argc, char** argv)
auto it = flag.find('='); auto it = flag.find('=');
if ( it == std::string::npos ) if ( it == std::string::npos ) {
{
if ( i + 1 < argc ) if ( i + 1 < argc )
opt_value = argv[i + 1]; opt_value = argv[i + 1];
} }
else else {
{
opt_value = flag.substr(it + 1); opt_value = flag.substr(it + 1);
flag = flag.substr(0, it); flag = flag.substr(0, it);
} }
@ -327,8 +299,7 @@ static void parse_options(int argc, char** argv)
if ( flags.find(flag) == flags.end() ) if ( flags.find(flag) == flags.end() )
usage_error("invalid argument: '%s'", arg); usage_error("invalid argument: '%s'", arg);
if ( flag == "-1" ) if ( flag == "-1" ) {
{
if ( ! opt_value.empty() && it != std::string::npos ) if ( ! opt_value.empty() && it != std::string::npos )
usage_error("invalid argument=value: '%s'", arg); usage_error("invalid argument=value: '%s'", arg);
@ -336,8 +307,7 @@ static void parse_options(int argc, char** argv)
continue; continue;
} }
if ( flag == "--version" ) if ( flag == "--version" ) {
{
if ( ! opt_value.empty() && it != std::string::npos ) if ( ! opt_value.empty() && it != std::string::npos )
usage_error("invalid argument=value: '%s'", arg); usage_error("invalid argument=value: '%s'", arg);
@ -345,8 +315,7 @@ static void parse_options(int argc, char** argv)
exit(0); exit(0);
} }
if ( flag == "-h" || flag == "--help" ) if ( flag == "-h" || flag == "--help" ) {
{
if ( ! opt_value.empty() && it != std::string::npos ) if ( ! opt_value.empty() && it != std::string::npos )
usage_error("invalid argument=value: '%s'", arg); usage_error("invalid argument=value: '%s'", arg);
@ -354,8 +323,7 @@ static void parse_options(int argc, char** argv)
exit(0); exit(0);
} }
if ( flag == "-v" || flag == "--verbose" ) if ( flag == "-v" || flag == "--verbose" ) {
{
if ( ! opt_value.empty() && it != std::string::npos ) if ( ! opt_value.empty() && it != std::string::npos )
usage_error("invalid argument=value: '%s'", arg); usage_error("invalid argument=value: '%s'", arg);
@ -369,22 +337,20 @@ static void parse_options(int argc, char** argv)
consume_option_value(flag, std::move(opt_value)); consume_option_value(flag, std::move(opt_value));
continue; continue;
} }
else else {
{ if ( options.src_dir.empty() ) {
if ( options.src_dir.empty() )
{
in_options = false; in_options = false;
options.src_dir = arg; options.src_dir = arg;
} }
else if ( options.dst_dir.empty() ) else if ( options.dst_dir.empty() ) {
{
in_options = false; in_options = false;
options.dst_dir = arg; options.dst_dir = arg;
} }
else else
usage_error("extra/invalid argument: '%s': <src_dir>/<dst_dir> " usage_error(
"already provided: %s/%s", arg, "extra/invalid argument: '%s': <src_dir>/<dst_dir> "
options.src_dir.data(), options.dst_dir.data()); "already provided: %s/%s",
arg, options.src_dir.data(), options.dst_dir.data());
} }
} }
@ -393,18 +359,16 @@ static void parse_options(int argc, char** argv)
if ( options.dst_dir.empty() ) if ( options.dst_dir.empty() )
usage_error("no <dst_dir> provided"); usage_error("no <dst_dir> provided");
} }
static bool make_dir(const char* dir) static bool make_dir(const char* dir) {
{
if ( mkdir(dir, 0775) == 0 ) if ( mkdir(dir, 0775) == 0 )
return true; return true;
auto mkdir_errno = errno; auto mkdir_errno = errno;
struct stat st; struct stat st;
if ( stat(dir, &st) == -1 ) if ( stat(dir, &st) == -1 ) {
{
// Show the original failure reason for mkdir() since nothing's there // Show the original failure reason for mkdir() since nothing's there
// or we can't even tell what is now. // or we can't even tell what is now.
error("Failed to create directory %s: %s", dir, strerror(mkdir_errno)); error("Failed to create directory %s: %s", dir, strerror(mkdir_errno));
@ -416,10 +380,9 @@ static bool make_dir(const char* dir)
error("Failed to create directory %s: exists but is not a directory", dir); error("Failed to create directory %s: exists but is not a directory", dir);
return false; return false;
} }
static bool make_dirs(std::string_view dir) static bool make_dirs(std::string_view dir) {
{
auto parts = split_string(dir, "/"); auto parts = split_string(dir, "/");
std::string current_dir = dir[0] == '/' ? "/" : ""; std::string current_dir = dir[0] == '/' ? "/" : "";
std::vector<std::string> dirs; std::vector<std::string> dirs;
@ -428,8 +391,7 @@ static bool make_dirs(std::string_view dir)
if ( ! p.empty() ) if ( ! p.empty() )
dirs.emplace_back(std::move(p)); dirs.emplace_back(std::move(p));
for ( size_t i = 0; i < dirs.size(); ++i ) for ( size_t i = 0; i < dirs.size(); ++i ) {
{
if ( i > 0 ) if ( i > 0 )
current_dir += '/'; current_dir += '/';
@ -440,14 +402,12 @@ static bool make_dirs(std::string_view dir)
} }
return true; return true;
} }
bool is_file(const char* path) bool is_file(const char* path) {
{
struct stat st; struct stat st;
if ( stat(path, &st) == -1 ) if ( stat(path, &st) == -1 ) {
{
if ( errno != ENOENT ) if ( errno != ENOENT )
error("can't stat %s: %s", path, strerror(errno)); error("can't stat %s: %s", path, strerror(errno));
@ -455,85 +415,72 @@ bool is_file(const char* path)
} }
return S_ISREG(st.st_mode); return S_ISREG(st.st_mode);
} }
std::optional<bool> same_filesystem(const char* path1, const char* path2) std::optional<bool> same_filesystem(const char* path1, const char* path2) {
{
struct stat st1; struct stat st1;
struct stat st2; struct stat st2;
if ( stat(path1, &st1) == -1 ) if ( stat(path1, &st1) == -1 ) {
{
error("can't stat %s: %s", path1, strerror(errno)); error("can't stat %s: %s", path1, strerror(errno));
return {}; return {};
} }
if ( stat(path2, &st2) == -1 ) if ( stat(path2, &st2) == -1 ) {
{
error("can't stat %s: %s", path2, strerror(errno)); error("can't stat %s: %s", path2, strerror(errno));
return {}; return {};
} }
return st1.st_dev == st2.st_dev; return st1.st_dev == st2.st_dev;
} }
static bool ends_with(std::string_view s, std::string_view ending) static bool ends_with(std::string_view s, std::string_view ending) {
{
if ( ending.size() > s.size() ) if ( ending.size() > s.size() )
return false; return false;
return std::equal(ending.rbegin(), ending.rend(), s.rbegin()); return std::equal(ending.rbegin(), ending.rend(), s.rbegin());
} }
static bool already_zipped(std::string_view file) static bool already_zipped(std::string_view file) {
{
for ( const auto& e : options.zip_file_extensions ) for ( const auto& e : options.zip_file_extensions )
if ( ends_with(file, e) ) if ( ends_with(file, e) )
return true; return true;
return false; return false;
} }
static pid_t child_pid = -1; static pid_t child_pid = -1;
static void signal_handler(int signal) static void signal_handler(int signal) {
{ if ( child_pid > 0 ) {
if ( child_pid > 0 )
{
kill(child_pid, SIGKILL); kill(child_pid, SIGKILL);
int status; int status;
waitpid(child_pid, &status, 0); waitpid(child_pid, &status, 0);
} }
_exit(131); _exit(131);
} }
// Fork a child and associate its stdin/stdout with the src and dst files, // Fork a child and associate its stdin/stdout with the src and dst files,
// then run compress_cmd via system(). // then run compress_cmd via system().
static int run_compress_cmd(const char* src_file, const char* dst_file) static int run_compress_cmd(const char* src_file, const char* dst_file) {
{
child_pid = fork(); child_pid = fork();
if ( child_pid == -1 ) if ( child_pid == -1 ) {
{
error("Failed to fork() to run compress command: %s", strerror(errno)); error("Failed to fork() to run compress command: %s", strerror(errno));
return -1; return -1;
} }
if ( child_pid == 0 ) if ( child_pid == 0 ) {
{
int src_fd = open(src_file, O_RDONLY); int src_fd = open(src_file, O_RDONLY);
if ( src_fd < 0 ) if ( src_fd < 0 ) {
{
error("Failed to open src_file %s: %s", src_file, strerror(errno)); error("Failed to open src_file %s: %s", src_file, strerror(errno));
exit(254); exit(254);
} }
if ( dup2(src_fd, STDIN_FILENO) == -1 ) if ( dup2(src_fd, STDIN_FILENO) == -1 ) {
{ error("Failed to redirect src_file %s to stdin: %s", src_file, strerror(errno));
error("Failed to redirect src_file %s to stdin: %s", src_file,
strerror(errno));
exit(253); exit(253);
} }
@ -542,16 +489,13 @@ static int run_compress_cmd(const char* src_file, const char* dst_file)
int dst_fd = open(dst_file, O_CREAT | O_TRUNC | O_WRONLY, 0664); int dst_fd = open(dst_file, O_CREAT | O_TRUNC | O_WRONLY, 0664);
if ( dst_fd < 0 ) if ( dst_fd < 0 ) {
{
error("Failed to open dst_file %s: %s", dst_file, strerror(errno)); error("Failed to open dst_file %s: %s", dst_file, strerror(errno));
exit(252); exit(252);
} }
if ( dup2(dst_fd, STDOUT_FILENO) == -1 ) if ( dup2(dst_fd, STDOUT_FILENO) == -1 ) {
{ error("Failed to redirect dst_file %s to stdout: %s", dst_file, strerror(errno));
error("Failed to redirect dst_file %s to stdout: %s", dst_file,
strerror(errno));
exit(251); exit(251);
} }
@ -568,17 +512,13 @@ static int run_compress_cmd(const char* src_file, const char* dst_file)
waitpid(child_pid, &status, 0); waitpid(child_pid, &status, 0);
child_pid = -1; child_pid = -1;
if ( ! (WIFEXITED(status) && WEXITSTATUS(status) == 0) ) if ( ! (WIFEXITED(status) && WEXITSTATUS(status) == 0) ) {
{
if ( WIFEXITED(status) ) if ( WIFEXITED(status) )
error("Compression of %s failed, command exit status: %d (0x%x)", error("Compression of %s failed, command exit status: %d (0x%x)", src_file, WEXITSTATUS(status), status);
src_file, WEXITSTATUS(status), status);
else if ( WIFSIGNALED(status) ) else if ( WIFSIGNALED(status) )
error("Compression of %s failed, got signal: %d (0x%x)", error("Compression of %s failed, got signal: %d (0x%x)", src_file, WTERMSIG(status), status);
src_file, WTERMSIG(status), status);
else else
error("Compression of %s failed, unknown reason/status: (0x%x)", error("Compression of %s failed, unknown reason/status: (0x%x)", src_file, status);
src_file, status);
// If the compression command failed, unlink the destination // If the compression command failed, unlink the destination
// file. Ignore any errors - it may not have been created. // file. Ignore any errors - it may not have been created.
@ -586,16 +526,14 @@ static int run_compress_cmd(const char* src_file, const char* dst_file)
} }
return WIFEXITED(status) ? WEXITSTATUS(status) : -1; return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
} }
static int archive_logs() static int archive_logs() {
{
int rval = 0; int rval = 0;
auto d = opendir(options.src_dir.data()); auto d = opendir(options.src_dir.data());
if ( ! d ) if ( ! d ) {
{
debug("Source directory '%s', does not exist", options.src_dir.data()); debug("Source directory '%s', does not exist", options.src_dir.data());
return rval; return rval;
} }
@ -603,15 +541,13 @@ static int archive_logs()
struct dirent* dp; struct dirent* dp;
std::vector<LogFile> log_files; std::vector<LogFile> log_files;
while ( (dp = readdir(d)) ) while ( (dp = readdir(d)) ) {
{
if ( dp->d_name[0] == '.' ) if ( dp->d_name[0] == '.' )
continue; continue;
std::string path = options.src_dir + "/" + dp->d_name; std::string path = options.src_dir + "/" + dp->d_name;
if ( ! is_file(path.data()) ) if ( ! is_file(path.data()) ) {
{
debug("Skipping archival of non-file: %s", dp->d_name); debug("Skipping archival of non-file: %s", dp->d_name);
continue; continue;
} }
@ -634,8 +570,7 @@ static int archive_logs()
// //
auto parts = split_string(dp->d_name, options.delimiter); auto parts = split_string(dp->d_name, options.delimiter);
if ( parts.size() != 4 && parts.size() != 5) if ( parts.size() != 4 && parts.size() != 5 ) {
{
debug("Skipping archival of non-log: %s", dp->d_name); debug("Skipping archival of non-log: %s", dp->d_name);
continue; continue;
} }
@ -646,8 +581,7 @@ static int archive_logs()
auto res = strptime(parts[1].data(), options.timestamp_fmt.data(), &lf.open); auto res = strptime(parts[1].data(), options.timestamp_fmt.data(), &lf.open);
if ( ! res ) if ( ! res ) {
{
debug("Skipping archival of log with bad timestamp format: %s", dp->d_name); debug("Skipping archival of log with bad timestamp format: %s", dp->d_name);
continue; continue;
} }
@ -657,8 +591,7 @@ static int archive_logs()
res = strptime(parts[2].data(), options.timestamp_fmt.data(), &lf.close); res = strptime(parts[2].data(), options.timestamp_fmt.data(), &lf.close);
if ( ! res ) if ( ! res ) {
{
debug("Skipping archival of log with bad timestamp format: %s", dp->d_name); debug("Skipping archival of log with bad timestamp format: %s", dp->d_name);
continue; continue;
} }
@ -668,8 +601,7 @@ static int archive_logs()
if ( parts.size() == 4 ) if ( parts.size() == 4 )
lf.ext = parts[3]; lf.ext = parts[3];
else else {
{
lf.ext = parts[4]; lf.ext = parts[4];
bool metadata_error = false; bool metadata_error = false;
@ -680,36 +612,30 @@ static int archive_logs()
if ( ! parts[3].empty() ) if ( ! parts[3].empty() )
metadata_parts = split_string(parts[3], ","); metadata_parts = split_string(parts[3], ",");
for (const auto& entry : metadata_parts) for ( const auto& entry : metadata_parts ) {
{
auto key_value = split_string(entry, "="); auto key_value = split_string(entry, "=");
if ( key_value.size() != 2 ) if ( key_value.size() != 2 ) {
{
metadata_error = true; metadata_error = true;
break; break;
} }
auto key = strip_string(key_value[0]); auto key = strip_string(key_value[0]);
auto value = strip_string(key_value[1]); auto value = strip_string(key_value[1]);
if ( key.empty() || value.empty() ) if ( key.empty() || value.empty() ) {
{
metadata_error = true; metadata_error = true;
break; break;
} }
// Only log_suffix is understood as metadata. // Only log_suffix is understood as metadata.
if ( key == "log_suffix" ) if ( key == "log_suffix" ) {
{
debug("Using log_suffix '%s'", value.data()); debug("Using log_suffix '%s'", value.data());
lf.suffix = value; lf.suffix = value;
} }
else else
debug("Ignoring unknown metadata entry %s in %s", key.data(), dp->d_name); debug("Ignoring unknown metadata entry %s in %s", key.data(), dp->d_name);
} }
if ( metadata_error ) if ( metadata_error ) {
{
debug("Skipping archival of log with bad metadata format: %s", dp->d_name); debug("Skipping archival of log with bad metadata format: %s", dp->d_name);
continue; continue;
} }
@ -720,24 +646,20 @@ static int archive_logs()
closedir(d); closedir(d);
for ( const auto& lf : log_files ) for ( const auto& lf : log_files ) {
{
auto dst_dir = options.dst_dir + "/" + lf.DestDir(); auto dst_dir = options.dst_dir + "/" + lf.DestDir();
auto dst_file = dst_dir + "/" + lf.DestFile(); auto dst_file = dst_dir + "/" + lf.DestFile();
auto tmp_file = dst_dir + "/.tmp." + lf.DestFile(); auto tmp_file = dst_dir + "/.tmp." + lf.DestFile();
const auto& src_file = lf.path; const auto& src_file = lf.path;
if ( ! make_dirs(dst_dir) ) if ( ! make_dirs(dst_dir) ) {
{ error("Skipped archiving %s: failed to create dir %s", src_file.data(), dst_dir.data());
error("Skipped archiving %s: failed to create dir %s",
src_file.data(), dst_dir.data());
continue; continue;
} }
bool compress = ! options.compress_cmd.empty() && ! already_zipped(lf.ext); bool compress = ! options.compress_cmd.empty() && ! already_zipped(lf.ext);
if ( compress ) if ( compress ) {
{
if ( ! options.compress_ext.empty() ) if ( ! options.compress_ext.empty() )
dst_file += "." + options.compress_ext; dst_file += "." + options.compress_ext;
@ -749,10 +671,8 @@ static int archive_logs()
res = rename(tmp_file.data(), dst_file.data()); res = rename(tmp_file.data(), dst_file.data());
if ( res == -1 ) if ( res == -1 ) {
{ error("Failed to rename %s -> %s: %s", tmp_file.data(), dst_file.data(), strerror(errno));
error("Failed to rename %s -> %s: %s",
tmp_file.data(), dst_file.data(), strerror(errno));
continue; continue;
} }
@ -767,26 +687,21 @@ static int archive_logs()
auto same_fs = same_filesystem(src_file.data(), dst_dir.data()); auto same_fs = same_filesystem(src_file.data(), dst_dir.data());
if ( ! same_fs ) if ( ! same_fs ) {
{ error("Failed to compare filesystems of %s and %s", src_file.data(), dst_dir.data());
error("Failed to compare filesystems of %s and %s",
src_file.data(), dst_dir.data());
continue; continue;
} }
if ( *same_fs ) if ( *same_fs ) {
{
debug("Archive via rename: %s -> %s", src_file.data(), dst_file.data()); debug("Archive via rename: %s -> %s", src_file.data(), dst_file.data());
auto res = rename(src_file.data(), dst_file.data()); auto res = rename(src_file.data(), dst_file.data());
if ( res == -1 ) if ( res == -1 )
error("Failed to rename %s -> %s: %s", error("Failed to rename %s -> %s: %s", src_file.data(), dst_file.data(), strerror(errno));
src_file.data(), dst_file.data(), strerror(errno));
else else
++rval; ++rval;
} }
else else {
{
debug("Archive via copy: %s -> %s", src_file.data(), dst_file.data()); debug("Archive via copy: %s -> %s", src_file.data(), dst_file.data());
std::ifstream src; std::ifstream src;
@ -794,25 +709,20 @@ static int archive_logs()
src.exceptions(std::ifstream::failbit | std::ifstream::badbit); src.exceptions(std::ifstream::failbit | std::ifstream::badbit);
dst.exceptions(std::ofstream::failbit | std::ofstream::badbit); dst.exceptions(std::ofstream::failbit | std::ofstream::badbit);
try try {
{
src.open(src_file, std::ios::binary); src.open(src_file, std::ios::binary);
dst.open(tmp_file, std::ios::binary); dst.open(tmp_file, std::ios::binary);
dst << src.rdbuf(); dst << src.rdbuf();
} } catch ( const std::system_error& e ) {
catch ( const std::system_error& e ) error("Failed to copy %s to temporary file %s: %s", src_file.data(), tmp_file.data(),
{ e.code().message().data());
error("Failed to copy %s to temporary file %s: %s",
src_file.data(), tmp_file.data(), e.code().message().data());
continue; continue;
} }
auto res = rename(tmp_file.data(), dst_file.data()); auto res = rename(tmp_file.data(), dst_file.data());
if ( res == -1 ) if ( res == -1 ) {
{ error("Failed to rename %s -> %s: %s", tmp_file.data(), dst_file.data(), strerror(errno));
error("Failed to rename %s -> %s: %s",
tmp_file.data(), dst_file.data(), strerror(errno));
continue; continue;
} }
@ -825,10 +735,9 @@ static int archive_logs()
} }
return rval; return rval;
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{
signal(SIGTERM, signal_handler); signal(SIGTERM, signal_handler);
parse_options(argc, argv); parse_options(argc, argv);
@ -847,15 +756,13 @@ int main(int argc, char** argv)
if ( ! make_dirs(options.dst_dir) ) if ( ! make_dirs(options.dst_dir) )
fatal("Failed to create destination archive dir: %s", options.dst_dir.data()); fatal("Failed to create destination archive dir: %s", options.dst_dir.data());
for ( ; ; ) for ( ;; ) {
{
using hrc = std::chrono::high_resolution_clock; using hrc = std::chrono::high_resolution_clock;
auto t0 = hrc::now(); auto t0 = hrc::now();
auto num_archived = archive_logs(); auto num_archived = archive_logs();
auto t1 = hrc::now(); auto t1 = hrc::now();
if ( num_archived > 0 ) if ( num_archived > 0 ) {
{
auto dt = std::chrono::duration<double>(t1 - t0).count(); auto dt = std::chrono::duration<double>(t1 - t0).count();
info("Archived %d logs in %f seconds", num_archived, dt); info("Archived %d logs in %f seconds", num_archived, dt);
} }
@ -867,4 +774,4 @@ int main(int argc, char** argv)
} }
return 0; return 0;
} }

View file

@ -1,14 +1,14 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include <string.h>
#include <limits.h>
#include <getopt.h> #include <getopt.h>
#include <limits.h>
#include <string.h>
// define required for FreeBSD // define required for FreeBSD
#define _WITH_GETLINE #define _WITH_GETLINE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <time.h> #include <time.h>
#include <unistd.h>
/* The maximum length of converted timestamp that zeek-cut can handle. */ /* The maximum length of converted timestamp that zeek-cut can handle. */
#define MAX_TIMESTAMP_LEN 100 #define MAX_TIMESTAMP_LEN 100
@ -19,23 +19,23 @@ struct useropts {
int minimalview; /* show headers in minimal view? (0=no, 1=yes) */ int minimalview; /* show headers in minimal view? (0=no, 1=yes) */
int negate; /* show all but the specified columns? (0=no, 1=yes) */ int negate; /* show all but the specified columns? (0=no, 1=yes) */
int timeconv; /* do time conversion? (0=no, 1=local, 2=UTC) */ int timeconv; /* do time conversion? (0=no, 1=local, 2=UTC) */
char **columns; /* array of user-specified column names */ char** columns; /* array of user-specified column names */
int num_columns; /* number of user-specified column names */ int num_columns; /* number of user-specified column names */
const char *ofs; /* user-specified output field separator character */ const char* ofs; /* user-specified output field separator character */
const char *timefmt; /* strftime format string for time conversion */ const char* timefmt; /* strftime format string for time conversion */
}; };
/* Parameters that might change with each log file being processed. */ /* Parameters that might change with each log file being processed. */
struct logparams { struct logparams {
int *out_indexes; /* array of log file column indices to output */ int* out_indexes; /* array of log file column indices to output */
int num_out_indexes; /* number of elements in "out_indexes" */ int num_out_indexes; /* number of elements in "out_indexes" */
int idx_range; /* max. value in "out_indexes" plus one */ int idx_range; /* max. value in "out_indexes" plus one */
int *time_cols; /* array of columns (0=not timestamp, 1=timestamp) */ int* time_cols; /* array of columns (0=not timestamp, 1=timestamp) */
char **tmp_fields; /* array of pointers to each field on a line */ char** tmp_fields; /* array of pointers to each field on a line */
int num_fields; /* number of fields in log file */ int num_fields; /* number of fields in log file */
char ifs[2]; /* input field separator character */ char ifs[2]; /* input field separator character */
char ofs[2]; /* output field separator character */ char ofs[2]; /* output field separator character */
char *unsetf; /* unset field string */ char* unsetf; /* unset field string */
long prev_ts; /* previous timestamp */ long prev_ts; /* previous timestamp */
}; };
@ -65,10 +65,10 @@ int usage(void) {
/* Return the index in "haystack" where "needle" is located (or -1 if not /* Return the index in "haystack" where "needle" is located (or -1 if not
* found). * found).
*/ */
int string_index(char *haystack[], int haystack_size, const char *needle) { int string_index(char* haystack[], int haystack_size, const char* needle) {
int i; int i;
for (i = 0; i < haystack_size; ++i) { for ( i = 0; i < haystack_size; ++i ) {
if (!strcmp(haystack[i], needle)) { if ( ! strcmp(haystack[i], needle) ) {
return i; return i;
} }
} }
@ -76,13 +76,14 @@ int string_index(char *haystack[], int haystack_size, const char *needle) {
} }
/* Return the input field separator from the log's "#separator " header line. */ /* Return the input field separator from the log's "#separator " header line. */
char parsesep(const char *sepstr) { char parsesep(const char* sepstr) {
char ifs; char ifs;
if (!strncmp(sepstr, "\\x", 2)) { if ( ! strncmp(sepstr, "\\x", 2) ) {
long sepval = strtol(sepstr + 2, NULL, 16); long sepval = strtol(sepstr + 2, NULL, 16);
ifs = sepval; ifs = sepval;
} else { }
else {
ifs = sepstr[0]; ifs = sepstr[0];
} }
@ -92,30 +93,30 @@ char parsesep(const char *sepstr) {
/* Determine the columns (if any) where the field is "time". Return 0 for /* Determine the columns (if any) where the field is "time". Return 0 for
* success, and non-zero otherwise. * success, and non-zero otherwise.
*/ */
int find_timecol(const char *line, struct logparams *lp) { int find_timecol(const char* line, struct logparams* lp) {
int i; int i;
int *tmpptr; int* tmpptr;
char *copy_of_line; char* copy_of_line;
char *field_ptr; char* field_ptr;
char *field; char* field;
tmpptr = (int *) realloc(lp->time_cols, lp->idx_range * sizeof(int)); tmpptr = (int*)realloc(lp->time_cols, lp->idx_range * sizeof(int));
if (tmpptr == NULL) { if ( tmpptr == NULL ) {
fputs("zeek-cut: out of memory\n", stderr); fputs("zeek-cut: out of memory\n", stderr);
return 1; return 1;
} }
lp->time_cols = tmpptr; lp->time_cols = tmpptr;
if ((copy_of_line = strdup(line)) == NULL) { if ( (copy_of_line = strdup(line)) == NULL ) {
fputs("zeek-cut: out of memory\n", stderr); fputs("zeek-cut: out of memory\n", stderr);
return 1; return 1;
} }
field_ptr = copy_of_line; field_ptr = copy_of_line;
int ret = 0; int ret = 0;
for (i = 0; i < lp->idx_range; ++i) { for ( i = 0; i < lp->idx_range; ++i ) {
if ((field = strsep(&field_ptr, lp->ifs)) == NULL) { if ( (field = strsep(&field_ptr, lp->ifs)) == NULL ) {
fputs("zeek-cut: log header does not have enough fields\n", stderr); fputs("zeek-cut: log header does not have enough fields\n", stderr);
ret = 1; ret = 1;
break; break;
@ -135,38 +136,38 @@ int find_timecol(const char *line, struct logparams *lp) {
* store in "idx_range" the maximum value contained in "out_indexes" plus one. * store in "idx_range" the maximum value contained in "out_indexes" plus one.
* Return 0 for success, and non-zero otherwise. * Return 0 for success, and non-zero otherwise.
*/ */
int find_output_indexes(char *line, struct logparams *lp, struct useropts *bopts) { int find_output_indexes(char* line, struct logparams* lp, struct useropts* bopts) {
int idx; int idx;
int *out_indexes; int* out_indexes;
char *field_ptr; char* field_ptr;
char *copy_of_line = NULL; char* copy_of_line = NULL;
char *field; char* field;
/* Get the number of fields */ /* Get the number of fields */
lp->num_fields = 0; lp->num_fields = 0;
field = line; field = line;
while ((field = strchr(field, lp->ifs[0])) != NULL) { while ( (field = strchr(field, lp->ifs[0])) != NULL ) {
lp->num_fields++; lp->num_fields++;
field++; field++;
} }
lp->num_fields++; lp->num_fields++;
char **tmpptr; char** tmpptr;
/* note: size is num_fields+1 because header lines have an extra field */ /* note: size is num_fields+1 because header lines have an extra field */
tmpptr = (char **) realloc(lp->tmp_fields, (lp->num_fields + 1) * sizeof(char *)); tmpptr = (char**)realloc(lp->tmp_fields, (lp->num_fields + 1) * sizeof(char*));
if (tmpptr == NULL) { if ( tmpptr == NULL ) {
return 1; return 1;
} }
lp->tmp_fields = tmpptr; lp->tmp_fields = tmpptr;
if (bopts->num_columns == 0) { if ( bopts->num_columns == 0 ) {
/* No columns specified on cmd-line, so use all the columns */ /* No columns specified on cmd-line, so use all the columns */
out_indexes = (int *) realloc(lp->out_indexes, lp->num_fields * sizeof(int)); out_indexes = (int*)realloc(lp->out_indexes, lp->num_fields * sizeof(int));
if (out_indexes == NULL) { if ( out_indexes == NULL ) {
return 1; return 1;
} }
for (idx = 0; idx < lp->num_fields; ++idx) { for ( idx = 0; idx < lp->num_fields; ++idx ) {
out_indexes[idx] = idx; out_indexes[idx] = idx;
} }
@ -177,44 +178,45 @@ int find_output_indexes(char *line, struct logparams *lp, struct useropts *bopts
} }
/* Set tmp_fields to point to each field on the line */ /* Set tmp_fields to point to each field on the line */
if ((copy_of_line = strdup(line)) == NULL) { if ( (copy_of_line = strdup(line)) == NULL ) {
return 1; return 1;
} }
field_ptr = copy_of_line; field_ptr = copy_of_line;
idx = 0; idx = 0;
while ((field = strsep(&field_ptr, lp->ifs)) != NULL) { while ( (field = strsep(&field_ptr, lp->ifs)) != NULL ) {
lp->tmp_fields[idx++] = field; lp->tmp_fields[idx++] = field;
} }
int out_idx = 0; int out_idx = 0;
int maxval = 0; int maxval = 0;
if (!bopts->negate) { if ( ! bopts->negate ) {
/* One or more column names were specified on cmd-line */ /* One or more column names were specified on cmd-line */
out_indexes = (int *) realloc(lp->out_indexes, bopts->num_columns * sizeof(int)); out_indexes = (int*)realloc(lp->out_indexes, bopts->num_columns * sizeof(int));
if (out_indexes == NULL) { if ( out_indexes == NULL ) {
return 1; return 1;
} }
for (idx = 0; idx < bopts->num_columns; ++idx) { for ( idx = 0; idx < bopts->num_columns; ++idx ) {
out_indexes[idx] = string_index(lp->tmp_fields, lp->num_fields, bopts->columns[idx]); out_indexes[idx] = string_index(lp->tmp_fields, lp->num_fields, bopts->columns[idx]);
if (out_indexes[idx] > maxval) { if ( out_indexes[idx] > maxval ) {
maxval = out_indexes[idx]; maxval = out_indexes[idx];
} }
} }
out_idx = bopts->num_columns; out_idx = bopts->num_columns;
} else { }
else {
/* The "-n" option was specified on cmd-line */ /* The "-n" option was specified on cmd-line */
out_indexes = (int *) realloc(lp->out_indexes, lp->num_fields * sizeof(int)); out_indexes = (int*)realloc(lp->out_indexes, lp->num_fields * sizeof(int));
if (out_indexes == NULL) { if ( out_indexes == NULL ) {
return 1; return 1;
} }
for (idx = 0; idx < lp->num_fields; ++idx) { for ( idx = 0; idx < lp->num_fields; ++idx ) {
if (string_index(bopts->columns, bopts->num_columns, lp->tmp_fields[idx]) == -1) { if ( string_index(bopts->columns, bopts->num_columns, lp->tmp_fields[idx]) == -1 ) {
out_indexes[out_idx++] = idx; out_indexes[out_idx++] = idx;
if (idx > maxval) { if ( idx > maxval ) {
maxval = idx; maxval = idx;
} }
} }
@ -235,40 +237,45 @@ int find_output_indexes(char *line, struct logparams *lp, struct useropts *bopts
* point (everything after the decimal point is ignored). If the time * point (everything after the decimal point is ignored). If the time
* conversion fails for any reason, then just output the field unmodified. * conversion fails for any reason, then just output the field unmodified.
*/ */
void output_time(const char *field, struct logparams *lp, struct useropts *bopts) { void output_time(const char* field, struct logparams* lp, struct useropts* bopts) {
/* Buffer is declared static in order to reuse the timestamp string */ /* Buffer is declared static in order to reuse the timestamp string */
static char tbuf[MAX_TIMESTAMP_LEN]; static char tbuf[MAX_TIMESTAMP_LEN];
char *tmp; char* tmp;
long tl = strtol(field, &tmp, 10); long tl = strtol(field, &tmp, 10);
if (tl < 0 || tl == LONG_MAX) { if ( tl < 0 || tl == LONG_MAX ) {
fprintf(stderr, "zeek-cut: time value out-of-range: %s\n", field); fprintf(stderr, "zeek-cut: time value out-of-range: %s\n", field);
} else if (*tmp != '.') { }
if (strcmp(field, lp->unsetf)) { else if ( *tmp != '.' ) {
if ( strcmp(field, lp->unsetf) ) {
/* field is not a valid value and is not the unset field string */ /* field is not a valid value and is not the unset field string */
fprintf(stderr, "zeek-cut: time field is not valid: %s\n", field); fprintf(stderr, "zeek-cut: time field is not valid: %s\n", field);
} }
} else if (tl == lp->prev_ts) { }
else if ( tl == lp->prev_ts ) {
/* timestamp is same as the previous one, so skip the conversion */ /* timestamp is same as the previous one, so skip the conversion */
fputs(tbuf, stdout); fputs(tbuf, stdout);
return; return;
} else { }
else {
time_t tt = tl; time_t tt = tl;
struct tm tmval; struct tm tmval;
struct tm* tmptr; struct tm* tmptr;
tmptr = bopts->timeconv == 1 ? localtime_r(&tt, &tmval) : gmtime_r(&tt, &tmval); tmptr = bopts->timeconv == 1 ? localtime_r(&tt, &tmval) : gmtime_r(&tt, &tmval);
if (tmptr) { if ( tmptr ) {
if (strftime(tbuf, sizeof(tbuf), bopts->timefmt, tmptr)) { if ( strftime(tbuf, sizeof(tbuf), bopts->timefmt, tmptr) ) {
/* output the formatted timestamp */ /* output the formatted timestamp */
fputs(tbuf, stdout); fputs(tbuf, stdout);
lp->prev_ts = tl; lp->prev_ts = tl;
return; return;
} else { }
else {
fputs("zeek-cut: failed to convert timestamp (try a shorter format string)\n", stderr); fputs("zeek-cut: failed to convert timestamp (try a shorter format string)\n", stderr);
} }
} else { }
else {
/* the time conversion will fail for large values */ /* the time conversion will fail for large values */
fprintf(stderr, "zeek-cut: time value out-of-range: %s\n", field); fprintf(stderr, "zeek-cut: time value out-of-range: %s\n", field);
} }
@ -281,9 +288,9 @@ void output_time(const char *field, struct logparams *lp, struct useropts *bopts
/* Output the columns of "line" that the user specified. The value of "hdr" /* Output the columns of "line" that the user specified. The value of "hdr"
* indicates whether "line" is a header line or not (0=not header, 1=header). * indicates whether "line" is a header line or not (0=not header, 1=header).
*/ */
void output_indexes(int hdr, char *line, struct logparams *lp, struct useropts *bopts) { void output_indexes(int hdr, char* line, struct logparams* lp, struct useropts* bopts) {
int i; int i;
char *field; char* field;
int dotimeconv = 0; /* do a time conversion on this line? (0=no, 1=yes) */ int dotimeconv = 0; /* do a time conversion on this line? (0=no, 1=yes) */
int dotimetypeconv = 0; /* change time type on this line? (0=no, 1=yes) */ int dotimetypeconv = 0; /* change time type on this line? (0=no, 1=yes) */
int idxrange = lp->idx_range + hdr; /* header lines have one extra field */ int idxrange = lp->idx_range + hdr; /* header lines have one extra field */
@ -292,12 +299,12 @@ void output_indexes(int hdr, char *line, struct logparams *lp, struct useropts *
/* If user selected time conversion and this line is not a header line, /* If user selected time conversion and this line is not a header line,
* then try to do a time conversion. * then try to do a time conversion.
*/ */
if (bopts->timeconv && !hdr) { if ( bopts->timeconv && ! hdr ) {
dotimeconv = 1; dotimeconv = 1;
} }
for (i = 0; i < idxrange; ++i) { for ( i = 0; i < idxrange; ++i ) {
if ((field = strsep(&line, lp->ifs)) == NULL) { if ( (field = strsep(&line, lp->ifs)) == NULL ) {
fputs("zeek-cut: skipping log line (not enough fields)\n", stderr); fputs("zeek-cut: skipping log line (not enough fields)\n", stderr);
return; return;
} }
@ -307,34 +314,35 @@ void output_indexes(int hdr, char *line, struct logparams *lp, struct useropts *
/* If user selected time conversion and this line is a "#types" header, /* If user selected time conversion and this line is a "#types" header,
* then try to change the "time" type field. * then try to change the "time" type field.
*/ */
if (bopts->timeconv && hdr && !strcmp(lp->tmp_fields[0], "#types")) { if ( bopts->timeconv && hdr && ! strcmp(lp->tmp_fields[0], "#types") ) {
dotimetypeconv = 1; dotimetypeconv = 1;
} }
if (hdr && bopts->minimalview == 0) { if ( hdr && bopts->minimalview == 0 ) {
/* Output the initial "#" field on the header line */ /* Output the initial "#" field on the header line */
fputs(lp->tmp_fields[0], stdout); fputs(lp->tmp_fields[0], stdout);
firstdone = 1; firstdone = 1;
} }
for (i = 0; i < lp->num_out_indexes; ++i) { for ( i = 0; i < lp->num_out_indexes; ++i ) {
int idxval = lp->out_indexes[i]; int idxval = lp->out_indexes[i];
if (firstdone) if ( firstdone )
fputs(lp->ofs, stdout); fputs(lp->ofs, stdout);
if (idxval != -1) { if ( idxval != -1 ) {
if (dotimeconv && lp->time_cols[idxval]) { if ( dotimeconv && lp->time_cols[idxval] ) {
/* output time field */ /* output time field */
output_time(lp->tmp_fields[idxval], lp, bopts); output_time(lp->tmp_fields[idxval], lp, bopts);
} else if (dotimetypeconv && !strcmp("time", lp->tmp_fields[idxval + hdr])) { }
else if ( dotimetypeconv && ! strcmp("time", lp->tmp_fields[idxval + hdr]) ) {
/* change the "time" type field to "string" */ /* change the "time" type field to "string" */
fputs("string", stdout); fputs("string", stdout);
} else { }
else {
/* output the field without modification */ /* output the field without modification */
fputs(lp->tmp_fields[idxval + hdr], stdout); fputs(lp->tmp_fields[idxval + hdr], stdout);
} }
} }
/* Note: even when idxval == -1, we still need to set "firstdone" so /* Note: even when idxval == -1, we still need to set "firstdone" so
@ -357,9 +365,9 @@ int zeek_cut(struct useropts bopts) {
int prev_fields_line = 0; /* previous line was #fields line? 0=no, 1=yes */ int prev_fields_line = 0; /* previous line was #fields line? 0=no, 1=yes */
ssize_t linelen; ssize_t linelen;
size_t linesize = 100000; size_t linesize = 100000;
char *line = (char *) malloc(linesize); char* line = (char*)malloc(linesize);
if (line == NULL) { if ( line == NULL ) {
fputs("zeek-cut: out of memory\n", stderr); fputs("zeek-cut: out of memory\n", stderr);
return 1; return 1;
} }
@ -377,24 +385,24 @@ int zeek_cut(struct useropts bopts) {
lp.unsetf = strdup("-"); lp.unsetf = strdup("-");
lp.prev_ts = -1; /* initialize with an invalid time value */ lp.prev_ts = -1; /* initialize with an invalid time value */
if (lp.unsetf == NULL) { if ( lp.unsetf == NULL ) {
fputs("zeek-cut: out of memory\n", stderr); fputs("zeek-cut: out of memory\n", stderr);
free(line); free(line);
return 1; return 1;
} }
while ((linelen = getline(&line, &linesize, stdin)) > 0) { while ( (linelen = getline(&line, &linesize, stdin)) > 0 ) {
/* Remove trailing '\n' */ /* Remove trailing '\n' */
line[linelen - 1] = '\0'; line[linelen - 1] = '\0';
if (prev_fields_line && strncmp(line, "#types", 6)) { if ( prev_fields_line && strncmp(line, "#types", 6) ) {
fputs("zeek-cut: bad log header (missing #types line)\n", stderr); fputs("zeek-cut: bad log header (missing #types line)\n", stderr);
ret = 1; ret = 1;
break; break;
} }
/* Check if this line is a header line or not */ /* Check if this line is a header line or not */
if (line[0] != '#') { if ( line[0] != '#' ) {
prev_line_hdr = 0; prev_line_hdr = 0;
output_indexes(0, line, &lp, &bopts); output_indexes(0, line, &lp, &bopts);
continue; continue;
@ -402,18 +410,18 @@ int zeek_cut(struct useropts bopts) {
/* The rest of this loop is for header processing */ /* The rest of this loop is for header processing */
if (!prev_line_hdr) { if ( ! prev_line_hdr ) {
/* Here we are transitioning from non-header to header line */ /* Here we are transitioning from non-header to header line */
prev_line_hdr = 1; prev_line_hdr = 1;
/* Once we've seen two header blocks, we stop counting them */ /* Once we've seen two header blocks, we stop counting them */
if (headers_seen < 2) { if ( headers_seen < 2 ) {
headers_seen++; headers_seen++;
} }
} }
if (!strncmp(line, "#separator ", 11)) { if ( ! strncmp(line, "#separator ", 11) ) {
char ifs = parsesep(line + 11); char ifs = parsesep(line + 11);
if (ifs == '\0') { if ( ifs == '\0' ) {
fputs("zeek-cut: bad log header (invalid #separator line)\n", stderr); fputs("zeek-cut: bad log header (invalid #separator line)\n", stderr);
ret = 1; ret = 1;
break; break;
@ -425,36 +433,40 @@ int zeek_cut(struct useropts bopts) {
* use the log file's input field separator. * use the log file's input field separator.
*/ */
lp.ofs[0] = bopts.ofs[0] ? bopts.ofs[0] : lp.ifs[0]; lp.ofs[0] = bopts.ofs[0] ? bopts.ofs[0] : lp.ifs[0];
} else if (!strncmp(line, "#unset_field", 12)) { }
if (line[12] && line[13]) { else if ( ! strncmp(line, "#unset_field", 12) ) {
if ( line[12] && line[13] ) {
free(lp.unsetf); free(lp.unsetf);
if ((lp.unsetf = strdup(line + 13)) == NULL) { if ( (lp.unsetf = strdup(line + 13)) == NULL ) {
fputs("zeek-cut: out of memory\n", stderr); fputs("zeek-cut: out of memory\n", stderr);
ret = 1; ret = 1;
break; break;
} }
} else { }
else {
fputs("zeek-cut: bad log header (invalid #unset_field line)\n", stderr); fputs("zeek-cut: bad log header (invalid #unset_field line)\n", stderr);
ret = 1; ret = 1;
break; break;
} }
} else if (!strncmp(line, "#fields", 7)) { }
else if ( ! strncmp(line, "#fields", 7) ) {
prev_fields_line = 1; prev_fields_line = 1;
if (find_output_indexes(line + 8, &lp, &bopts)) { if ( find_output_indexes(line + 8, &lp, &bopts) ) {
fputs("zeek-cut: out of memory\n", stderr); fputs("zeek-cut: out of memory\n", stderr);
ret = 1; ret = 1;
break; break;
} }
} else if (!strncmp(line, "#types", 6)) { }
if (!prev_fields_line) { else if ( ! strncmp(line, "#types", 6) ) {
if ( ! prev_fields_line ) {
fputs("zeek-cut: bad log header (missing #fields line)\n", stderr); fputs("zeek-cut: bad log header (missing #fields line)\n", stderr);
ret = 1; ret = 1;
break; break;
} }
prev_fields_line = 0; prev_fields_line = 0;
if (bopts.timeconv) { if ( bopts.timeconv ) {
if (find_timecol(line + 7, &lp)) { if ( find_timecol(line + 7, &lp) ) {
ret = 1; ret = 1;
break; break;
} }
@ -462,16 +474,16 @@ int zeek_cut(struct useropts bopts) {
} }
/* Decide if we want to output this header */ /* Decide if we want to output this header */
if (bopts.showhdr >= headers_seen) { if ( bopts.showhdr >= headers_seen ) {
if (!strncmp(line, "#fields", 7) || (!strncmp(line, "#types", 6) && (bopts.minimalview == 0))) { if ( ! strncmp(line, "#fields", 7) || (! strncmp(line, "#types", 6) && (bopts.minimalview == 0)) ) {
/* Output a modified "#fields" or "#types" header line */ /* Output a modified "#fields" or "#types" header line */
output_indexes(1, line, &lp, &bopts); output_indexes(1, line, &lp, &bopts);
} else if (bopts.minimalview == 0) { }
else if ( bopts.minimalview == 0 ) {
/* Output the header line with no changes */ /* Output the header line with no changes */
puts(line); puts(line);
} }
} }
} }
free(lp.time_cols); free(lp.time_cols);
@ -482,13 +494,15 @@ int zeek_cut(struct useropts bopts) {
return ret; return ret;
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
int c; int c;
char *envtimefmt = getenv("ZEEK_CUT_TIMEFMT"); char* envtimefmt = getenv("ZEEK_CUT_TIMEFMT");
if (envtimefmt == NULL) { if ( envtimefmt == NULL ) {
envtimefmt = getenv("BRO_CUT_TIMEFMT"); envtimefmt = getenv("BRO_CUT_TIMEFMT");
if (envtimefmt != NULL) if ( envtimefmt != NULL )
fprintf(stderr, "zeek-cut warning: using legacy environment variable BRO_CUT_TIMEFMT, set ZEEK_CUT_TIMEFMT instead\n"); fprintf(
stderr,
"zeek-cut warning: using legacy environment variable BRO_CUT_TIMEFMT, set ZEEK_CUT_TIMEFMT instead\n");
} }
struct useropts bopts; struct useropts bopts;
@ -499,13 +513,10 @@ int main(int argc, char *argv[]) {
bopts.ofs = ""; bopts.ofs = "";
bopts.timefmt = envtimefmt ? envtimefmt : "%Y-%m-%dT%H:%M:%S%z"; bopts.timefmt = envtimefmt ? envtimefmt : "%Y-%m-%dT%H:%M:%S%z";
static struct option long_opts[] = { static struct option long_opts[] = {{"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "cCmMnF:duD:U:h", long_opts, NULL)) != -1) { while ( (c = getopt_long(argc, argv, "cCmMnF:duD:U:h", long_opts, NULL)) != -1 ) {
switch (c) { switch ( c ) {
case 'c': case 'c':
bopts.minimalview = 0; bopts.minimalview = 0;
bopts.showhdr = 1; bopts.showhdr = 1;
@ -522,22 +533,16 @@ int main(int argc, char *argv[]) {
bopts.minimalview = 1; bopts.minimalview = 1;
bopts.showhdr = 2; bopts.showhdr = 2;
break; break;
case 'n': case 'n': bopts.negate = 1; break;
bopts.negate = 1;
break;
case 'F': case 'F':
if (strlen(optarg) != 1) { if ( strlen(optarg) != 1 ) {
fputs("zeek-cut: field separator must be a single character\n", stderr); fputs("zeek-cut: field separator must be a single character\n", stderr);
exit(1); exit(1);
} }
bopts.ofs = optarg; bopts.ofs = optarg;
break; break;
case 'd': case 'd': bopts.timeconv = 1; break;
bopts.timeconv = 1; case 'u': bopts.timeconv = 2; break;
break;
case 'u':
bopts.timeconv = 2;
break;
case 'D': case 'D':
bopts.timeconv = 1; bopts.timeconv = 1;
bopts.timefmt = optarg; bopts.timefmt = optarg;
@ -546,13 +551,11 @@ int main(int argc, char *argv[]) {
bopts.timeconv = 2; bopts.timeconv = 2;
bopts.timefmt = optarg; bopts.timefmt = optarg;
break; break;
default: default: usage(); break;
usage();
break;
} }
} }
if (bopts.timeconv && strlen(bopts.timefmt) == 0) { if ( bopts.timeconv && strlen(bopts.timefmt) == 0 ) {
fputs("zeek-cut: time format string cannot be empty\n", stderr); fputs("zeek-cut: time format string cannot be empty\n", stderr);
exit(1); exit(1);
} }