mux2.0/game/
mux2.0/game/data/
mux2.0/src/tools/
/*
 * log.c - logging routines 
 */
/*
 * $Id: log.cpp,v 1.2 2000/04/29 08:05:38 sdennis Exp $ 
 */

#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"

#include <sys/types.h>

#include "db.h"
#include "mudconf.h"
#include "flags.h"
#include "powers.h"
#include "alloc.h"
#include "htab.h"
#include "ansi.h"

#ifndef STANDALONE

NAMETAB logdata_nametab[] =
{
    {(char *)"flags",       1,  0,  LOGOPT_FLAGS},
    {(char *)"location",        1,  0,  LOGOPT_LOC},
    {(char *)"owner",       1,  0,  LOGOPT_OWNER},
    {(char *)"timestamp",       1,  0,  LOGOPT_TIMESTAMP},
    { NULL,             0,  0,  0}
};

NAMETAB logoptions_nametab[] =
{
    {(char *)"accounting",      2,  0,  LOG_ACCOUNTING},
    {(char *)"all_commands",    2,  0,  LOG_ALLCOMMANDS},
    {(char *)"bad_commands",    2,  0,  LOG_BADCOMMANDS},
    {(char *)"buffer_alloc",    3,  0,  LOG_ALLOCATE},
    {(char *)"bugs",            3,  0,  LOG_BUGS},
    {(char *)"checkpoints",     2,  0,  LOG_DBSAVES},
    {(char *)"config_changes",  2,  0,  LOG_CONFIGMODS},
    {(char *)"create",          2,  0,  LOG_PCREATES},
    {(char *)"killing",         1,  0,  LOG_KILLS},
    {(char *)"logins",          1,  0,  LOG_LOGIN},
    {(char *)"network",         1,  0,  LOG_NET},
    {(char *)"problems",        1,  0,  LOG_PROBLEMS},
    {(char *)"security",        2,  0,  LOG_SECURITY},
    {(char *)"shouts",          2,  0,  LOG_SHOUTS},
    {(char *)"startup",         2,  0,  LOG_STARTUP},
    {(char *)"time_usage",      1,  0,  LOG_TIMEUSE},
    {(char *)"wizard",          1,  0,  LOG_WIZARD},
    { NULL,                     0,  0,  0}
};

#endif

/*
 * ---------------------------------------------------------------------------
 * * start_log: see if it is OK to log something, and if so, start writing the
 * * log entry.
 */

int start_log(const char *primary, const char *secondary)
{
    /*
     * Format the timestamp 
     */

    char buffer[256];
    buffer[0] = '\0';
    if ((mudconf.log_info & LOGOPT_TIMESTAMP) != 0)
    {
        CLinearTimeAbsolute ltaNow;
        ltaNow.GetLocal();
        FIELDEDTIME ft;
        ltaNow.ReturnFields(&ft);
        sprintf(buffer, "%d.%02d%02d:%02d%02d%02d ",ft.iYear, ft.iMonth,
                ft.iDayOfMonth, ft.iHour, ft.iMinute, ft.iSecond);
    }

#ifndef STANDALONE
    /*
     * Write the header to the log 
     */

    if (secondary && *secondary)
        Log.printf("%s%s %3s/%-5s: ", buffer, mudconf.mud_name, primary, secondary);
    else
        Log.printf("%s%s %-9s: ", buffer, mudconf.mud_name, primary);
#endif

    return 1;
}

/*
 * ---------------------------------------------------------------------------
 * * end_log: Finish up writing a log entry
 */

void NDECL(end_log)
{
    Log.WriteString("\n");
    Log.Flush();
}

/*
 * ---------------------------------------------------------------------------
 * * log_perror: Write perror message to the log
 */

void log_perror(const char *primary, const char *secondary, const char *extra, const char *failing_object)
{
    start_log(primary, secondary);
    if (extra && *extra)
    {
        log_text((char *)"(");
        log_text((char *)extra);
        log_text((char *)") ");
    }

    // <Failing_object text>: <strerror() text>
    //
    Log.WriteString(failing_object);
    Log.WriteString(": ");
    Log.WriteString(strerror(errno));
#ifndef WIN32
    Log.WriteString("\n");
#endif
    Log.Flush();
}

/*
 * ---------------------------------------------------------------------------
 * * log_text, log_number: Write text or number to the log file.
 */

void log_text(char *text)
{
    Log.WriteString(strip_ansi(text));
}

void log_number(int num)
{
    Log.WriteInteger(num);
}

/*
 * ---------------------------------------------------------------------------
 * * log_name: write the name, db number, and flags of an object to the log.
 * * If the object does not own itself, append the name, db number, and flags
 * * of the owner.
 */

void log_name(dbref target)
{
#ifndef STANDALONE
    char *tp;

    if ((mudconf.log_info & LOGOPT_FLAGS) != 0)
        tp = unparse_object((dbref) GOD, target, 0);
    else
        tp = unparse_object_numonly(target);
    Log.WriteString(strip_ansi(tp));
    free_lbuf(tp);
    if (((mudconf.log_info & LOGOPT_OWNER) != 0) &&
        (target != Owner(target))) {
        if ((mudconf.log_info & LOGOPT_FLAGS) != 0)
            tp = unparse_object((dbref) GOD, Owner(target), 0);
        else
            tp = unparse_object_numonly(Owner(target));
        Log.printf("[%s]", strip_ansi(tp));
        free_lbuf(tp);
    }
#else
    Log.printf("%s(#%d)", Name(target), target);
#endif
    return;
}

/*
 * ---------------------------------------------------------------------------
 * * log_name_and_loc: Log both the name and location of an object
 */

void log_name_and_loc(dbref player)
{
    log_name(player);
    if ((mudconf.log_info & LOGOPT_LOC) && Has_location(player)) {
        log_text((char *)" in ");
        log_name(Location(player));
    }
    return;
}

char *OBJTYP(dbref thing)
{
    if (!Good_obj(thing)) {
        return (char *)"??OUT-OF-RANGE??";
    }
    switch (Typeof(thing)) {
    case TYPE_PLAYER:
        return (char *)"PLAYER";
    case TYPE_THING:
        return (char *)"THING";
    case TYPE_ROOM:
        return (char *)"ROOM";
    case TYPE_EXIT:
        return (char *)"EXIT";
    case TYPE_GARBAGE:
        return (char *)"GARBAGE";
    default:
        return (char *)"??ILLEGAL??";
    }
}

void log_type_and_name(dbref thing)
{
    char nbuf[16];

    log_text(OBJTYP(thing));
    sprintf(nbuf, " #%d(", thing);
    log_text(nbuf);
    if (Good_obj(thing))
        log_text(Name(thing));
    log_text((char *)")");
    return;
}

void log_type_and_num(dbref thing)
{
    char nbuf[16];

    log_text(OBJTYP(thing));
    sprintf(nbuf, " #%d", thing);
    log_text(nbuf);
    return;
}

#ifndef STANDALONE
void do_log(dbref player, dbref cause, int key, char *whichlog, char *logtext)
{
    BOOL bValid = TRUE;

    // Strip the filename of all ANSI.
    //
    char *pFilename = strip_ansi(whichlog);

    // Restrict filename to a subdirectory to reduce the possibility
    // of a security hole.
    //
    char *temp_ptr = strrchr(pFilename, '/');
    if (temp_ptr)
    {
        pFilename = ++temp_ptr;
    }
    temp_ptr = strrchr(pFilename, '\\');
    if (temp_ptr)
    {
        pFilename = ++temp_ptr;
    }

    // Check for and disallow leading periods, empty strings
    // and filenames over 30 characters.
    //
    if (  pFilename[0] == '\0'
       || pFilename[0] == '.'
       || strlen(pFilename) > 30)
    {
        bValid = FALSE;
    }

    char *pFullName = 0;
    char *pMessage;
    if (bValid)
    {
        pFullName = alloc_lbuf("do_log_filename");
        sprintf(pFullName, "logs/%s", pFilename);

        // Strip the message of all ANSI.
        //
        pMessage = strip_ansi(logtext);

        // Check for and disallow empty messages.
        //
        if (pMessage[0] == '\0')
        {
            bValid = FALSE;
        }
    }
    if (!bValid)
    {
        if (pFullName) free_lbuf(pFullName);
        notify(player, "Syntax: @log file=message");
        return;
    }

    FILE *hFile = fopen(pFullName, "a");
    if (hFile == NULL)
    {
        notify(player, "Not a valid log file.");
        if (pFullName) free_lbuf(pFullName);
        return;
    }

    // Okay, at this point, the file exists.
    //
    fprintf(hFile, "%s\n", pMessage);
    fclose(hFile);                        /* Send and close... */
    free_lbuf(pFullName);
}
#endif