Exemple #1
0
int	ModuleCmd_Switch(	Tcl_Interp	*interp,
                 		int		 argc,
                 		char		*argv[])
{
    char	*oldmodule,
		*newmodule,
		*realname,
		*oldfile,
		*newfile,
		*oldname,
		*newname,
                *oldmodule_buffer	= (char *) NULL;
    int		 ret_val = TCL_OK;
    
    /**
     ** allocate buffer memory
     **/
    if (!(oldfile = stringer(NULL, MOD_BUFSIZE, NULL)))
	if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
	    goto unwind0;

    if (!(newfile = stringer(NULL, MOD_BUFSIZE, NULL)))
	if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
	    goto unwind1;

    if (!(oldname = stringer(NULL, MOD_BUFSIZE, NULL)))
	if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
	    goto unwind2;

    if (!(newname = stringer(NULL, MOD_BUFSIZE, NULL)))
	if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
	    goto unwind3;

    /**
     **  Parameter check. the required syntax is:
     **    module switch [ <old> ] <new>
     **  If <old> is not specified, then the pathname of <new> is assumed.
     **/

    if( argc == 1) {
      newmodule = argv[0];
      if(!(oldmodule_buffer = stringer(NULL,0,newmodule,NULL)))
	if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
          goto unwind4;

      /* starting from the end of the module name, find the first
       * forward slash and replace with null 
       */
      if ((oldmodule = strrchr(oldmodule_buffer, *psep))) {
	  *oldmodule = 0;
      }
      oldmodule = oldmodule_buffer;
    } else if( argc == 2) {
      oldmodule = argv[0];
      newmodule = argv[1];
    } else {
      if( OK != ErrorLogger( ERR_USAGE, LOC, "switch oldmodule newmodule",
			     NULL))
	return( TCL_ERROR);		/** ------- EXIT (FAILURE) --------> **/
    }


    /**
     ** Set the name of the module specified on the command line
     **/

    g_specified_module = oldmodule;

    /**
     **  First try to find a match for the modulefile out of the LOADEDMODULES.
     **/

    if( !IsLoaded( interp, oldmodule, &realname, oldfile)) 
	if( OK != ErrorLogger( ERR_NOTLOADED, LOC, oldmodule, NULL))
	    goto unwind4;
    
    /**
     **  If we have another name to try, try finding it on disk.
     **/

    if( realname) 
        ret_val = Locate_ModuleFile( interp, realname, oldname, oldfile);

    /**
     **  If we've made it this far without finding a file, then look using the
     **  exact name the user gave me -- i.e. the old method. 
     **/

    if( ret_val == TCL_ERROR) {

        if( TCL_ERROR == (ret_val = Locate_ModuleFile( interp, oldmodule,
	    oldname, oldfile)))
	    if( OK != ErrorLogger( ERR_LOCATE, LOC, oldmodule, NULL))
		goto unwind4;

	/**
	 **  OK, this one is known. Is it loaded, too?
	 **/

        if( !IsLoaded( interp, oldname, NULL, oldfile)) 
	    if( OK != ErrorLogger( ERR_NOTLOADED, LOC, oldmodule, NULL))
		goto unwind4;
    }

    /**
     ** Set the name of the module specified on the command line
     **/

    g_specified_module = newmodule;

    /**
     **  Now try to find the new file to swap with.
     **/

    if( TCL_ERROR == (ret_val = Locate_ModuleFile( interp, newmodule, newname,
	newfile)))
	if( OK != ErrorLogger( ERR_LOCATE, LOC, newmodule, NULL))
	    goto unwind4;
    
    ErrorLogger( NO_ERR_VERBOSE, LOC, "Switching '$1' to '$2'", oldmodule,
	newmodule, NULL);

    /**
     **  We'll remove the current modulefile with the SWITCH1 state set.
     **  This means that instead of really removing the paths, markers will
     **  be put in its place for later use.
     **/

    g_flags |= (M_REMOVE | M_SWSTATE1);
    
    g_specified_module = oldmodule;
    g_current_module = oldname;
    if( Read_Modulefile( interp, oldfile) == 0)
	Update_LoadedList( interp, oldname, oldfile);
    else {
        ErrorLogger( NO_ERR_VERBOSE, LOC, "failed", NULL);
	goto unwind4;
    }
    
    g_flags &= ~(M_REMOVE | M_SWSTATE1);

    /**
     **  Move on to state SWITCH2.  This loads the modulefile at the append
     **  and prepend markers.
     **/

    g_flags |= M_SWSTATE2;

    g_specified_module = newmodule;
    g_current_module = newname;
    if( Read_Modulefile( interp, newfile) == 0)
	Update_LoadedList( interp, newname, newfile);
    else {
        ErrorLogger( NO_ERR_VERBOSE, LOC, "failed", NULL);
	goto unwind4;
    }

    g_flags &= ~M_SWSTATE2;

    /**
     **  This actually unsets environment variables and gets rid of the
     **  markers.
     **/

    g_flags |= (M_REMOVE | M_SWSTATE3);

    g_specified_module = oldmodule;
    g_current_module = oldname;
    if( Read_Modulefile( interp, oldfile) == 0)
	Update_LoadedList( interp, newname, newfile);
    else {
        ErrorLogger( NO_ERR_VERBOSE, LOC, "failed", NULL);
	goto unwind4;
    }
 
    /**
     **  Return on success
     **/

    ErrorLogger( NO_ERR_VERBOSE, LOC, "done", NULL);

    /**
     ** free space
     **   assume don't need what's pointed to by g_current_module
     **   and g_specified_module
     **/
    null_free((void *) &newname);
    null_free((void *) &oldname);
    null_free((void *) &newfile);
    null_free((void *) &oldfile);

    return( TCL_OK);			/** ------- EXIT (SUCCESS) --------> **/

unwind4:
    if (oldmodule == oldmodule_buffer)
    	null_free((void *) &oldmodule);
    null_free((void *) &newname);
unwind3:
    null_free((void *) &oldname);
unwind2:
    null_free((void *) &newfile);
unwind1:
    null_free((void *) &oldfile);
unwind0:
    return( TCL_ERROR);			/** ------- EXIT (FAILURE) --------> **/

} /** End of 'ModuleCmd_Switch' **/
int ModuleCmd_Whatis(	Tcl_Interp	*interp,
			int		 argc,
			char		*argv[])
{
    struct stat	 stats;
    Tcl_Interp	*whatis_interp;
    Tcl_DString	 cmdbuf;
    int		 i, result = TCL_OK, done = 0;
    char	 modulefile[ MOD_BUFSIZE],
		 modulename[ MOD_BUFSIZE],
		*modpath = (char *)NULL,/** Buffer for the contents of the   **/
					/** environment variable MODULEPATH  **/
		**wptr,
		*dirname = (char *)NULL,
		*cache_file = (char *) NULL;	/** Name of the cache file   **/
    FILE	*cachefp = (FILE *) NULL;	/** Cache file pointer	     **/

#if WITH_DEBUGGING_MODULECMD
    ErrorLogger( NO_ERR_START, LOC, _proc_ModuleCmd_Whatis, NULL);
#endif

    /**
     **	 Initialize the command buffer and set up the modules flag to
     **	 'whatisonly'
     **/
    Tcl_DStringInit( &cmdbuf);
    g_flags |= M_WHATIS;

    /**
     **	 Handle each passed module file. Create a Tcl interpreter for each
     **	 module file to be handled and initialize it with custom module commands
     **/

    if ( argc) {
    /**
     **	 User provided a list of modules for ``whatis'' info
     **/
	for(i=0; i<argc && argv[i]; i++) {

	    whatis_interp = EM_CreateInterp();
	    if( TCL_OK != (result = InitializeModuleCommands( whatis_interp))) {
		EM_DeleteInterp( whatis_interp);
		result = TCL_ERROR;
		break;
	    }

	    /**
	     **	 locate the filename related to the passed module
	     **/
	    if( TCL_ERROR ==
		Locate_ModuleFile(whatis_interp,argv[i],modulename,modulefile)){
		EM_DeleteInterp( whatis_interp);
		if( OK != ErrorLogger( ERR_LOCATE, LOC, argv[i], NULL))
		    break;
		else
		    continue;
	    }

	    /**
	     **	 Print out everything that would happen if the module file were
	     **	 executed ...
	     **/
	    g_current_module = modulename;

	    cmdModuleWhatisInit();
	    result = CallModuleProcedure( whatis_interp, &cmdbuf, modulefile,
		"ModulesWhatis", 0);

	    /**
	     **	 Print the result ...
	     **/
	    if( whatis) {
		wptr = whatis;
		while( *wptr)
		    fprintf( stderr, "%-21s: %s\n", argv[i], *wptr++);
	    }

	    /**
	     **	 Remove the Tcl interpreter that has been used for printing ...
	     **/
	    EM_DeleteInterp( whatis_interp);
	    cmdModuleWhatisShut();

	} /** for **/
    } else {
       /**
	**  User wants all module ``whatis'' info
	**/

	/**
	 **  If no MODULEPATH defined, we can not output anything
	 **/
	if( !(modpath = (char *) xgetenv( "MODULEPATH")))
	    if( OK != ErrorLogger( ERR_MODULE_PATH, LOC, NULL))
		goto unwind0;

	/**
	 **  Check whether a cache file exists then list all the ``whatis'' info
	 **  Otherwise read all module files ...
	 **/
	cache_file = apropos_cache();
	if( !sw_create && cache_file && !stat( cache_file, &stats)) {

	    /**
	     **	 Open the cache file
	     **/
	    if((FILE *) NULL == (cachefp = fopen( cache_file, "r"))) {
		if( OK != ErrorLogger( ERR_OPEN, LOC, cache_file, NULL))
		    goto unwind1;
	
	    } else {
		
		/**
		 **  Read the cache and close the file
		 **/
		result = read_cache( argc, argv, cachefp, WHATIS_ALL);

		if( EOF == fclose( cachefp))
		    if( OK != ErrorLogger( ERR_CLOSE, LOC, cache_file, NULL))
			goto unwind1;

		done = 1;
	    }
	}

	/**
	 **  If we're not done now, we have to scan the files
	 **/
	 if( !done) {

	     /**
	      **  Open the cache file if neccessary
	      **/
	     if( sw_create && cache_file)
		 if((FILE *) NULL == (cachefp = fopen( cache_file, "w")))
		     if( OK != ErrorLogger( ERR_OPEN, LOC, cache_file, NULL))
			 goto unwind1;
		
	     /**
	      **  Tokenize the module path string and check all dirs
	      **/
	     for( dirname = xstrtok( modpath, ":");
		  dirname;
		  dirname = xstrtok( NULL, ":") ) {
	
		 if( !check_dir( dirname))
		     continue;
	
		 whatis_dir( dirname, argc, argv, cachefp, WHATIS_ALL);

	     } /** for **/

	     /**
	      **  Close the cache file
	      **/
	     if( cachefp)
		 if( EOF == fclose( cachefp))
		     if( OK != ErrorLogger( ERR_CLOSE, LOC, cache_file, NULL))
			 goto unwind1;
	 }
    }

    /**
     **	 Leave the 'whatis only mode', free up what has been used and return
     **/
    g_flags &= ~M_WHATIS;
    fprintf( stderr, "\n");

    Tcl_DStringFree( &cmdbuf);

    /**
     **	 Free up allocated resources
     **/
    null_free((void *) &cache_file);
    null_free((void *) &modpath);

    /**
     **	 Return on success
     **/

#if WITH_DEBUGGING_MODULECMD
    ErrorLogger( NO_ERR_END, LOC, _proc_ModuleCmd_Whatis, NULL);
#endif

    return( result);			/** --- EXIT PROCEDURE (result)  --> **/

unwind1:
    null_free((void *) &cache_file);
    null_free((void *) &modpath);
unwind0:
    return( TCL_ERROR);			/** --- EXIT PROCEDURE (FAILURE) --> **/

} /** End of 'ModuleCmd_Whatis' **/
static	int	PerModuleHelp(	Tcl_Interp	*interp,
		    		int         	 argc,
		    		char		*argv[])
{
    Tcl_Interp	*help_interp;
    Tcl_DString	 cmdbuf;
    int		 i,
    		 result;
    char	 modulefile[ MOD_BUFSIZE];
    char	 modulename[ MOD_BUFSIZE];
    
#if WITH_DEBUGGING_UTIL_1
    ErrorLogger( NO_ERR_START, LOC, _proc_PerModuleHelp, NULL);
#endif

    /**
     **  Initialize the command buffer
     **/

    Tcl_DStringInit( &cmdbuf);
    g_flags |= M_HELP;

    /**
     **  Handle each passed module file. Create a Tcl interpreter for each 
     **  module file to be handled
     **/

    for(i=0; i<argc; i++) {

	help_interp = EM_CreateInterp();
	if( TCL_OK != (result = InitializeModuleCommands( help_interp))) {
	    EM_DeleteInterp( help_interp);
	    result = TCL_ERROR;
	    break;
	}

	/**
	 **  locate the filename related to the passed module
	 **/

	if( Locate_ModuleFile( help_interp, argv[i], modulename, modulefile)) {
	    if( OK != ErrorLogger( ERR_LOCATE, LOC, argv[i], NULL))
		continue;
	}

	/**
	 **  Now print the module specific help ...
	 **/

        g_current_module = modulename;
	fprintf( stderr,
		 "\n----------- Module Specific Help for '%s' %.*s-------\n\n", 
		 g_current_module, (int)(20-strlen( g_current_module)),
		 "--------------------");
	result = CallModuleProcedure( help_interp, &cmdbuf, modulefile,
	    "ModulesHelp", 1);

	/**
	 **  If there hasn't been any help ...
	 **/

	if( result == TCL_ERROR)
	    fprintf( stderr, "\t*** No Module Specific Help for %s ***\n", 
		g_current_module);

	/**
	 **  Finally clear up the Tcl interpreter and handle the next module
	 **/

	EM_DeleteInterp( help_interp);
    }

    /**
     **  Free the used command buffer and return on success
     **/

    g_flags &= ~M_HELP;
    Tcl_DStringFree(&cmdbuf);

    return( TCL_OK);

} /** End of 'PerModuleHelp' **/