/*
* 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
*/