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' **/