/
Sapphire/bin/
Sapphire/db/
Sapphire/db/OLC_rooms/
Sapphire/db/abi/
Sapphire/db/em_src/
Sapphire/db/helps/
Sapphire/db/helps/emman/ifunc/
Sapphire/db/npcs/Tatt/
Sapphire/db/objects/Tatt/
Sapphire/db/q_data/
Sapphire/db/rooms/Tatt/
Sapphire/doc/
Sapphire/doc/em/
Sapphire/etc/
Sapphire/src/abic/
Sapphire/src/areacon/
Sapphire/src/client/
Sapphire/src/embc/
Sapphire/src/emi/
Sapphire/src/emi/test/
Sapphire/src/include/
Sapphire/src/sapphire/em/
Sapphire/src/tcon/
/*
 * Copyright (C) 1995-1997 Christopher D. Granz
 *
 * This header may not be removed.
 *
 * Refer to the file "License" included in this package for further
 * information and before using any of the following.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <kvm.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/user.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>

#include "sapphire.h"


/*
 * Functions
 */

/*
 * WARNING: This command can be very dangerous.
 *
 * Removes a player file from the player directory.
 */
void cmd_delete( CHAR_DATA *pChar, char *pArgument )
{
    FILE *pFile;
    TERM_DATA *pTerm;
    CHAR_DATA *pDelChar;
    char cArg[MAX_INPUT];
    char cBuf[MAX_STRING];
    char cBuf2[MAX_STRING];
    int i;

    if ( IS_NPC( pChar ) )
    {
        send_string( pChar, "This command is not for NPCs.\n\r" );
        return;
    }

    one_arg( pArgument, cArg );

    if ( cArg[0] == '\0' )
    {
        send_string( pChar, "Usage: delete <player name>\n\r" );
        return;
    }

    if ( str_compare( pChar->pPCData->sName, cArg ) == TRUE )
    {
        send_string( pChar, "Now why would you want to do that?\n\r" );
        return;
    }

    sprintf( cBuf, "%s%s.plr", pPlayerDir,
      strcpy( cArg, capit( cArg ) ) );

    if ( ( pFile = fopen( cBuf, "r" ) ) == NULL )
    {
        send_string( pChar, "No such player.\n\r" );
        return;
    }

    fclose( pFile );
    sprintf( cBuf2, "%s%s.plr.del", pTempDir, cArg );
    rename( cBuf, cBuf2 );
    send_string( pChar, "Player deleted.\n\r" );

    for ( i = 0; i < iHashListSize; i++ )
    {
        for ( pDelChar = ppCharList[i]; pDelChar != NULL;
          pDelChar = pDelChar->pNext )
        {
            if ( !IS_NPC( pDelChar )
              && strcmp( pDelChar->pPCData->sName, cArg ) == 0 )
                goto end;
        }
    }

    return;

end:
    cmd_save( pDelChar, "" );
    send_game_message( "~c fades out of this world, gone forever.",
      MESSAGE_DEST_ROOM, TRUE, pDelChar, NULL, pDelChar->pInRoom, TRUE,
      NUMBER_POSITION_RESTING, pDelChar );
    send_string( pDelChar,
      "You are being deleted.\n\r" );
    lprintf( "%s has left the game.", cArg );
    pTerm = pDelChar->pTerm;
    free_char( &pDelChar );

    if ( pTerm != NULL )
    {
        pTerm->pChar = NULL;
        close_connection( &pTerm );
    }
}

#ifdef DEBUG
/*
 * Core dump and still keep the game running :)
 */
void cmd_coredump( CHAR_DATA *pChar, char *pArgument )
{
    char cBuf[1024];
    char cBuf2[1024];
    pid_t pPid;
    int i;

    if ( IS_NPC( pChar ) )
    {
        send_string( pChar, "This command is not for NPCs.\n\r" );
        return;
    }

    do
    {
        errno = 0;
        pPid  = fork( );
    }
    while ( errno == EINTR );

    if ( errno != 0 )
    {
        sap_error( "Fork process: %s.", strerror( errno ) );
        send_string( pChar, "There was an error.\n\r" );
        return;
    }

    if ( pPid == 0 )
        abort( );

    if ( wait( &i ) < 0 )
        sap_error( "Wait: %s.", strerror( errno ) );

    send_string( pChar, "Core dump completed.\n\r" );
    lprintf( "Core dump by %s.", pChar->pPCData->sName );
    snprintf( cBuf, 1024, "%s.core", pProgramName );
    snprintf( cBuf2, 1024, "%s%s.core", pShellDir, pProgramName );
    rename( cBuf, cBuf2 );
}
#endif

void cmd_reboot( CHAR_DATA *pChar, char *pArgument )
{
    TERM_DATA *pTerm, *pTermNext;
    char *pArg[]  = { pProgramName, pBootFilename, NULL, NULL };
    char cBuf[128];

    if ( IS_NPC( pChar ) )
    {
        send_string( pChar, "Attemping to terminate yourself eh?\n\r" );
        return;
    }

    for ( pTerm = pTermList; pTerm != NULL; pTerm = pTermNext )
    {
        pTermNext = pTerm->pNext;
        sprintf( cBuf, "%sReboot by %s.\n\r",
          ( pTerm != pChar->pTerm ? "\n\r" : "" ),
          pChar->pPCData->sName );
        write_string_buffer( pTerm, cBuf );
        close_connection( &pTerm );
    }

    if ( sTelnetControl > -1 )
        close( sTelnetControl );

    if ( sBinaryControl > -1 )
        close( sBinaryControl );

    if ( sMUDCommControl > -1 )
        close( sMUDCommControl );

    if ( pLogFile == stdout )
        pArg[2]   = "-l";
    else
        fclose( pLogFile );

    lprintf( "Reboot by %s.", pChar->pPCData->sName );
    fprintf( stderr, "Reboot by %s.\n", pChar->pPCData->sName );

    sleep( 15 );

    do
    {
        errno     = 0;
        execv( pProgramName, pArg );
    }
    while ( errno == EINTR );

    if ( errno != 0 )
        exit( 1 );
}


/*
 * Command to report memory usage.
 */
void cmd_memory( CHAR_DATA *pChar, char *pArgument )
{
    NPC_INDEX_DATA *pNPCIndex;
    OBJ_INDEX_DATA *pObjIndex;
    ROOM_INDEX_DATA *pRoomIndex;
    CHAR_DATA *pCharBuf;
    OBJ_DATA *pObj;
#if 0
    kvm_t *kvm;
#endif
    char cBuf[MAX_STRING];
    int iCount = 0;
    int i;
#if 0
    if ( ( kvm = kvm_openfiles( NULL, NULL, NULL, O_RDONLY, cBuf ) )
      == NULL )
        sap_warning( "KVM Open: %s.", cBuf );
    else
    {
        struct kinfo_proc *pProcInfo;

        pProcInfo = kvm_getprocs( kvm, KERN_PROC_PID, getpid( ), &iCount );

        /* printf( "p->p_dsize = %ld\n", pProcInfo->kp_proc.p_dsize );
        printf( "p->p_ssize = %ld\n", pProcInfo->kp_proc.p_ssize );
        printf( "p->p_xsize = %ld\n", pProcInfo->kp_proc.p_xsize );
        printf( "p->p_rssize = %ld\n", pProcInfo->kp_proc.p_rssize ); */

        printf( "e.e_xccount = %ld\n", pProcInfo->kp_eproc.e_xccount );
        printf( "e.e_xrssize = %ld\n", pProcInfo->kp_eproc.e_xrssize );
        printf( "e.e_vm.vm_rssize = %ld\n",
          pProcInfo->kp_eproc.e_vm.vm_rssize );

        kvm_close( kvm );
    }
#endif
    send_string( pChar, "Strings           : %11ld bytes.\n\r\n\r",
      lStringSpace );

    iCount = 0;

    for ( i = 0; i < iHashListSize; i++ )
    {
        for ( pNPCIndex = ppNPCIndexList[i]; pNPCIndex;
          pNPCIndex = pNPCIndex->pNext )
            iCount++;
    }

    send_string( pChar, "NPC prototypes    : %4d * %4d (%d) bytes.\n\r",
      sizeof( NPC_INDEX_DATA ), iCount,
      ( sizeof( NPC_INDEX_DATA ) * iCount ) );

    iCount = 0;

    for ( i = 0; i < iHashListSize; i++ )
    {
        for ( pObjIndex = ppObjIndexList[i]; pObjIndex;
          pObjIndex = pObjIndex->pNext )
            iCount++;
    }

    send_string( pChar, "Object prototypes : %4d * %4d (%d) bytes.\n\r",
      sizeof( OBJ_INDEX_DATA ), iCount,
      ( sizeof( OBJ_INDEX_DATA ) * iCount ) );

    iCount = 0;

    for ( i = 0; i < iHashListSize; i++ )
    {
        for ( pRoomIndex = ppRoomIndexList[i]; pRoomIndex;
          pRoomIndex = pRoomIndex->pNext )
            iCount++;
    }

    send_string( pChar, "Rooms             : %4d * %4d (%d) bytes.\n\r",
      sizeof( ROOM_INDEX_DATA ), iCount,
      ( sizeof( ROOM_INDEX_DATA ) * iCount ) );

    for ( iCount = 0, i = 0; i < iHashListSize; i++ )
    {
        for ( pCharBuf = ppCharList[i]; pCharBuf != NULL;
          pCharBuf = pCharBuf->pNext )
             iCount++;
    }

    send_string( pChar, "Real characters   : %4d * %4d (%d) bytes.\n\r",
      sizeof( CHAR_DATA ), iCount,
      ( sizeof( CHAR_DATA ) * iCount ) );

    for ( iCount = 0, i = 0; i < iHashListSize; i++ )
    {
        for ( pObj = ppObjList[i]; pObj != NULL; pObj = pObj->pNext )
            iCount++;
    }

    send_string( pChar, "Real objects      : %4d * %4d (%d) bytes.\n\r",
      sizeof( OBJ_DATA ), iCount,
      ( sizeof( OBJ_DATA ) * iCount ) );
}


void cmd_fwrite( CHAR_DATA *pChar, char *pArgument )
{
    TERM_DATA *pTerm;
    char cArg[MAX_INPUT];
    int iDesc;

    pArgument = one_arg( pArgument, cArg );

    if ( cArg[0] == '\0' || pArgument[0] == '\0'
      || is_number( cArg ) != TRUE || ( iDesc = atoi( cArg ) ) < 0 )
    {
        send_string( pChar, "Usage: fwrite <socket> <string>\n\r" );
        return;
    }

    for ( pTerm = pTermList; pTerm != NULL; pTerm = pTerm->pNext )
    {
        if ( pTerm->sTelnetSocket == iDesc
          || pTerm->sBinarySocket == iDesc )
            break;
    }

    if ( pTerm == NULL )
    {
        send_string( pChar, "No such socket.\n\r" );
        return;
    }

    write_string_buffer( pTerm, "\n\r" );
    write_string_buffer( pTerm, pArgument );
    write_string_buffer( pTerm, "\n\r" );
    send_string( pChar, "String forcefully written to socket %d.\n\r",
      iDesc );
}


void cmd_lset( CHAR_DATA *pChar, char *pArgument )
{
    CHAR_DATA *pChar2;
    KNOWN_PERSON_DATA *pKnownPerson;
    KNOWN_PERSON_DATA *pKnownPersonNext;
    KNOWN_EXIT_DATA *pKnownExit;
    KNOWN_EXIT_DATA *pKnownExitNext;
    char cArg[MAX_INPUT];
    int iLevel;

    pArgument = one_arg( pArgument, cArg );

    if ( cArg[0] == '\0' || pArgument[0] == '\0'
      || is_number( pArgument ) != TRUE
      || ( iLevel = atoi( pArgument ) ) < 1
      || iLevel > MAX_LEVEL )
    {
        send_string( pChar, "Usage: lset <name> <level>\n\r" );
        return;
    }

    for ( pChar2 = ppCharList[0]; pChar2; pChar2 = pChar2->pNext )
    {
        if ( multi_compare( cArg, pChar2->pPCData->sName ) == TRUE )
            break;
    }

    if ( pChar2 == NULL )
    {
        send_string( pChar, "No such character.\n\r" );
        return;
    }

    if ( pChar2->iLevel == iLevel )
    {
        send_string( pChar, "That character is already that level.\n\r" );
        return;
    }

    if ( pChar2->iLevel < iLevel )
        send_string( pChar2,
          "\n\rYou feel new strength flow through you." );
    else
        send_string( pChar2, "\n\rYou feel your strength weaken." );

    /*
     * Builders and implementors automaticly know everyone's name and
     * know about hidden exits so we can free the "known" data :)
     */
    if ( iLevel >= BUILDER_LEVEL )
    {
        for ( pKnownPerson = pChar2->pPCData->pKnownPeople; pKnownPerson;
          pKnownPerson = pKnownPersonNext )
        {
            pKnownPersonNext         = pKnownPerson->pNext;
            free_string( &pKnownPerson->sName );
            free_mem( (void **) &pKnownPerson );
        }

        pChar2->pPCData->pKnownExits = NULL;

        for ( pKnownExit = pChar2->pPCData->pKnownExits; pKnownExit;
          pKnownExit = pKnownExitNext )
        {
            pKnownExitNext           = pKnownExit->pNext;
            free_mem( (void **) &pKnownExit );
        }

        pChar2->pPCData->pKnownExits = NULL;
    }

    pChar2->iLevel = iLevel;
    send_string( pChar2, "  You are now level %d.\n\r", iLevel );

    send_string( pChar, "Level set.\n\r" );
}


/*
 * End of imp_cmd.c
 */