newsyslog.c (3c0f0ccce76efc877c8d68a1233878a202b05c5e) newsyslog.c (2f8d7c56da1ce2c5069fab78876cc6a90b343cfa)
1/*
2 * This file contains changes from the Open Software Foundation.
3 */
4
5/*
6 * Copyright 1988, 1989 by the Massachusetts Institute of Technology
7 *
8 * Permission to use, copy, modify, and distribute this software and its

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

50#include <signal.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <time.h>
55#include <unistd.h>
56
57#include "pathnames.h"
1/*
2 * This file contains changes from the Open Software Foundation.
3 */
4
5/*
6 * Copyright 1988, 1989 by the Massachusetts Institute of Technology
7 *
8 * Permission to use, copy, modify, and distribute this software and its

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

50#include <signal.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <time.h>
55#include <unistd.h>
56
57#include "pathnames.h"
58#include "extern.h"
58
59/*
60 * Bit-values for the 'flags' parsed from a config-file entry.
61 */
62#define CE_COMPACT 0x0001 /* Compact the achived log files with gzip. */
63#define CE_BZCOMPACT 0x0002 /* Compact the achived log files with bzip2. */
64#define CE_COMPACTWAIT 0x0004 /* wait until compressing one file finishes */
65 /* before starting the next step. */

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

144static void bzcompress_log(char *logname, int dowait);
145static int sizefile(char *file);
146static int age_old_log(char *file);
147static int send_signal(const struct conf_entry *ent);
148static void movefile(char *from, char *to, int perm, uid_t owner_uid,
149 gid_t group_gid);
150static void createdir(const struct conf_entry *ent, char *dirpart);
151static void createlog(const struct conf_entry *ent);
59
60/*
61 * Bit-values for the 'flags' parsed from a config-file entry.
62 */
63#define CE_COMPACT 0x0001 /* Compact the achived log files with gzip. */
64#define CE_BZCOMPACT 0x0002 /* Compact the achived log files with bzip2. */
65#define CE_COMPACTWAIT 0x0004 /* wait until compressing one file finishes */
66 /* before starting the next step. */

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

145static void bzcompress_log(char *logname, int dowait);
146static int sizefile(char *file);
147static int age_old_log(char *file);
148static int send_signal(const struct conf_entry *ent);
149static void movefile(char *from, char *to, int perm, uid_t owner_uid,
150 gid_t group_gid);
151static void createdir(const struct conf_entry *ent, char *dirpart);
152static void createlog(const struct conf_entry *ent);
152static time_t parse8601(const char *s);
153static time_t parseDWM(char *s);
154
155/*
156 * All the following are defined to work on an 'int', in the
157 * range 0 to 255, plus EOF. Define wrappers which can take
158 * values of type 'char', either signed or unsigned.
159 */
160#define isdigitch(Anychar) isdigit(((int) Anychar) & 255)
161#define isprintch(Anychar) isprint(((int) Anychar) & 255)

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

592{
593 const char TN[] = "TN=";
594
595 if (strncmp(doption, TN, sizeof(TN) - 1) == 0) {
596 /*
597 * The "TimeNow" debugging option. This probably will
598 * be off by an hour when crossing a timezone change.
599 */
153
154/*
155 * All the following are defined to work on an 'int', in the
156 * range 0 to 255, plus EOF. Define wrappers which can take
157 * values of type 'char', either signed or unsigned.
158 */
159#define isdigitch(Anychar) isdigit(((int) Anychar) & 255)
160#define isprintch(Anychar) isprint(((int) Anychar) & 255)

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

591{
592 const char TN[] = "TN=";
593
594 if (strncmp(doption, TN, sizeof(TN) - 1) == 0) {
595 /*
596 * The "TimeNow" debugging option. This probably will
597 * be off by an hour when crossing a timezone change.
598 */
600 dbg_timenow = parse8601(doption + sizeof(TN) - 1);
599 dbg_timenow = parse8601(doption + sizeof(TN) - 1, NULL);
601 if (dbg_timenow == (time_t)-1) {
602 warnx("Malformed time given on -D %s", doption);
603 return (0); /* failure */
604 }
605 if (dbg_timenow == (time_t)-2) {
606 warnx("Non-existent time specified on -D %s", doption);
607 return (0); /* failure */
608 }

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

1032 errx(1, "interval is too large:\n%s", errline);
1033 else
1034 working->hours = ul;
1035
1036 if (*ep != '\0' && *ep != '@' && *ep != '*' &&
1037 *ep != '$')
1038 errx(1, "malformed interval/at:\n%s", errline);
1039 if (*ep == '@') {
600 if (dbg_timenow == (time_t)-1) {
601 warnx("Malformed time given on -D %s", doption);
602 return (0); /* failure */
603 }
604 if (dbg_timenow == (time_t)-2) {
605 warnx("Non-existent time specified on -D %s", doption);
606 return (0); /* failure */
607 }

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

1031 errx(1, "interval is too large:\n%s", errline);
1032 else
1033 working->hours = ul;
1034
1035 if (*ep != '\0' && *ep != '@' && *ep != '*' &&
1036 *ep != '$')
1037 errx(1, "malformed interval/at:\n%s", errline);
1038 if (*ep == '@') {
1040 working->trim_at = parse8601(ep + 1);
1039 working->trim_at = parse8601(ep + 1, NULL);
1041 working->flags |= CE_TRIMAT;
1042 } else if (*ep == '$') {
1040 working->flags |= CE_TRIMAT;
1041 } else if (*ep == '$') {
1043 working->trim_at = parseDWM(ep + 1);
1042 working->trim_at = parseDWM(ep + 1, NULL);
1044 working->flags |= CE_TRIMAT;
1045 }
1046 if (working->flags & CE_TRIMAT) {
1047 if (working->trim_at == (time_t)-1)
1048 errx(1, "malformed at:\n%s", errline);
1049 if (working->trim_at == (time_t)-2)
1050 errx(1, "nonexistent time:\n%s",
1051 errline);

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

1774 failed = rename(tempfile, realfile);
1775 if (failed)
1776 err(1, "can't mv %s to %s", tempfile, realfile);
1777 }
1778
1779 if (fd >= 0)
1780 close(fd);
1781}
1043 working->flags |= CE_TRIMAT;
1044 }
1045 if (working->flags & CE_TRIMAT) {
1046 if (working->trim_at == (time_t)-1)
1047 errx(1, "malformed at:\n%s", errline);
1048 if (working->trim_at == (time_t)-2)
1049 errx(1, "nonexistent time:\n%s",
1050 errline);

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

1773 failed = rename(tempfile, realfile);
1774 if (failed)
1775 err(1, "can't mv %s to %s", tempfile, realfile);
1776 }
1777
1778 if (fd >= 0)
1779 close(fd);
1780}
1782
1783/*-
1784 * Parse a limited subset of ISO 8601. The specific format is as follows:
1785 *
1786 * [CC[YY[MM[DD]]]][THH[MM[SS]]] (where `T' is the literal letter)
1787 *
1788 * We don't accept a timezone specification; missing fields (including timezone)
1789 * are defaulted to the current date but time zero.
1790 */
1791static time_t
1792parse8601(const char *s)
1793{
1794 char *t;
1795 time_t tsecs;
1796 struct tm tm, *tmp;
1797 long l;
1798
1799 tmp = localtime(&timenow);
1800 tm = *tmp;
1801
1802 tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
1803
1804 l = strtol(s, &t, 10);
1805 if (l < 0 || l >= INT_MAX || (*t != '\0' && *t != 'T'))
1806 return (-1);
1807
1808 /*
1809 * Now t points either to the end of the string (if no time was
1810 * provided) or to the letter `T' which separates date and time in
1811 * ISO 8601. The pointer arithmetic is the same for either case.
1812 */
1813 switch (t - s) {
1814 case 8:
1815 tm.tm_year = ((l / 1000000) - 19) * 100;
1816 l = l % 1000000;
1817 case 6:
1818 tm.tm_year -= tm.tm_year % 100;
1819 tm.tm_year += l / 10000;
1820 l = l % 10000;
1821 case 4:
1822 tm.tm_mon = (l / 100) - 1;
1823 l = l % 100;
1824 case 2:
1825 tm.tm_mday = l;
1826 case 0:
1827 break;
1828 default:
1829 return (-1);
1830 }
1831
1832 /* sanity check */
1833 if (tm.tm_year < 70 || tm.tm_mon < 0 || tm.tm_mon > 12
1834 || tm.tm_mday < 1 || tm.tm_mday > 31)
1835 return (-1);
1836
1837 if (*t != '\0') {
1838 s = ++t;
1839 l = strtol(s, &t, 10);
1840 if (l < 0 || l >= INT_MAX || (*t != '\0' && !isspace(*t)))
1841 return (-1);
1842
1843 switch (t - s) {
1844 case 6:
1845 tm.tm_sec = l % 100;
1846 l /= 100;
1847 case 4:
1848 tm.tm_min = l % 100;
1849 l /= 100;
1850 case 2:
1851 tm.tm_hour = l;
1852 case 0:
1853 break;
1854 default:
1855 return (-1);
1856 }
1857
1858 /* sanity check */
1859 if (tm.tm_sec < 0 || tm.tm_sec > 60 || tm.tm_min < 0
1860 || tm.tm_min > 59 || tm.tm_hour < 0 || tm.tm_hour > 23)
1861 return (-1);
1862 }
1863
1864 tsecs = mktime(&tm);
1865 /*
1866 * Check for invalid times, including things like the missing
1867 * hour when switching from "standard time" to "daylight saving".
1868 */
1869 if (tsecs == (time_t)-1)
1870 tsecs = (time_t)-2;
1871 return (tsecs);
1872}
1873
1874/*-
1875 * Parse a cyclic time specification, the format is as follows:
1876 *
1877 * [Dhh] or [Wd[Dhh]] or [Mdd[Dhh]]
1878 *
1879 * to rotate a logfile cyclic at
1880 *
1881 * - every day (D) within a specific hour (hh) (hh = 0...23)
1882 * - once a week (W) at a specific day (d) OR (d = 0..6, 0 = Sunday)
1883 * - once a month (M) at a specific day (d) (d = 1..31,l|L)
1884 *
1885 * We don't accept a timezone specification; missing fields
1886 * are defaulted to the current date but time zero.
1887 */
1888static time_t
1889parseDWM(char *s)
1890{
1891 char *t;
1892 time_t tsecs;
1893 struct tm tm, *tmp;
1894 long l;
1895 int nd;
1896 static int mtab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1897 int WMseen = 0;
1898 int Dseen = 0;
1899
1900 tmp = localtime(&timenow);
1901 tm = *tmp;
1902
1903 /* set no. of days per month */
1904
1905 nd = mtab[tm.tm_mon];
1906
1907 if (tm.tm_mon == 1) {
1908 if (((tm.tm_year + 1900) % 4 == 0) &&
1909 ((tm.tm_year + 1900) % 100 != 0) &&
1910 ((tm.tm_year + 1900) % 400 == 0)) {
1911 nd++; /* leap year, 29 days in february */
1912 }
1913 }
1914 tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
1915
1916 for (;;) {
1917 switch (*s) {
1918 case 'D':
1919 if (Dseen)
1920 return (-1);
1921 Dseen++;
1922 s++;
1923 l = strtol(s, &t, 10);
1924 if (l < 0 || l > 23)
1925 return (-1);
1926 tm.tm_hour = l;
1927 break;
1928
1929 case 'W':
1930 if (WMseen)
1931 return (-1);
1932 WMseen++;
1933 s++;
1934 l = strtol(s, &t, 10);
1935 if (l < 0 || l > 6)
1936 return (-1);
1937 if (l != tm.tm_wday) {
1938 int save;
1939
1940 if (l < tm.tm_wday) {
1941 save = 6 - tm.tm_wday;
1942 save += (l + 1);
1943 } else {
1944 save = l - tm.tm_wday;
1945 }
1946
1947 tm.tm_mday += save;
1948
1949 if (tm.tm_mday > nd) {
1950 tm.tm_mon++;
1951 tm.tm_mday = tm.tm_mday - nd;
1952 }
1953 }
1954 break;
1955
1956 case 'M':
1957 if (WMseen)
1958 return (-1);
1959 WMseen++;
1960 s++;
1961 if (tolower(*s) == 'l') {
1962 tm.tm_mday = nd;
1963 s++;
1964 t = s;
1965 } else {
1966 l = strtol(s, &t, 10);
1967 if (l < 1 || l > 31)
1968 return (-1);
1969
1970 if (l > nd)
1971 return (-1);
1972 tm.tm_mday = l;
1973 }
1974 break;
1975
1976 default:
1977 return (-1);
1978 break;
1979 }
1980
1981 if (*t == '\0' || isspace(*t))
1982 break;
1983 else
1984 s = t;
1985 }
1986
1987 tsecs = mktime(&tm);
1988 /*
1989 * Check for invalid times, including things like the missing
1990 * hour when switching from "standard time" to "daylight saving".
1991 */
1992 if (tsecs == (time_t)-1)
1993 tsecs = (time_t)-2;
1994 return (tsecs);
1995}