/* * PARSEC - External Commands * * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:23 $ * * Orginally written by: * Copyright (c) Markus Hadwiger 1996-2001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // C library #include #include #include #include #include // compilation flags/debug support #include "config.h" #include "debug.h" // general definitions #include "general.h" #include "objstruc.h" // global externals #include "globals.h" // local module header #include "con_ext.h" // proprietary module headers #include "con_act.h" #include "con_aux.h" #include "con_list.h" #include "con_main.h" #include "con_std.h" #include "con_vald.h" #include "e_demo.h" #include "e_record.h" #include "e_replay.h" #include "sys_file.h" #include "sys_path.h" // maximum depth of recursion in command batch files #define MAX_BATCH_REC_DEPTH 16 // special eof needed in package console scripts #define PACKAGE_CON_EOF ";eof" #define PACKAGE_CON_EOF_LEN 4 // generic string paste area #define PASTE_STR_LEN 255 static char paste_str[ PASTE_STR_LEN + 1 ]; // string constants static char con_extension[] = CON_FILE_EXTENSION; static char invalid_batch_name[]= "invalid name specifier."; static char recursion_canceled[]= "command canceled due to recursion."; static char recursion_maxdepth[]= "maximum recursion depth reached."; static char replaying_script[] = "replay in progress (script)."; static char replaying_binary[] = "replay in progress (binary)."; static char no_replay[] = "no replay in progress."; static char stopped_replay[] = "replay has been stopped."; static char record_disallowed[] = "recording not allowed (object camera is active)."; static char con_file_wldcard1[] = "*" CON_FILE_EXTENSION; static char con_file_wldcard2[] = REFCON_COMMANDS_DIR "*" CON_FILE_EXTENSION; static char con_file_wldcard3[] = STDCON_COMMANDS_DIR "*" CON_FILE_EXTENSION; static char con_file_wldcard4[] = RECORD_COMMANDS_DIR "*" CON_FILE_EXTENSION; // name of batch command file to execute on every gameloop start char gameloop_start_script[ PATH_MAX + 1 ] = ""; // list of external commands char external_commands[ MAX_EXTERNAL_COMMANDS + 1 ][ COMMAND_NAME_ALLOC_LEN + 1 ]; int external_command_types[ MAX_EXTERNAL_COMMANDS + 1 ]; int num_external_commands = 0; // external batch execution vars int processing_batch = 0; // flag that commands are called from batch int idle_reclevel = 0; // level of recursion idle wait stalled execution on int rec_depth = 0; // current level of recursion // action commands not allowed? int preempt_action_commands = FALSE; // batch execution recursive call stack static int extcom_on_level[ MAX_BATCH_REC_DEPTH + 1 ]; static FILE *fp_for_level[ MAX_BATCH_REC_DEPTH + 1 ]; // log file (created command batch) FILE *log_fp; char log_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; int log_commands = 0; // recording file static char record_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; // packet recording/replay file names char packet_record_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; char packet_replay_name[ COMMAND_NAME_ALLOC_LEN + 1 ]; // single command line static char com_line[ MAX_CONSOLE_LINE_LENGTH + 1 ]; // cat feature variables static char cat_name[ MAX_CONSOLE_LINE_LENGTH + 1 ]; static int cat_pos; // current active mod name PUBLIC char* mod_names[ MAX_REGISTERED_MODS ]; PUBLIC int mod_numnames = 0; PUBLIC int mod_override = FALSE; // acquire scripts located in mod directories --------------------------------- // PRIVATE void AcquireModScripts() { for ( int mod = 0; mod < mod_numnames; mod++ ) { char *path = (char *) ALLOCMEM( strlen( mod_names[ mod ] ) + strlen( con_file_wldcard1 ) + 2 ); if ( path == NULL ) { OUTOFMEM( 0 ); } strcpy( path, mod_names[ mod ] ); strcat( path, "/" ); strcat( path, con_file_wldcard1 ); char *npath = SYSs_ProcessPathString( path ); SYSs_AcquireScriptPath( npath, COMTYPE_MODIFICATION, mod_names[ mod ] ); FREEMEM( path ); } } // build list of externally available commands -------------------------------- // void BuildExternalCommandList() { //NOTE: // the sequence of paths scanned in this function mostly determines the // display order of console scripts (ls command, tab completion, ...). // the actual precedence of scripts is determined by the search order // in OpenScript(). for consistency, the two orders should be the same. num_external_commands = 0; SYS_AcquirePackageScripts( COMTYPE_PACKAGE ); if ( mod_override ) { AcquireModScripts(); } SYSs_AcquireScriptPath( con_file_wldcard1, COMTYPE_ROOT, NULL ); SYSs_AcquireScriptPath( con_file_wldcard2, COMTYPE_REFERENCE, NULL ); SYSs_AcquireScriptPath( con_file_wldcard3, COMTYPE_STANDARD, NULL ); SYSs_AcquireScriptPath( con_file_wldcard4, COMTYPE_RECORDING, NULL ); if ( !mod_override ) { AcquireModScripts(); } } // check if string is valid external command ---------------------------------- // int CheckExternalCommand( char *com ) { ASSERT( com != NULL ); //NOTE: // command script directories are only scanned once. therefore, // new commands copied into a directory while the game is still // running will not be noticed until next startup or explicit // rescanning via the "rescan" command. // to ensure scripts with explicitly specified paths work com = SYSs_ProcessPathString( com ); // scan list in memory (no directory rescanning!!) int cid = -1; for ( int eid = 0; eid < num_external_commands; eid++ ) { ASSERT( external_commands[ eid ] != NULL ); if ( stricmp( external_commands[ eid ], com ) == 0 ) { cid = eid; break; } } // return command number + 1 (thus 0 means command is invalid) return ( cid + 1 ); } // insert command into log file (command batch) ------------------------------- // int InsertCommandLog( char *command ) { ASSERT( command != NULL ); if ( log_commands && ( strcmp( command, CMSTR( CM_CLOSE ) ) != 0 ) ) { // append command to currently open logfile fprintf( log_fp, "%s\n", command ); return TRUE; } return FALSE; } // search all console script paths and open batch if it exists ---------------- // PRIVATE FILE *OpenScript( char *script ) { ASSERT( script != NULL ); //NOTE: // the sequence of paths scanned in this function determines the // precedence of console scripts of the same name but located in // different directories. //NOTE: // the path search sequence is: // 1. data package // 2. root (local) directory // 3. reference directory (refs) // 4. standard directory (cons) // 5. recording directory (recs) //NOTE: // to avoid inconsistencies the search order in E_RECORD::LoadPacket() // and E_DEMO::DEMO_BinaryOpenDemo() should be consistent // with the search order used here. FILE *fp = NULL; strcpy( paste_str, script ); strcat( paste_str, con_extension ); // to ensure scripts with explicitly specified paths work char *path = SYSs_ProcessPathString( paste_str ); if ( !AUX_DISABLE_PACKAGE_SCRIPTS ) { // try to read from package first if ( ( fp = SYS_fopen( path, "r" ) ) != NULL ) { return fp; } } // search root (local) directory if ( ( fp = fopen( path, "r" ) ) != NULL ) { return fp; } strcpy( paste_str, REFCON_COMMANDS_DIR ); strcat( paste_str, script ); strcat( paste_str, con_extension ); // search reference directory (refs) if ( ( fp = fopen( paste_str, "r" ) ) != NULL ) { return fp; } strcpy( paste_str, STDCON_COMMANDS_DIR ); strcat( paste_str, script ); strcat( paste_str, con_extension ); // search standard directory (cons) if ( ( fp = fopen( paste_str, "r" ) ) != NULL ) { return fp; } strcpy( paste_str, RECORD_COMMANDS_DIR ); strcat( paste_str, script ); strcat( paste_str, con_extension ); // search recording directory (recs) return fopen( paste_str, "r" ); } // display content of command batch file -------------------------------------- // PRIVATE void CatExternalCommands_ctd() { int i = 0; FILE *fp = OpenScript( cat_name ); if ( fp != NULL ) { SYS_fseek( fp, cat_pos, SEEK_SET ); int packeof = 0; while ( SYS_fgets( com_line, MAX_CONSOLE_LINE_LENGTH, fp ) != NULL ) { // check special package eof if ( strncmp( com_line, PACKAGE_CON_EOF, PACKAGE_CON_EOF_LEN ) == 0 ) { packeof = 1; break; } ProcessExternalLine( com_line ); CON_AddLine( com_line ); if ( ++i >= cur_vis_conlines - 1 ) { break; } } if ( packeof || SYS_feof( fp ) ) { CON_ListEndPrompt(); } else { CON_ListCtdPrompt(); cat_pos = SYS_ftell( fp ); } SYS_fclose( fp ); } } // display content of command batch file (command "cat") ---------------------- // int Cmd_CatExternalCommands( char *cstr ) { ASSERT( cstr != NULL ); HANDLE_COMMAND_DOMAIN_SEP( cstr ); char *name = strtok( cstr, " " ); if ( ( name == NULL ) || ( strtok( NULL, " " ) != NULL ) ) { CON_AddLine( "syntax: cat