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 --- |