]>
jfr.im git - irc/quakenet/snircd.git/blob - ircd/ircd_log.c
1 /************************************************************************
2 * IRC - Internet Relay Chat, src/ircd_log.c
3 * Copyright (C) 1999 Thomas Helvey (BleepSoft)
4 * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
6 * See file AUTHORS in IRC package for additional names of
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * @brief IRC logging implementation.
25 * @version $Id: ircd_log.c,v 1.22.2.1 2006/02/16 03:49:54 entrope Exp $
31 #include "ircd_alloc.h"
32 #include "ircd_reply.h"
33 #include "ircd_snprintf.h"
34 #include "ircd_string.h"
41 /* #include <assert.h> -- Now using assert in ircd_log.h */
49 #include <sys/types.h>
57 #define LOG_BUFSIZE 2048 /**< Maximum length for a log message. */
59 /** Select default log level cutoff. */
61 # define L_DEFAULT L_DEBUG
63 # define L_DEFAULT L_INFO
66 #define LOG_DOSYSLOG 0x10 /**< Try to use syslog. */
67 #define LOG_DOFILELOG 0x20 /**< Try to log to a file. */
68 #define LOG_DOSNOTICE 0x40 /**< Try to notify operators via notice. */
69 /** Bitmask of valid delivery mechanisms. */
70 #define LOG_DOMASK (LOG_DOSYSLOG | LOG_DOFILELOG | LOG_DOSNOTICE)
72 /** Map severity levels to strings and syslog levels */
73 static struct LevelData
{
74 enum LogLevel level
; /**< Log level being described. */
75 char *string
; /**< Textual name of level. */
76 int syslog
; /**< Syslog priority for log level. */
77 unsigned int snomask
; /**< Server notice mask; 0 means use default in LogDesc. */
79 #define L(level, syslog, mask) { L_ ## level, #level, (syslog), (mask) }
80 L(CRIT
, LOG_CRIT
, SNO_OLDSNO
),
82 L(WARNING
, LOG_WARNING
, 0),
83 L(NOTICE
, LOG_NOTICE
, 0),
84 L(TRACE
, LOG_INFO
, 0),
86 L(DEBUG
, LOG_INFO
, SNO_DEBUG
),
88 { L_LAST_LEVEL
, 0, 0, 0 }
91 /* Just in case some implementation of syslog has them... */
96 #define LOG_NONE -1 /**< don't syslog */
97 #define LOG_DEFAULT 0 /**< syslog to logInfo.facility */
98 #define LOG_NOTFOUND -2 /**< didn't find a facility corresponding to name */
100 /** Map names to syslog facilities. */
102 char *name
; /**< Textual name of facility. */
103 int facility
; /**< Facility value for syslog(). */
105 #define F(fac) { #fac, LOG_ ## fac }
106 F(NONE
), F(DEFAULT
), F(AUTH
),
110 F(CRON
), F(DAEMON
), F(LOCAL0
), F(LOCAL1
), F(LOCAL2
), F(LOCAL3
),
111 F(LOCAL4
), F(LOCAL5
), F(LOCAL6
), F(LOCAL7
), F(LPR
), F(MAIL
),
112 F(NEWS
), F(USER
), F(UUCP
),
117 #define SNO_NONE 0x00000000 /**< don't send server notices */
118 #define SNO_NOTFOUND 0xffffffff /**< didn't find a SNO_MASK value for name */
120 /** Map names to snomask values. */
122 char *name
; /**< Name of server notice bit. */
123 unsigned int snomask
; /**< Bitmask corresponding to name. */
125 #define M(mask) { #mask, SNO_ ## mask }
126 M(NONE
), M(OLDSNO
), M(SERVKILL
), M(OPERKILL
), M(HACK2
),
127 M(HACK3
), M(UNAUTH
), M(TCPCOMMON
), M(TOOMANY
), M(HACK4
),
128 M(GLINE
), M(NETWORK
), M(IPMISMATCH
), M(THROTTLE
), M(OLDREALOP
),
129 M(CONNEXIT
), M(DEBUG
), M(AUTH
),
134 #define LOG_MARK_FILE 0x0001 /**< file has been changed */
135 #define LOG_MARK_FACILITY 0x0002 /**< facility has been changed */
136 #define LOG_MARK_SNOMASK 0x0004 /**< snomask has been changed */
137 #define LOG_MARK_LEVEL 0x0008 /**< level has been changed */
139 /** Descriptions of all logging subsystems. */
140 static struct LogDesc
{
141 enum LogSys subsys
; /**< number for subsystem */
142 char *name
; /**< subsystem name */
143 struct LogFile
*file
; /**< file descriptor for subsystem */
144 unsigned int mark
; /**< subsystem has been changed */
145 int def_fac
; /**< default facility */
146 unsigned int def_sno
; /**< default snomask */
147 int facility
; /**< -1 means don't use syslog */
148 unsigned int snomask
; /**< 0 means no server message */
149 enum LogLevel level
; /**< logging level */
151 #define S(sys, p, sn) { LS_##sys, #sys, 0, 0, (p), (sn), (p), (sn), L_DEFAULT }
153 S(CONFIG
, 0, SNO_OLDSNO
),
154 S(OPERMODE
, -1, SNO_HACK4
),
155 S(GLINE
, -1, SNO_GLINE
),
156 S(JUPE
, -1, SNO_NETWORK
),
158 S(NETWORK
, -1, SNO_NETWORK
),
162 S(OPER
, -1, SNO_OLDREALOP
),
165 S(IAUTH
, -1, SNO_NETWORK
),
166 S(DEBUG
, -1, SNO_DEBUG
),
167 S(SETHOST
, -1, SNO_OLDSNO
),
169 { LS_LAST_SYSTEM
, 0, 0, -1, 0, -1, 0 }
172 /** Describes a log file. */
174 struct LogFile
*next
; /**< next log file descriptor */
175 struct LogFile
**prev_p
; /**< what points to us */
176 int fd
; /**< file's descriptor-- -1 if not open */
177 int ref
; /**< how many things refer to us? */
178 char *file
; /**< file name */
181 /** Modifiable static information. */
183 struct LogFile
*filelist
; /**< list of log files */
184 struct LogFile
*freelist
; /**< list of free'd log files */
185 int facility
; /**< default facility */
186 const char *procname
; /**< process's name */
187 struct LogFile
*dbfile
; /**< debug file */
188 } logInfo
= { 0, 0, LOG_USER
, "ircd", 0 };
190 /** Helper routine to open a log file if needed.
191 * If the log file is already open, do nothing.
192 * @param[in,out] lf Log file to open.
195 log_open(struct LogFile
*lf
)
197 /* only open the file if we haven't already */
198 if (lf
&& lf
->fd
< 0) {
199 lf
->fd
= open(lf
->file
, O_WRONLY
| O_CREAT
| O_APPEND
,
206 /** Reopen debug log file. */
208 log_debug_reopen(void)
210 if (!logInfo
.dbfile
) /* no open debugging file */
213 if (!logInfo
.dbfile
->file
) { /* using terminal output */
214 logInfo
.dbfile
->fd
= 2;
218 /* Ok, it's a real file; close it if necessary and use log_open to open it */
219 if (logInfo
.dbfile
->fd
>= 0) {
220 close(logInfo
.dbfile
->fd
);
221 logInfo
.dbfile
->fd
= -1; /* mark that it's closed for log_open */
224 log_open(logInfo
.dbfile
);
226 if (logInfo
.dbfile
->fd
< 0) { /* try again with /dev/null */
227 if ((logInfo
.dbfile
->fd
= open("/dev/null", O_WRONLY
)) < 0)
231 /* massage the file descriptor to be stderr */
232 if (logInfo
.dbfile
->fd
!= 2) {
234 fd
= dup2(logInfo
.dbfile
->fd
, 2);
235 close(logInfo
.dbfile
->fd
);
236 logInfo
.dbfile
->fd
= fd
;
240 /** initialize debugging log file.
241 * @param[in] usetty If non-zero, log to terminal instead of file.
244 log_debug_init(int usetty
)
246 logInfo
.dbfile
= (struct LogFile
*) MyMalloc(sizeof(struct LogFile
));
248 logInfo
.dbfile
->next
= 0; /* initialize debugging filename */
249 logInfo
.dbfile
->prev_p
= 0;
250 logInfo
.dbfile
->fd
= -1;
251 logInfo
.dbfile
->ref
= 1;
253 if (usetty
) /* store pathname to use */
254 logInfo
.dbfile
->file
= 0;
256 DupString(logInfo
.dbfile
->file
, LOGFILE
);
258 log_debug_reopen(); /* open the debug log */
260 logDesc
[LS_DEBUG
].file
= logInfo
.dbfile
; /* remember where it went */
263 #endif /* DEBUGMODE */
265 /** Set the debug log file name.
266 * @param[in] file File name, or NULL to select the default.
267 * @return Zero if the file was reopened; non-zero if not debugging to file.
270 log_debug_file(const char *file
)
276 /* If we weren't started with debugging enabled, or if we're using
277 * the terminal, don't do anything at all.
279 if (!logInfo
.dbfile
|| !logInfo
.dbfile
->file
)
282 MyFree(logInfo
.dbfile
->file
); /* free old pathname */
283 DupString(logInfo
.dbfile
->file
, file
); /* store new pathname */
285 log_debug_reopen(); /* reopen the debug log */
286 #endif /* DEBUGMODE */
290 /** Initialize logging subsystem.
291 * @param[in] process_name Process name to interactions with syslog.
294 log_init(const char *process_name
)
296 /* store the process name; probably belongs in ircd.c, but oh well... */
297 if (!EmptyString(process_name
))
298 logInfo
.procname
= process_name
;
300 /* ok, open syslog; default facility: LOG_USER */
301 openlog(logInfo
.procname
, LOG_PID
| LOG_NDELAY
, logInfo
.facility
);
304 /** Reopen log files (so admins can do things like rotate log files). */
308 log_close(); /* close everything...we reopen on demand */
311 log_debug_reopen(); /* reopen debugging log if necessary */
312 #endif /* DEBUGMODE */
314 /* reopen syslog, if needed; default facility: LOG_USER */
315 openlog(logInfo
.procname
, LOG_PID
| LOG_NDELAY
, logInfo
.facility
);
318 /** Close all log files. */
324 closelog(); /* close syslog */
326 for (ptr
= logInfo
.filelist
; ptr
; ptr
= ptr
->next
) {
328 close(ptr
->fd
); /* close all the files... */
333 if (logInfo
.dbfile
&& logInfo
.dbfile
->file
) {
334 if (logInfo
.dbfile
->fd
>= 0)
335 close(logInfo
.dbfile
->fd
); /* close the debug log file */
337 logInfo
.dbfile
->fd
= -1;
341 /** Write a logging entry.
342 * @param[in] subsys Target subsystem.
343 * @param[in] severity Severity of message.
344 * @param[in] flags Combination of zero or more of LOG_NOSYSLOG, LOG_NOFILELOG, LOG_NOSNOTICE to suppress certain output.
345 * @param[in] fmt Format string for message.
348 log_write(enum LogSys subsys
, enum LogLevel severity
, unsigned int flags
,
349 const char *fmt
, ...)
354 log_vwrite(subsys
, severity
, flags
, fmt
, vl
);
358 /** Write a logging entry using a va_list.
359 * @param[in] subsys Target subsystem.
360 * @param[in] severity Severity of message.
361 * @param[in] flags Combination of zero or more of LOG_NOSYSLOG, LOG_NOFILELOG, LOG_NOSNOTICE to suppress certain output.
362 * @param[in] fmt Format string for message.
363 * @param[in] vl Variable-length argument list for message.
366 log_vwrite(enum LogSys subsys
, enum LogLevel severity
, unsigned int flags
,
367 const char *fmt
, va_list vl
)
370 struct LogDesc
*desc
;
371 struct LevelData
*ldata
;
373 struct iovec vector
[3];
375 char buf
[LOG_BUFSIZE
];
376 /* 1234567890123456789012 3 */
377 /* [2000-11-28 16:11:20] \0 */
380 /* check basic assumptions */
381 assert(-1 < (int)subsys
);
382 assert((int)subsys
< LS_LAST_SYSTEM
);
383 assert(-1 < (int)severity
);
384 assert((int)severity
< L_LAST_LEVEL
);
385 assert(0 == (flags
& ~LOG_NOMASK
));
388 /* find the log data and the severity data */
389 desc
= &logDesc
[subsys
];
390 ldata
= &levelData
[severity
];
392 /* check the set of ordering assumptions */
393 assert(desc
->subsys
== subsys
);
394 assert(ldata
->level
== severity
);
396 /* check severity... */
397 if (severity
> desc
->level
)
400 /* figure out where all we need to log */
401 if (!(flags
& LOG_NOFILELOG
) && desc
->file
) {
402 log_open(desc
->file
);
403 if (desc
->file
->fd
>= 0) /* don't log to file if we can't open the file */
404 flags
|= LOG_DOFILELOG
;
407 if (!(flags
& LOG_NOSYSLOG
) && desc
->facility
>= 0)
408 flags
|= LOG_DOSYSLOG
; /* will syslog */
410 if (!(flags
& LOG_NOSNOTICE
) && (desc
->snomask
!= 0 || ldata
->snomask
!= 0))
411 flags
|= LOG_DOSNOTICE
; /* will send a server notice */
413 /* short-circuit if there's nothing to do... */
414 if (!(flags
& LOG_DOMASK
))
417 /* Build the basic log string */
419 va_copy(vd
.vd_args
, vl
);
421 /* save the length for writev */
422 /* Log format: "SYSTEM [SEVERITY]: log message" */
424 ircd_snprintf(0, buf
, sizeof(buf
), "%s [%s]: %v", desc
->name
,
427 /* if we have something to write to... */
428 if (flags
& LOG_DOFILELOG
) {
430 tstamp
= localtime(&curtime
); /* build the timestamp */
433 ircd_snprintf(0, timebuf
, sizeof(timebuf
), "[%d-%d-%d %d:%02d:%02d] ",
434 tstamp
->tm_year
+ 1900, tstamp
->tm_mon
+ 1,
435 tstamp
->tm_mday
, tstamp
->tm_hour
, tstamp
->tm_min
,
438 /* set up the remaining parts of the writev vector... */
439 vector
[0].iov_base
= timebuf
;
440 vector
[1].iov_base
= buf
;
442 vector
[2].iov_base
= (void*) "\n"; /* terminate lines with a \n */
443 vector
[2].iov_len
= 1;
445 /* write it out to the log file */
446 writev(desc
->file
->fd
, vector
, 3);
449 /* oh yeah, syslog it too... */
450 if (flags
& LOG_DOSYSLOG
)
451 syslog(ldata
->syslog
| desc
->facility
, "%s", buf
);
453 /* can't forget server notices... */
454 if (flags
& LOG_DOSNOTICE
)
455 sendto_opmask_butone(0, ldata
->snomask
? ldata
->snomask
: desc
->snomask
,
459 /** Log an appropriate message for kills.
460 * @param[in] victim %Client being killed.
461 * @param[in] killer %User or server doing the killing.
462 * @param[in] inpath Peer that sent us the KILL message.
463 * @param[in] path Kill path that sent to us by \a inpath.
464 * @param[in] msg Kill reason.
467 log_write_kill(const struct Client
*victim
, const struct Client
*killer
,
468 const char *inpath
, const char *path
, const char *msg
)
471 log_write(IsServer(killer
) ? LS_SERVKILL
: LS_OPERKILL
, L_TRACE
, 0,
472 "A local client %#C KILLED by %#C Path: %s!%s %s",
473 victim
, killer
, inpath
, path
, msg
);
475 log_write(IsServer(killer
) ? LS_SERVKILL
: LS_OPERKILL
, L_TRACE
, 0,
476 "KILL from %C For %C Path: %s!%s %s", killer
, victim
, inpath
,
480 /** Find a reference-counted LogFile by file name.
481 * @param[in] file Name of file.
482 * @return A log file descriptor with LogFile::ref at least 1.
484 static struct LogFile
*
485 log_file_create(const char *file
)
491 /* if one already exists for that file, return it */
492 for (tmp
= logInfo
.filelist
; tmp
; tmp
= tmp
->next
)
493 if (!strcmp(tmp
->file
, file
)) {
498 if (logInfo
.freelist
) { /* pop one off the free list */
499 tmp
= logInfo
.freelist
;
500 logInfo
.freelist
= tmp
->next
;
501 } else /* allocate a new one */
502 tmp
= (struct LogFile
*) MyMalloc(sizeof(struct LogFile
));
504 tmp
->fd
= -1; /* initialize the structure */
506 DupString(tmp
->file
, file
);
508 tmp
->next
= logInfo
.filelist
; /* link it into the list... */
509 tmp
->prev_p
= &logInfo
.filelist
;
510 if (logInfo
.filelist
)
511 logInfo
.filelist
->prev_p
= &tmp
->next
;
512 logInfo
.filelist
= tmp
;
517 /** Dereference a log file.
518 * If the reference count is exactly one on entry to this function,
519 * the file is closed and its structure is freed.
520 * @param[in] lf Log file to dereference.
523 log_file_destroy(struct LogFile
*lf
)
527 if (--lf
->ref
== 0) {
528 if (lf
->next
) /* clip it out of the list */
529 lf
->next
->prev_p
= lf
->prev_p
;
530 *lf
->prev_p
= lf
->next
;
532 lf
->prev_p
= 0; /* we won't use it for the free list */
536 MyFree(lf
->file
); /* free the file name */
538 lf
->next
= logInfo
.freelist
; /* stack it onto the free list */
539 logInfo
.freelist
= lf
;
543 /** Look up a log subsystem by name.
544 * @param[in] subsys Subsystem name.
545 * @return Pointer to the subsystem's LogDesc, or NULL if none exists.
547 static struct LogDesc
*
548 log_find(const char *subsys
)
554 /* find the named subsystem */
555 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++)
556 if (!ircd_strcmp(subsys
, logDesc
[i
].name
))
559 return 0; /* not found */
562 /** Return canonical version of log subsystem name.
563 * @param[in] subsys Subsystem name.
564 * @return A constant string containing the canonical name.
567 log_canon(const char *subsys
)
569 struct LogDesc
*desc
;
571 if (!(desc
= log_find(subsys
)))
577 /** Look up a log level by name.
578 * @param[in] level Log level name.
579 * @return LogLevel enumeration, or L_LAST_LEVEL if none exists.
582 log_lev_find(const char *level
)
588 /* find the named level */
589 for (i
= 0; levelData
[i
].string
; i
++)
590 if (!ircd_strcmp(level
, levelData
[i
].string
))
591 return levelData
[i
].level
;
593 return L_LAST_LEVEL
; /* not found */
596 /** Look up the canonical name for a log level.
598 * @return A constant string containing the level's canonical name.
601 log_lev_name(enum LogLevel lev
)
603 assert(-1 < (int)lev
);
604 assert((int)lev
< L_LAST_LEVEL
);
605 assert(lev
== levelData
[lev
].level
);
607 return levelData
[lev
].string
;
610 /** Look up a syslog facility by name.
611 * @param[in] facility Facility name.
612 * @return Syslog facility value, or LOG_NOTFOUND if none exists.
615 log_fac_find(const char *facility
)
619 assert(0 != facility
);
621 /* find the named facility */
622 for (i
= 0; facilities
[i
].name
; i
++)
623 if (!ircd_strcmp(facility
, facilities
[i
].name
))
624 return facilities
[i
].facility
;
626 return LOG_NOTFOUND
; /* not found */
629 /** Look up the name for a syslog facility.
630 * @param[in] fac Facility value.
631 * @return Canonical name for facility, or NULL if none exists.
634 log_fac_name(int fac
)
638 /* find the facility */
639 for (i
= 0; facilities
[i
].name
; i
++)
640 if (facilities
[i
].facility
== fac
)
641 return facilities
[i
].name
;
643 return 0; /* not found; should never happen */
646 /** Look up a server notice mask by name.
647 * @param[in] maskname Name of server notice mask.
648 * @return Bitmask for server notices, or 0 if none exists.
651 log_sno_find(const char *maskname
)
655 assert(0 != maskname
);
657 /* find the named snomask */
658 for (i
= 0; masks
[i
].name
; i
++)
659 if (!ircd_strcmp(maskname
, masks
[i
].name
))
660 return masks
[i
].snomask
;
662 return SNO_NOTFOUND
; /* not found */
665 /** Look up the canonical name for a server notice mask.
666 * @param[in] sno Server notice mask.
667 * @return Canonical name for the mask, or NULL if none exists.
670 log_sno_name(unsigned int sno
)
674 /* find the snomask */
675 for (i
= 0; masks
[i
].name
; i
++)
676 if (masks
[i
].snomask
== sno
)
677 return masks
[i
].name
;
679 return 0; /* not found; should never happen */
682 /** Set a log file for a particular subsystem.
683 * @param[in] subsys Subsystem name.
684 * @param[in] filename Log file to write to.
685 * @return Zero on success; non-zero on error.
688 log_set_file(const char *subsys
, const char *filename
)
690 struct LogDesc
*desc
;
693 if (!(desc
= log_find(subsys
)))
697 desc
->mark
|= LOG_MARK_FILE
; /* mark that file has been changed */
699 desc
->mark
&= ~LOG_MARK_FILE
; /* file has been reset to defaults */
701 /* no change, don't go to the trouble of destroying and recreating */
702 if (desc
->file
&& desc
->file
->file
&& filename
&&
703 !strcmp(desc
->file
->file
, filename
))
706 /* debug log is special, since it has to be opened on fd 2 */
707 if (desc
->subsys
== LS_DEBUG
)
708 return log_debug_file(filename
);
710 if (desc
->file
) /* destroy previous entry... */
711 log_file_destroy(desc
->file
);
713 /* set the file to use */
714 desc
->file
= filename
? log_file_create(filename
) : 0;
719 /** Find the log file name for a subsystem.
720 * @param[in] subsys Subsystem name.
721 * @return Log file for the subsystem, or NULL if not being logged to a file.
724 log_get_file(const char *subsys
)
726 struct LogDesc
*desc
;
729 if (!(desc
= log_find(subsys
)))
732 return desc
->file
? desc
->file
->file
: 0;
735 /** Set the syslog facility for a particular subsystem.
736 * @param[in] subsys Subsystem name.
737 * @param[in] facility Facility name to log to.
738 * @return Zero on success; non-zero on error.
741 log_set_facility(const char *subsys
, const char *facility
)
743 struct LogDesc
*desc
;
747 if (!(desc
= log_find(subsys
)))
750 /* set syslog facility */
751 if (EmptyString(facility
)) {
752 desc
->facility
= desc
->def_fac
;
753 desc
->mark
&= ~LOG_MARK_FACILITY
;
754 } else if ((fac
= log_fac_find(facility
)) != LOG_NOTFOUND
) {
755 desc
->facility
= fac
;
756 if (fac
== desc
->def_fac
)
757 desc
->mark
&= ~LOG_MARK_FACILITY
;
759 desc
->mark
|= LOG_MARK_FACILITY
;
766 /** Find the facility name for a subsystem.
767 * @param[in] subsys Subsystem name.
768 * @return Facility name being used, or NULL if not being logged to syslog.
771 log_get_facility(const char *subsys
)
773 struct LogDesc
*desc
;
776 if (!(desc
= log_find(subsys
)))
779 /* find the facility's name */
780 return log_fac_name(desc
->facility
);
783 /** Set the server notice mask for a subsystem.
784 * @param[in] subsys Subsystem name.
785 * @param[in] snomask Server notice mask name.
786 * @return Zero on success; non-zero on error.
789 log_set_snomask(const char *subsys
, const char *snomask
)
791 struct LogDesc
*desc
;
792 unsigned int sno
= SNO_DEFAULT
;
795 if (!(desc
= log_find(subsys
)))
798 /* set snomask value */
799 if (EmptyString(snomask
)) {
800 desc
->snomask
= desc
->def_sno
;
801 desc
->mark
&= ~LOG_MARK_SNOMASK
;
802 } else if ((sno
= log_sno_find(snomask
)) != SNO_NOTFOUND
) {
804 if (sno
== desc
->def_sno
)
805 desc
->mark
&= ~LOG_MARK_SNOMASK
;
807 desc
->mark
|= LOG_MARK_SNOMASK
;
814 /** Find the server notice mask name for a subsystem.
815 * @param[in] subsys Subsystem name.
816 * @return Name of server notice mask being used, or NULL if none.
819 log_get_snomask(const char *subsys
)
821 struct LogDesc
*desc
;
824 if (!(desc
= log_find(subsys
)))
827 /* find the snomask value's name */
828 return log_sno_name(desc
->snomask
);
831 /** Set the verbosity level for a subsystem.
832 * @param[in] subsys Subsystem name.
833 * @param[in] level Minimum log level.
834 * @return Zero on success; non-zero on error.
837 log_set_level(const char *subsys
, const char *level
)
839 struct LogDesc
*desc
;
843 if (!(desc
= log_find(subsys
)))
846 /* set logging level */
847 if (EmptyString(level
)) {
848 desc
->level
= L_DEFAULT
;
849 desc
->mark
&= ~LOG_MARK_LEVEL
;
850 } else if ((lev
= log_lev_find(level
)) != L_LAST_LEVEL
) {
852 if (lev
== L_DEFAULT
)
853 desc
->mark
&= ~LOG_MARK_LEVEL
;
855 desc
->mark
|= LOG_MARK_LEVEL
;
862 /** Find the verbosity level for a subsystem.
863 * @param[in] subsys Subsystem name.
864 * @return Minimum verbosity level being used, or NULL on error.
867 log_get_level(const char *subsys
)
869 struct LogDesc
*desc
;
872 if (!(desc
= log_find(subsys
)))
875 /* find the level's name */
876 return log_lev_name(desc
->level
);
879 /** Set the default syslog facility.
880 * @param[in] facility Syslog facility name.
881 * @return Zero on success, non-zero on error.
884 log_set_default(const char *facility
)
888 oldfac
= logInfo
.facility
;
890 if (EmptyString(facility
))
891 logInfo
.facility
= LOG_USER
;
892 else if ((fac
= log_fac_find(facility
)) != LOG_NOTFOUND
&&
893 fac
!= LOG_NONE
&& fac
!= LOG_DEFAULT
)
894 logInfo
.facility
= fac
;
898 if (logInfo
.facility
!= oldfac
) {
899 closelog(); /* reopen syslog with new facility setting */
900 openlog(logInfo
.procname
, LOG_PID
| LOG_NDELAY
, logInfo
.facility
);
906 /** Find the default syslog facility name.
907 * @return Canonical name of default syslog facility, or NULL if none.
910 log_get_default(void)
912 /* find the facility's name */
913 return log_fac_name(logInfo
.facility
);
916 /** Clear all marks. */
918 log_feature_unmark(void)
922 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++)
926 /** Reset unmodified fields in all log subsystems to their defaults.
927 * @param[in] flag If non-zero, clear default syslog facility.
930 log_feature_mark(int flag
)
937 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++) {
938 if (!(logDesc
[i
].mark
& LOG_MARK_FILE
)) {
939 if (logDesc
[i
].subsys
!= LS_DEBUG
) { /* debug is special */
940 if (logDesc
[i
].file
) /* destroy previous entry... */
941 log_file_destroy(logDesc
[i
].file
);
946 if (!(logDesc
[i
].mark
& LOG_MARK_FACILITY
)) /* set default facility */
947 logDesc
[i
].facility
= logDesc
[i
].def_fac
;
949 if (!(logDesc
[i
].mark
& LOG_MARK_SNOMASK
)) /* set default snomask */
950 logDesc
[i
].snomask
= logDesc
[i
].def_sno
;
952 if (!(logDesc
[i
].mark
& LOG_MARK_LEVEL
)) /* set default level */
953 logDesc
[i
].level
= L_DEFAULT
;
956 return 0; /* we don't have a notify handler */
959 /** Feature list callback to report log settings.
960 * @param[in] to Client requesting list.
961 * @param[in] flag If non-zero, report default syslog facility.
964 log_feature_report(struct Client
*to
, int flag
)
968 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++)
970 if (logDesc
[i
].mark
& LOG_MARK_FILE
) /* report file */
971 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s FILE %s",
972 logDesc
[i
].name
, (logDesc
[i
].file
&& logDesc
[i
].file
->file
?
973 logDesc
[i
].file
->file
: "(terminal)"));
975 if (logDesc
[i
].mark
& LOG_MARK_FACILITY
) /* report facility */
976 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s FACILITY %s",
977 logDesc
[i
].name
, log_fac_name(logDesc
[i
].facility
));
979 if (logDesc
[i
].mark
& LOG_MARK_SNOMASK
) /* report snomask */
980 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s SNOMASK %s",
981 logDesc
[i
].name
, log_sno_name(logDesc
[i
].snomask
));
983 if (logDesc
[i
].mark
& LOG_MARK_LEVEL
) /* report log level */
984 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s LEVEL %s",
985 logDesc
[i
].name
, log_lev_name(logDesc
[i
].level
));
988 if (flag
) /* report default facility */
989 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s",
990 log_fac_name(logInfo
.facility
));