1    | /*****
2    |  ** ** Module Header ******************************************************* **
3    |  ** 									     **
4    |  **   Modules Revision 3.0						     **
5    |  **   Providing a flexible user environment				     **
6    |  ** 									     **
7    |  **   File:		ModuleCmd_Load.c				     **
8    |  **   First Edition:	1991/10/23					     **
9    |  ** 									     **
10   |  **   Authors:	John Furlan, jlf@behere.com				     **
11   |  **		Jens Hamisch, jens@Strawberry.COM			     **
12   |  ** 									     **
13   |  **   Description:	The load and unload procedure that takes care of     **
14   |  **			adding and removing modulefiles to and from the	     **
15   |  **			user's environment.				     **
16   |  ** 									     **
17   |  **   Exports:		ModuleCmd_Load					     **
18   |  ** 									     **
19   |  **   Notes:								     **
20   |  ** 									     **
21   |  ** ************************************************************************ **
22   |  ****/
23   | 
24   | /** ** Copyright *********************************************************** **
25   |  ** 									     **
26   |  ** Copyright 1991-1994 by John L. Furlan.                      	     **
27   |  ** see LICENSE.GPL, which must be provided, for details		     **
28   |  ** 									     ** 
29   |  ** ************************************************************************ **/
30   | 
31   | static char Id[] = "@(#)$Id: ModuleCmd_Load.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
32   | static void *UseId[] = { &UseId, Id };
33   | 
34   | /** ************************************************************************ **/
35   | /** 				      HEADERS				     **/
36   | /** ************************************************************************ **/
37   | 
38   | #include "modules_def.h"
39   | 
40   | /** ************************************************************************ **/
41   | /** 				  LOCAL DATATYPES			     **/
42   | /** ************************************************************************ **/
43   | 
44   | /** not applicable **/
45   | 
46   | /** ************************************************************************ **/
47   | /** 				     CONSTANTS				     **/
48   | /** ************************************************************************ **/
49   | 
50   | /** not applicable **/
51   | 
52   | /** ************************************************************************ **/
53   | /**				      MACROS				     **/
54   | /** ************************************************************************ **/
55   | 
56   | /** not applicable **/
57   | 
58   | /** ************************************************************************ **/
59   | /** 				    LOCAL DATA				     **/
60   | /** ************************************************************************ **/
61   | 
62   | static	char	module_name[] = "ModuleCmd_Load.c";	/** File name of this module **/
63   | 
64   | #if WITH_DEBUGGING_MODULECMD
65   | static	char	_proc_ModuleCmd_Load[] = "ModuleCmd_Load";
66   | #endif
67   | 
68   | /** ************************************************************************ **/
69   | /**				    PROTOTYPES				     **/
70   | /** ************************************************************************ **/
71   | 
72   | /** not applicable **/
73   | 
74   | 
75   | /*++++
76   |  ** ** Function-Header ***************************************************** **
77   |  ** 									     **
78   |  **   Function:		ModuleCmd_Load					     **
79   |  ** 									     **
80   |  **   Description:	Execution of the module-commands 'load' and 'unload' **
81   |  ** 									     **
82   |  **   First Edition:	1991/10/23					     **
83   |  ** 									     **
84   |  **   Parameters:	Tcl_Interp	*interp		Attached Tcl Interp. **
85   |  **			int		 load		Controls 'load' or   **
86   |  **							'unload' to be done  **
87   |  **			int		 argc		Number of arguments  **
88   |  **			char 		*argv[]		Argument list	     **
89   |  ** 									     **
90   |  **   Result:		int	0		None of the passed modules   **
91   |  **						has been load		     **
92   |  **				1		At least one module has been **
93   |  **						read			     **
94   |  ** 									     **
95   |  **   Attached Globals:	g_specified_module	The module name from the     **
96   |  **						command line		     **
97   |  **   			g_flags		These are set up accordingly before  **
98   |  **					this function is called in order to  **
99   |  **					control everything		     **
100  |  **			g_current_module	The module which is handled  **
101  |  **						by the current command	     **
102  |  ** 									     **
103  |  ** ************************************************************************ **
104  |  ++++*/
105  | 
106  | int	ModuleCmd_Load(	Tcl_Interp	*interp,
107  |                		int		 load,
108  |                		int		 argc,
109  |                		char		*argv[])
110  | {
111  |     int			  i,
112  |     			  return_val,		/** Subroutine return values **/
113  |     			  a_successful_load = 0;	/** Command return   **/
114  |     char		  filename[ MOD_BUFSIZE],	/** Module filename  **/
115  |     			  modulename[ MOD_BUFSIZE];	/** Real module name **/
116  |     Tcl_Interp		 *tmp_interp;		/** Tcl interpreter to be    **/
117  | 						/** used internally	     **/
118  |     Tcl_HashTable	**oldTables = NULL;
119  | 
120  | #if WITH_DEBUGGING_MODULECMD
121  |     ErrorLogger( NO_ERR_START, LOC, _proc_ModuleCmd_Load, NULL);
122  | #endif
123  | 
124  |     /**
125  |      **  Set up the flags controling the Tcl callback functions
126  |      **/
127  | 
128  |     if( load)
129  |         g_flags |= M_LOAD;
130  |     else
131  |         g_flags |= M_REMOVE;
132  |     
133  |     /**
134  |      **  Handle all module files in the order they are passed to me
135  |      **/
136  | 
137  |     for( i=0; i<argc && argv[i]; i++) {
138  | 	/**
139  | 	 ** Set the name of the module specified on the command line
140  | 	 **/
141  | 
142  | 	g_specified_module = argv[i];
143  | 
144  | 	/**
145  | 	 **  Create a Tcl interpreter and initialize it with the module commands
146  | 	 **/
147  | 
148  |         tmp_interp = Tcl_CreateInterp();
149  | 	if( TCL_OK != (return_val = InitializeModuleCommands( tmp_interp)))
150  | 	    return( return_val);	/** -------- EXIT (FAILURE) -------> **/
151  |         filename[0] = '\0';
152  | 
153  | 	/**
154  | 	 **  UNLOAD to be done
155  | 	 **  At first check if it is loaded ...
156  | 	 **/
157  | 
158  |         if( !load) {
159  | 
160  |             char	*tmpname;
161  | 
162  |             if( !IsLoaded( tmp_interp, argv[i], &tmpname, filename)) {
163  | #if 0
164  | 		/** do we really care if it's not loaded ... **/
165  | 		if( OK != ErrorLogger( ERR_NOTLOADED, LOC, argv[i], NULL))
166  | #endif
167  | 		    return_val = TCL_ERROR;
168  |             } else {
169  | 
170  | 		/**
171  | 		 **  So it is loaded ...
172  | 		 **  Do we know the filename?
173  | 		 **/
174  |                 if ((char *) NULL == stringer(modulename, MOD_BUFSIZE,
175  | 			tmpname, NULL))
176  | 		    if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
177  | 			goto unwind0;
178  |                 if( !filename[0])
179  |                     if( TCL_ERROR == (return_val = Locate_ModuleFile(
180  | 			tmp_interp, argv[i], tmpname, filename))) 
181  | 			ErrorLogger( ERR_LOCATE, LOC, argv[i], NULL);
182  | 
183  |                 /**
184  |                  **  If IsLoaded() created tmpname, then we must free it.
185  |                  **/
186  | 
187  |                 if( tmpname && (tmpname != argv[i]))
188  |                     null_free((void *) &tmpname);
189  | 
190  |             } /** if loaded **/
191  | 
192  | 	/**
193  | 	 **  LOAD to be done
194  | 	 **  Only check the filename
195  | 	 **/
196  | 
197  |         } else {
198  | 
199  | 	    if( TCL_ERROR == (return_val = Locate_ModuleFile( tmp_interp,
200  | 		argv[i], modulename, filename)))
201  | 		ErrorLogger( ERR_LOCATE, LOC, argv[i], NULL);
202  |         }
203  | 
204  |         /**
205  |          **  If return_val has been set to something other than TCL_OK,
206  |          **  then read_status should not be set -- by the ANSI definition.
207  | 	 **
208  | 	 **  The functions Read_Modulefile and Update_LoadedList will take 
209  | 	 **  respect to the 'flags' which are set to M_LOAD or M_REMOVE
210  | 	 **  according to the intention of calling this procedure.
211  |          **/
212  | 
213  | 	g_current_module = modulename;
214  | 	if( TCL_OK == return_val) {
215  | 	    return_val = Read_Modulefile( tmp_interp, filename);
216  | 
217  | 	    switch (return_val) {
218  | 	    case TCL_OK:
219  | 		/**
220  | 		 ** If module terminates TCL_OK, add it to the loaded list...
221  | 		 **/
222  | 		Update_LoadedList( tmp_interp, modulename, filename);
223  | 
224  | 	    case TCL_BREAK:
225  | 		/**
226  | 		 ** If module terminates TCL_BREAK, don't add it to the list,
227  | 		 ** but assume that everything was OK with the module anyway.
228  | 		 **/
229  | 		/**
230  | 		 **  Save the current environment setup before the next module
231  | 		 **  file is (un)loaded in case something is broken ...
232  | 		 **  ... for Unwind_Modulefile_Changes later on
233  | 		 **/
234  |         	if( oldTables) {
235  |                     Delete_Hash_Tables( oldTables);
236  |                     null_free((void *) &oldTables);
237  |         	}
238  |         	oldTables = Copy_Hash_Tables();
239  | 		a_successful_load = 1;
240  | 		break;	/* switch */
241  | 
242  | 	    case TCL_ERROR:
243  | 	    default:
244  | 		/**
245  | 		 **  Reset what has been changed.
246  | 		 **/
247  | 
248  | 		Unwind_Modulefile_Changes( tmp_interp, oldTables);
249  |             
250  |         	oldTables = NULL;
251  | 		return_val = TCL_ERROR;
252  | 		break;	/* switch */
253  | 	    }
254  | 	}
255  |         Tcl_DeleteInterp(tmp_interp);
256  |     } /** for **/
257  |     
258  |     /**
259  |      **  There may only be a spare save environment left, if the final module
260  |      **  has been load successfully. Remove it in this case
261  |      **/
262  |     if( return_val == TCL_OK && oldTables) {
263  |         Delete_Hash_Tables( oldTables);
264  |         null_free((void *) &oldTables);
265  |     }
266  | 
267  |     /**
268  |      **  Clean up the flags and return 
269  |      **/
270  |     if( load)
271  |         g_flags &= ~M_LOAD;
272  |     else
273  |         g_flags &= ~M_REMOVE;
274  | 
275  | #if WITH_DEBUGGING_MODULECMD
276  |     ErrorLogger( NO_ERR_END, LOC, _proc_ModuleCmd_Load, NULL);
277  | #endif
278  | 
279  |     return( a_successful_load);
280  | 
281  | unwind0:
282  |     return( TCL_ERROR);			/** -------- EXIT (FAILURE) -------> **/
283  | 
284  | } /** End of 'ModuleCmd_Load' **/