mux/src/log.cpp

Go to the documentation of this file.
00001 // log.cpp -- Logging routines.
00002 //
00003 // $Id: log.cpp,v 1.9 2006/01/07 19:57:38 sdennis Exp $
00004 //
00005 
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010 
00011 #include <sys/types.h>
00012 
00013 #include "command.h"
00014 
00015 NAMETAB logdata_nametab[] =
00016 {
00017     {"flags",           1,  0,  LOGOPT_FLAGS},
00018     {"location",        1,  0,  LOGOPT_LOC},
00019     {"owner",           1,  0,  LOGOPT_OWNER},
00020     {"timestamp",       1,  0,  LOGOPT_TIMESTAMP},
00021     { NULL,             0,  0,  0}
00022 };
00023 
00024 NAMETAB logoptions_nametab[] =
00025 {
00026     {"accounting",      2,  0,  LOG_ACCOUNTING},
00027     {"all_commands",    2,  0,  LOG_ALLCOMMANDS},
00028     {"bad_commands",    2,  0,  LOG_BADCOMMANDS},
00029     {"buffer_alloc",    3,  0,  LOG_ALLOCATE},
00030     {"bugs",            3,  0,  LOG_BUGS},
00031     {"checkpoints",     2,  0,  LOG_DBSAVES},
00032     {"config_changes",  2,  0,  LOG_CONFIGMODS},
00033     {"create",          2,  0,  LOG_PCREATES},
00034     {"killing",         1,  0,  LOG_KILLS},
00035     {"logins",          1,  0,  LOG_LOGIN},
00036     {"network",         1,  0,  LOG_NET},
00037     {"problems",        1,  0,  LOG_PROBLEMS},
00038     {"security",        2,  0,  LOG_SECURITY},
00039     {"shouts",          2,  0,  LOG_SHOUTS},
00040     {"startup",         2,  0,  LOG_STARTUP},
00041     {"suspect",         2,  0,  LOG_SUSPECTCMDS},
00042     {"time_usage",      1,  0,  LOG_TIMEUSE},
00043     {"wizard",          1,  0,  LOG_WIZARD},
00044     { NULL,                     0,  0,  0}
00045 };
00046 
00047 /* ---------------------------------------------------------------------------
00048  * start_log: see if it is OK to log something, and if so, start writing the
00049  * log entry.
00050  */
00051 
00052 bool start_log(const char *primary, const char *secondary)
00053 {
00054     mudstate.logging++;
00055     if (  1 <= mudstate.logging
00056        && mudstate.logging <= 2)
00057     {
00058         if (!mudstate.bStandAlone)
00059         {
00060             // Format the timestamp.
00061             //
00062             char buffer[256];
00063             buffer[0] = '\0';
00064             if (mudconf.log_info & LOGOPT_TIMESTAMP)
00065             {
00066                 CLinearTimeAbsolute ltaNow;
00067                 ltaNow.GetLocal();
00068                 FIELDEDTIME ft;
00069                 ltaNow.ReturnFields(&ft);
00070                 sprintf(buffer, "%d.%02d%02d:%02d%02d%02d ",ft.iYear,
00071                     ft.iMonth, ft.iDayOfMonth, ft.iHour, ft.iMinute,
00072                     ft.iSecond);
00073             }
00074 
00075             // Write the header to the log.
00076             //
00077             if (  secondary
00078                && *secondary)
00079             {
00080                 Log.tinyprintf("%s%s %3s/%-5s: ", buffer, mudconf.mud_name,
00081                     primary, secondary);
00082             }
00083             else
00084             {
00085                 Log.tinyprintf("%s%s %-9s: ", buffer, mudconf.mud_name,
00086                     primary);
00087             }
00088         }
00089 
00090         // If a recursive call, log it and return indicating no log.
00091         //
00092         if (mudstate.logging == 1)
00093         {
00094             return true;
00095         }
00096         Log.WriteString("Recursive logging request." ENDLINE);
00097     }
00098     mudstate.logging--;
00099     return false;
00100 }
00101 
00102 /* ---------------------------------------------------------------------------
00103  * end_log: Finish up writing a log entry
00104  */
00105 
00106 void end_log(void)
00107 {
00108     Log.WriteString(ENDLINE);
00109     Log.Flush();
00110     mudstate.logging--;
00111 }
00112 
00113 /* ---------------------------------------------------------------------------
00114  * log_perror: Write perror message to the log
00115  */
00116 
00117 void log_perror(const char *primary, const char *secondary, const char *extra, const char *failing_object)
00118 {
00119     start_log(primary, secondary);
00120     if (extra && *extra)
00121     {
00122         log_text("(");
00123         log_text(extra);
00124         log_text(") ");
00125     }
00126 
00127     // <Failing_object text>: <strerror() text>
00128     //
00129     Log.WriteString(failing_object);
00130     Log.WriteString(": ");
00131     Log.WriteString(strerror(errno));
00132 #ifndef WIN32
00133     Log.WriteString(ENDLINE);
00134 #endif // !WIN32
00135     Log.Flush();
00136     mudstate.logging--;
00137 }
00138 
00139 /* ---------------------------------------------------------------------------
00140  * log_text, log_number: Write text or number to the log file.
00141  */
00142 
00143 void log_text(const char *text)
00144 {
00145     Log.WriteString(strip_ansi(text));
00146 }
00147 
00148 void log_number(int num)
00149 {
00150     Log.WriteInteger(num);
00151 }
00152 
00153 void DCL_CDECL log_printf(const char *fmt, ...)
00154 {
00155     va_list ap;
00156     va_start(ap, fmt);
00157     char aTempBuffer[SIZEOF_LOG_BUFFER];
00158     int nString = mux_vsnprintf(aTempBuffer, SIZEOF_LOG_BUFFER, fmt, ap);
00159     va_end(ap);
00160     Log.WriteBuffer(nString, aTempBuffer);
00161 }
00162 
00163 /* ---------------------------------------------------------------------------
00164  * log_name: write the name, db number, and flags of an object to the log.
00165  * If the object does not own itself, append the name, db number, and flags
00166  * of the owner.
00167  */
00168 
00169 void log_name(dbref target)
00170 {
00171     if (mudstate.bStandAlone)
00172     {
00173         Log.tinyprintf("%s(#%d)", Name(target), target);
00174     }
00175     else
00176     {
00177         char *tp;
00178 
00179         if (mudconf.log_info & LOGOPT_FLAGS)
00180         {
00181             tp = unparse_object(GOD, target, false);
00182         }
00183         else
00184         {
00185             tp = unparse_object_numonly(target);
00186         }
00187         Log.WriteString(strip_ansi(tp));
00188         free_lbuf(tp);
00189         if (  (mudconf.log_info & LOGOPT_OWNER)
00190            && target != Owner(target))
00191         {
00192             if (mudconf.log_info & LOGOPT_FLAGS)
00193             {
00194                 tp = unparse_object(GOD, Owner(target), false);
00195             }
00196             else
00197             {
00198                 tp = unparse_object_numonly(Owner(target));
00199             }
00200             Log.tinyprintf("[%s]", strip_ansi(tp));
00201             free_lbuf(tp);
00202         }
00203     }
00204 }
00205 
00206 /* ---------------------------------------------------------------------------
00207  * log_name_and_loc: Log both the name and location of an object
00208  */
00209 
00210 void log_name_and_loc(dbref player)
00211 {
00212     log_name(player);
00213     if (  (mudconf.log_info & LOGOPT_LOC)
00214        && Has_location(player))
00215     {
00216         log_text(" in ");
00217         log_name(Location(player));
00218     }
00219     return;
00220 }
00221 
00222 static const char *OBJTYP(dbref thing)
00223 {
00224     if (!Good_dbref(thing))
00225     {
00226         return "??OUT-OF-RANGE??";
00227     }
00228     switch (Typeof(thing))
00229     {
00230     case TYPE_PLAYER:
00231         return "PLAYER";
00232     case TYPE_THING:
00233         return "THING";
00234     case TYPE_ROOM:
00235         return "ROOM";
00236     case TYPE_EXIT:
00237         return "EXIT";
00238     case TYPE_GARBAGE:
00239         return "GARBAGE";
00240     default:
00241         return "??ILLEGAL??";
00242     }
00243 }
00244 
00245 void log_type_and_name(dbref thing)
00246 {
00247     char nbuf[16];
00248 
00249     log_text(OBJTYP(thing));
00250     sprintf(nbuf, " #%d(", thing);
00251     log_text(nbuf);
00252     if (Good_obj(thing))
00253     {
00254         log_text(Name(thing));
00255     }
00256     log_text(")");
00257     return;
00258 }
00259 
00260 void do_log
00261 (
00262     dbref executor,
00263     dbref caller,
00264     dbref enactor,
00265     int   key,
00266     int   nargs,
00267     char *whichlog,
00268     char *logtext
00269 )
00270 {
00271     UNUSED_PARAMETER(caller);
00272     UNUSED_PARAMETER(enactor);
00273     UNUSED_PARAMETER(key);
00274     UNUSED_PARAMETER(nargs);
00275 
00276     bool bValid = true;
00277 
00278     // Strip the filename of all ANSI.
00279     //
00280     char *pFilename = strip_ansi(whichlog);
00281 
00282     // Restrict filename to a subdirectory to reduce the possibility
00283     // of a security hole.
00284     //
00285     char *temp_ptr = strrchr(pFilename, '/');
00286     if (temp_ptr)
00287     {
00288         pFilename = ++temp_ptr;
00289     }
00290     temp_ptr = strrchr(pFilename, '\\');
00291     if (temp_ptr)
00292     {
00293         pFilename = ++temp_ptr;
00294     }
00295 
00296     // Check for and disallow leading periods, empty strings
00297     // and filenames over 30 characters.
00298     //
00299     size_t n = strlen(pFilename);
00300     if (  n == 0
00301        || n > 30)
00302     {
00303         bValid = false;
00304     }
00305     else
00306     {
00307         unsigned int i;
00308         for (i = 0; i < n; i++)
00309         {
00310             if (!mux_isalnum(pFilename[i]))
00311             {
00312                 bValid = false;
00313                 break;
00314             }
00315         }
00316     }
00317 
00318     char *pFullName = NULL;
00319     char *pMessage = "";
00320     if (bValid)
00321     {
00322         pFullName = alloc_lbuf("do_log_filename");
00323         sprintf(pFullName, "logs/M-%s.log", pFilename);
00324 
00325         // Strip the message of all ANSI.
00326         //
00327         pMessage = strip_ansi(logtext);
00328 
00329         // Check for and disallow empty messages.
00330         //
00331         if (pMessage[0] == '\0')
00332         {
00333             bValid = false;
00334         }
00335     }
00336     if (!bValid)
00337     {
00338         if (pFullName) free_lbuf(pFullName);
00339         notify(executor, "Syntax: @log file=message");
00340         return;
00341     }
00342 
00343     FILE *hFile = fopen(pFullName, "r");
00344     if (hFile)
00345     {
00346         fclose(hFile);
00347         hFile = fopen(pFullName, "a");
00348     }
00349     if (hFile == NULL)
00350     {
00351         notify(executor, "Not a valid log file.");
00352         if (pFullName) free_lbuf(pFullName);
00353         return;
00354     }
00355 
00356     // Okay, at this point, the file exists.
00357     //
00358     fprintf(hFile, "%s" ENDLINE, pMessage);
00359     fclose(hFile);
00360     free_lbuf(pFullName);
00361 }

Generated on Mon May 28 04:40:10 2007 for MUX by  doxygen 1.4.7