/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * _/ _/_/_/ _/ _/ _/ ACK! MUD is modified * * _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code * * _/ _/ _/ _/_/ _/ (c)Stephen Zepp 1998 * * _/_/_/_/ _/ _/ _/ Version #: 4.3 * * _/ _/ _/_/_/ _/ _/ _/ * * * * http://ackmud.nuc.net/ * * zenithar@ackmud.nuc.net * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ #include <sys/types.h> #include <sys/time.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include "globals.h" #include "tables.h" #ifdef DEBUG_MONEY #ifndef DEC_MONEY_H #include "money.h" #endif #endif #include "ssm.h" /* String checker, Spectrum 11/96 * * Basic idea is to walk through all the strings we know about, and mark them * as referenced. Then we check for strings that have a reference count thats * different from ptr->usage and log them */ /* * Things which are walked (anything else must be touched from these): * * o char_list * o descriptor_list * o object_list * o mob_index hash table * o obj_index hash table * o room_index hash table * o socials table * o helps * o areas * o notes/ideas/etc * */ /* From ban.c: */ extern BAN_DATA *first_ban; extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH]; extern OBJ_INDEX_DATA *obj_index_hash[MAX_KEY_HASH]; extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH]; /* Main code */ static void touch( char *str ) { BufEntry *p; if( !str ) return; if( str < string_space || str > top_string ) return; /* not in string space */ p = ( BufEntry * ) ( str - HEADER_SIZE ); p->ref++; } static void clear( void ) { /* * Set all reference counts to 0 */ BufEntry *p; for( p = ssm_buf_head; p; p = p->next ) p->ref = 0; } static BufEntry *dump_ptr[2]; static long dump( void ) { /* * Dump strings that have ref!=usage */ FILE *dumpf; BufEntry *p; long count = 0; fclose( fpReserve ); dumpf = fopen( "../reports/leaks.dmp", "w" ); for( p = ssm_buf_head; p; p = p->next ) { if( p->usage > 0 && p->usage != p->ref ) { /* * things to ignore: * * the common <%hhp %mm %vmv> prompt string * * a '$' (from socials) */ if( !str_cmp( p->buf, "<%hhp %mm %vmv> " ) || !str_cmp( p->buf, "$" ) ) continue; fprintf( dumpf, "usage %2d/%2d, caller %s, string %s\n", p->ref, p->usage, p->caller, p->buf ); count += abs( p->usage - p->ref ); } dump_ptr[0] = dump_ptr[1]; dump_ptr[1] = p; } fclose( dumpf ); fpReserve = fopen( NULL_FILE, "r" ); return count; } static void walk_mprog_data( MPROG_DATA * prog ) { if( !prog ) return; touch( prog->arglist ); touch( prog->comlist ); touch( prog->filename ); } static void walk_mprog_act_data( MPROG_ACT_LIST * act ) { if( !act ) return; touch( act->buf ); } static void walk_mob_index_data( MOB_INDEX_DATA * m ) { MPROG_DATA *mobprog; if( !m ) return; touch( m->player_name ); touch( m->short_descr ); touch( m->long_descr ); touch( m->description ); touch( m->target ); for( mobprog = m->first_mprog; mobprog; mobprog = mobprog->next ) walk_mprog_data( mobprog ); } static void walk_ngroup_data( NPC_GROUP_DATA * ngrp ) { if( !ngrp ) return; touch( ngrp->enemies ); touch( ngrp->last_fighting ); touch( ngrp->wants ); touch( ngrp->needs ); } static void walk_ngroups( void ) { NPC_GROUP_DATA *ngroup; for( ngroup = first_npc_group; ngroup; ngroup = ngroup->next ) { walk_ngroup_data( ngroup ); } } static void walk_pcdata( PC_DATA * p ) { int i; if( !p ) return; touch( p->pwd ); touch( p->bamfin ); touch( p->bamfout ); touch( p->title ); touch( p->room_enter ); touch( p->room_exit ); touch( p->host ); touch( p->who_name ); touch( p->header ); touch( p->message ); touch( p->lastlogin ); touch( p->load_msg ); for( i = 0; i < MAX_IGNORES; i++ ) touch( p->ignore_list[i] ); for( i = 0; i < MAX_ALIASES; i++ ) { touch( p->alias[i] ); touch( p->alias_name[i] ); } for( i = 0; i < 5; i++ ) { touch( p->pedit_string[i] ); } touch( p->pedit_state ); touch( p->email_address ); touch( p->assist_msg ); } static void walk_shield_data( MAGIC_SHIELD * shield ) { if( !shield ) return; touch( shield->name ); touch( shield->absorb_message_room ); touch( shield->absorb_message_victim ); touch( shield->absorb_message_self ); touch( shield->wearoff_room ); touch( shield->wearoff_self ); } static void walk_note_data( NOTE_DATA * note ) { if( !note ) return; touch( note->sender ); touch( note->date ); touch( note->to_list ); touch( note->subject ); touch( note->text ); } static void walk_brand_data( BRAND_DATA * brand ) { if( !brand ) return; touch( brand->branded ); touch( brand->branded_by ); touch( brand->dt_stamp ); touch( brand->message ); touch( brand->priority ); } static void walk_brands( void ) { BRAND_DATA *this_brand; DL_LIST *brands; for( brands = first_brand; brands; brands = brands->next ) { this_brand = brands->this_one; walk_brand_data( this_brand ); } } static void walk_shieldlist( MAGIC_SHIELD * shield ) { for( ; shield; shield = shield->next ) walk_shield_data( shield ); } static void walk_mprog_act( MPROG_ACT_LIST * act ) { for( ; act; act = act->next ) walk_mprog_act_data( act ); } void walk_notelist( NOTE_DATA * pnote ) { for( ; pnote; pnote = pnote->next ) walk_note_data( pnote ); } static void walk_char_data( CHAR_DATA * ch ) { if( !ch ) return; walk_notelist( ch->pnote ); walk_pcdata( ch->pcdata ); walk_shieldlist( ch->first_shield ); walk_mprog_act( ch->first_mpact ); touch( ch->name ); touch( ch->short_descr ); touch( ch->long_descr ); touch( ch->long_descr_orig ); touch( ch->description ); touch( ch->prompt ); touch( ch->old_prompt ); touch( ch->searching ); touch( ch->target ); #ifdef DEBUG_MONEY if( ch->money ) touch( ch->money->money_key ); if( ch->bank_money ) touch( ch->bank_money->money_key ); #endif } static void walk_extra_descr_data( EXTRA_DESCR_DATA * ed ) { if( !ed ) return; touch( ed->keyword ); touch( ed->description ); } static void walk_obj_index_data( OBJ_INDEX_DATA * o ) { EXTRA_DESCR_DATA *ed; if( !o ) return; for( ed = o->first_exdesc; ed; ed = ed->next ) walk_extra_descr_data( ed ); touch( o->name ); touch( o->short_descr ); touch( o->description ); touch( o->owner ); } static void walk_obj_data( OBJ_DATA * o ) { EXTRA_DESCR_DATA *ed; if( !o ) return; for( ed = o->first_exdesc; ed; ed = ed->next ) walk_extra_descr_data( ed ); touch( o->owner ); touch( o->name ); touch( o->short_descr ); touch( o->description ); #ifdef DEBUG_MONEY if( o->money ) touch( o->money->money_key ); #endif } static void walk_exit_data( EXIT_DATA * e ) { if( !e ) return; touch( e->keyword ); touch( e->description ); } static void walk_reset_data( RESET_DATA * r ) { if( !r ) return; touch( r->notes ); touch( r->auto_message ); } static void walk_area_data( AREA_DATA * ad ) { RESET_DATA *reset; if( !ad ) return; touch( ad->filename ); touch( ad->name ); touch( ad->owner ); touch( ad->can_read ); touch( ad->can_write ); touch( ad->keyword ); /* spec- missed strings */ touch( ad->level_label ); /* spec - missed strings */ touch( ad->reset_msg ); for( reset = ad->first_reset; reset; reset = reset->next ) walk_reset_data( reset ); } /* spec - for the new rulers stuff */ static void walk_ruler_data( RULER_DATA * ruler ) { if( !ruler ) return; touch( ruler->name ); touch( ruler->affiliation_name ); touch( ruler->keywords ); } static void walk_room_index_data( ROOM_INDEX_DATA * r ) { int i; EXTRA_DESCR_DATA *ed; /* BUILD_DATA_LIST *reset; */ if( !r ) return; for( i = 0; i < 6; i++ ) walk_exit_data( r->exit[i] ); for( ed = r->first_exdesc; ed; ed = ed->next ) walk_extra_descr_data( ed ); touch( r->name ); touch( r->description ); touch( r->auto_message ); #ifdef DEBUG_MONEY touch( r->treasure->money_key ); #endif } static void walk_social_type( struct social_type *s ) { if( !s ) return; touch( s->name ); touch( s->char_no_arg ); touch( s->others_no_arg ); touch( s->char_found ); touch( s->others_found ); touch( s->vict_found ); touch( s->char_auto ); touch( s->others_auto ); } static void walk_help_data( HELP_DATA * h ) { if( !h ) return; touch( h->keyword ); touch( h->text ); } static void walk_descriptor_data( DESCRIPTOR_DATA * d ) { if( !d ) return; touch( d->host ); } static void walk_ban_data( BAN_DATA * b ) { touch( b->name ); touch( b->banned_by ); } static void walk_socials( void ) { extern int maxSocial; int i; for( i = 0; i < maxSocial; i++ ) walk_social_type( &social_table[i] ); } static void walk_helps( void ) { HELP_DATA *h; for( h = first_help; h; h = h->next ) walk_help_data( h ); } static void walk_chars( void ) { CHAR_DATA *ch; for( ch = first_char; ch; ch = ch->next ) walk_char_data( ch ); } static void walk_descriptors( void ) { DESCRIPTOR_DATA *d; for( d = first_desc; d; d = d->next ) walk_descriptor_data( d ); } static void walk_objects( void ) { OBJ_DATA *o; for( o = first_obj; o; o = o->next ) walk_obj_data( o ); } static void walk_areas( void ) { AREA_DATA *ad; for( ad = first_area; ad; ad = ad->next ) walk_area_data( ad ); } /* spec- more rulers stuff */ static void walk_rulers( void ) { RULER_LIST *r; for( r = first_ruler_list; r; r = r->next ) walk_ruler_data( r->this_one ); } static void walk_mob_indexes( void ) { MOB_INDEX_DATA *m; int i; for( i = 0; i < MAX_KEY_HASH; i++ ) for( m = mob_index_hash[i]; m; m = m->next ) walk_mob_index_data( m ); } static void walk_obj_indexes( void ) { OBJ_INDEX_DATA *o; int i; for( i = 0; i < MAX_KEY_HASH; i++ ) for( o = obj_index_hash[i]; o; o = o->next ) walk_obj_index_data( o ); } static void walk_room_indexes( void ) { ROOM_INDEX_DATA *r; int i; for( i = 0; i < MAX_KEY_HASH; i++ ) for( r = room_index_hash[i]; r; r = r->next ) walk_room_index_data( r ); } static void walk_notes( void ) { walk_notelist( first_note ); } static void walk_bans( void ) { BAN_DATA *b; for( b = first_ban; b; b = b->next ) walk_ban_data( b ); } static void walk_mark_data( MARK_DATA * m ) { if( !m ) return; touch( m->message ); touch( m->author ); } void walk_marklist( void ) { MARK_LIST_MEMBER *tmark; for( tmark = first_mark_list; tmark; tmark = tmark->next ) walk_mark_data( tmark->mark ); } static void walk_message_data( MESSAGE_DATA * m ) { if( !m ) return; touch( m->message ); touch( m->author ); touch( m->title ); } void walk_messages( MESSAGE_DATA * m ) { for( ; m; m = m->next ) walk_message_data( m ); } void walk_boards( void ) { BOARD_DATA *board; extern BOARD_DATA *first_board; for( board = first_board; board; board = board->next ) walk_messages( board->first_message ); } void walk_councils( void ) { sh_int index; extern COUNCIL_DATA super_councils[MAX_SUPER]; for( index = 0; index < MAX_SUPER; index++ ) touch( super_councils[index].council_name ); } void walk_sysdata( void ) { sh_int looper; touch( sysdata.playtesters ); for( looper = 0; looper < MAX_NUM_IMMS; looper++ ) touch( sysdata.imms[looper].this_string ); } void do_scheck( CHAR_DATA * ch, char *argument ) { char buf[MAX_STRING_LENGTH]; extern bool disable_timer_abort; disable_timer_abort = TRUE; clear( ); walk_socials( ); walk_helps( ); walk_chars( ); walk_descriptors( ); walk_objects( ); walk_areas( ); walk_bans( ); walk_mob_indexes( ); walk_obj_indexes( ); walk_room_indexes( ); walk_notes( ); walk_marklist( ); walk_councils( ); walk_boards( ); walk_rulers( ); walk_brands( ); walk_sysdata( ); walk_ngroups( ); sprintf( buf, "%ld leaks dumped to leaks.dmp\n\r", dump( ) ); send_to_char( buf, ch ); disable_timer_abort = FALSE; }