newsyslog.c (5c1b641b097a9bbd90e899d4ab83d764b5d078bd) newsyslog.c (28984f255263ee10de1fc3d0f86e9af7e562450d)
1/*-
2 * ------+---------+---------+-------- + --------+---------+---------+---------*
3 * This file includes significant modifications done by:
4 * Copyright (c) 2003, 2004 - Garance Alistair Drosehn <gad@FreeBSD.org>.
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

--- 46 unchanged lines hidden (view full) ---

55
56#include <sys/cdefs.h>
57__FBSDID("$FreeBSD$");
58
59#define OSF
60
61#include <sys/param.h>
62#include <sys/queue.h>
1/*-
2 * ------+---------+---------+-------- + --------+---------+---------+---------*
3 * This file includes significant modifications done by:
4 * Copyright (c) 2003, 2004 - Garance Alistair Drosehn <gad@FreeBSD.org>.
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

--- 46 unchanged lines hidden (view full) ---

55
56#include <sys/cdefs.h>
57__FBSDID("$FreeBSD$");
58
59#define OSF
60
61#include <sys/param.h>
62#include <sys/queue.h>
63#include <sys/sbuf.h>
63#include <sys/stat.h>
64#include <sys/wait.h>
65
66#include <assert.h>
67#include <ctype.h>
68#include <err.h>
69#include <errno.h>
70#include <dirent.h>

--- 11 unchanged lines hidden (view full) ---

82#include <syslog.h>
83#include <time.h>
84#include <unistd.h>
85
86#include "pathnames.h"
87#include "extern.h"
88
89/*
64#include <sys/stat.h>
65#include <sys/wait.h>
66
67#include <assert.h>
68#include <ctype.h>
69#include <err.h>
70#include <errno.h>
71#include <dirent.h>

--- 11 unchanged lines hidden (view full) ---

83#include <syslog.h>
84#include <time.h>
85#include <unistd.h>
86
87#include "pathnames.h"
88#include "extern.h"
89
90/*
90 * Compression suffixes
91 */
92#ifndef COMPRESS_SUFFIX_GZ
93#define COMPRESS_SUFFIX_GZ ".gz"
94#endif
95
96#ifndef COMPRESS_SUFFIX_BZ2
97#define COMPRESS_SUFFIX_BZ2 ".bz2"
98#endif
99
100#ifndef COMPRESS_SUFFIX_XZ
101#define COMPRESS_SUFFIX_XZ ".xz"
102#endif
103
104#ifndef COMPRESS_SUFFIX_ZST
105#define COMPRESS_SUFFIX_ZST ".zst"
106#endif
107
108#define COMPRESS_SUFFIX_MAXLEN MAX(MAX(MAX(sizeof(COMPRESS_SUFFIX_GZ),sizeof(COMPRESS_SUFFIX_BZ2)),sizeof(COMPRESS_SUFFIX_XZ)),sizeof(COMPRESS_SUFFIX_ZST))
109
110/*
111 * Compression types
112 */
113#define COMPRESS_TYPES 5 /* Number of supported compression types */
114
115#define COMPRESS_NONE 0
116#define COMPRESS_GZIP 1
117#define COMPRESS_BZIP2 2
118#define COMPRESS_XZ 3

--- 27 unchanged lines hidden (view full) ---

146#define DEFAULT_TIMEFNAME_FMT "%Y%m%dT%H%M%S"
147
148#define MAX_OLDLOGS 65536 /* Default maximum number of old logfiles */
149
150struct compress_types {
151 const char *flag; /* Flag in configuration file */
152 const char *suffix; /* Compression suffix */
153 const char *path; /* Path to compression program */
91 * Compression types
92 */
93#define COMPRESS_TYPES 5 /* Number of supported compression types */
94
95#define COMPRESS_NONE 0
96#define COMPRESS_GZIP 1
97#define COMPRESS_BZIP2 2
98#define COMPRESS_XZ 3

--- 27 unchanged lines hidden (view full) ---

126#define DEFAULT_TIMEFNAME_FMT "%Y%m%dT%H%M%S"
127
128#define MAX_OLDLOGS 65536 /* Default maximum number of old logfiles */
129
130struct compress_types {
131 const char *flag; /* Flag in configuration file */
132 const char *suffix; /* Compression suffix */
133 const char *path; /* Path to compression program */
154 char **args; /* Compression program arguments */
155 int nargs; /* Program argument count */
134 const char **flags; /* Compression program flags */
135 int nflags; /* Program flags count */
156};
157
136};
137
158static char f_arg[] = "-f";
159static char q_arg[] = "-q";
160static char rm_arg[] = "--rm";
161static char *gz_args[] = { NULL, f_arg, NULL, NULL };
162#define bz2_args gz_args
163#define xz_args gz_args
164static char *zstd_args[] = { NULL, q_arg, rm_arg, NULL, NULL };
138static const char *gzip_flags[] = { "-f" };
139#define bzip2_flags gzip_flags
140#define xz_flags gzip_flags
141static const char *zstd_flags[] = { "-q", "--rm" };
165
166static const struct compress_types compress_type[COMPRESS_TYPES] = {
142
143static const struct compress_types compress_type[COMPRESS_TYPES] = {
167 { "", "", "", NULL, 0},
168 { "Z", COMPRESS_SUFFIX_GZ, _PATH_GZIP, gz_args, nitems(gz_args) },
169 { "J", COMPRESS_SUFFIX_BZ2, _PATH_BZIP2, bz2_args, nitems(bz2_args) },
170 { "X", COMPRESS_SUFFIX_XZ, _PATH_XZ, xz_args, nitems(xz_args) },
171 { "Y", COMPRESS_SUFFIX_ZST, _PATH_ZSTD, zstd_args, nitems(zstd_args) }
144 { "", "", "", NULL, 0 },
145 { "Z", ".gz", _PATH_GZIP, gzip_flags, nitems(gzip_flags) },
146 { "J", ".bz2", _PATH_BZIP2, bzip2_flags, nitems(bzip2_flags) },
147 { "X", ".xz", _PATH_XZ, xz_flags, nitems(xz_flags) },
148 { "Y", ".zst", _PATH_ZSTD, zstd_flags, nitems(zstd_flags) }
172};
173
174struct conf_entry {
175 STAILQ_ENTRY(conf_entry) cf_nextp;
176 char *log; /* Name of the log */
177 char *pid_cmd_file; /* PID or command file */
178 char *r_reason; /* The reason this file is being rotated */
179 int firstcreate; /* Creating log for the first time (-C). */

--- 1835 unchanged lines hidden (view full) ---

2015 sleep(secs);
2016 }
2017 }
2018}
2019
2020static void
2021do_zipwork(struct zipwork_entry *zwork)
2022{
149};
150
151struct conf_entry {
152 STAILQ_ENTRY(conf_entry) cf_nextp;
153 char *log; /* Name of the log */
154 char *pid_cmd_file; /* PID or command file */
155 char *r_reason; /* The reason this file is being rotated */
156 int firstcreate; /* Creating log for the first time (-C). */

--- 1835 unchanged lines hidden (view full) ---

1992 sleep(secs);
1993 }
1994 }
1995}
1996
1997static void
1998do_zipwork(struct zipwork_entry *zwork)
1999{
2023 const char *pgm_name, *pgm_path;
2024 int errsav, fcount, zstatus;
2000 const struct compress_types *ct;
2001 struct sbuf *command;
2025 pid_t pidzip, wpid;
2002 pid_t pidzip, wpid;
2026 char zresult[MAXPATHLEN];
2027 char command[BUFSIZ];
2028 char **args;
2029 int c, i, nargs;
2003 int c, errsav, fcount, zstatus;
2004 const char **args, *pgm_name, *pgm_path;
2005 char *zresult;
2030
2006
2007 command = NULL;
2031 assert(zwork != NULL);
2008 assert(zwork != NULL);
2032 pgm_path = NULL;
2033 strlcpy(zresult, zwork->zw_fname, sizeof(zresult));
2034 if (zwork->zw_conf != NULL &&
2035 zwork->zw_conf->compress > COMPRESS_NONE)
2036 for (c = 1; c < COMPRESS_TYPES; c++) {
2037 if (zwork->zw_conf->compress == c) {
2038 nargs = compress_type[c].nargs;
2039 args = calloc(nargs, sizeof(*args));
2040 if (args == NULL)
2041 err(1, "calloc()");
2042 pgm_path = compress_type[c].path;
2043 (void) strlcat(zresult,
2044 compress_type[c].suffix, sizeof(zresult));
2045 /* the first argument is always NULL, skip it */
2046 for (i = 1; i < nargs; i++) {
2047 if (compress_type[c].args[i] == NULL)
2048 break;
2049 args[i] = compress_type[c].args[i];
2050 }
2051 break;
2052 }
2053 }
2054 if (pgm_path == NULL) {
2055 warnx("invalid entry for %s in do_zipwork", zwork->zw_fname);
2056 return;
2057 }
2058 pgm_name = strrchr(pgm_path, '/');
2059 if (pgm_name == NULL)
2060 pgm_name = pgm_path;
2061 else
2062 pgm_name++;
2009 assert(zwork->zw_conf != NULL);
2010 assert(zwork->zw_conf->compress > COMPRESS_NONE);
2011 assert(zwork->zw_conf->compress < COMPRESS_TYPES);
2063
2012
2064 args[0] = strdup(pgm_name);
2065 if (args[0] == NULL)
2066 err(1, "strdup()");
2067 for (c = 0; args[c] != NULL; c++)
2068 ;
2069 args[c] = zwork->zw_fname;
2070
2071 if (zwork->zw_swork != NULL && zwork->zw_swork->sw_runcmd == 0 &&
2072 zwork->zw_swork->sw_pidok <= 0) {
2073 warnx(
2074 "log %s not compressed because daemon(s) not notified",
2075 zwork->zw_fname);
2076 change_attrs(zwork->zw_fname, zwork->zw_conf);
2077 return;
2078 }
2079
2013 if (zwork->zw_swork != NULL && zwork->zw_swork->sw_runcmd == 0 &&
2014 zwork->zw_swork->sw_pidok <= 0) {
2015 warnx(
2016 "log %s not compressed because daemon(s) not notified",
2017 zwork->zw_fname);
2018 change_attrs(zwork->zw_fname, zwork->zw_conf);
2019 return;
2020 }
2021
2080 strlcpy(command, pgm_path, sizeof(command));
2022 ct = &compress_type[zwork->zw_conf->compress];
2023
2024 /*
2025 * execv will be called with the array [ program, flags ... ,
2026 * filename, NULL ] so allocate nflags+3 elements for the array.
2027 */
2028 args = calloc(ct->nflags + 3, sizeof(*args));
2029 if (args == NULL)
2030 err(1, "calloc");
2031
2032 pgm_path = ct->path;
2033 pgm_name = strrchr(pgm_path, '/');
2034 if (pgm_name == NULL)
2035 pgm_name = pgm_path;
2036 else
2037 pgm_name++;
2038
2039 /* Build the argument array. */
2040 args[0] = pgm_name;
2041 for (c = 0; c < ct->nflags; c++)
2042 args[c + 1] = ct->flags[c];
2043 args[c + 1] = zwork->zw_fname;
2044
2045 /* Also create a space-delimited version if we need to print it. */
2046 if ((command = sbuf_new_auto()) == NULL)
2047 errx(1, "sbuf_new");
2048 sbuf_cpy(command, pgm_path);
2081 for (c = 1; args[c] != NULL; c++) {
2049 for (c = 1; args[c] != NULL; c++) {
2082 strlcat(command, " ", sizeof(command));
2083 strlcat(command, args[c], sizeof(command));
2050 sbuf_putc(command, ' ');
2051 sbuf_cat(command, args[c]);
2084 }
2052 }
2053 if (sbuf_finish(command) == -1)
2054 err(1, "sbuf_finish");
2055
2056 /* Determine the filename of the compressed file. */
2057 asprintf(&zresult, "%s%s", zwork->zw_fname, ct->suffix);
2058 if (zresult == NULL)
2059 errx(1, "asprintf");
2060
2061 if (verbose)
2062 printf("Executing: %s\n", sbuf_data(command));
2063
2085 if (noaction) {
2086 printf("\t%s %s\n", pgm_name, zwork->zw_fname);
2087 change_attrs(zresult, zwork->zw_conf);
2064 if (noaction) {
2065 printf("\t%s %s\n", pgm_name, zwork->zw_fname);
2066 change_attrs(zresult, zwork->zw_conf);
2088 return;
2067 goto out;
2089 }
2090
2068 }
2069
2091 if (verbose) {
2092 printf("Executing: %s\n", command);
2093 }
2094 fcount = 1;
2095 pidzip = fork();
2096 while (pidzip < 0) {
2097 /*
2098 * The fork failed. If the failure was due to a temporary
2099 * problem, then wait a short time and try it again.
2100 */
2101 errsav = errno;
2102 warn("fork() for `%s %s'", pgm_name, zwork->zw_fname);
2103 if (errsav != EAGAIN || fcount > 5)
2104 errx(1, "Exiting...");
2105 sleep(fcount * 12);
2106 fcount++;
2107 pidzip = fork();
2108 }
2109 if (!pidzip) {
2110 /* The child process executes the compression command */
2070 fcount = 1;
2071 pidzip = fork();
2072 while (pidzip < 0) {
2073 /*
2074 * The fork failed. If the failure was due to a temporary
2075 * problem, then wait a short time and try it again.
2076 */
2077 errsav = errno;
2078 warn("fork() for `%s %s'", pgm_name, zwork->zw_fname);
2079 if (errsav != EAGAIN || fcount > 5)
2080 errx(1, "Exiting...");
2081 sleep(fcount * 12);
2082 fcount++;
2083 pidzip = fork();
2084 }
2085 if (!pidzip) {
2086 /* The child process executes the compression command */
2111 execv(pgm_path, (char *const*) args);
2112 err(1, "execv(`%s')", command);
2087 execv(pgm_path, __DECONST(char *const*, args));
2088 err(1, "execv(`%s')", sbuf_data(command));
2113 }
2114
2115 wpid = waitpid(pidzip, &zstatus, 0);
2116 if (wpid == -1) {
2117 /* XXX - should this be a fatal error? */
2118 warn("%s: waitpid(%d)", pgm_path, pidzip);
2089 }
2090
2091 wpid = waitpid(pidzip, &zstatus, 0);
2092 if (wpid == -1) {
2093 /* XXX - should this be a fatal error? */
2094 warn("%s: waitpid(%d)", pgm_path, pidzip);
2119 return;
2095 goto out;
2120 }
2121 if (!WIFEXITED(zstatus)) {
2096 }
2097 if (!WIFEXITED(zstatus)) {
2122 warnx("`%s' did not terminate normally", command);
2123 free(args[0]);
2124 free(args);
2125 return;
2098 warnx("`%s' did not terminate normally", sbuf_data(command));
2099 goto out;
2126 }
2127 if (WEXITSTATUS(zstatus)) {
2100 }
2101 if (WEXITSTATUS(zstatus)) {
2128 warnx("`%s' terminated with a non-zero status (%d)", command,
2129 WEXITSTATUS(zstatus));
2130 free(args[0]);
2131 free(args);
2132 return;
2102 warnx("`%s' terminated with a non-zero status (%d)",
2103 sbuf_data(command), WEXITSTATUS(zstatus));
2104 goto out;
2133 }
2134
2105 }
2106
2135 free(args[0]);
2136 free(args);
2137 /* Compression was successful, set file attributes on the result. */
2138 change_attrs(zresult, zwork->zw_conf);
2107 /* Compression was successful, set file attributes on the result. */
2108 change_attrs(zresult, zwork->zw_conf);
2109
2110out:
2111 if (command != NULL)
2112 sbuf_delete(command);
2113 free(args);
2114 free(zresult);
2139}
2140
2141/*
2142 * Save information on any process we need to signal. Any single
2143 * process may need to be sent different signal-values for different
2144 * log files, but usually a single signal-value will cause the process
2145 * to close and re-open all of its log files.
2146 */

--- 290 unchanged lines hidden (view full) ---

2437}
2438
2439/* Return the age in hours of the most recent archive of the logfile. */
2440static int
2441age_old_log(const char *file)
2442{
2443 struct stat sb;
2444 const char *logfile_suffix;
2115}
2116
2117/*
2118 * Save information on any process we need to signal. Any single
2119 * process may need to be sent different signal-values for different
2120 * log files, but usually a single signal-value will cause the process
2121 * to close and re-open all of its log files.
2122 */

--- 290 unchanged lines hidden (view full) ---

2413}
2414
2415/* Return the age in hours of the most recent archive of the logfile. */
2416static int
2417age_old_log(const char *file)
2418{
2419 struct stat sb;
2420 const char *logfile_suffix;
2445 char tmp[MAXPATHLEN + sizeof(".0") + COMPRESS_SUFFIX_MAXLEN + 1];
2421 static unsigned int suffix_maxlen = 0;
2422 char *tmp;
2446 time_t mtime;
2423 time_t mtime;
2424 int c;
2447
2425
2426 if (suffix_maxlen == 0) {
2427 for (c = 0; c < COMPRESS_TYPES; c++)
2428 suffix_maxlen = MAX(suffix_maxlen,
2429 strlen(compress_type[c].suffix));
2430 }
2431
2432 tmp = alloca(MAXPATHLEN + sizeof(".0") + suffix_maxlen + 1);
2433
2448 if (archtodir) {
2449 char *p;
2450
2451 /* build name of archive directory into tmp */
2452 if (*archdirname == '/') { /* absolute */
2453 strlcpy(tmp, archdirname, sizeof(tmp));
2454 } else { /* relative */
2455 /* get directory part of logfile */

--- 331 unchanged lines hidden ---
2434 if (archtodir) {
2435 char *p;
2436
2437 /* build name of archive directory into tmp */
2438 if (*archdirname == '/') { /* absolute */
2439 strlcpy(tmp, archdirname, sizeof(tmp));
2440 } else { /* relative */
2441 /* get directory part of logfile */

--- 331 unchanged lines hidden ---