summaryrefslogtreecommitdiff
path: root/src/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/log.c')
-rw-r--r--src/log.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 000000000..a4f354993
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,336 @@
+/* Logging routines.
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ * $Id$
+ *
+ */
+
+#include "services.h"
+#include "pseudo.h"
+
+static FILE *logfile;
+
+static int curday = 0;
+
+/*************************************************************************/
+
+static int get_logname(char *name, int count, struct tm *tm)
+{
+ char timestamp[32];
+ time_t t;
+
+
+ if (!tm) {
+ time(&t);
+ tm = localtime(&t);
+ }
+
+ /* fix bug 577 */
+ strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
+ snprintf(name, count, "logs/%s.%s", log_filename, timestamp);
+ curday = tm->tm_yday;
+
+ return 1;
+}
+
+/*************************************************************************/
+
+static void remove_log(void)
+{
+ time_t t;
+ struct tm tm;
+
+ char name[PATH_MAX];
+
+ if (!KeepLogs)
+ return;
+
+ time(&t);
+ t -= (60 * 60 * 24 * KeepLogs);
+ tm = *localtime(&t);
+
+ /* removed if from here cause get_logchan is always 1 */
+ get_logname(name, sizeof(name), &tm);
+#ifndef _WIN32
+ unlink(name);
+#else
+ DeleteFile(name);
+#endif
+}
+
+/*************************************************************************/
+
+static void checkday(void)
+{
+ time_t t;
+ struct tm tm;
+
+ time(&t);
+ tm = *localtime(&t);
+
+ if (curday != tm.tm_yday) {
+ close_log();
+ remove_log();
+ open_log();
+ }
+}
+
+/*************************************************************************/
+
+/* Open the log file. Return -1 if the log file could not be opened, else
+ * return 0. */
+
+int open_log(void)
+{
+ char name[PATH_MAX];
+
+ if (logfile)
+ return 0;
+
+ /* if removed again.. get_logname is always 1 */
+ get_logname(name, sizeof(name), NULL);
+ logfile = fopen(name, "a");
+
+ if (logfile)
+ setbuf(logfile, NULL);
+ return logfile != NULL ? 0 : -1;
+}
+
+/*************************************************************************/
+
+/* Close the log file. */
+
+void close_log(void)
+{
+ if (!logfile)
+ return;
+ fclose(logfile);
+ logfile = NULL;
+}
+
+/*************************************************************************/
+
+/* added cause this is used over and over in the code */
+char *log_gettimestamp(void)
+{
+ time_t t;
+ struct tm tm;
+ static char tbuf[256];
+
+ time(&t);
+ tm = *localtime(&t);
+#if HAVE_GETTIMEOFDAY
+ if (debug) {
+ char *s;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S", &tm);
+ s = tbuf + strlen(tbuf);
+ s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06d",
+ (int) tv.tv_usec);
+ strftime(s, sizeof(tbuf) - (s - tbuf) - 1, " %Y]", &tm);
+ } else {
+#endif
+ strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S %Y]", &tm);
+#if HAVE_GETTIMEOFDAY
+ }
+#endif
+ return tbuf;
+}
+
+/*************************************************************************/
+
+/* Log stuff to the log file with a datestamp. Note that errno is
+ * preserved by this routine and log_perror().
+ */
+
+void alog(const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int errno_save = errno;
+ char str[BUFSIZE];
+
+ checkday();
+
+ if (!fmt) {
+ return;
+ }
+
+ va_start(args, fmt);
+ vsnprintf(str, sizeof(str), fmt, args);
+ va_end(args);
+
+ buf = log_gettimestamp();
+
+ if (logfile) {
+ fprintf(logfile, "%s %s\n", buf, str);
+ }
+ if (nofork) {
+ fprintf(stderr, "%s %s\n", buf, str);
+ }
+ if (LogChannel && logchan && !debug && findchan(LogChannel)) {
+ privmsg(s_GlobalNoticer, LogChannel, "%s", str);
+ }
+ errno = errno_save;
+}
+
+/*************************************************************************/
+
+/* Like alog(), but tack a ": " and a system error message (as returned by
+ * strerror()) onto the end.
+ */
+
+void log_perror(const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ int errno_save = errno;
+ char str[BUFSIZE];
+
+ checkday();
+
+ if (!fmt) {
+ return;
+ }
+
+ va_start(args, fmt);
+ vsnprintf(str, sizeof(str), fmt, args);
+ va_end(args);
+
+ buf = log_gettimestamp();
+
+ if (logfile) {
+ fprintf(logfile, "%s %s : %s\n", buf, str, strerror(errno_save));
+ }
+ if (nofork) {
+ fprintf(stderr, "%s %s : %s\n", buf, str, strerror(errno_save));
+ }
+ errno = errno_save;
+}
+
+/*************************************************************************/
+
+/* We've hit something we can't recover from. Let people know what
+ * happened, then go down.
+ */
+
+void fatal(const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ char buf2[4096];
+
+ checkday();
+
+ if (!fmt) {
+ return;
+ }
+
+ va_start(args, fmt);
+ vsnprintf(buf2, sizeof(buf2), fmt, args);
+ va_end(args);
+
+ buf = log_gettimestamp();
+
+ if (logfile)
+ fprintf(logfile, "%s FATAL: %s\n", buf, buf2);
+ if (nofork)
+ fprintf(stderr, "%s FATAL: %s\n", buf, buf2);
+ if (servsock >= 0)
+ anope_cmd_global(NULL, "FATAL ERROR! %s", buf2);
+
+ /* one of the many places this needs to be called from */
+ ModuleRunTimeDirCleanUp();
+
+ exit(1);
+}
+
+/*************************************************************************/
+
+/* Same thing, but do it like perror(). */
+
+void fatal_perror(const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ char buf2[4096];
+ int errno_save = errno;
+
+ checkday();
+
+ if (!fmt) {
+ return;
+ }
+
+ va_start(args, fmt);
+ vsnprintf(buf2, sizeof(buf2), fmt, args);
+ va_end(args);
+
+ buf = log_gettimestamp();
+
+ if (logfile)
+ fprintf(logfile, "%s FATAL: %s: %s\n", buf, buf2,
+ strerror(errno_save));
+ if (nofork)
+ fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
+ strerror(errno_save));
+ if (servsock >= 0)
+ anope_cmd_global(NULL, "FATAL ERROR! %s: %s", buf2,
+ strerror(errno_save));
+
+ /* one of the many places this needs to be called from */
+ ModuleRunTimeDirCleanUp();
+
+ exit(1);
+}
+
+/*************************************************************************/
+
+/* Same thing, but do it like perror().
+ * This is for socket errors. On *nix, it works just like fatal_perror,
+ * on Win32, it uses the socket error code and formatting functions.
+ */
+
+void fatal_sockerror(const char *fmt, ...)
+{
+ va_list args;
+ char *buf;
+ char buf2[4096];
+ int errno_save = ano_sockgeterr();
+
+ if (!fmt) {
+ return;
+ }
+
+ checkday();
+
+ /* this will fix 581 */
+ va_start(args, fmt);
+ vsnprintf(buf2, sizeof(buf2), fmt, args);
+ va_end(args);
+
+ buf = log_gettimestamp();
+
+ if (logfile)
+ fprintf(logfile, "%s FATAL: %s: %s\n", buf, buf2,
+ ano_sockstrerror(errno_save));
+ if (stderr)
+ fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
+ ano_sockstrerror(errno_save));
+ if (servsock >= 0)
+ anope_cmd_global(NULL, "FATAL ERROR! %s: %s", buf2,
+ strerror(errno_save));
+
+ /* one of the many places this needs to be called from */
+ ModuleRunTimeDirCleanUp();
+
+ exit(1);
+}