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