/***** ** ** Module Header ******************************************************* ** ** ** ** Modules Revision 3.0 ** ** Providing a flexible user environment ** ** ** ** File: cmdModule.c ** ** First Edition: 1991/10/23 ** ** ** ** Authors: John Furlan, jlf@behere.com ** ** Jens Hamisch, jens@Strawberry.COM ** ** ** ** Description: The actual module command from the Tcl level. This ** ** routines calls other ModuleCmd routines to carry out ** ** the subcommand requested. ** ** ** ** Exports: cmdModule ** ** Read_Modulefile ** ** Execute_TclFile ** ** CallModuleProcedure ** ** ** ** Notes: ** ** ** ** ************************************************************************ ** ****/ /** ** Copyright *********************************************************** ** ** ** ** Copyright 1991-1994 by John L. Furlan. ** ** see LICENSE.GPL, which must be provided, for details ** ** ** ** ************************************************************************ **/ static char Id[] = "@(#)$Id: 4d1847137a7622b402945cc19f9a9877aa06ed78 $"; static void *UseId[] = { &UseId, Id }; /** ************************************************************************ **/ /** HEADERS **/ /** ************************************************************************ **/ #include "modules_def.h" /** ************************************************************************ **/ /** LOCAL DATATYPES **/ /** ************************************************************************ **/ /** not applicable **/ /** ************************************************************************ **/ /** CONSTANTS **/ /** ************************************************************************ **/ /** not applicable **/ /** ************************************************************************ **/ /** MACROS **/ /** ************************************************************************ **/ /** For Tcl < 8.6 compatibility **/ #if (TCL_MAJOR_VERSION < 8) || (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6) #define Tcl_GetErrorLine(interp) (interp->errorLine) #define Tcl_SetErrorLine(interp,lineNum) (interp->errorLine = lineNum) #endif /** ************************************************************************ **/ /** LOCAL DATA **/ /** ************************************************************************ **/ char _fil_stdin[] = "stdin"; char _fil_stdout[] = "stdout"; char _fil_stderr[] = "stderr"; char _fil_devnull[] = "/dev/null"; int linenum = 0; static char module_name[] = "cmdModule.c"; /** File name of this module **/ #if WITH_DEBUGGING_CALLBACK static char _proc_cmdModule[] = "cmdModule"; #endif #if WITH_DEBUGGING_UTIL static char _proc_Read_Modulefile[] = "Read_Modulefile"; #endif #if WITH_DEBUGGING_UTIL_1 static char _proc_Execute_TclFile[] = "Execute_TclFile"; static char _proc_CallModuleProcedure[] = "CallModuleProcedure"; #endif char *module_command; /** ************************************************************************ **/ /** PROTOTYPES **/ /** ************************************************************************ **/ /** not applicable **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: cmdModule ** ** ** ** Description: Evaluation of the module command line and callup of ** ** the according subroutine ** ** ** ** First Edition: 1991/10/23 ** ** ** ** Parameters: ClientData client_data ** ** Tcl_Interp *interp According Tcl interp.** ** int argc Number of arguments ** ** char *argv[] Argument array ** ** ** ** Result: int TCL_OK Successful completion ** ** TCL_ERROR Any error ** ** ** ** Attached Globals: g_flags These are set up accordingly before ** ** this function is called in order to ** ** control everything ** ** g_current_module The module which is handled ** ** by the current command ** ** ** ** ************************************************************************ ** ++++*/ int cmdModule( ClientData client_data, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { int return_val = -1, i; int store_flags = g_flags; char *store_curmodule = NULL; char *save_module_command = NULL; int match = 0; /** ** These skip the arguments past the shell and command. **/ int num_modulefiles = argc - 2; char **modulefile_list = (char **) argv + 2; #if 0 int x=0; # define _XD fprintf(stderr,":%d:",++x), #else # define _XD #endif #define _MTCH _XD match = #define _ISERR ((match == -1) && (*TCL_RESULT(interp))) #define _TCLCHK(a) {if(_ISERR) ErrorLogger(ERR_EXEC,LOC,TCL_RESULT(a),NULL);} #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_START, LOC, _proc_cmdModule, NULL); #endif /** ** Help or whatis mode? **/ if( g_flags & (M_HELP | M_WHATIS)) return( TCL_OK); /** ** Parameter check **/ if( argc < 2) { (void) ErrorLogger( ERR_USAGE, LOC, "module", " command ", " [arguments ...] ", NULL); (void) ModuleCmd_Help( interp, 0, modulefile_list); return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** Non-persist mode? **/ if (g_flags & M_NONPERSIST) { return (TCL_OK); } /** ** Display whatis mode? **/ if( g_flags & M_DISPLAY) { fprintf( stderr, "%s\t\t ", argv[ 0]); for( i=1; i **/ } /** ** Check for the module 'magic cookie' ** Trust stdin as a valid module file ... **/ if( !strcmp( filename, _fil_stdin) && !check_magic( filename, MODULES_MAGIC_COOKIE, MODULES_MAGIC_COOKIE_LENGTH)) { if( OK != ErrorLogger( ERR_MAGIC, LOC, filename, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** Now do execute that module file and evaluate the result of the ** latest executed command **/ result = Execute_TclFile(interp, filename); #if WITH_DEBUGGING_UTIL if(EM_ERROR == ReturnValue(interp, result)) ErrorLogger( NO_ERR_DEBUG, LOC, "Execution of '", filename, "' failed", NULL); #endif /** ** Return the result as derivered from the module file execution **/ #if WITH_DEBUGGING_UTIL ErrorLogger( NO_ERR_END, LOC, _proc_Read_Modulefile, NULL); #endif return( result); } /** End of 'Read_Modulefile' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: Execute_TclFile ** ** ** ** Description: Read in and execute all commands concerning the Tcl ** ** file passed as parameter ** ** ** ** First Edition: 1991/10/23 ** ** ** ** Parameters: Tcl_Interp *interp According Tcl interp.** ** char *filename ** ** ** ** Result: int TCL_OK Successful completion ** ** TCL_ERROR Any error ** ** ** ** Attached Globals: line Input read buffer ** ** ** ** ************************************************************************ ** ++++*/ int Execute_TclFile( Tcl_Interp *interp, char *filename) { FILE *infile; int gotPartial = 0; int result = 0; EM_RetVal em_result = EM_OK; char *cmd; Tcl_DString cmdbuf; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_Execute_TclFile, NULL); #endif /** ** If there isn't a line buffer allocated so far, do it now **/ if( line == NULL) { if( NULL == (line = (char*) module_malloc(LINELENGTH * sizeof(char)))) { if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } } /** ** If we're supposed to be interpreting from stdin, set infile ** equal to stdin, otherwise, open the file and interpret **/ if( !strcmp( filename, _fil_stdin)) { infile = stdin; } else { if( NULL == (infile = fopen( filename, "r"))) { if( OK != ErrorLogger( ERR_OPEN, LOC, filename, "reading", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } } /** ** Allow access to which file is being loaded. **/ linenum = 0; Tcl_SetVar( interp, "ModulesCurrentModulefile", filename, 0); Tcl_DStringInit( &cmdbuf); while( 1) { linenum++; if( fgets(line, LINELENGTH, infile) == NULL) { if( !gotPartial) { break; /** while **/ } line[0] = '\0'; } /** ** Put the whole command on the command buffer **/ cmd = Tcl_DStringAppend( &cmdbuf, line, (-1)); if( line[0] != 0 && !Tcl_CommandComplete(cmd)) { gotPartial++; continue; } /** ** Now evaluate the command and react on its result ** Reinitialize the command buffer **/ #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_DEBUG, LOC, " Evaluating '", cmd, "'", NULL); #endif result = Tcl_Eval( interp, cmd); if( EM_ERROR == (em_result = ReturnValue(interp, result))) { ErrorLogger( ERR_EXEC, LOC, cmd, NULL); } Tcl_DStringTrunc( &cmdbuf, 0); #if WITH_DEBUGGING_UTIL_1 { char buffer[ 80]; switch( result) { case TCL_OK: strcpy( buffer, "TCL_OK"); break; case TCL_ERROR: strcpy( buffer, "TCL_ERROR"); break; case TCL_LEVEL0_RETURN: strcpy( buffer, "TCL_LEVEL0_RETURN"); break; } ErrorLogger( NO_ERR_DEBUG, LOC, " Result: '", buffer, "'", NULL); } #endif switch( result) { case TCL_OK: gotPartial = 0; continue; /** while **/ case TCL_ERROR: Tcl_SetErrorLine(interp, ((linenum-1)-gotPartial) + Tcl_GetErrorLine(interp)); /* FALLTHROUGH */ case TCL_LEVEL0_RETURN: break; /** switch **/ } /** ** If the while loop hasn't been continued so far, it is to be broken ** now **/ break; /** while **/ } /** while **/ /** ** Free up what has been used, close the input file and return the result ** of the last command to the caller **/ Tcl_DStringFree( &cmdbuf); if( EOF == fclose( infile)) if( OK != ErrorLogger( ERR_CLOSE, LOC, filename, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_END, LOC, _proc_Execute_TclFile, NULL); #endif return( result); } /** End of 'Execute_TclFile' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: CallModuleProcedure ** ** ** ** Description: Call a Tcl Procedure ** ** Executes the passed modulefile (conditionally hidden)** ** and then evaluates the passed Tcl procedure ** ** ** ** First Edition: 1991/10/23 ** ** ** ** Parameters: Tcl_Interp *interp According Tcl interp.** ** Tcl_DString *cmdptr Buffer fot the Tcl ** ** command ** ** char *modulefile According module file** ** char *procname Name of the Tcl Proc.** ** int suppress_output Controlls redirect.** ** of stdout and stderr ** ** ** ** Result: int TCL_OK Successful completion ** ** TCL_ERROR Any error ** ** ** ** Attached Globals: - ** ** ** ** ************************************************************************ ** ++++*/ int CallModuleProcedure( Tcl_Interp *interp, Tcl_DString *cmdptr, char *modulefile, char *procname, int suppress_output) { char cmdline[ LINELENGTH]; char *cmd; int result; int saved_stdout = 0, saved_stderr = 0, devnull; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_CallModuleProcedure, NULL); #endif /** ** Must send stdout and stderr to /dev/null until the ** ModulesHelp procedure is called. **/ if( suppress_output) { if( 0 > (devnull = open( _fil_devnull, O_RDWR))) { if( OK != ErrorLogger( ERR_OPEN, LOC, _fil_devnull, "changing", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** Close STDOUT and reopen it as /dev/null **/ if( -1 == ( saved_stdout = dup( 1))) if( OK != ErrorLogger( ERR_DUP, LOC, _fil_stdout, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == close( 1)) if( OK != ErrorLogger( ERR_CLOSE, LOC, _fil_stdout, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == dup( devnull)) if( OK != ErrorLogger( ERR_DUP, LOC, _fil_devnull, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ /** ** Close STDERR and reopen it as /dev/null **/ if( -1 == ( saved_stdout = dup( 2))) if( OK != ErrorLogger( ERR_DUP, LOC, _fil_stderr, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == close( 2)) if( OK != ErrorLogger( ERR_CLOSE, LOC, _fil_stderr, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == dup( devnull)) if( OK != ErrorLogger( ERR_DUP, LOC, _fil_devnull, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ } /** ** Read the passed module file **/ Read_Modulefile( interp, modulefile); /** ** Reinstall stdout and stderr **/ if( suppress_output) { /** ** Reinstall STDOUT **/ if( EOF == fflush( stdout)) if( OK != ErrorLogger( ERR_FLUSH, LOC, _fil_stdout, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( EOF == fflush( stderr)) if( OK != ErrorLogger( ERR_FLUSH, LOC, _fil_stderr, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == close( 1)) if( OK != ErrorLogger( ERR_CLOSE, LOC, _fil_stdout, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ /** ** Reinstall STDERR **/ if( -1 == dup( saved_stdout)) if( OK != ErrorLogger( ERR_DUP, LOC, _fil_stdout, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == close( 2)) if( OK != ErrorLogger( ERR_CLOSE, LOC, _fil_stderr, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ if( -1 == dup( saved_stderr)) if( OK != ErrorLogger( ERR_DUP, LOC, _fil_stderr, NULL)) return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/ } /** ** Now evaluate the Tcl Procedure **/ /* sprintf( cmdline, "%s\n", procname); */ strcpy( cmdline, procname); strcat( cmdline, "\n"); cmd = Tcl_DStringAppend( cmdptr, cmdline, (-1)); result = Tcl_Eval( interp, cmd); Tcl_DStringTrunc( cmdptr, 0); #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_END, LOC, _proc_CallModuleProcedure, NULL); #endif return( result); } /** End of 'CallModuleProcedure' **/