/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Pfile autocleanup code *
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "mud.h"
extern char * GfpName;
extern bool StopFP;
/* Globals */
time_t pfile_time;
HOUR_MIN_SEC set_pfile_time_struct;
HOUR_MIN_SEC * set_pfile_time;
struct tm * new_pfile_time;
struct tm new_pfile_struct;
time_t new_pfile_time_t;
sh_int num_pfiles; /* Count up number of pfiles */
#ifndef SOLANCODE
void save_timedata( void )
{
FILE *fp;
char filename[MAX_INPUT_LENGTH];
sprintf( filename, "%stime.dat", SYSTEM_DIR );
FCLOSE( fpReserve );
if ( ( fp = fopen( filename, "w" ) ) == NULL )
{
bug( "save_timedata: fopen" );
perror( filename );
}
else
{
fprintf( fp, "#TIME\n" );
fprintf( fp, "Mhour %d\n", time_info.hour );
fprintf( fp, "Mday %d\n", time_info.day );
fprintf( fp, "Mmonth %d\n", time_info.month );
fprintf( fp, "Myear %d\n", time_info.year );
fprintf( fp, "Purgetime %ld\n", new_pfile_time_t );
fprintf( fp, "LastRMonth %d\n", time_info.lastRealMonth );
fprintf( fp, "End\n\n" );
fprintf( fp, "#END\n" );
}
FCLOSE( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
#ifdef KEY
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
/* Reads the actual time file from disk - Samson 1-21-99 */
void fread_timedata( FILE *fp )
{
char *word = NULL;
bool fMatch = FALSE;
for ( ; ; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER(word[0]) )
{
case '*':
fMatch = TRUE;
fread_to_eol( fp );
break;
case 'E':
if ( !str_cmp( word, "End" ) )
return;
break;
case 'L':
KEY( "LastRMonth", time_info.hour, fread_number( fp ) );
case 'M':
KEY( "Mhour", time_info.hour, fread_number( fp ) );
KEY( "Mday", time_info.day, fread_number( fp ) );
KEY( "Mmonth", time_info.month, fread_number( fp ) );
KEY( "Myear", time_info.year, fread_number( fp ) );
break;
case 'P':
KEY( "Purgetime", new_pfile_time_t, fread_number( fp ) );
break;
}
if ( !fMatch )
{
bug( "Fread_timedata: no match: %s", word );
fread_to_eol( fp );
}
}
}
bool load_timedata( void )
{
char filename[MAX_INPUT_LENGTH];
FILE *fp;
bool found;
found = FALSE;
sprintf( filename, "%stime.dat", SYSTEM_DIR );
if ( ( fp = fopen( filename, "r" ) ) != NULL )
{
found = TRUE;
for ( ; ; )
{
char letter = '\0';
char *word = NULL;
letter = fread_letter( fp );
if ( letter == '*' )
{
fread_to_eol( fp );
continue;
}
if ( letter != '#' )
{
bug( "Load_timedata: # not found." );
break;
}
word = fread_word( fp );
if ( !str_cmp( word, "TIME" ) )
{
fread_timedata( fp );
break;
}
else
if ( !str_cmp( word, "END" ) )
break;
else
{
bug( "Load_timedata: bad section - %s.", word );
break;
}
}
FCLOSE( fp );
}
return found;
}
#endif
void init_pfile_scan_time( void )
{
/*
* Init pfile scan time.
*/
set_pfile_time = &set_pfile_time_struct;
new_pfile_time = update_time(localtime(¤t_time));
/* Copies *new_pfile_time to new_pfile_struct, and then points
new_pfile_time to new_pfile_struct again. -- Alty */
new_pfile_struct = *new_pfile_time;
new_pfile_time = &new_pfile_struct;
if(new_pfile_time->tm_hour > 5)
new_pfile_time->tm_mday += 1;
new_pfile_time->tm_sec = 0;
new_pfile_time->tm_min = 0;
new_pfile_time->tm_hour = 5;
/* Update new_pfile_time (due to day increment) */
new_pfile_time = update_time(new_pfile_time);
new_pfile_struct = *new_pfile_time;
new_pfile_time = &new_pfile_struct;
/* Bug fix submitted by Gabe Yoder */
new_pfile_time_t = mktime(new_pfile_time);
/* check_pfiles(mktime(new_pfile_time)); */
#ifndef SOLANCODE
if( !load_timedata() )
{
strcpy( log_buf, "Pfile scan time reset to default time of 5am." );
log_string( log_buf );
}
#endif
return;
}
time_t now_time;
sh_int deleted = 0;
sh_int days = 0;
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !strcmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
void fread_pfile( FILE *fp, time_t tdiff, char *fname )
{
char *word;
char *name = NULL;
sh_int level = 0;
sh_int file_ver = 0;
bool fMatch;
long double exp = 0;
char * description;
for ( ; ; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
if (StopFP)
{
bug("Bad Pfile detected. Stoping proccessing of bad Pfile.");
StopFP = FALSE;
return;
}
switch ( UPPER(word[0]) )
{
case '*':
fMatch = TRUE;
fread_to_eol( fp );
break;
case 'B':
if ( !strcmp( word, "Bio" ) )
goto timecheck;
break;
case 'D':
KEY( "Description", description, fread_string( fp ) );
break;
case 'E':
KEY( "Exp", exp, fread_number_ld( fp ) );
if ( !strcmp( word, "End" ) )
goto timecheck;
break;
case 'L':
KEY( "Level", level, fread_number( fp ) );
break;
case 'N':
KEY( "Name", name, fread_string( fp ) );
break;
case 'V':
KEY( "Version", file_ver, fread_number( fp ) );
break;
}
if ( !fMatch )
fread_to_eol( fp );
}
timecheck:
if ( ( exp < 5000 && tdiff > sysdata.newbie_purge && level < LEVEL_IMMORTAL )
|| ( level < LEVEL_IMMORTAL && tdiff > sysdata.regular_purge ) )
{
if ( level < LEVEL_IMMORTAL )
{
if ( unlink(fname) == -1 )
perror( "Unlink" );
else
{
if ( exp < 5000 )
days = sysdata.newbie_purge;
else
days = sysdata.regular_purge;
sprintf( log_buf, "Player %s was deleted. Exceeded time limit of %d days.", name, days );
log_string( log_buf );
#ifdef AUTO_AUTH
remove_from_auth( name );
#endif
++deleted;
return;
}
}
}
}
void read_pfile( char *dirname, char *filename )
{
FILE *fp;
char fname[MAX_STRING_LENGTH];
struct stat fst;
time_t tdiff;
now_time = time(0);
sprintf( fname, "%s/%s", dirname, filename );
GfpName = fname;
if ( stat( fname, &fst ) != -1 )
{
tdiff = (now_time - fst.st_mtime) / 86400;
if ( ( fp = fopen ( fname, "r" ) ) != NULL )
{
for ( ; ; )
{
char letter;
char *word;
if (StopFP)
{
bug("Bad Pfile detected. Stoping proccessing of bad Pfile.");
StopFP = FALSE;
return;
}
letter = fread_letter( fp );
if ( letter != '#' )
continue;
word = fread_word( fp );
if ( !str_cmp( word, "End" ) )
break;
if ( !str_cmp( word, "PLAYER" ) )
fread_pfile( fp, tdiff, fname );
else
if ( !str_cmp( word, "END" ) ) /* Done */
break;
}
FCLOSE( fp );
}
}
return;
}
void pfile_scan( bool count )
{
DIR *dp;
struct dirent *dentry;
char dir_name[100];
sh_int alpha_loop;
sh_int cou = 0;
now_time = time(0);
for ( alpha_loop = 0; alpha_loop <= 25; alpha_loop++ )
{
sprintf( dir_name, "%s%c", PLAYER_DIR, 'a' + alpha_loop );
dp = opendir( dir_name );
dentry = readdir( dp );
while ( dentry )
{
if ( dentry->d_name[0] != '.' )
{
if( !count )
read_pfile( dir_name, dentry->d_name );
cou++;
}
dentry = readdir( dp );
}
closedir( dp );
}
if( !count )
log_string( "Pfile cleanup completed." );
else
log_string( "Pfile count completed." );
sprintf( log_buf, "Total pfiles scanned: %d", cou );
log_string( log_buf );
if( !count )
{
sprintf( log_buf, "Total pfiles deleted: %d", deleted );
log_string( log_buf );
sprintf( log_buf, "Total pfiles remaining: %d", cou - deleted );
num_pfiles = cou - deleted;
log_string( log_buf );
}
else
num_pfiles = cou;
return;
}
void do_pfiles( CHAR_DATA *ch, char *argument )
{
// char buf[MAX_STRING_LENGTH];
if ( IS_NPC(ch) )
{
send_to_char( "Mobs cannot use this command!\n\r", ch );
return;
}
if ( argument[0] == '\0' || !argument )
{
/* Makes a backup copy of existing pfiles just in case - Samson */
/*
strcpy( buf, "tar -cf " );
strcat( buf, PLAYER_DIR );
strcat( buf, "pfiles.tar " );
strcat( buf, PLAYER_DIR );
*/
// strcat( buf, "*/*" );
/* GAH, the shell pipe won't process the command that gets pieced
together in the preceeding lines! God only knows why. - Samson */
// system( buf );
sprintf( log_buf, "Manual pfile cleanup started by %s.", ch->name );
log_string( log_buf );
pfile_scan( FALSE );
return;
}
if ( !str_cmp( argument, "settime" ) )
{
new_pfile_time_t = current_time + 86400;
save_timedata( );
send_to_char( "New cleanup time set for 24 hrs from now.\n\r", ch );
return;
}
if ( !str_cmp( argument, "count" ) )
{
sprintf( log_buf, "Pfile count started by %s.", ch->name );
log_string( log_buf );
pfile_scan( TRUE );
return;
}
if( !str_cmp( argument, "wipe" ) )
{
sprintf( log_buf, "Pfile wipe started by %s.", ch->name );
log_string( log_buf );
/* commented out because this function doesn't exist -Goku 09.19.04 */
// pfile_wipe();
return;
}
send_to_char( "Invalid argument.\n\r", ch );
return;
}
void check_pfiles( time_t reset )
{
/* This only counts them up on reboot if the cleanup isn't needed - Samson 1-2-00 */
if ( reset == 255 && new_pfile_time_t > current_time )
{
reset = 0; /* Call me paranoid, but it might be meaningful later on */
log_string( "Counting pfiles....." );
pfile_scan( TRUE );
return;
}
if ( new_pfile_time_t <= current_time )
{
if( sysdata.CLEANPFILES == TRUE )
{
char buf[MAX_STRING_LENGTH];
/* Makes a backup copy of existing pfiles just in case - Samson */
/*
strcpy( buf, "tar -cf " );
strcat( buf, PLAYER_DIR );
strcat( buf, "pfiles.tar " );
strcat( buf, PLAYER_DIR );
*/
// strcat( buf, "*/*" );
/* Would use the shell pipe for this, but alas, it requires a ch in order
to work, this also gets called during boot_db before the rare item
checks for the rent code - Samson */
system( buf );
new_pfile_time_t = current_time + 86400;
save_timedata( );
log_string( "Automated pfile cleanup beginning...." );
pfile_scan( FALSE );
#ifdef RENTCODE
if( reset == 0 )
rent_update();
#endif
}
else
{
new_pfile_time_t = current_time + 86400;
save_timedata( );
log_string( "Counting pfiles....." );
pfile_scan( TRUE );
#ifdef RENTCODE
if( reset == 0 )
rent_update();
#endif
}
}
return;
}