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