#include <stdio.h> #include <stdlib.h> /* #include <unistd.h> */ #include <sys/types.h> #include <stdarg.h> #include <time.h> #include <string.h> #include <sys/timeb.h> #include "global.h" #include "utils.h" #include "comm.h" #include "multiclass.h" #include "db.h" #define _BUG_C #include "bug.h" const char *LogNames[] = { "INFO", "ERROR", "FATAL", "BOOT", "AUTH", "KILL", "DEATH", "RESET", "IMC" }; /* Handy query for checking logs: * * select to_char(date_trunc('second', log_date), 'HH24:MI:SS'), log_types.name, log_entry * from logfile join log_types using (log_type_id) * where log_date > now() - interval '1 day' * order by log_date desc * limit 20; */ /* * Things we want to have when logging events..... * * BugFile is the filename you want to log to, NULL means stderr * * File, Func, Line can all be provided by the compiler as * __FILE__, __PRETTY_FUNCTION__, and __LINE__ * * Level is the minimum character level which will see the * bug if they're logged in. * * The AreaFile and AreaLine are the file and line number * we were reading while booting the world database. * * Type is the type of error, typically things like * LOG_INFO, LOG_ERROR, LOG_FATAL, LOG_BOOT, LOG_AUTH * * ch is the char_data pointer for the player/mob * obj is an obj_data pointer, if you have one * room is.... the room_data pointer. * * Str is, of course, the message, and it gets printed * using varargs, so you can have this be a printf type * set of macros. */ void bug_logger(unsigned int Type, const char *BugFile, const char *File, const char *Func, int Line, const char *AreaFile, int AreaLine, struct char_data *ch, struct char_data *victim, unsigned int Level, const char *Str, ...) { va_list arg; char Result[MAX_STRING_LENGTH] = "\0\0\0"; char Temp[MAX_STRING_LENGTH] = "\0\0\0"; FILE *fp = NULL; struct timeb right_now; struct tm *now_part = NULL; bzero(Result, MAX_STRING_LENGTH); va_start(arg, Str); if (Str && *Str) { struct descriptor_data *i; sprintf(Result, "%s> ", LogNames[Type]); vsprintf(Temp, Str, arg); strcat(Result, Temp); for (i = descriptor_list; i; i = i->next) if ((!i->connected) && (GetMaxLevel(i->character) >= Level) && (IS_SET(i->character->specials.act, PLR_LOGS))) write_to_q(Result, &i->output, 1); bzero(Result, MAX_STRING_LENGTH); } else strcpy(Temp, "PING!"); va_end(arg); ftime(&right_now); now_part = localtime((const time_t *)&right_now); sprintf(Result, "<: %02d%02d%02d.%02d%02d%02d.%03d", now_part->tm_year, now_part->tm_mon + 1, now_part->tm_mday, now_part->tm_hour, now_part->tm_min, now_part->tm_sec, right_now.millitm); sprintf(Result + strlen(Result), " - %s -", LogNames[Type]); if (File || Func || Line) { strcat(Result, " ("); if (File && *File) { strcat(Result, File); } if (Func && *Func) sprintf(Result + strlen(Result), ";%s", Func); if (Line) sprintf(Result + strlen(Result), ",%d)", Line); else strcat(Result, ")"); } if (ch || victim) { if (ch) sprintf(Result + strlen(Result), " ch \"%s\" [#%d]", NAME(ch), ch->in_room); if (victim) sprintf(Result + strlen(Result), " victim \"%s\" [#%d]", NAME(victim), victim->in_room); /* if (obj) sprintf(Result + strlen(Result), " obj \"%s\" [#%d]", SAFE_ONAME(obj), obj->in_room); if (room) sprintf(Result + strlen(Result), " room \"%s\" [#%d]", room->name?room->name:"", room->number); */ strcat(Result, "\n"); } else if (File || Func || Line) strcat(Result, "\n"); strcat(Result, " : "); strcat(Result, Temp); if (BugFile && *BugFile) { if (!(fp = fopen(BugFile, "a"))) { perror(BugFile); if (ch) send_to_char("Could not open the file!\r\n", ch); } else { fprintf(fp, "%s\n", Result); FCLOSE(fp); } } if (stderr) { fprintf(stderr, "%s\n", Result); fflush(stderr); } }