1 /************************************************************************
2 * IRC - Internet Relay Chat, src/ircd_log.c
3 * Copyright (C) 1999 Thomas Helvey (BleepSoft)
5 * See file AUTHORS in IRC package for additional names of
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 1, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "ircd_snprintf.h"
28 #include "ircd_string.h"
38 #include <sys/types.h>
44 #define LOG_BUFSIZE 2048
46 /* These constants are present even if we don't use syslog */
54 # define LOG_WARNING 0
63 /* Map severity levels to strings and syslog levels */
64 static struct LevelData {
69 #define L(level, syslog) { L_ ## level, #level, (syslog) }
72 L(WARNING, LOG_WARNING),
73 L(NOTICE, LOG_NOTICE),
81 /* Descriptions of all logging subsystems */
82 static struct LogDesc {
83 enum LogSys subsys; /* number for subsystem */
84 char *name; /* subsystem name */
85 struct LogFile *file; /* file descriptor for subsystem */
86 int facility; /* -1 means don't use syslog */
88 #define S(system, defprio) { LS_ ## system, #system, 0, (defprio) }
91 { LS_LAST_SYSTEM, 0, 0, -1 }
95 struct LogFile *next; /* next log file descriptor */
96 int fd; /* file's descriptor-- -1 if not open */
97 char *file; /* file name */
100 static struct LogFile *logFileList = 0; /* list of log files */
102 static const char *procname = "ircd"; /* process's name */
104 static int logLevel = L_INFO;
107 static int sysLogLevel[] = {
118 void ircd_log(int priority, const char* fmt, ...)
120 #if defined(USE_SYSLOG) || defined(DEBUGMODE)
121 char buf[LOG_BUFSIZE];
123 assert(-1 < priority);
124 assert(priority < L_LAST_LEVEL);
127 if (priority > logLevel)
131 vsprintf(buf, fmt, args);
135 syslog(sysLogLevel[priority], "%s", buf);
138 Debug((DEBUG_INFO, "LOG: %s", buf));
142 void open_log(const char* process_name)
145 if (EmptyString(process_name))
146 process_name = "ircd";
147 openlog(process_name, LOG_PID | LOG_NDELAY, LOG_USER);
158 void set_log_level(int level)
160 if (L_ERROR < level && level < L_LAST_LEVEL)
164 int get_log_level(void)
170 * ircd_log_kill - log information about a kill
172 void ircd_log_kill(const struct Client* victim, const struct Client* killer,
173 const char* inpath, const char* path)
175 if (MyUser(victim)) {
177 * get more infos when your local clients are killed -- _dl
179 if (IsServer(killer))
181 "A local client %s!%s@%s KILLED from %s [%s] Path: %s!%s)",
182 victim->name, victim->user->username, victim->user->host,
183 killer->name, killer->name, inpath, path);
186 "A local client %s!%s@%s KILLED by %s [%s!%s@%s] (%s!%s)",
187 victim->name, victim->user->username, victim->user->host,
188 killer->name, killer->name, killer->user->username, killer->user->host,
192 ircd_log(L_TRACE, "KILL From %s For %s Path %s!%s",
193 killer->name, victim->name, inpath, path);
198 log_init(const char *process_name)
200 /* store the process name; probably belongs in ircd.c, but oh well... */
201 if (!EmptyString(process_name))
202 procname = process_name;
205 /* ok, open syslog; default facility: LOG_USER */
206 openlog(procname, LOG_PID | LOG_NDELAY, LOG_USER);
213 log_close(); /* close everything...we reopen on demand */
216 /* reopen syslog, if needed; default facility: LOG_USER */
217 openlog(procname, LOG_PID | LOG_NDELAY, LOG_USER);
221 /* close the log files */
228 closelog(); /* close syslog */
231 for (ptr = logFileList; ptr; ptr = ptr->next) {
240 log_open(struct LogFile *lf)
242 /* only open the file if we haven't already */
243 if (lf && lf->fd < 0) {
245 lf->fd = open(lf->file, O_WRONLY | O_CREAT | O_APPEND,
251 /* This writes an entry to a log file */
253 log_write(enum LogSys subsys, enum LogLevel severity, const char *fmt, ...)
256 struct LogDesc *desc;
257 struct LevelData *ldata;
259 struct iovec vector[3];
261 char buf[LOG_BUFSIZE];
262 /* 1234567890123456789012 3 */
263 /* [2000-11-28 16:11:20] \0 */
266 /* check basic assumptions */
268 assert(subsys < LS_LAST_SYSTEM);
269 assert(-1 < severity);
270 assert(severity < L_LAST_LEVEL);
273 /* find the log data and the severity data */
274 desc = &logDesc[subsys];
275 ldata = &levelData[severity];
277 /* check the set of ordering assumptions */
278 assert(desc->subsys == subsys);
279 assert(ldata->level == severity);
281 /* if we don't have anything to log to, short-circuit */
284 && desc->facility < 0
289 /* Build the basic log string */
291 va_start(vd.vd_args, fmt);
293 /* save the length for writev */
294 /* Log format: "SYSTEM [SEVERITY] log message */
296 ircd_snprintf(0, buf, sizeof(buf), "%s [%s] %v", desc->name,
297 ldata->string, &vd) - 1;
301 /* open the log file if we haven't already */
302 log_open(desc->file);
303 /* if we have something to write to... */
304 if (desc->file && desc->file->fd >= 0) {
306 tstamp = localtime(&curtime); /* build the timestamp */
309 ircd_snprintf(0, timebuf, sizeof(timebuf), "[%d-%d-%d %d:%02d:%02d] ",
310 tstamp->tm_year + 1900, tstamp->tm_mon + 1,
311 tstamp->tm_mday, tstamp->tm_hour, tstamp->tm_min,
314 /* set up the remaining parts of the writev vector... */
315 vector[0].iov_base = timebuf;
316 vector[1].iov_base = buf;
318 vector[2].iov_base = "\n"; /* terminate lines with a \n */
319 vector[2].iov_len = 1;
321 /* write it out to the log file */
322 writev(desc->file->fd, vector, 3);
326 /* oh yeah, syslog it too... */
327 if (desc->facility >= 0)
328 syslog(ldata->syslog | desc->facility, "%s", buf);