/******************************************************************************************************** File handling functions for SMAUG by Greg (Keberus Maou'San ) Mosley and Darien (ldevil@hotmail.com) This code is meant to replace fopen and fclose calls so the mud can keep track of which files are open and the location from where they file opening was called. It now also writes to a temporary file first, then once all the writing is done, it renames the file to minimize the likelihood of corrupting files. Initally this was a port from the file handling functions for ROM made by Darien. This is be released with his permission and with a few changes. Namely, not only does it now keep track of open files, but it writes files to a .temporary file before renaming them to help minimize the possiblity of file corruption. Code tested and compiled with smaugfuss v1.9 ********************************************************************************************************/ //This is the Semi-original composite header (the instructions are still pretty much valid) /******************************************************************************************************* My File Open/Close System, i've seen dozens of them out there But frankly, none of them are as good as this one. Atleast in my books. Replace all fopen's with FileOpen, and fclose with FileClose Remove all referances to fpReserve (minus the FILE *fpReserve in comm.c) And the inital opening of the fpReserve in comm.c, also leave the fopen for the fpReserve in your copyover function(if you have one) These are the only Instances for you to leave them. This system can really help your mud out, and if you do a good job, it won't delay Your mud at all :) if everything is closed properly, your mud won't use any extra mem :) Contact me on msn or in email via: ldevil@hotmail.com ********************************************************************************************************/ in mud.h add: -------------------------------------- FILE * __FileOpen( const char *filename, const char *mode, const char *file, const char *function, int line ); void FileClose( FILE * fp ); #define FileOpen( filename, mode) __FileOpen(filename, mode, __FILE__, __FUNCTION__, __LINE__) typedef struct file_data FILE_DATA; extern FILE_DATA *first_filedata; extern FILE_DATA *last_filedata; extern int FilesOpen; struct file_data { FILE_DATA *next; FILE_DATA *prev; FILE *fp; char *filename; char *mode; // *Where they were called from* // char *file; char *function; int line; }; in db.c find: -------------- CHAR_DATA *first_char; CHAR_DATA *last_char; ---after that add:---- int FilesOpen; FILE_DATA *first_filedata; FILE_DATA *last_filedata; then in db.c, boot_db find -------------- extracted_obj_queue = NULL; extracted_char_queue = NULL; ---after that add:---- first_filedata = NULL; last_filedata = NULL; FilesOpen = 0; --------- Create a file with the text below or add it to a file -------------------------------------------------------------------------------------------------------- #include #include #include #include #include #include "mud.h" char *str_replace( const char *seed, const char *apple, char *tree ); FILE *__FileOpen( const char *filename, const char *mode, const char *file, const char *function, int line ) { FILE *fp = NULL; char fbuf[256]; if( !filename || filename[0] == '\0' || !mode || mode[0] == '\0' ) { log_string( "FileOpen called improperly." ); return NULL; } //If writing...first create a temp file, otherwise just open the file -->KeB 10/29/08 if( strstr( mode, "w" ) ) snprintf( fbuf, 256, "%s.temporary", filename ); else snprintf( fbuf, 256, "%s", filename ); if( ( fp = fopen( fbuf, mode ) ) == NULL ) { perror( fbuf ); return NULL; } else { // *If you want to be really picky, define this* // #ifdef DEBUG_FILEDATA FILE_DATA *file_data; for( file_data = file_list; file_data; file_data->next ) { if( file_data->fp == fp ) { log_string( "FileOpen: Double opening of a file!" ); } } #endif FILE_DATA *filedata; CREATE( filedata, FILE_DATA, 1 ); filedata->filename = str_dup( fbuf ); filedata->mode = str_dup( mode ); filedata->file = str_dup( file ); filedata->function = str_dup( function ); filedata->line = line; filedata->fp = fp; LINK( filedata, first_filedata, last_filedata, next, prev ); FilesOpen++; } return fp; } void free_filedata( FILE_DATA * filedata ) { UNLINK( filedata, first_filedata, last_filedata, next, prev ); DISPOSE( filedata->filename ); DISPOSE( filedata->file ); DISPOSE( filedata->function ); DISPOSE( filedata->mode ); DISPOSE( filedata ); } void free_all_filedata( void ) { FILE_DATA *filedata, *filedata_next; for( filedata = first_filedata; filedata; filedata = filedata_next ) { filedata_next = filedata->next; free_filedata( filedata ); } return; } // *Close the file-data* // void FileClose( FILE * fp ) { char new_fname[MIL]; char old_fname[MIL]; new_fname[0] = '\0'; if( fp ) { FILE_DATA *filedata, *filedata_next; for( filedata = first_filedata; filedata; filedata = filedata_next ) { filedata_next = filedata->next; if( filedata->fp == fp ) { if( !str_suffix( ".temporary", filedata->filename ) ) { snprintf( old_fname, MIL, "%s", filedata->filename ); snprintf( new_fname, MIL, "%s", filedata->filename ); str_replace( ".temporary", "", new_fname ); } free_filedata( filedata ); break; } } fclose( fp ); FilesOpen--; if( FilesOpen < 0 ) { FilesOpen = 0; log_string( "FileClose passed a null fp somewhere and schewed the list." ); } if( new_fname[0] != '\0' ) { if( rename( old_fname, new_fname ) ) { log_printf( "FileClose: Problem with renaming %s to %s", old_fname, new_fname ); return; } } } } // *ALL files should be closed. I mean that, there is 100% no need to have an open file, unless your a sloppy coder* // // *Remember that, what this does is link all the open file-data, and display it to you, this will allow you to find out * // // *Where, and why your mud is crapping out. I plugged this into a base, i forget which one, and after it compiled * // // *I booted the mud up, and when i typed fileio, the damned thing had almost 30 open files because they didn't * // // *Close the files properly, so i recommend this to people, because, if you have open files. This will be a perfect* // // * Way to find them, see exactly where they were opened, and why (mode) thus allowing you to find why they.* // // *didn't close* // void do_fileio( CHAR_DATA *ch, const char *argument ) { FILE_DATA *filedata; char buf[MSL]; int count = 0; pager_printf( ch, " &YFilename &wMode &WOpened &CFunction &OLine\r\n" ); send_to_pager( "&c------------------------------------------------------------------------------------------\r\n", ch ); if( !first_filedata ) send_to_pager( "\r\n&RCongrats, &Yyou have no &WOpen &Yfiles!\r\n", ch ); for( filedata = first_filedata; filedata; filedata = filedata->next ) { sprintf( buf, "&Y%-25.25s &w%-1.1s &W%-20.20s &C%-15.15s &O%-4.4d\r\n", filedata->filename, filedata->mode, filedata->file, filedata->function, filedata->line ); count++; send_to_pager( buf, ch ); } // *Add to the evil* // send_to_pager( "\r\n", ch ); // *Make sure the count is right.* // if( FilesOpen != count ) { send_to_pager( "&RThats Odd, the FilesOpen and count don't match!!!!", ch ); } return; } /********************************************************************************** * If you need the str_replace() function, use this one, I did not code it and * I don't remember who did. **********************************************************************************/ char *str_replace( const char *seed, const char *apple, char *tree ) { static char buffer[MSL * 2]; // working buffer char *nail; // pointer to location in tree char *bpt; // pointer to location in buffer buffer[0] = '\0'; // initialize static buffer bpt = &buffer[0]; // point bpt to first char of buffer nail = &tree[0]; // point nail to first char of tree while( *nail != '\0' ) // while nail doesn't point to end { if( strncasecmp( nail, seed, strlen( seed ) ) ) // if seed isn't found { strncat( bpt, nail, 1 ); // append first char of nail to bpt bpt++; nail++; // increment them to the next char } else // if seed was found { strcat( buffer, apple ); // tag apple onto buffer bpt += strlen( apple ); // increment bpt by length of apple nail += strlen( seed ); // increment nail by length of seed } } *bpt++ = '\0'; // add null character to end of buffer strcpy( tree, buffer ); // copy buffer into original string return buffer; // and return buffer }