/[LeafOK_CVS]/lbbs/src/log.c
ViewVC logotype

Contents of /lbbs/src/log.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.39 - (show annotations)
Sat Jan 3 10:27:14 2026 UTC (2 months, 1 week ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.38: +1 -1 lines
Content type: text/x-csrc
Update copyright info

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * log
4 * - logger
5 *
6 * Copyright (C) 2004-2026 Leaflet <leaflet@leafok.com>
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "common.h"
14 #include "io.h"
15 #include "log.h"
16 #include <errno.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include <time.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22
23 enum _log_constant_t
24 {
25 STR_LOG_TIME_MAX_LEN = 50,
26 };
27
28 static char path_common_log[FILE_PATH_LEN];
29 static char path_error_log[FILE_PATH_LEN];
30 static FILE *fp_common_log = NULL;
31 static FILE *fp_error_log = NULL;
32 static int redir_common_log = 0;
33 static int redir_error_log = 0;
34
35 int log_begin(const char *common_log_file, const char *error_log_file)
36 {
37 strncpy(path_common_log, common_log_file, sizeof(path_common_log) - 1);
38 path_common_log[sizeof(path_common_log) - 1] = '\0';
39 strncpy(path_error_log, error_log_file, sizeof(path_error_log) - 1);
40 path_error_log[sizeof(path_error_log) - 1] = '\0';
41
42 fp_common_log = fopen(path_common_log, "a");
43 if (fp_common_log == NULL)
44 {
45 fprintf(stderr, "fopen(%s) error: %s\n", path_common_log, strerror(errno));
46 return -1;
47 }
48
49 fp_error_log = fopen(path_error_log, "a");
50 if (fp_error_log == NULL)
51 {
52 fprintf(stderr, "fopen(%s) error: %s\n", path_error_log, strerror(errno));
53 fclose(fp_common_log);
54 fp_common_log = NULL;
55 return -2;
56 }
57
58 redir_common_log = 0;
59 redir_error_log = 0;
60
61 return 0;
62 }
63
64 void log_end()
65 {
66 if (fp_common_log)
67 {
68 fclose(fp_common_log);
69 fp_common_log = NULL;
70 }
71 if (fp_error_log)
72 {
73 fclose(fp_error_log);
74 fp_error_log = NULL;
75 }
76 }
77
78 inline static int log_head(char *buf, size_t len, int log_level, const char *app_file, int app_line)
79 {
80 time_t t;
81 struct tm gm_tm;
82 char s_time[STR_LOG_TIME_MAX_LEN + 1];
83 int ret;
84
85 time(&t);
86 gmtime_r(&t, &gm_tm);
87 strftime(s_time, sizeof(s_time), "%Y-%m-%d %H:%M:%S", &gm_tm);
88
89 if (log_level == LOG_LEVEL_COMMON)
90 {
91 ret = snprintf(buf, len, "[%s] [%d] [INFO] ", s_time, getpid());
92 }
93 else if (log_level == LOG_LEVEL_ERROR)
94 {
95 ret = snprintf(buf, len, "[%s] [%d] [ERROR] [%s:%d] ", s_time, getpid(), app_file, app_line);
96 }
97 else // if (log_level == LOG_LEVEL_DEBUG)
98 {
99 ret = snprintf(buf, len, "[%s] [%d] [DEBUG] [%s:%d] ", s_time, getpid(), app_file, app_line);
100 }
101
102 return ret;
103 }
104
105 int log_printf(enum log_level_t log_level, const char *app_file, int app_line, const char *format, ...)
106 {
107 va_list args;
108 char buf[LINE_BUFFER_LEN];
109 FILE *fp_log;
110 int offset;
111 int ret;
112
113 fp_log = (log_level == LOG_LEVEL_COMMON ? fp_common_log : fp_error_log);
114
115 offset = log_head(buf, sizeof(buf), log_level, app_file, app_line);
116
117 va_start(args, format);
118 ret = vsnprintf(buf + offset, sizeof(buf) - (size_t)offset, format, args);
119 va_end(args);
120
121 if (ret < 0)
122 {
123 // Encoding error
124 return -1;
125 }
126 else if (offset + ret + 1 >= sizeof(buf))
127 {
128 buf[sizeof(buf) - 2] = '\n'; // Add newline for truncated messages
129 buf[sizeof(buf) - 1] = '\0'; // Ensure null termination
130 if (fputs(buf, fp_log) == EOF)
131 {
132 return -3; // Write error
133 }
134 ret = -2; // Indicate truncation
135 }
136 else
137 {
138 buf[offset + ret] = '\n'; // Add newline
139 buf[offset + ret + 1] = '\0'; // Ensure null termination
140 if (fputs(buf, fp_log) == EOF)
141 {
142 return -3; // Write error
143 }
144 ret = offset + ret + 1; // Return number of characters written (including newline)
145 }
146
147 if (fflush(fp_log) == EOF)
148 {
149 return -4; // Flush error
150 }
151
152 return ret;
153 }
154
155 int log_common_redir(int fd)
156 {
157 redir_common_log = 1;
158 return dup2(fd, fileno(fp_common_log));
159 }
160
161 int log_error_redir(int fd)
162 {
163 redir_error_log = 1;
164 return dup2(fd, fileno(fp_error_log));
165 }
166
167 int log_restart(void)
168 {
169 FILE *fp_common = NULL;
170 FILE *fp_error = NULL;
171
172 if (!redir_common_log)
173 {
174 fp_common = fopen(path_common_log, "a");
175 if (fp_common == NULL)
176 {
177 log_error("fopen(%s) error: %s", path_common_log, strerror(errno));
178 return -1;
179 }
180 }
181
182 if (!redir_error_log)
183 {
184 fp_error = fopen(path_error_log, "a");
185 if (fp_error == NULL)
186 {
187 log_error("fopen(%s) error: %s", path_error_log, strerror(errno));
188 if (fp_common)
189 {
190 fclose(fp_common);
191 }
192 return -2;
193 }
194 }
195
196 // Apply new file pointers
197 if (fp_common)
198 {
199 fclose(fp_common_log);
200 fp_common_log = fp_common;
201 }
202 if (fp_error)
203 {
204 fclose(fp_error_log);
205 fp_error_log = fp_error;
206 }
207
208 return 0;
209 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1