| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /*
- * Copyright (C) 1997 Robey Pointer
- * Copyright (C) 1999 - 2002 Eggheads Development Team
- * Copyright (C) 2002 - 2014 Bryan Drewery
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- /*
- * log.c -- handles:
- *
- * What else?!
- *
- */
- #include "common.h"
- #include "log.h"
- #include "tandem.h"
- #include "color.h"
- #include "userrec.h"
- #include "botnet.h"
- #include "botmsg.h"
- #include "dcc.h"
- #include "dccutil.h"
- #include "rfc1459.h"
- #include "users.h"
- #include "misc.h"
- #include "main.h"
- #include "chanprog.h"
- #include <ctype.h>
- #include <stdarg.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- int conmask = LOG_MODES | LOG_CMDS | LOG_MISC; /* Console mask */
- bool debug_output = 1; /* Disply output to server to LOG_SERVEROUT */
- typedef struct {
- int flag;
- char *type;
- unsigned char c;
- } logmode_mapping_t;
- static logmode_mapping_t logmode_mappings[] = {
- {LOG_MSGS, "msgs", 'm'},
- {LOG_PUBLIC, "public", 'p'},
- {LOG_JOIN, "joins", 'j'},
- {LOG_MODES, "kicks/modes", 'k'},
- {LOG_CMDS, "cmds", 'c'},
- {LOG_MISC, "misc", 'o'},
- {LOG_BOTS, "bots", 'b'},
- {LOG_RAW, "raw", 'r'},
- {LOG_WALL, "wallops", 'w'},
- {LOG_FILES, "files", 'x'},
- {LOG_SERV, "server", 's'},
- {LOG_DEBUG, "debug", 'd'},
- {LOG_SRVOUT, "server output", 'v'},
- {LOG_BOTNET, "botnet traffic", 't'},
- {LOG_BOTSHARE, "share traffic", 'h'},
- {LOG_ERRORS, "errors", 'e'},
- {LOG_GETIN, "getin", 'g'},
- {LOG_WARN, "warnings", 'u'},
- {0, NULL, 0}
- };
- #define LOG_LEVELS 18 /* change this if you change the levels */
- #define NEEDS_DEBUG_OUTPUT (LOG_RAW|LOG_SRVOUT|LOG_BOTNET|LOG_BOTSHARE)
- int logmodes(const char *s)
- {
- logmode_mapping_t *mapping = NULL;
- int modes = 0;
- while (*s) {
- if (*s == '*') return(LOG_ALL);
- for (mapping = logmode_mappings; mapping->type; mapping++) {
- if (mapping->c == tolower(*s)) break;
- }
- if (mapping->type) modes |= mapping->flag;
- s++;
- }
- return(modes);
- }
- char *masktype(int x)
- {
- static char s[LOG_LEVELS + 1];
- char *p = s;
- logmode_mapping_t *mapping = NULL;
- for (mapping = logmode_mappings; mapping->type; mapping++) {
- if (x & mapping->flag) {
- if ((mapping->flag & NEEDS_DEBUG_OUTPUT) && !debug_output) continue;
- *p++ = mapping->c;
- }
- }
- if (p == s) *p++ = '-';
- *p = 0;
- return(s);
- }
- char *maskname(int x)
- {
- static char s[1024] = "";
- logmode_mapping_t *mapping = NULL;
- int len;
- *s = 0;
- for (mapping = logmode_mappings; mapping->type; mapping++) {
- if (x & mapping->flag) {
- if ((mapping->flag & NEEDS_DEBUG_OUTPUT) && !debug_output) continue;
- strlcat(s, mapping->type, sizeof(s));
- strlcat(s, ", ", sizeof(s));
- }
- }
- len = strlen(s);
- if (len) s[len-2] = 0;
- else strlcpy(s, "none", sizeof(s));
- return(s);
- }
- /*
- * Logging functions
- */
- void logidx(int idx, const char *format, ...)
- {
- char va_out[LOGLINEMAX + 1];
- va_list va;
- va_start(va, format);
- egg_vsnprintf(va_out, sizeof(va_out), format, va);
- va_end(va);
- if (idx < 0)
- putlog(LOG_MISC, "*", "%s", va_out);
- else
- dprintf(idx, "%s\n", va_out);
- }
- #ifdef DEBUG
- /* CURRENTLY SPAWNS TONS OF FILES */
- FILE *log_f;
- bool flush_log = 1;
- bool init_log_exit = 0;
- char log_last[LOGLINEMAX + 1] = "";
- int repeats = 0;
- void logfile_close(void)
- {
- if (!log_f)
- return;
- char date[50] = "";
- strftime(date, sizeof date, "%c %Z", gmtime(&now));
- fprintf(log_f, "--- Log session end: %s ---\n", date);
- fclose(log_f);
- log_f = NULL;
- }
- bool logfile_open()
- {
- if (!conf.bot || !conf.bot->nick) return 0;
- char filename[20] = "";
- simple_snprintf(filename, sizeof(filename), ".l-%s", conf.bot->nick);
- if (!(log_f = fopen(filename, "w")))
- return 0;
- if (!init_log_exit) {
- init_log_exit = 1;
- atexit(logfile_close);
- }
- char date[50] = "";
- strftime(date, sizeof date, "%c %Z", gmtime(&now));
- fprintf(log_f, "--- Log session begin: %s ---\n", date);
- return 1;
- }
- #ifdef unused
- bool logfile_stat(const char *fname)
- {
- struct stat st;
- int fd = open(fname, O_RDONLY);
- if (fd == -1 || fstat(fd, &st) < 0) {
- if (fd != -1)
- close(fd);
- fclose(log_f);
- log_f = NULL;
- if (!logfile_open())
- return 0;
- }
- return 1;
- }
- #endif
- void logfile(int type, const char *msg)
- {
- // Only log if this is an actual bot and not a startup/cron proc
- if (!safe_to_log || (!log_f && !logfile_open()))
- return;
- // if (!logfile_stat(".l"))
- // return;
- if (!strncasecmp(msg, log_last, sizeof(log_last))) {
- repeats++;
- return;
- }
- if (repeats) {
- fprintf(log_f, "Last message repeated %d times.\n", repeats);
- repeats = 0;
- }
- strlcpy(log_last, msg, sizeof(log_last));
- fprintf(log_f, "%s\n", msg);
- if (flush_log)
- fflush(log_f);
- }
- #endif
- /* Log something
- * putlog(level,channel_name,format,...);
- * Broadcast the log if chname is not '@'
- */
- char last_log[LOGLINEMAX + 1] = "";
- int log_repeats = 0;
- char last_chname[25] = "";
- int last_type;
- bool log_repeated;
- void putlog(int type, const char *chname, const char *format, ...)
- {
- char va_out[LOGLINEMAX + 1] = "";
- va_list va;
- va_start(va, format);
- egg_vsnprintf(va_out, sizeof(va_out), format, va);
- va_end(va);
- if (!va_out[0]) {
- putlog(LOG_ERRORS, "*", "Empty putlog() detected");
- return;
- }
- if (!log_repeated) {
- if (type == last_type &&
- !strncasecmp(chname, last_chname, sizeof(last_chname)) &&
- !strncasecmp(va_out, last_log, sizeof(last_log))) {
- ++log_repeats;
- return;
- }
- if (log_repeats) {
- log_repeated = 1;
- putlog(type, last_chname, "Last message repeated %d times.\n", log_repeats);
- log_repeats = 0;
- }
- strlcpy(last_log, va_out, sizeof(last_log));
- last_type = type;
- strlcpy(last_chname, chname, sizeof(last_chname));
- } else
- log_repeated = 0;
- char *p = NULL;
- if ((p = strchr(va_out, '\n'))) /* make sure no trailing newline */
- *p = 0;
- int idx = 0;
- char out[LOGLINEMAX + 1] = "";
- if (conf.bot && conf.bot->hub) {
- char stamp[34] = "";
- time_t synced = now + timesync;
- struct tm *t = gmtime(&synced);
- strftime(stamp, sizeof(stamp), LOG_TS, t);
- /* Place the timestamp in the string to be printed */
- strlcpy(out, stamp, sizeof(out));
- strlcat(out, " ", sizeof(out));
- strlcat(out, va_out, sizeof(out));
- } else
- strlcpy(out, va_out, sizeof(out));
- /* strcat(out, "\n"); */
- #ifdef DEBUG
- /* FIXME: WRITE LOG HERE */
- int logfile_masks = LOG_ALL;
- if ((logfile_masks && (logfile_masks & type)) || 1)
- logfile(type, out);
- #endif
- /* broadcast to hubs */
- if (chname[0] == '*' && conf.bot && conf.bot->nick)
- botnet_send_log(-1, conf.bot->nick, type, out, (conf.bot->hub ? 1 : 0));
- for (idx = 0; idx < dcc_total; idx++) {
- if (dcc[idx].type && (dcc[idx].type == &DCC_CHAT && dcc[idx].simul == -1) && (dcc[idx].u.chat->con_flags & type)) {
- if ((chname[0] == '@') || (chname[0] == '*') || (dcc[idx].u.chat->con_chan[0] == '*') ||
- (!rfc_casecmp(chname, dcc[idx].u.chat->con_chan)))
- dprintf(idx, "%s\n", out);
- }
- }
- if ((!backgrd) && (!term_z)) {
- dprintf(DP_STDOUT, "%s\n", out);
- } else if ((type & LOG_ERRORS || type & LOG_MISC) && use_stderr) {
- dprintf(DP_STDERR, "%s\n", va_out);
- }
- }
- void
- irc_log(struct chanset_t *chan, const char *format, ...)
- {
- #ifdef NOTHANKS
- char va_out[LOGLINEMAX + 1];
- va_list va;
- va_start(va, format);
- egg_vsnprintf(va_out, sizeof(va_out), format, va);
- va_end(va);
- if ((chan && strcasecmp(chan->dname, relay_chan)) || !chan) {
- bd::String msg;
- msg = bd::String::printf("[%s] %s", chan ? chan->dname : "*" , va_out);
- privmsg(relay_chan, msg, DP_HELP);
- }
- /*
- chanout_but(-1, 1, "[%s] %s\n", chan->dname, va_out);
- botnet_send_chan(-1, conf.bot->nick, chan->dname, 1, va_out);
- if (chan)
- putlog(LOG_PUBLIC, "*", "[%s] %s", chan->dname, va_out);
- else
- putlog(LOG_PUBLIC, "*", "%s", va_out);
- sdprintf("%s", va_out);
- */
- #endif
- }
- /* vim: set sts=2 sw=2 ts=8 et: */
|