1: /*
2: * $Id: log.c,v 1.10 2025/04/15 14:39:06 snw Exp $
3: * freem error logging
4: *
5: *
6: * Author: Serena Willis <snw@coherent-logic.com>
7: * Copyright (C) 1998 MUG Deutschland
8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
26: * $Log: log.c,v $
27: * Revision 1.10 2025/04/15 14:39:06 snw
28: * Further improvements to logging
29: *
30: * Revision 1.9 2025/04/15 02:24:43 snw
31: * Improve FreeM logging capabilities
32: *
33: * Revision 1.8 2025/04/04 02:12:25 snw
34: * Bump to 0.63.0-rc5 and make sure m_log function is never empty
35: *
36: * Revision 1.7 2025/04/04 01:18:21 snw
37: * Remove vestigial logging code and bump to 0.63.0-rc4
38: *
39: * Revision 1.6 2025/04/01 23:21:45 snw
40: * fmadm commands for stopping, starting, and restarting environments now functional
41: *
42: * Revision 1.5 2025/04/01 20:11:46 snw
43: * Further work on fmadm
44: *
45: * Revision 1.4 2025/03/09 19:50:47 snw
46: * Second phase of REUSE compliance and header reformat
47: *
48: *
49: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
50: * SPDX-License-Identifier: AGPL-3.0-or-later
51: **/
52:
53: #include <stdio.h>
54: #include <string.h>
55: #if defined(__linux__) | defined(__FreeBSD__) | defined(__sun__)
56: # include <syslog.h>
57: #endif
58: #include <stdlib.h>
59: #include <stdarg.h>
60:
61: #if defined(USE_SYS_TIME_H) && !defined(MSDOS) && !defined(__osf__)
62: # include <sys/time.h>
63: #else
64: # include <time.h>
65: #endif
66:
67: #include "mpsdef.h"
68:
69: short log_threshold_file;
70: short log_threshold_syslog;
71: short log_threshold_stderr;
72:
73:
74: void init_log(void)
75: {
76: log_threshold_file = LOG_INFO;
77: log_threshold_syslog = LOG_INFO;
78: log_threshold_stderr = LOG_WARNING;
79: }
80:
81: void log_level_to_text(int level, char *buf)
82: {
83: switch (level) {
84:
85: case LOG_DEBUG:
86: sprintf (buf, "DEBUG");
87: break;
88:
89: case LOG_INFO:
90: sprintf (buf, "INFO");
91: break;
92:
93: case LOG_WARNING:
94: sprintf (buf, "WARNING");
95: break;
96:
97: case LOG_ERROR:
98: sprintf (buf, "ERROR");
99: break;
100:
101: case LOG_FATAL:
102: sprintf (buf, "FATAL");
103: break;
104:
105: default:
106: sprintf (buf, "LEVEL %d", level);
107: break;
108:
109: }
110: }
111:
112: void m_log(int level, const char *msg)
113: {
114:
115: FILE *fp;
116: time_t unix_epoch;
117: char timeval[255];
118: char filename[4096];
119: char lvl[20];
120: struct tm *logtime;
121:
122: log_level_to_text (level, lvl);
123:
124: if (level >= log_threshold_file) {
125: snprintf (filename, sizeof (filename) - 1, "/var/log/freem/%s.log", shm_env);
126:
127: if ((fp = fopen (filename, "a+")) != NULL) {
128: unix_epoch = time (0L);
129: logtime = localtime (&unix_epoch);
130: strftime (timeval, sizeof (timeval) - 1, "%F %T", logtime);
131: fprintf (fp, "%s [LEVEL %s PID %ld]: %s\n", timeval, lvl, pid, msg);
132: fclose (fp);
133: }
134: }
135:
136: #if defined(__linux__) | defined(__FreeBSD__) | defined(__sun__)
137: if (level >= log_threshold_syslog) {
138: syslog (level, "%s", msg);
139: }
140: #endif
141:
142: if (level >= log_threshold_stderr) fprintf (stderr, "%s\r\n", msg);
143:
144: if (level >= LOG_FATAL) {
145: cleanup ();
146: exit (LOG_FATAL);
147: }
148:
149: return;
150: }
151:
152: void logprintf(int level, char *fmt, ...)
153: {
154: va_list ptr;
155: va_start (ptr, fmt);
156:
157: char logmsg[BIGSTR];
158: char tmps[BIGSTR];
159:
160: char ch;
161: char typ;
162: char subtyp;
163:
164: register int i;
165:
166: for (i = 0; fmt[i] != '\0'; i++) {
167: ch = fmt[i];
168:
169: switch (ch) {
170:
171: case '%':
172: typ = fmt[++i];
173:
174: switch (typ) {
175:
176: case '%': /* literal percent sign */
177: strcat (logmsg, "%");
178: break;
179:
180: case 'c': /* char */
181: sprintf (tmps, "%c", va_arg (ptr, int));
182: strcat (logmsg, tmps);
183: break;
184:
185: case 's': /* C string */
186: strcat (logmsg, va_arg (ptr, char *));
187: break;
188:
189: case 'S': /* FreeM string */
190: stcpy (tmps, va_arg (ptr, char *));
191: stcnv_m2c (tmps);
192: strcat (logmsg, tmps);
193: break;
194:
195: case 'd': /* int */
196: sprintf (tmps, "%d", va_arg (ptr, int));
197: strcat (logmsg, tmps);
198: break;
199:
200: case 'l': /* long... */
201: subtyp = fmt[++i];
202: switch (subtyp) {
203:
204: case 'd': /* long int */
205: sprintf (tmps, "%ld", va_arg (ptr, long));
206: strcat (logmsg, tmps);
207: break;
208:
209: case 'f': /* float */
210: sprintf (tmps, "%lf", va_arg (ptr, double));
211: strcat (logmsg, tmps);
212: break;
213:
214: }
215: break;
216: }
217:
218: case '\\':
219: typ = fmt[++i];
220: switch (typ) {
221: case 'n':
222: sprintf (tmps, "\n");
223: strcat (logmsg, tmps);
224: break;
225:
226: case 'r':
227: sprintf (tmps, "\r");
228: strcat (logmsg, tmps);
229: break;
230:
231: case 't':
232: sprintf (tmps, "\t");
233: strcat (logmsg, tmps);
234: break;
235:
236: case '\\':
237: sprintf (tmps, "\\");
238: strcat (logmsg, tmps);
239: break;
240: }
241:
242: default:
243: sprintf (tmps, "%c", ch);
244: strcat (logmsg, tmps);
245: break;
246: }
247: }
248:
249: m_log (level, logmsg);
250:
251: va_end (ptr);
252: return;
253: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>