1 | /*****
2 | ** ** Module Header ******************************************************* **
3 | ** **
4 | ** Modules Revision 3.0 **
5 | ** Providing a flexible user environment **
6 | ** **
7 | ** File: ModuleCmd_Switch.c **
8 | ** First Edition: 1991/10/23 **
9 | ** **
10 | ** Authors: John Furlan, jlf@behere.com **
11 | ** Jens Hamisch, jens@Strawberry.COM **
12 | ** **
13 | ** Description: Switches two modulefiles such that the paths are **
14 | ** switched in-place. **
15 | ** **
16 | ** Exports: ModuleCmd_Switch **
17 | ** **
18 | ** Notes: **
19 | ** **
20 | ** ************************************************************************ **
21 | ****/
22 |
23 | /** ** Copyright *********************************************************** **
24 | ** **
25 | ** Copyright 1991-1994 by John L. Furlan. **
26 | ** see LICENSE.GPL, which must be provided, for details **
27 | ** **
28 | ** ************************************************************************ **/
29 |
30 | static char Id[] = "@(#)$Id: ModuleCmd_Switch.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
31 | static void *UseId[] = { &UseId, Id };
32 |
33 | /** ************************************************************************ **/
34 | /** HEADERS **/
35 | /** ************************************************************************ **/
36 |
37 | #include "modules_def.h"
38 |
39 | /** ************************************************************************ **/
40 | /** LOCAL DATATYPES **/
41 | /** ************************************************************************ **/
42 |
43 | /** not applicable **/
44 |
45 | /** ************************************************************************ **/
46 | /** CONSTANTS **/
47 | /** ************************************************************************ **/
48 |
49 | /** not applicable **/
50 |
51 | /** ************************************************************************ **/
52 | /** MACROS **/
53 | /** ************************************************************************ **/
54 |
55 | /** not applicable **/
56 |
57 | /** ************************************************************************ **/
58 | /** LOCAL DATA **/
59 | /** ************************************************************************ **/
60 |
61 | static char module_name[] = "ModuleCmd_Switch.c"; /** File name of this module **/
62 |
63 | /** ************************************************************************ **/
64 | /** PROTOTYPES **/
65 | /** ************************************************************************ **/
66 |
67 | /** not applicable **/
68 |
69 |
70 | /*++++
71 | ** ** Function-Header ***************************************************** **
72 | ** **
73 | ** Function: ModuleCmd_Switch **
74 | ** **
75 | ** Description: Execution of the module-command 'switch' **
76 | ** **
77 | ** First Edition: 1991/10/23 **
78 | ** **
79 | ** Parameters: Tcl_Interp *interp Attached Tcl Interp. **
80 | ** int argc Number of arguments **
81 | ** char *argv[] Argument list **
82 | ** **
83 | ** Result: int TCL_ERROR Failure **
84 | ** TCL_OK Successfull operation **
85 | ** **
86 | ** Attached Globals: g_flags Controlling the callback **
87 | ** functions. **
88 | ** g_specified_module The module name from the **
89 | ** command line. **
90 | ** g_current_module The module which is handled **
91 | ** by the current command **
92 | ** **
93 | ** ************************************************************************ **
94 | ++++*/
95 |
96 | int ModuleCmd_Switch( Tcl_Interp *interp,
97 | int argc,
98 | char *argv[])
99 | {
100 | char *oldmodule,
101 | *newmodule,
102 | *realname,
103 | *oldfile,
104 | *newfile,
105 | *oldname,
106 | *newname,
107 | *oldmodule_buffer = (char *) NULL;
108 | int ret_val = TCL_OK;
109 |
110 | #if WITH_DEBUGGING_MODULECMD
111 | fprintf( stderr, "ModuleCmd_Switch(%d):DEBUG: Starting\n", __LINE__);
112 | #endif
113 | /**
114 | ** allocate buffer memory
115 | **/
116 | if ((char *) NULL == (oldfile = stringer(NULL, MOD_BUFSIZE, NULL)))
117 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
118 | goto unwind0;
119 |
120 | if ((char *) NULL == (newfile = stringer(NULL, MOD_BUFSIZE, NULL)))
121 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
122 | goto unwind1;
123 |
124 | if ((char *) NULL == (oldname = stringer(NULL, MOD_BUFSIZE, NULL)))
125 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
126 | goto unwind2;
127 |
128 | if ((char *) NULL == (newname = stringer(NULL, MOD_BUFSIZE, NULL)))
129 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
130 | goto unwind3;
131 |
132 | /**
133 | ** Parameter check. the required syntax is:
134 | ** module switch [ <old> ] <new>
135 | ** If <old> is not specified, then the pathname of <new> is assumed.
136 | **/
137 |
138 | if( argc == 1) {
139 | newmodule = argv[0];
140 | if((char *) NULL == (oldmodule_buffer = stringer(NULL,0,newmodule,NULL)))
141 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
142 | goto unwind4;
143 |
144 | /* starting from the end of the module name, find the first
145 | * forward slash and replace with null
146 | */
147 | if ((oldmodule = strrchr(oldmodule_buffer, '/'))) {
148 | *oldmodule = 0;
149 | }
150 | oldmodule = oldmodule_buffer;
151 | } else if( argc == 2) {
152 | oldmodule = argv[0];
153 | newmodule = argv[1];
154 | } else {
155 | if( OK != ErrorLogger( ERR_USAGE, LOC, "switch oldmodule newmodule",
156 | NULL))
157 | return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/
158 | }
159 |
160 |
161 | /**
162 | ** Set the name of the module specified on the command line
163 | **/
164 |
165 | g_specified_module = oldmodule;
166 |
167 | /**
168 | ** First try to find a match for the modulefile out of the LOADEDMODULES.
169 | **/
170 |
171 | if( !IsLoaded( interp, oldmodule, &realname, oldfile))
172 | if( OK != ErrorLogger( ERR_NOTLOADED, LOC, oldmodule, NULL))
173 | goto unwind4;
174 |
175 | /**
176 | ** If we have another name to try, try finding it on disk.
177 | **/
178 |
179 | if( realname)
180 | ret_val = Locate_ModuleFile( interp, realname, oldname, oldfile);
181 |
182 | /**
183 | ** If we've made it this far without finding a file, then look using the
184 | ** exact name the user gave me -- i.e. the old method.
185 | **/
186 |
187 | if( ret_val == TCL_ERROR) {
188 |
189 | if( TCL_ERROR == (ret_val = Locate_ModuleFile( interp, oldmodule,
190 | oldname, oldfile)))
191 | if( OK != ErrorLogger( ERR_LOCATE, LOC, oldmodule, NULL))
192 | goto unwind4;
193 |
194 | /**
195 | ** OK, this one is known. Is it loaded, too?
196 | **/
197 |
198 | if( !IsLoaded( interp, oldname, NULL, oldfile))
199 | if( OK != ErrorLogger( ERR_NOTLOADED, LOC, oldmodule, NULL))
200 | goto unwind4;
201 | }
202 |
203 | /**
204 | ** Set the name of the module specified on the command line
205 | **/
206 |
207 | g_specified_module = newmodule;
208 |
209 | /**
210 | ** Now try to find the new file to swap with.
211 | **/
212 |
213 | if( TCL_ERROR == (ret_val = Locate_ModuleFile( interp, newmodule, newname,
214 | newfile)))
215 | if( OK != ErrorLogger( ERR_LOCATE, LOC, newmodule, NULL))
216 | goto unwind4;
217 |
218 | ErrorLogger( NO_ERR_VERBOSE, LOC, "Switching '$1' to '$2'", oldmodule,
219 | newmodule, NULL);
220 |
221 | /**
222 | ** We'll remove the current modulefile with the SWITCH1 state set.
223 | ** This means that instead of really removing the paths, markers will
224 | ** be put in its place for later use.
225 | **/
226 |
227 | g_flags |= (M_REMOVE | M_SWSTATE1);
228 |
229 | g_specified_module = oldmodule;
230 | g_current_module = oldname;
231 | if( Read_Modulefile( interp, oldfile) == 0)
232 | Update_LoadedList( interp, oldname, oldfile);
233 | else {
234 | ErrorLogger( NO_ERR_VERBOSE, LOC, "failed", NULL);
235 | goto unwind4;
236 | }
237 |
238 | g_flags &= ~(M_REMOVE | M_SWSTATE1);
239 |
240 | /**
241 | ** Move on to state SWITCH2. This loads the modulefile at the append
242 | ** and prepend markers.
243 | **/
244 |
245 | g_flags |= M_SWSTATE2;
246 |
247 | g_specified_module = newmodule;
248 | g_current_module = newname;
249 | if( Read_Modulefile( interp, newfile) == 0)
250 | Update_LoadedList( interp, newname, newfile);
251 | else {
252 | ErrorLogger( NO_ERR_VERBOSE, LOC, "failed", NULL);
253 | goto unwind4;
254 | }
255 |
256 | g_flags &= ~M_SWSTATE2;
257 |
258 | /**
259 | ** This actually unsets environment variables and gets rid of the
260 | ** markers.
261 | **/
262 |
263 | g_flags |= (M_REMOVE | M_SWSTATE3);
264 |
265 | g_specified_module = oldmodule;
266 | g_current_module = oldname;
267 | if( Read_Modulefile( interp, oldfile) == 0)
268 | Update_LoadedList( interp, newname, newfile);
269 | else {
270 | ErrorLogger( NO_ERR_VERBOSE, LOC, "failed", NULL);
271 | goto unwind4;
272 | }
273 |
274 | /**
275 | ** Return on success
276 | **/
277 |
278 | ErrorLogger( NO_ERR_VERBOSE, LOC, "done", NULL);
279 |
280 | #if WITH_DEBUGGING_MODULECMD
281 | fprintf( stderr, "ModuleCmd_Switch(%d):DEBUG: End\n", __LINE__);
282 | #endif
283 | /**
284 | ** free space
285 | ** assume don't need what's pointed to by g_current_module
286 | ** and g_specified_module
287 | **/
288 | null_free((void *) &newname);
289 | null_free((void *) &oldname);
290 | null_free((void *) &newfile);
291 | null_free((void *) &oldfile);
292 |
293 | return( TCL_OK); /** ------- EXIT (SUCCESS) --------> **/
294 |
295 | unwind4:
296 | if (oldmodule == oldmodule_buffer)
297 | null_free((void *) &oldmodule);
298 | null_free((void *) &newname);
299 | unwind3:
300 | null_free((void *) &oldname);
301 | unwind2:
302 | null_free((void *) &newfile);
303 | unwind1:
304 | null_free((void *) &oldfile);
305 | unwind0:
306 | return( TCL_ERROR); /** ------- EXIT (FAILURE) --------> **/
307 |
308 | } /** End of 'ModuleCmd_Switch' **/
309 |