1    | /*****
2    |  ** ** Module Header ******************************************************* **
3    |  ** 									     **
4    |  **   Modules Revision 3.0						     **
5    |  **   Providing a flexible user environment				     **
6    |  ** 									     **
7    |  **   File:		cmdSetenv.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 routines for setting and unsetting environment   **
14   |  **			variables from within modulefiles.		     **
15   |  ** 									     **
16   |  **   Exports:		cmdSetEnv					     **
17   |  **			cmdUnsetEnv					     **
18   |  **			moduleSetenv					     **
19   |  **			moduleUnsetenv					     **
20   |  ** 									     **
21   |  **   Notes:								     **
22   |  ** 									     **
23   |  ** ************************************************************************ **
24   |  ****/
25   | 
26   | /** ** Copyright *********************************************************** **
27   |  ** 									     **
28   |  ** Copyright 1991-1994 by John L. Furlan.                      	     **
29   |  ** see LICENSE.GPL, which must be provided, for details		     **
30   |  ** 									     ** 
31   |  ** ************************************************************************ **/
32   | 
33   | static char Id[] = "@(#)$Id: cmdSetenv.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
34   | static void *UseId[] = { &UseId, Id };
35   | 
36   | /** ************************************************************************ **/
37   | /** 				      HEADERS				     **/
38   | /** ************************************************************************ **/
39   | 
40   | #include "modules_def.h"
41   | 
42   | /** ************************************************************************ **/
43   | /** 				  LOCAL DATATYPES			     **/
44   | /** ************************************************************************ **/
45   | 
46   | /** not applicable **/
47   | 
48   | /** ************************************************************************ **/
49   | /** 				     CONSTANTS				     **/
50   | /** ************************************************************************ **/
51   | 
52   | /** not applicable **/
53   | 
54   | /** ************************************************************************ **/
55   | /**				      MACROS				     **/
56   | /** ************************************************************************ **/
57   | 
58   | /** not applicable **/
59   | 
60   | /** ************************************************************************ **/
61   | /** 				    LOCAL DATA				     **/
62   | /** ************************************************************************ **/
63   | 
64   | static	char	module_name[] = "cmdSetenv.c";	/** File name of this module **/
65   | 
66   | #if WITH_DEBUGGING_CALLBACK
67   | static	char	_proc_cmdSetEnv[] = "cmdSetEnv";
68   | static	char	_proc_cmdUnsetEnv[] = "cmdUnsetEnv";
69   | #endif
70   | #if WITH_DEBUGGING_UTIL_1
71   | static	char	_proc_moduleSetenv[] = "moduleSetenv";
72   | static	char	_proc_moduleUnsetenv[] = "moduleUnsetenv";
73   | #endif
74   | 
75   | /** ************************************************************************ **/
76   | /**				    PROTOTYPES				     **/
77   | /** ************************************************************************ **/
78   | 
79   | /** not applicable **/
80   | 
81   | 
82   | /*++++
83   |  ** ** Function-Header ***************************************************** **
84   |  ** 									     **
85   |  **   Function:		cmdSetEnv					     **
86   |  ** 									     **
87   |  **   Description:	Callback function for the 'setenv' command	     **
88   |  ** 									     **
89   |  **   First Edition:	1991/10/23					     **
90   |  ** 									     **
91   |  **   Parameters:	ClientData	 client_data			     **
92   |  **			Tcl_Interp	*interp		According Tcl interp.**
93   |  **			int		 argc		Number of arguments  **
94   |  **			char		*argv[]		Argument array	     **
95   |  ** 									     **
96   |  **   Result:		int	TCL_OK		Successfull completion	     **
97   |  **				TCL_ERROR	Any error		     **
98   |  ** 									     **
99   |  **   Attached Globals:	g_flags		These are set up accordingly before  **
100  |  **					this function is called in order to  **
101  |  **					control everything		     **
102  |  ** 									     **
103  |  ** ************************************************************************ **
104  |  ++++*/
105  | 
106  | int	cmdSetEnv(	ClientData	 client_data,
107  | 	  		Tcl_Interp	*interp,
108  | 	  		int		 argc,
109  | 	  		CONST84 char	*argv[])
110  | {
111  |     int		 force;			/** Force removale of variables	     **/
112  |     char	*var;			/** Varibales name		     **/
113  |     char	*val;			/** Varibales value		     **/
114  | 
115  | #if WITH_DEBUGGING_CALLBACK
116  |     ErrorLogger( NO_ERR_START, LOC, _proc_cmdSetEnv, NULL);
117  | #endif
118  | 
119  |     /**
120  |      **  Check parameters. Usage is:  [-force] variable value
121  |      **/
122  | 
123  |     if( argc < 3 || argc > 4) {
124  | 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "[-force] variable value",
125  | 	    NULL))
126  | 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
127  |     }
128  | 
129  |     /**
130  |      **  Get variables name and value from the argument array
131  |      **/
132  | 
133  |     if( *argv[1] == '-') {
134  |         if( !strncmp( argv[1], "-force", 6)) {
135  |             force = 1;
136  |             var = (char *) argv[2];
137  |             val = (char *) argv[3];
138  |         } else {
139  | 	    if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "[-force] variable value",
140  | 		NULL))
141  | 		return( TCL_ERROR);	/** -------- EXIT (FAILURE) -------> **/
142  |         }            
143  |     } else  {
144  |         force = 0;
145  |         var = (char *) argv[1];
146  |         val = (char *) argv[2];
147  |     }
148  | 
149  |     moduleSetenv( interp, var, val, force);
150  | 
151  |     /**
152  |      **  This has to be done after everything has been set because the
153  |      **  variables may be needed later in the modulefile.
154  |      **/
155  | 
156  |     if( g_flags & M_DISPLAY) {
157  | 	fprintf( stderr, "%s\t\t ", argv[ 0]);
158  | 	while( --argc)
159  | 	    fprintf( stderr, "%s ", *++argv);
160  | 	fprintf( stderr, "\n");
161  |     }
162  | 
163  | #if WITH_DEBUGGING_CALLBACK
164  |     ErrorLogger( NO_ERR_END, LOC, _proc_cmdSetEnv, NULL);
165  | #endif
166  | 
167  |     return( TCL_OK);
168  | 
169  | } /** End of 'cmdSetEnv' **/
170  | 
171  | /*++++
172  |  ** ** Function-Header ***************************************************** **
173  |  ** 									     **
174  |  **   Function:		moduleSetenv					     **
175  |  ** 									     **
176  |  **   Description:	Set or unset environment variables		     **
177  |  ** 									     **
178  |  **   First Edition:	1991/10/23					     **
179  |  ** 									     **
180  |  **   Parameters:	Tcl_Interp	*interp		According Tcl interp.**
181  |  **			char		*variable	Name of the variable **
182  |  **			char		*value		Value to be set	     **
183  |  **			int		 force		Force removal	     **
184  |  ** 									     **
185  |  **   Result:		int	TCL_OK		Successfull completion	     **
186  |  **				TCL_ERROR	Any error		     **
187  |  ** 									     **
188  |  **   Attached Globals:	g_flags		These are set up accordingly before  **
189  |  **					this function is called in order to  **
190  |  **					control everything		     **
191  |  ** 									     **
192  |  ** ************************************************************************ **
193  |  ++++*/
194  | 
195  | int	moduleSetenv(	Tcl_Interp	*interp,
196  |              		char		*variable,
197  |              		char		*value,
198  |              		int  		 force)
199  | {
200  |     char	*oldval;			/** Old value of 'variable'  **/
201  | 
202  | #if WITH_DEBUGGING_UTIL_1
203  |     ErrorLogger( NO_ERR_START, LOC, _proc_moduleSetenv, NULL);
204  | #endif
205  | 
206  |     oldval = (char *) Tcl_GetVar2( interp, "env", variable, TCL_GLOBAL_ONLY);
207  |   
208  |     /**
209  |      **  Check to see if variable is already set correctly... 
210  |      **/
211  | 
212  |     if( !(g_flags & (M_REMOVE|M_DISPLAY|M_SWITCH|M_NONPERSIST)) && oldval) {
213  |         if( !strcmp( value, oldval)) {
214  |             return( TCL_OK);		/** -------- EXIT (SUCCESS) -------> **/
215  |         }
216  |     }
217  | 
218  |     /**
219  |      **  If I'm in SWSTATE1, I'm removing stuff from the old modulefile, so
220  |      **  I'll just mark the variables that were used with the SWSTATE1 flag and
221  |      **  return.
222  |      **
223  |      **  When I come back through in SWSTATE2, I'm setting the variables that
224  |      **  are in the new modulefile.  So, I'll keep track of these by marking
225  |      **  them as touched by SWSTATE2 and then actually setting their values in
226  |      **  the environment down below.
227  |      **
228  |      **  Finally, in SWSTATE3, I'll check to see if the variables in the old
229  |      **  modulefiles that have been marked are still marked as SWSTATE1.  If
230  |      **  they are still the same, then I'll just unset them and return.
231  |      **
232  |      **  And, if I'm not doing any switching, then just unset the variable if
233  |      **  I'm in remove mode. 
234  |      **/
235  | 
236  |     if( g_flags & M_SWSTATE1) {
237  |         set_marked_entry( markVariableHashTable, variable, M_SWSTATE1);
238  |         return( TCL_OK);		/** -------- EXIT (SUCCESS) -------> **/
239  |     } else if( g_flags & M_SWSTATE2) {
240  |         set_marked_entry( markVariableHashTable, variable, M_SWSTATE2);
241  |     } else if( g_flags & M_SWSTATE3) {
242  |         intptr_t marked_val;
243  |         marked_val = chk_marked_entry( markVariableHashTable, variable);
244  |         if( marked_val) {
245  |             if( marked_val == M_SWSTATE1)
246  |                 return( moduleUnsetenv(interp, variable));	/** -------> **/
247  |             else
248  | 		return( TCL_OK);	/** -------- EXIT (SUCCESS) -------> **/
249  |         }
250  |     } else if( (g_flags & M_REMOVE) && !force) {
251  | 	return( moduleUnsetenv( interp, variable));		/** -------> **/
252  |     }
253  | 
254  |     /**
255  |      **  Keep track of our changes just in case we have to bail out and restore
256  |      **  the environment.
257  |      **/
258  | 
259  |     if( !(g_flags & (M_NONPERSIST | M_DISPLAY | M_WHATIS | M_HELP))) {
260  |         store_hash_value( setenvHashTable, variable, value);
261  |         clear_hash_value( unsetenvHashTable, variable);
262  |     }
263  | 
264  |     /**
265  |      **  Store the value into the environment
266  |      **/
267  | 
268  |     Tcl_SetVar2( interp, "env", variable, value, TCL_GLOBAL_ONLY);
269  | 
270  | #if WITH_DEBUGGING_UTIL_1
271  |     ErrorLogger( NO_ERR_END, LOC, _proc_moduleSetenv, NULL);
272  | #endif
273  | 
274  |     return( TCL_OK);
275  | 
276  | } /** End of 'moduleSetenv' **/
277  | 
278  | /*++++
279  |  ** ** Function-Header ***************************************************** **
280  |  ** 									     **
281  |  **   Function:		cmdUnsetEnv					     **
282  |  ** 									     **
283  |  **   Description:	Callback function for the 'unset' command	     **
284  |  ** 									     **
285  |  **   First Edition:	1991/10/23					     **
286  |  ** 									     **
287  |  **   Parameters:	ClientData	 client_data			     **
288  |  **			Tcl_Interp	*interp		According Tcl interp.**
289  |  **			int		 argc		Number of arguments  **
290  |  **			char		*argv[]		Argument array	     **
291  |  ** 									     **
292  |  **   Result:		int	TCL_OK		Successfull completion	     **
293  |  **				TCL_ERROR	Any error		     **
294  |  ** 									     **
295  |  **   Attached Globals:	g_flags		These are set up accordingly before  **
296  |  **					this function is called in order to  **
297  |  **					control everything		     **
298  |  ** 									     **
299  |  ** ************************************************************************ **
300  |  ++++*/
301  | 
302  | int	cmdUnsetEnv(	ClientData	 client_data,
303  | 	  		Tcl_Interp	*interp,
304  | 	  		int		 argc,
305  | 	  		CONST84 char	*argv[])
306  | {
307  |     /**
308  |      **  Parameter check. The name of the variable has to be specified
309  |      **/
310  |     
311  | #if WITH_DEBUGGING_CALLBACK
312  |     ErrorLogger( NO_ERR_START, LOC, _proc_cmdUnsetEnv, NULL);
313  | #endif
314  | 
315  |     if( argc < 2 || argc > 3) {
316  | 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "variable [value]",
317  | 	    NULL))
318  | 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
319  |     }
320  | 
321  |   
322  |     /**
323  |      **  Non-persist mode?
324  |      **/
325  |     
326  |     if (g_flags & M_NONPERSIST) {
327  | 	return (TCL_OK);
328  |     }
329  | 
330  |     /**
331  |      **  Unset the variable or just display what to do ...
332  |      **/
333  | 
334  |     if( g_flags & M_DISPLAY) {
335  | 	fprintf( stderr, "%s\t ", argv[ 0]);
336  | 	while( --argc)
337  | 	    fprintf( stderr, "%s ", *++argv);
338  | 	fprintf( stderr, "\n");
339  |     } else if( g_flags & M_REMOVE && argc == 3) {
340  | 	int save_flags = g_flags;
341  | 	/** allow an optional 3rd argument to set the env.var. to on removal **/
342  | 	g_flags = (g_flags & ~M_REMOVE) | M_LOAD;
343  | 	moduleSetenv( interp, (char *) argv[1], (char *) argv[2], 0);
344  | 	g_flags = save_flags;
345  |     } else {
346  | 	moduleUnsetenv( interp, (char *) argv[1]);
347  |     }
348  | 
349  |     /**
350  |      **  Return on success
351  |      **/
352  | 
353  | #if WITH_DEBUGGING_CALLBACK
354  |     ErrorLogger( NO_ERR_END, LOC, _proc_cmdUnsetEnv, NULL);
355  | #endif
356  | 
357  |     return( TCL_OK);
358  | 
359  | } /** End of 'cmdUnsetEnv' **/
360  | 
361  | /*++++
362  |  ** ** Function-Header ***************************************************** **
363  |  ** 									     **
364  |  **   Function:		moduleUnsetenv					     **
365  |  ** 									     **
366  |  **   Description:	Unset environment variables			     **
367  |  ** 									     **
368  |  **   First Edition:	1991/10/23					     **
369  |  ** 									     **
370  |  **   Parameters:	Tcl_Interp	*interp		According Tcl interp.**
371  |  **			char		*variable	Name of the variable **
372  |  ** 									     **
373  |  **   Result:		int	TCL_OK		Successfull completion	     **
374  |  **				TCL_ERROR	Any error		     **
375  |  ** 									     **
376  |  **   Attached Globals:	g_flags		These are set up accordingly before  **
377  |  **					this function is called in order to  **
378  |  **					control everything		     **
379  |  ** 									     **
380  |  ** ************************************************************************ **
381  |  ++++*/
382  | 
383  | int	moduleUnsetenv(	Tcl_Interp	*interp,
384  |              		char		*variable)
385  | {
386  | 
387  | #if WITH_DEBUGGING_UTIL_1
388  |     ErrorLogger( NO_ERR_START, LOC, _proc_moduleUnsetenv, NULL);
389  | #endif
390  | 
391  |     /**
392  |      ** Don't unset the variable in Tcl Space.
393  |      ** If module writer *REALLY* wants it gone, use $env
394  |      **/
395  | 
396  |     if( !(g_flags & (M_NONPERSIST | M_DISPLAY | M_WHATIS | M_HELP))) {
397  |         store_hash_value( unsetenvHashTable, variable, NULL);
398  |         clear_hash_value( setenvHashTable, variable);
399  |     }
400  |   
401  | #if WITH_DEBUGGING_UTIL_1
402  |     ErrorLogger( NO_ERR_END, LOC, _proc_moduleUnsetenv, NULL);
403  | #endif
404  | 
405  |     return( TCL_OK);
406  | 
407  | } /** end of 'moduleUnsetenv' **/
408  |