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  |