log_file_daemon.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10
11#include <cassert>
12#include <cerrno>
13#include <csignal>
14#include <cstring>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#if HAVE_FCNTL_H
19#include <fcntl.h>
20#endif
21#if HAVE_SYS_PARAM_H
22#include <sys/param.h>
23#endif
24#if HAVE_SYS_STAT_H
25#include <sys/stat.h>
26#endif
27#if HAVE_PATHS_H
28#include <paths.h>
29#endif
30
32
33/* parse buffer - ie, length of longest expected line */
34#define LOGFILE_BUF_LEN 65536
35
36static void
37rotate(const char *path, int rotate_count)
38{
39#ifdef S_ISREG
40 struct stat sb;
41#endif
42 int i;
43 char from[MAXPATHLEN];
44 char to[MAXPATHLEN];
45 assert(path);
46#ifdef S_ISREG
47 if (stat(path, &sb) == 0)
48 if (S_ISREG(sb.st_mode) == 0)
49 return;
50#endif
51 /* Rotate numbers 0 through N up one */
52 for (i = rotate_count; i > 1;) {
53 --i;
54 snprintf(from, MAXPATHLEN, "%s.%d", path, i - 1);
55 snprintf(to, MAXPATHLEN, "%s.%d", path, i);
56#if _SQUID_OS2_ || _SQUID_WINDOWS_
57 if (remove(to) < 0) {
58 int xerrno = errno;
59 fprintf(stderr, "WARNING: remove '%s' failure: %s\n", to, xstrerr(xerrno));
60 }
61#endif
62 if (rename(from, to) < 0 && errno != ENOENT) {
63 int xerrno = errno;
64 fprintf(stderr, "WARNING: rename '%s' to '%s' failure: %s\n", from, to, xstrerr(xerrno));
65 }
66 }
67 if (rotate_count > 0) {
68 snprintf(to, MAXPATHLEN, "%s.%d", path, 0);
69#if _SQUID_OS2_ || _SQUID_WINDOWS_
70 if (remove(to) < 0) {
71 int xerrno = errno;
72 fprintf(stderr, "WARNING: remove '%s' failure: %s\n", to, xstrerr(xerrno));
73 }
74#endif
75 if (rename(path, to) < 0 && errno != ENOENT) {
76 int xerrno = errno;
77 fprintf(stderr, "WARNING: rename %s to %s failure: %s\n", path, to, xstrerr(xerrno));
78 }
79 }
80}
81
93int
94main(int argc, char *argv[])
95{
96 int t;
97 FILE *fp;
98 char buf[LOGFILE_BUF_LEN];
99 int rotate_count = 10;
100 int do_buffer = 1;
101
102 if (argc < 2) {
103 printf("Error: usage: %s <logfile>\n", argv[0]);
104 exit(EXIT_FAILURE);
105 }
106 fp = fopen(argv[1], "a");
107 if (fp == nullptr) {
108 perror("fopen");
109 exit(EXIT_FAILURE);
110 }
111 setbuf(stdout, nullptr);
112 /* XXX stderr should not be closed, but in order to support squid must be
113 * able to collect and manage modules' stderr first.
114 */
115 close(2);
116 t = open(_PATH_DEVNULL, O_RDWR);
117 assert(t > -1);
118 dup2(t, 2);
119
120 while (fgets(buf, LOGFILE_BUF_LEN, stdin)) {
121 /* First byte indicates what we're logging! */
122 switch (buf[0]) {
123 case 'L':
124 if (buf[1] != '\0') {
125 fprintf(fp, "%s", buf + 1);
126 /* try to detect the 32-bit file too big write error and rotate */
127 int err = ferror(fp);
128 clearerr(fp);
129 if (err != 0) {
130 /* file too big - recover by rotating the logs and starting a new one.
131 * out of device space - recover by rotating and hoping that rotation count drops a big one.
132 */
133 if (err == EFBIG || err == ENOSPC) {
134 fprintf(stderr, "WARNING: %s writing %s. Attempting to recover via a log rotation.\n",xstrerr(err),argv[1]);
135 fclose(fp);
136 rotate(argv[1], rotate_count);
137 fp = fopen(argv[1], "a");
138 if (fp == nullptr) {
139 perror("fopen");
140 exit(EXIT_FAILURE);
141 }
142 fprintf(fp, "%s", buf + 1);
143 } else {
144 perror("fprintf");
145 exit(EXIT_FAILURE);
146 }
147 }
148 }
149 if (!do_buffer)
150 fflush(fp);
151 break;
152 case 'R':
153 fclose(fp);
154 rotate(argv[1], rotate_count);
155 fp = fopen(argv[1], "a");
156 if (fp == nullptr) {
157 perror("fopen");
158 exit(EXIT_FAILURE);
159 }
160 break;
161 case 'T':
162 break;
163 case 'O':
164 break;
165 case 'r':
166 //fprintf(fp, "SET ROTATE: %s\n", buf + 1);
167 rotate_count = atoi(buf + 1);
168 break;
169 case 'b':
170 //fprintf(fp, "SET BUFFERED: %s\n", buf + 1);
171 do_buffer = (buf[1] == '1');
172 break;
173 case 'F':
174 fflush(fp);
175 break;
176 default:
177 /* Just in case .. */
178 fprintf(fp, "%s", buf);
179 break;
180 }
181 }
182 fclose(fp);
183 fp = nullptr;
184 return EXIT_SUCCESS;
185}
186
#define assert(EX)
Definition: assert.h:17
int main(int argc, char *argv[])
static void rotate(const char *path, int rotate_count)
#define LOGFILE_BUF_LEN
static struct stat sb
Definition: squidclient.cc:71
#define MAXPATHLEN
Definition: stdio.h:62
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors