]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/log_daemon/file/log_file_daemon.cc
Merged from trunk
[thirdparty/squid.git] / helpers / log_daemon / file / log_file_daemon.cc
1 #include "squid.h"
2
3 #include <cassert>
4 #include <cerrno>
5 #include <csignal>
6 #include <cstring>
7 #if HAVE_UNISTD_H
8 #include <unistd.h>
9 #endif
10 #if HAVE_FCNTL_H
11 #include <fcntl.h>
12 #endif
13 #if HAVE_SYS_PARAM_H
14 #include <sys/param.h>
15 #endif
16 #if HAVE_SYS_STAT_H
17 #include <sys/stat.h>
18 #endif
19 #if HAVE_PATHS_H
20 #include <paths.h>
21 #endif
22
23 #include "defines.h"
24
25 /* parse buffer - ie, length of longest expected line */
26 #define LOGFILE_BUF_LEN 65536
27
28 static void
29 rotate(const char *path, int rotate_count)
30 {
31 #ifdef S_ISREG
32 struct stat sb;
33 #endif
34 int i;
35 char from[MAXPATHLEN];
36 char to[MAXPATHLEN];
37 assert(path);
38 #ifdef S_ISREG
39 if (stat(path, &sb) == 0)
40 if (S_ISREG(sb.st_mode) == 0)
41 return;
42 #endif
43 /* Rotate numbers 0 through N up one */
44 for (i = rotate_count; i > 1;) {
45 --i;
46 snprintf(from, MAXPATHLEN, "%s.%d", path, i - 1);
47 snprintf(to, MAXPATHLEN, "%s.%d", path, i);
48 #if _SQUID_OS2_ || _SQUID_WINDOWS_
49 if (remove(to) < 0) {
50 fprintf(stderr, "WARNING: remove '%s' failure: %s\n", to, xstrerror());
51 }
52 #endif
53 if (rename(from, to) < 0 && errno != ENOENT) {
54 fprintf(stderr, "WARNING: rename '%s' to '%s' failure: %s\n", from, to, xstrerror());
55 }
56 }
57 if (rotate_count > 0) {
58 snprintf(to, MAXPATHLEN, "%s.%d", path, 0);
59 #if _SQUID_OS2_ || _SQUID_WINDOWS_
60 if (remove(to) < 0) {
61 fprintf(stderr, "WARNING: remove '%s' failure: %s\n", to, xstrerror());
62 }
63 #endif
64 if (rename(path, to) < 0 && errno != ENOENT) {
65 fprintf(stderr, "WARNING: rename %s to %s failure: %s\n", path, to, xstrerror());
66 }
67 }
68 }
69
70 /**
71 * The commands:
72 *
73 * L<data>\n - logfile data
74 * R\n - rotate file
75 * T\n - truncate file
76 * O\n - repoen file
77 * F\n - flush file
78 * r<n>\n - set rotate count to <n>
79 * b<n>\n - 1 = buffer output, 0 = don't buffer output
80 */
81 int
82 main(int argc, char *argv[])
83 {
84 int t;
85 FILE *fp;
86 char buf[LOGFILE_BUF_LEN];
87 int rotate_count = 10;
88 int do_buffer = 1;
89
90 if (argc < 2) {
91 printf("Error: usage: %s <logfile>\n", argv[0]);
92 exit(1);
93 }
94 fp = fopen(argv[1], "a");
95 if (fp == NULL) {
96 perror("fopen");
97 exit(1);
98 }
99 setbuf(stdout, NULL);
100 close(2);
101 t = open(_PATH_DEVNULL, O_RDWR);
102 assert(t > -1);
103 dup2(t, 2);
104
105 while (fgets(buf, LOGFILE_BUF_LEN, stdin)) {
106 /* First byte indicates what we're logging! */
107 switch (buf[0]) {
108 case 'L':
109 if (buf[1] != '\0') {
110 fprintf(fp, "%s", buf + 1);
111 /* try to detect the 32-bit file too big write error and rotate */
112 int err = ferror(fp);
113 clearerr(fp);
114 if (err < 0) {
115 /* file too big - recover by rotating the logs and starting a new one.
116 * out of device space - recover by rotating and hoping that rotation count drops a big one.
117 */
118 if (err == EFBIG || err == ENOSPC) {
119 fprintf(stderr, "WARNING: %s writing %s. Attempting to recover via a log rotation.\n",xstrerr(err),argv[1]);
120 fclose(fp);
121 rotate(argv[1], rotate_count);
122 fp = fopen(argv[1], "a");
123 if (fp == NULL) {
124 perror("fopen");
125 exit(1);
126 }
127 fprintf(fp, "%s", buf + 1);
128 } else {
129 perror("fprintf");
130 exit(1);
131 }
132 }
133 }
134 if (!do_buffer)
135 fflush(fp);
136 break;
137 case 'R':
138 fclose(fp);
139 rotate(argv[1], rotate_count);
140 fp = fopen(argv[1], "a");
141 if (fp == NULL) {
142 perror("fopen");
143 exit(1);
144 }
145 break;
146 case 'T':
147 break;
148 case 'O':
149 break;
150 case 'r':
151 //fprintf(fp, "SET ROTATE: %s\n", buf + 1);
152 rotate_count = atoi(buf + 1);
153 break;
154 case 'b':
155 //fprintf(fp, "SET BUFFERED: %s\n", buf + 1);
156 do_buffer = (buf[1] == '1');
157 break;
158 case 'F':
159 fflush(fp);
160 break;
161 default:
162 /* Just in case .. */
163 fprintf(fp, "%s", buf);
164 break;
165 }
166 }
167 fclose(fp);
168 fp = NULL;
169 exit(0);
170 }