src/log.c

Go to the documentation of this file.
00001 /*
00002  * log.c - logging routines 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include <sys/types.h>
00009 #include <sys/time.h>
00010 #include <time.h>
00011 
00012 #include "db.h"
00013 #include "mudconf.h"
00014 #include "externs.h"
00015 #include "flags.h"
00016 #include "powers.h"
00017 #include "alloc.h"
00018 #include "htab.h"
00019 #include "ansi.h"
00020 #ifdef ARBITRARY_LOGFILES
00021 #include "logcache.h"
00022 #endif
00023 
00024 NAMETAB logdata_nametab[] = {
00025         {(char *) "flags", 1, 0, LOGOPT_FLAGS},
00026         {(char *) "location", 1, 0, LOGOPT_LOC},
00027         {(char *) "owner", 1, 0, LOGOPT_OWNER},
00028         {(char *) "timestamp", 1, 0, LOGOPT_TIMESTAMP},
00029         {NULL, 0, 0, 0}
00030 };
00031 
00032 NAMETAB logoptions_nametab[] = {
00033         {(char *) "accounting", 2, 0, LOG_ACCOUNTING},
00034         {(char *) "all_commands", 2, 0, LOG_ALLCOMMANDS},
00035         {(char *) "suspect_commands", 2, 0, LOG_SUSPECTCMDS},
00036         {(char *) "bad_commands", 2, 0, LOG_BADCOMMANDS},
00037         {(char *) "buffer_alloc", 3, 0, LOG_ALLOCATE},
00038         {(char *) "bugs", 3, 0, LOG_BUGS},
00039         {(char *) "checkpoints", 2, 0, LOG_DBSAVES},
00040         {(char *) "config_changes", 2, 0, LOG_CONFIGMODS},
00041         {(char *) "create", 2, 0, LOG_PCREATES},
00042         {(char *) "killing", 1, 0, LOG_KILLS},
00043         {(char *) "logins", 1, 0, LOG_LOGIN},
00044         {(char *) "network", 1, 0, LOG_NET},
00045         {(char *) "problems", 1, 0, LOG_PROBLEMS},
00046         {(char *) "security", 2, 0, LOG_SECURITY},
00047         {(char *) "shouts", 2, 0, LOG_SHOUTS},
00048         {(char *) "startup", 2, 0, LOG_STARTUP},
00049         {(char *) "wizard", 1, 0, LOG_WIZARD},
00050         {NULL, 0, 0, 0}
00051 };
00052 
00053 char *strip_ansi_r(char *dest, const char *raw, size_t n)
00054 {
00055         char *p = (char *) raw;
00056         char *q = dest;
00057 
00058         while (p && *p && ((q - dest) < n)) {
00059                 if(*p == ESC_CHAR) {
00060                         /*
00061                          * Start of ANSI code. Skip to end. 
00062                          */
00063                         while (*p && !isalpha(*p))
00064                                 p++;
00065                         if(*p)
00066                                 p++;
00067                 } else
00068                         *q++ = *p++;
00069         }
00070         *q = '\0';
00071         return dest;
00072 }
00073 
00074 char *normal_to_white_r(char *dest, const char *raw, size_t n) {
00075     char *p = (char *) raw;
00076         char *q = dest;
00077     
00078         while (p && *p && ((q - dest) < n)) {
00079                 if(*p == ESC_CHAR) {
00080                         /*
00081                          * Start of ANSI code. 
00082                          */
00083                         *q++ = *p++;            /*
00084                                                                  * ESC CHAR 
00085                                                                  */
00086                         *q++ = *p++;            /*
00087                                                                  * [ character. 
00088                                                                  */
00089                         if(*p == '0') {
00090                 if((q - dest + 7) < n) {
00091                     memcpy(q, "0m\x1b[37m", 7);
00092                     q += 7;
00093                 }
00094                                 p += 2;
00095                         }
00096                 } else
00097                         *q++ = *p++;
00098         }
00099         *q = '\0';
00100         return dest;
00101 }
00102 
00107 int start_log(const char *primary, const char *secondary)
00108 {
00109         struct tm *tp;
00110         time_t now;
00111 
00112         mudstate.logging++;
00113         switch (mudstate.logging) {
00114         case 1:
00115         case 2:
00116 
00117                 /*
00118                  * Format the timestamp 
00119                  */
00120 
00121                 if((mudconf.log_info & LOGOPT_TIMESTAMP) != 0) {
00122                         time((time_t *) (&now));
00123                         tp = localtime((time_t *) (&now));
00124                         sprintf(mudstate.buffer, "%d%02d%02d.%02d%02d%02d ",
00125                                         tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday,
00126                                         tp->tm_hour, tp->tm_min, tp->tm_sec);
00127                 } else {
00128                         mudstate.buffer[0] = '\0';
00129                 }
00130 
00131                 /*
00132                  * Write the header to the log 
00133                  */
00134 
00135                 if(secondary && *secondary)
00136                         fprintf(stderr, "%s%s %3s/%-5s: ", mudstate.buffer,
00137                                         mudconf.mud_name, primary, secondary);
00138                 else
00139                         fprintf(stderr, "%s%s %-9s: ", mudstate.buffer,
00140                                         mudconf.mud_name, primary);
00141                 /*
00142                  * If a recursive call, log it and return indicating no log 
00143                  */
00144 
00145                 if(mudstate.logging == 1)
00146                         return 1;
00147                 fprintf(stderr, "Recursive logging request.\r\n");
00148         default:
00149                 mudstate.logging--;
00150         }
00151         return 0;
00152 }
00153 
00157 void end_log(void)
00158 {
00159         fprintf(stderr, "\n");
00160         fflush(stderr);
00161         mudstate.logging--;
00162 }
00163 
00167 void log_perror(const char *primary, const char *secondary, const char *extra,
00168                                 const char *failing_object)
00169 {
00170         start_log(primary, secondary);
00171         if(extra && *extra) {
00172                 log_text((char *) "(");
00173                 log_text((char *) extra);
00174                 log_text((char *) ") ");
00175         }
00176         perror((char *) failing_object);
00177         fflush(stderr);
00178         mudstate.logging--;
00179 }
00180 
00184 void log_text(char *text)
00185 {
00186         char new[LBUF_SIZE];
00187         strncpy(new, text, LBUF_SIZE-1);
00188         fprintf(stderr, "%s", strip_ansi_r(new,text,strlen(text)));
00189 }
00190 
00191 void log_error(int key, char *primary, char *secondary, char *format, ...)
00192 {
00193         char buffer[LBUF_SIZE];
00194         char stripped_buffer[LBUF_SIZE];
00195         va_list ap;
00196 
00197     if(!(key & mudconf.log_options))
00198                 return;
00199 
00200         if(mudconf.log_info & LOGOPT_TIMESTAMP) {
00201                 time_t now;
00202                 struct tm tm;
00203                 time(&now);
00204                 localtime_r(&now, &tm);
00205                 fprintf(stderr, "%d%02d%02d.%02d%02d%02d ",
00206                                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
00207                                 tm.tm_hour, tm.tm_min, tm.tm_sec);
00208         }
00209 
00210         if(secondary && &secondary) {
00211                 fprintf(stderr, "%s%s %3s/%-5s: ", mudstate.buffer,
00212                                 mudconf.mud_name, primary, secondary);
00213         } else {
00214                 fprintf(stderr, "%s%s %-9s: ", mudstate.buffer,
00215                                 mudconf.mud_name, primary);
00216         }
00217 
00218         va_start(ap, format);
00219         vsnprintf(buffer, LBUF_SIZE, format, ap);
00220         va_end(ap);
00221 
00222         strip_ansi_r(stripped_buffer, buffer, LBUF_SIZE);
00223         fprintf(stderr, "%s\n", stripped_buffer);
00224 }
00225 
00226 void log_printf(char *format, ...)
00227 {
00228         char buffer[LBUF_SIZE];
00229         char stripped_buffer[LBUF_SIZE];
00230         va_list ap;
00231 
00232         va_start(ap, format);
00233         vsnprintf(buffer, LBUF_SIZE, format, ap);
00234         va_end(ap);
00235 
00236         strip_ansi_r(stripped_buffer, buffer, LBUF_SIZE);
00237         fprintf(stderr, "%s\n", stripped_buffer);
00238 }
00239 
00240 /*
00241  * Write a number to log file.
00242  */
00243 void log_number(int num)
00244 {
00245         fprintf(stderr, "%d", num);
00246 }
00247 
00253 void log_name(dbref target)
00254 {
00255         char *tp;
00256         char new[LBUF_SIZE];
00257 
00258         if((mudconf.log_info & LOGOPT_FLAGS) != 0)
00259                 tp = unparse_object((dbref) GOD, target, 0);
00260         else
00261                 tp = unparse_object_numonly(target);
00262         strncpy(new, tp, LBUF_SIZE-1);
00263         fprintf(stderr, "%s", strip_ansi_r(new,tp,strlen(tp)));
00264         free_lbuf(tp);
00265         if(((mudconf.log_info & LOGOPT_OWNER) != 0) && (target != Owner(target))) {
00266                 if((mudconf.log_info & LOGOPT_FLAGS) != 0)
00267                         tp = unparse_object((dbref) GOD, Owner(target), 0);
00268                 else
00269                         tp = unparse_object_numonly(Owner(target));
00270                 strncpy(new, tp, LBUF_SIZE-1);
00271                 fprintf(stderr, "[%s]", strip_ansi_r(new,tp,strlen(tp)));
00272                 free_lbuf(tp);
00273         }
00274         return;
00275 }
00276 
00280 void log_name_and_loc(dbref player)
00281 {
00282         log_name(player);
00283         if((mudconf.log_info & LOGOPT_LOC) && Has_location(player)) {
00284                 log_text((char *) " in ");
00285                 log_name(Location(player));
00286         }
00287         return;
00288 }
00289 
00290 /*
00291  * Returns the object type of specified object.
00292  */
00293 char *OBJTYP(dbref thing)
00294 {
00295         if(!Good_obj(thing)) {
00296                 return (char *) "??OUT-OF-RANGE??";
00297         }
00298         switch (Typeof(thing)) {
00299         case TYPE_PLAYER:
00300                 return (char *) "PLAYER";
00301         case TYPE_THING:
00302                 return (char *) "THING";
00303         case TYPE_ROOM:
00304                 return (char *) "ROOM";
00305         case TYPE_EXIT:
00306                 return (char *) "EXIT";
00307         case TYPE_GARBAGE:
00308                 return (char *) "GARBAGE";
00309         default:
00310                 return (char *) "??ILLEGAL??";
00311         }
00312 }
00313 
00314 void log_type_and_name(dbref thing)
00315 {
00316         char nbuf[16];
00317 
00318         log_text(OBJTYP(thing));
00319         sprintf(nbuf, " #%d(", thing);
00320         log_text(nbuf);
00321         if(Good_obj(thing))
00322                 log_text(Name(thing));
00323         log_text((char *) ")");
00324         return;
00325 }
00326 
00327 void log_type_and_num(dbref thing)
00328 {
00329         char nbuf[16];
00330 
00331         log_text(OBJTYP(thing));
00332         sprintf(nbuf, " #%d", thing);
00333         log_text(nbuf);
00334         return;
00335 }
00336 
00337 #ifdef ARBITRARY_LOGFILES
00338 int log_to_file(dbref thing, const char *logfile, const char *message)
00339 {
00340         char pathname[210];                     /* Arbitrary limit in logfile length */
00341         char message_buffer[4096];
00342 
00343         if(!message || !*message)
00344                 return 1;                               /* Nothing to do */
00345 
00346         if(!logfile || !*logfile || strlen(logfile) > 200)
00347                 return 0;                               /* invalid logfile name */
00348 
00349         if(strstr(pathname, "..") != NULL)
00350                 return 0;
00351         if(strstr(pathname, "/") != NULL)
00352                 return 0;
00353         snprintf(pathname, 210, "logs/%s", logfile);
00354 
00355         /* Hacking checks. */
00356 
00357         if(access(pathname, R_OK | W_OK) != 0)
00358                 return 0;
00359 
00360         snprintf(message_buffer, 4096, "%s\n", message);
00361 
00362         if(!logcache_writelog(pathname, message_buffer)) {
00363                 notify(thing, "Serious failure while trying to write to log.");
00364                 return 0;
00365         }
00366         return 1;
00367 }
00368 
00369 void do_log(dbref player, dbref cause, int key, char *logfile, char *message)
00370 {
00371         if(!message || !*message) {
00372                 notify(player, "Nothing to log!");
00373                 return;
00374         }
00375 
00376         if(!logfile || !*logfile) {
00377                 notify(player, "Invalid logfile.");
00378                 return;
00379         }
00380 
00381         if(!log_to_file(player, logfile, message)) {
00382                 notify(player, "Request failed.");
00383                 return;
00384         }
00385 
00386         notify(player, "Message logged.");
00387 }
00388 #endif

Generated on Mon May 28 04:25:24 2007 for BattletechMUX by  doxygen 1.4.7