]>
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 2005/08/25 01:26:46 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
),
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
),
168 { LS_LAST_SYSTEM
, 0, 0, -1, 0, -1, 0 }
171 /** Describes a log file. */
173 struct LogFile
*next
; /**< next log file descriptor */
174 struct LogFile
**prev_p
; /**< what points to us */
175 int fd
; /**< file's descriptor-- -1 if not open */
176 int ref
; /**< how many things refer to us? */
177 char *file
; /**< file name */
180 /** Modifiable static information. */
182 struct LogFile
*filelist
; /**< list of log files */
183 struct LogFile
*freelist
; /**< list of free'd log files */
184 int facility
; /**< default facility */
185 const char *procname
; /**< process's name */
186 struct LogFile
*dbfile
; /**< debug file */
187 } logInfo
= { 0, 0, LOG_USER
, "ircd", 0 };
189 /** Helper routine to open a log file if needed.
190 * If the log file is already open, do nothing.
191 * @param[in,out] lf Log file to open.
194 log_open(struct LogFile
*lf
)
196 /* only open the file if we haven't already */
197 if (lf
&& lf
->fd
< 0) {
198 lf
->fd
= open(lf
->file
, O_WRONLY
| O_CREAT
| O_APPEND
,
205 /** Reopen debug log file. */
207 log_debug_reopen(void)
209 if (!logInfo
.dbfile
) /* no open debugging file */
212 if (!logInfo
.dbfile
->file
) { /* using terminal output */
213 logInfo
.dbfile
->fd
= 2;
217 /* Ok, it's a real file; close it if necessary and use log_open to open it */
218 if (logInfo
.dbfile
->fd
>= 0) {
219 close(logInfo
.dbfile
->fd
);
220 logInfo
.dbfile
->fd
= -1; /* mark that it's closed for log_open */
223 log_open(logInfo
.dbfile
);
225 if (logInfo
.dbfile
->fd
< 0) { /* try again with /dev/null */
226 if ((logInfo
.dbfile
->fd
= open("/dev/null", O_WRONLY
)) < 0)
230 /* massage the file descriptor to be stderr */
231 if (logInfo
.dbfile
->fd
!= 2) {
233 fd
= dup2(logInfo
.dbfile
->fd
, 2);
234 close(logInfo
.dbfile
->fd
);
235 logInfo
.dbfile
->fd
= fd
;
239 /** initialize debugging log file.
240 * @param[in] usetty If non-zero, log to terminal instead of file.
243 log_debug_init(int usetty
)
245 logInfo
.dbfile
= (struct LogFile
*) MyMalloc(sizeof(struct LogFile
));
247 logInfo
.dbfile
->next
= 0; /* initialize debugging filename */
248 logInfo
.dbfile
->prev_p
= 0;
249 logInfo
.dbfile
->fd
= -1;
250 logInfo
.dbfile
->ref
= 1;
252 if (usetty
) /* store pathname to use */
253 logInfo
.dbfile
->file
= 0;
255 DupString(logInfo
.dbfile
->file
, LOGFILE
);
257 log_debug_reopen(); /* open the debug log */
259 logDesc
[LS_DEBUG
].file
= logInfo
.dbfile
; /* remember where it went */
262 #endif /* DEBUGMODE */
264 /** Set the debug log file name.
265 * @param[in] file File name, or NULL to select the default.
266 * @return Zero if the file was reopened; non-zero if not debugging to file.
269 log_debug_file(const char *file
)
275 /* If we weren't started with debugging enabled, or if we're using
276 * the terminal, don't do anything at all.
278 if (!logInfo
.dbfile
|| !logInfo
.dbfile
->file
)
281 MyFree(logInfo
.dbfile
->file
); /* free old pathname */
282 DupString(logInfo
.dbfile
->file
, file
); /* store new pathname */
284 log_debug_reopen(); /* reopen the debug log */
285 #endif /* DEBUGMODE */
289 /** Initialize logging subsystem.
290 * @param[in] process_name Process name to interactions with syslog.
293 log_init(const char *process_name
)
295 /* store the process name; probably belongs in ircd.c, but oh well... */
296 if (!EmptyString(process_name
))
297 logInfo
.procname
= process_name
;
299 /* ok, open syslog; default facility: LOG_USER */
300 openlog(logInfo
.procname
, LOG_PID
| LOG_NDELAY
, logInfo
.facility
);
303 /** Reopen log files (so admins can do things like rotate log files). */
307 log_close(); /* close everything...we reopen on demand */
310 log_debug_reopen(); /* reopen debugging log if necessary */
311 #endif /* DEBUGMODE */
313 /* reopen syslog, if needed; default facility: LOG_USER */
314 openlog(logInfo
.procname
, LOG_PID
| LOG_NDELAY
, logInfo
.facility
);
317 /** Close all log files. */
323 closelog(); /* close syslog */
325 for (ptr
= logInfo
.filelist
; ptr
; ptr
= ptr
->next
) {
327 close(ptr
->fd
); /* close all the files... */
332 if (logInfo
.dbfile
&& logInfo
.dbfile
->file
) {
333 if (logInfo
.dbfile
->fd
>= 0)
334 close(logInfo
.dbfile
->fd
); /* close the debug log file */
336 logInfo
.dbfile
->fd
= -1;
340 /** Write a logging entry.
341 * @param[in] subsys Target subsystem.
342 * @param[in] severity Severity of message.
343 * @param[in] flags Combination of zero or more of LOG_NOSYSLOG, LOG_NOFILELOG, LOG_NOSNOTICE to suppress certain output.
344 * @param[in] fmt Format string for message.
347 log_write(enum LogSys subsys
, enum LogLevel severity
, unsigned int flags
,
348 const char *fmt
, ...)
353 log_vwrite(subsys
, severity
, flags
, fmt
, vl
);
357 /** Write a logging entry using a va_list.
358 * @param[in] subsys Target subsystem.
359 * @param[in] severity Severity of message.
360 * @param[in] flags Combination of zero or more of LOG_NOSYSLOG, LOG_NOFILELOG, LOG_NOSNOTICE to suppress certain output.
361 * @param[in] fmt Format string for message.
362 * @param[in] vl Variable-length argument list for message.
365 log_vwrite(enum LogSys subsys
, enum LogLevel severity
, unsigned int flags
,
366 const char *fmt
, va_list vl
)
369 struct LogDesc
*desc
;
370 struct LevelData
*ldata
;
372 struct iovec vector
[3];
374 char buf
[LOG_BUFSIZE
];
375 /* 1234567890123456789012 3 */
376 /* [2000-11-28 16:11:20] \0 */
379 /* check basic assumptions */
380 assert(-1 < (int)subsys
);
381 assert((int)subsys
< LS_LAST_SYSTEM
);
382 assert(-1 < (int)severity
);
383 assert((int)severity
< L_LAST_LEVEL
);
384 assert(0 == (flags
& ~LOG_NOMASK
));
387 /* find the log data and the severity data */
388 desc
= &logDesc
[subsys
];
389 ldata
= &levelData
[severity
];
391 /* check the set of ordering assumptions */
392 assert(desc
->subsys
== subsys
);
393 assert(ldata
->level
== severity
);
395 /* check severity... */
396 if (severity
> desc
->level
)
399 /* figure out where all we need to log */
400 if (!(flags
& LOG_NOFILELOG
) && desc
->file
) {
401 log_open(desc
->file
);
402 if (desc
->file
->fd
>= 0) /* don't log to file if we can't open the file */
403 flags
|= LOG_DOFILELOG
;
406 if (!(flags
& LOG_NOSYSLOG
) && desc
->facility
>= 0)
407 flags
|= LOG_DOSYSLOG
; /* will syslog */
409 if (!(flags
& LOG_NOSNOTICE
) && (desc
->snomask
!= 0 || ldata
->snomask
!= 0))
410 flags
|= LOG_DOSNOTICE
; /* will send a server notice */
412 /* short-circuit if there's nothing to do... */
413 if (!(flags
& LOG_DOMASK
))
416 /* Build the basic log string */
418 va_copy(vd
.vd_args
, vl
);
420 /* save the length for writev */
421 /* Log format: "SYSTEM [SEVERITY]: log message" */
423 ircd_snprintf(0, buf
, sizeof(buf
), "%s [%s]: %v", desc
->name
,
426 /* if we have something to write to... */
427 if (flags
& LOG_DOFILELOG
) {
429 tstamp
= localtime(&curtime
); /* build the timestamp */
432 ircd_snprintf(0, timebuf
, sizeof(timebuf
), "[%d-%d-%d %d:%02d:%02d] ",
433 tstamp
->tm_year
+ 1900, tstamp
->tm_mon
+ 1,
434 tstamp
->tm_mday
, tstamp
->tm_hour
, tstamp
->tm_min
,
437 /* set up the remaining parts of the writev vector... */
438 vector
[0].iov_base
= timebuf
;
439 vector
[1].iov_base
= buf
;
441 vector
[2].iov_base
= (void*) "\n"; /* terminate lines with a \n */
442 vector
[2].iov_len
= 1;
444 /* write it out to the log file */
445 writev(desc
->file
->fd
, vector
, 3);
448 /* oh yeah, syslog it too... */
449 if (flags
& LOG_DOSYSLOG
)
450 syslog(ldata
->syslog
| desc
->facility
, "%s", buf
);
452 /* can't forget server notices... */
453 if (flags
& LOG_DOSNOTICE
)
454 sendto_opmask_butone(0, ldata
->snomask
? ldata
->snomask
: desc
->snomask
,
458 /** Log an appropriate message for kills.
459 * @param[in] victim %Client being killed.
460 * @param[in] killer %User or server doing the killing.
461 * @param[in] inpath Peer that sent us the KILL message.
462 * @param[in] path Kill path that sent to us by \a inpath.
463 * @param[in] msg Kill reason.
466 log_write_kill(const struct Client
*victim
, const struct Client
*killer
,
467 const char *inpath
, const char *path
, const char *msg
)
470 log_write(IsServer(killer
) ? LS_SERVKILL
: LS_OPERKILL
, L_TRACE
, 0,
471 "A local client %#C KILLED by %#C Path: %s!%s %s",
472 victim
, killer
, inpath
, path
, msg
);
474 log_write(IsServer(killer
) ? LS_SERVKILL
: LS_OPERKILL
, L_TRACE
, 0,
475 "KILL from %C For %C Path: %s!%s %s", killer
, victim
, inpath
,
479 /** Find a reference-counted LogFile by file name.
480 * @param[in] file Name of file.
481 * @return A log file descriptor with LogFile::ref at least 1.
483 static struct LogFile
*
484 log_file_create(const char *file
)
490 /* if one already exists for that file, return it */
491 for (tmp
= logInfo
.filelist
; tmp
; tmp
= tmp
->next
)
492 if (!strcmp(tmp
->file
, file
)) {
497 if (logInfo
.freelist
) { /* pop one off the free list */
498 tmp
= logInfo
.freelist
;
499 logInfo
.freelist
= tmp
->next
;
500 } else /* allocate a new one */
501 tmp
= (struct LogFile
*) MyMalloc(sizeof(struct LogFile
));
503 tmp
->fd
= -1; /* initialize the structure */
505 DupString(tmp
->file
, file
);
507 tmp
->next
= logInfo
.filelist
; /* link it into the list... */
508 tmp
->prev_p
= &logInfo
.filelist
;
509 if (logInfo
.filelist
)
510 logInfo
.filelist
->prev_p
= &tmp
->next
;
511 logInfo
.filelist
= tmp
;
516 /** Dereference a log file.
517 * If the reference count is exactly one on entry to this function,
518 * the file is closed and its structure is freed.
519 * @param[in] lf Log file to dereference.
522 log_file_destroy(struct LogFile
*lf
)
526 if (--lf
->ref
== 0) {
527 if (lf
->next
) /* clip it out of the list */
528 lf
->next
->prev_p
= lf
->prev_p
;
529 *lf
->prev_p
= lf
->next
;
531 lf
->prev_p
= 0; /* we won't use it for the free list */
535 MyFree(lf
->file
); /* free the file name */
537 lf
->next
= logInfo
.freelist
; /* stack it onto the free list */
538 logInfo
.freelist
= lf
;
542 /** Look up a log subsystem by name.
543 * @param[in] subsys Subsystem name.
544 * @return Pointer to the subsystem's LogDesc, or NULL if none exists.
546 static struct LogDesc
*
547 log_find(const char *subsys
)
553 /* find the named subsystem */
554 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++)
555 if (!ircd_strcmp(subsys
, logDesc
[i
].name
))
558 return 0; /* not found */
561 /** Return canonical version of log subsystem name.
562 * @param[in] subsys Subsystem name.
563 * @return A constant string containing the canonical name.
566 log_canon(const char *subsys
)
568 struct LogDesc
*desc
;
570 if (!(desc
= log_find(subsys
)))
576 /** Look up a log level by name.
577 * @param[in] level Log level name.
578 * @return LogLevel enumeration, or L_LAST_LEVEL if none exists.
581 log_lev_find(const char *level
)
587 /* find the named level */
588 for (i
= 0; levelData
[i
].string
; i
++)
589 if (!ircd_strcmp(level
, levelData
[i
].string
))
590 return levelData
[i
].level
;
592 return L_LAST_LEVEL
; /* not found */
595 /** Look up the canonical name for a log level.
597 * @return A constant string containing the level's canonical name.
600 log_lev_name(enum LogLevel lev
)
602 assert(-1 < (int)lev
);
603 assert((int)lev
< L_LAST_LEVEL
);
604 assert(lev
== levelData
[lev
].level
);
606 return levelData
[lev
].string
;
609 /** Look up a syslog facility by name.
610 * @param[in] facility Facility name.
611 * @return Syslog facility value, or LOG_NOTFOUND if none exists.
614 log_fac_find(const char *facility
)
618 assert(0 != facility
);
620 /* find the named facility */
621 for (i
= 0; facilities
[i
].name
; i
++)
622 if (!ircd_strcmp(facility
, facilities
[i
].name
))
623 return facilities
[i
].facility
;
625 return LOG_NOTFOUND
; /* not found */
628 /** Look up the name for a syslog facility.
629 * @param[in] fac Facility value.
630 * @return Canonical name for facility, or NULL if none exists.
633 log_fac_name(int fac
)
637 /* find the facility */
638 for (i
= 0; facilities
[i
].name
; i
++)
639 if (facilities
[i
].facility
== fac
)
640 return facilities
[i
].name
;
642 return 0; /* not found; should never happen */
645 /** Look up a server notice mask by name.
646 * @param[in] maskname Name of server notice mask.
647 * @return Bitmask for server notices, or 0 if none exists.
650 log_sno_find(const char *maskname
)
654 assert(0 != maskname
);
656 /* find the named snomask */
657 for (i
= 0; masks
[i
].name
; i
++)
658 if (!ircd_strcmp(maskname
, masks
[i
].name
))
659 return masks
[i
].snomask
;
661 return SNO_NOTFOUND
; /* not found */
664 /** Look up the canonical name for a server notice mask.
665 * @param[in] sno Server notice mask.
666 * @return Canonical name for the mask, or NULL if none exists.
669 log_sno_name(unsigned int sno
)
673 /* find the snomask */
674 for (i
= 0; masks
[i
].name
; i
++)
675 if (masks
[i
].snomask
== sno
)
676 return masks
[i
].name
;
678 return 0; /* not found; should never happen */
681 /** Set a log file for a particular subsystem.
682 * @param[in] subsys Subsystem name.
683 * @param[in] filename Log file to write to.
684 * @return Zero on success; non-zero on error.
687 log_set_file(const char *subsys
, const char *filename
)
689 struct LogDesc
*desc
;
692 if (!(desc
= log_find(subsys
)))
696 desc
->mark
|= LOG_MARK_FILE
; /* mark that file has been changed */
698 desc
->mark
&= ~LOG_MARK_FILE
; /* file has been reset to defaults */
700 /* no change, don't go to the trouble of destroying and recreating */
701 if (desc
->file
&& desc
->file
->file
&& filename
&&
702 !strcmp(desc
->file
->file
, filename
))
705 /* debug log is special, since it has to be opened on fd 2 */
706 if (desc
->subsys
== LS_DEBUG
)
707 return log_debug_file(filename
);
709 if (desc
->file
) /* destroy previous entry... */
710 log_file_destroy(desc
->file
);
712 /* set the file to use */
713 desc
->file
= filename
? log_file_create(filename
) : 0;
718 /** Find the log file name for a subsystem.
719 * @param[in] subsys Subsystem name.
720 * @return Log file for the subsystem, or NULL if not being logged to a file.
723 log_get_file(const char *subsys
)
725 struct LogDesc
*desc
;
728 if (!(desc
= log_find(subsys
)))
731 return desc
->file
? desc
->file
->file
: 0;
734 /** Set the syslog facility for a particular subsystem.
735 * @param[in] subsys Subsystem name.
736 * @param[in] facility Facility name to log to.
737 * @return Zero on success; non-zero on error.
740 log_set_facility(const char *subsys
, const char *facility
)
742 struct LogDesc
*desc
;
746 if (!(desc
= log_find(subsys
)))
749 /* set syslog facility */
750 if (EmptyString(facility
)) {
751 desc
->facility
= desc
->def_fac
;
752 desc
->mark
&= ~LOG_MARK_FACILITY
;
753 } else if ((fac
= log_fac_find(facility
)) != LOG_NOTFOUND
) {
754 desc
->facility
= fac
;
755 if (fac
== desc
->def_fac
)
756 desc
->mark
&= ~LOG_MARK_FACILITY
;
758 desc
->mark
|= LOG_MARK_FACILITY
;
765 /** Find the facility name for a subsystem.
766 * @param[in] subsys Subsystem name.
767 * @return Facility name being used, or NULL if not being logged to syslog.
770 log_get_facility(const char *subsys
)
772 struct LogDesc
*desc
;
775 if (!(desc
= log_find(subsys
)))
778 /* find the facility's name */
779 return log_fac_name(desc
->facility
);
782 /** Set the server notice mask for a subsystem.
783 * @param[in] subsys Subsystem name.
784 * @param[in] snomask Server notice mask name.
785 * @return Zero on success; non-zero on error.
788 log_set_snomask(const char *subsys
, const char *snomask
)
790 struct LogDesc
*desc
;
791 unsigned int sno
= SNO_DEFAULT
;
794 if (!(desc
= log_find(subsys
)))
797 /* set snomask value */
798 if (EmptyString(snomask
)) {
799 desc
->snomask
= desc
->def_sno
;
800 desc
->mark
&= ~LOG_MARK_SNOMASK
;
801 } else if ((sno
= log_sno_find(snomask
)) != SNO_NOTFOUND
) {
803 if (sno
== desc
->def_sno
)
804 desc
->mark
&= ~LOG_MARK_SNOMASK
;
806 desc
->mark
|= LOG_MARK_SNOMASK
;
813 /** Find the server notice mask name for a subsystem.
814 * @param[in] subsys Subsystem name.
815 * @return Name of server notice mask being used, or NULL if none.
818 log_get_snomask(const char *subsys
)
820 struct LogDesc
*desc
;
823 if (!(desc
= log_find(subsys
)))
826 /* find the snomask value's name */
827 return log_sno_name(desc
->snomask
);
830 /** Set the verbosity level for a subsystem.
831 * @param[in] subsys Subsystem name.
832 * @param[in] level Minimum log level.
833 * @return Zero on success; non-zero on error.
836 log_set_level(const char *subsys
, const char *level
)
838 struct LogDesc
*desc
;
842 if (!(desc
= log_find(subsys
)))
845 /* set logging level */
846 if (EmptyString(level
)) {
847 desc
->level
= L_DEFAULT
;
848 desc
->mark
&= ~LOG_MARK_LEVEL
;
849 } else if ((lev
= log_lev_find(level
)) != L_LAST_LEVEL
) {
851 if (lev
== L_DEFAULT
)
852 desc
->mark
&= ~LOG_MARK_LEVEL
;
854 desc
->mark
|= LOG_MARK_LEVEL
;
861 /** Find the verbosity level for a subsystem.
862 * @param[in] subsys Subsystem name.
863 * @return Minimum verbosity level being used, or NULL on error.
866 log_get_level(const char *subsys
)
868 struct LogDesc
*desc
;
871 if (!(desc
= log_find(subsys
)))
874 /* find the level's name */
875 return log_lev_name(desc
->level
);
878 /** Set the default syslog facility.
879 * @param[in] facility Syslog facility name.
880 * @return Zero on success, non-zero on error.
883 log_set_default(const char *facility
)
887 oldfac
= logInfo
.facility
;
889 if (EmptyString(facility
))
890 logInfo
.facility
= LOG_USER
;
891 else if ((fac
= log_fac_find(facility
)) != LOG_NOTFOUND
&&
892 fac
!= LOG_NONE
&& fac
!= LOG_DEFAULT
)
893 logInfo
.facility
= fac
;
897 if (logInfo
.facility
!= oldfac
) {
898 closelog(); /* reopen syslog with new facility setting */
899 openlog(logInfo
.procname
, LOG_PID
| LOG_NDELAY
, logInfo
.facility
);
905 /** Find the default syslog facility name.
906 * @return Canonical name of default syslog facility, or NULL if none.
909 log_get_default(void)
911 /* find the facility's name */
912 return log_fac_name(logInfo
.facility
);
915 /** Clear all marks. */
917 log_feature_unmark(void)
921 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++)
925 /** Reset unmodified fields in all log subsystems to their defaults.
926 * @param[in] flag If non-zero, clear default syslog facility.
929 log_feature_mark(int flag
)
936 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++) {
937 if (!(logDesc
[i
].mark
& LOG_MARK_FILE
)) {
938 if (logDesc
[i
].subsys
!= LS_DEBUG
) { /* debug is special */
939 if (logDesc
[i
].file
) /* destroy previous entry... */
940 log_file_destroy(logDesc
[i
].file
);
945 if (!(logDesc
[i
].mark
& LOG_MARK_FACILITY
)) /* set default facility */
946 logDesc
[i
].facility
= logDesc
[i
].def_fac
;
948 if (!(logDesc
[i
].mark
& LOG_MARK_SNOMASK
)) /* set default snomask */
949 logDesc
[i
].snomask
= logDesc
[i
].def_sno
;
951 if (!(logDesc
[i
].mark
& LOG_MARK_LEVEL
)) /* set default level */
952 logDesc
[i
].level
= L_DEFAULT
;
955 return 0; /* we don't have a notify handler */
958 /** Feature list callback to report log settings.
959 * @param[in] to Client requesting list.
960 * @param[in] flag If non-zero, report default syslog facility.
963 log_feature_report(struct Client
*to
, int flag
)
967 for (i
= 0; i
< LS_LAST_SYSTEM
; i
++)
969 if (logDesc
[i
].mark
& LOG_MARK_FILE
) /* report file */
970 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s FILE %s",
971 logDesc
[i
].name
, (logDesc
[i
].file
&& logDesc
[i
].file
->file
?
972 logDesc
[i
].file
->file
: "(terminal)"));
974 if (logDesc
[i
].mark
& LOG_MARK_FACILITY
) /* report facility */
975 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s FACILITY %s",
976 logDesc
[i
].name
, log_fac_name(logDesc
[i
].facility
));
978 if (logDesc
[i
].mark
& LOG_MARK_SNOMASK
) /* report snomask */
979 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s SNOMASK %s",
980 logDesc
[i
].name
, log_sno_name(logDesc
[i
].snomask
));
982 if (logDesc
[i
].mark
& LOG_MARK_LEVEL
) /* report log level */
983 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s LEVEL %s",
984 logDesc
[i
].name
, log_lev_name(logDesc
[i
].level
));
987 if (flag
) /* report default facility */
988 send_reply(to
, SND_EXPLICIT
| RPL_STATSFLINE
, "F LOG %s",
989 log_fac_name(logInfo
.facility
));