1    | /*****
2    |  ** ** Module Header ******************************************************* **
3    |  ** 									     **
4    |  **   Modules Revision 3.0						     **
5    |  **   Providing a flexible user environment				     **
6    |  ** 									     **
7    |  **   File:		cmdConflict.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 Tcl conflict and prereq commands.		     **
14   |  ** 									     **
15   |  **   Exports:		cmdConflict					     **
16   |  **			cmdPrereq					     **
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: cmdConflict.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 error_module[ MOD_BUFSIZE];
62   | static	char	module_name[] = "cmdConflict.c";	/** File name of this module **/
63   | #if WITH_DEBUGGING_UTIL
64   | static	char	_proc_checkConflict[] = "checkConflict";
65   | #endif
66   | #if WITH_DEBUGGING_CALLBACK
67   | static	char	_proc_cmdConflict[] = "cmdConflict";
68   | static	char	_proc_cmdPrereq[] = "cmdPrereq";
69   | #endif
70   | 
71   | /** ************************************************************************ **/
72   | /**				    PROTOTYPES				     **/
73   | /** ************************************************************************ **/
74   | 
75   | /** not applicable **/
76   | 
77   | 
78   | /*++++
79   |  ** ** Function-Header ***************************************************** **
80   |  ** 									     **
81   |  **   Function:		checkConflict					     **
82   |  ** 									     **
83   |  **   Description:	Check whether the 'g_current_module' is in the list  **
84   |  **			of passed modules				     **
85   |  ** 									     **
86   |  **   First Edition:	1991/10/23					     **
87   |  ** 									     **
88   |  **   Parameters:	Tcl_Interp	*interp		According Tcl interp.**
89   |  **			char		*path		Modulepath to be chk.**
90   |  **			char		**modulelist	List of loaded mod.  **
91   |  **			int		 nummodules	Number of loaded mod.**
92   |  ** 									     **
93   |  **   Result:		int	TCL_OK		Successfull completion	     **
94   |  **				TCL_ERROR	Any error		     **
95   |  ** 									     **
96   |  **   Attached Globals:	g_flags		These are set up accordingly before  **
97   |  **					this function is called in order to  **
98   |  **					control everything		     **
99   |  **									     **
100  |  **		  	g_current_module	Module to check for	     **
101  |  ** 									     **
102  |  ** ************************************************************************ **
103  |  ++++*/
104  | 
105  | static	int	checkConflict(	Tcl_Interp	*interp,
106  |        		       		char		*path,
107  |               			char		**modulelist,
108  |               			unsigned	  int nummodules)
109  | {
110  |     char	**new_modulelist;
111  |     int		  new_nummodules, k;
112  |     struct stat	  stat_info;
113  |     char	 *buffer;
114  |     
115  | #if WITH_DEBUGGING_UTIL
116  |     ErrorLogger( NO_ERR_START, LOC, _proc_checkConflict, NULL);
117  | #endif
118  | 
119  |     memset( error_module, '\0', MOD_BUFSIZE);
120  | 
121  |     /**
122  |      **  Check all modules passed to me as parameter
123  |      **  At first clarify if they really so exist ...
124  |      **/
125  | 
126  |     for( k=0; k<nummodules; k++) {
127  | 
128  | 	if ((char *) NULL == (buffer = stringer(NULL,0,
129  | 		path,"/", modulelist[k], NULL)))
130  | 	    if( OK != ErrorLogger( ERR_STRING, LOC,NULL))
131  | 		goto unwind0;
132  | 
133  |         if( stat( buffer, &stat_info) < 0) {
134  | 	    if( OK != ErrorLogger( ERR_FILEINDIR,LOC,modulelist[k], path,NULL))
135  | 		if ((char *) NULL == stringer(error_module,MOD_BUFSIZE,
136  | 			modulelist[k], NULL))
137  | 		    if( OK != ErrorLogger( ERR_STRING, LOC,NULL))
138  | 			goto unwind1;
139  | 	    goto unwind1;
140  | 	}
141  | 
142  | 	/**
143  | 	 **  Is it a directory what has been passed? If it is, list the
144  | 	 **  according directory and call myself recursivly in order to 
145  | 	 **/
146  | 
147  |         if( S_ISDIR( stat_info.st_mode)) {
148  | 
149  |             if( NULL == (new_modulelist = SortedDirList( interp, path, 
150  | 		modulelist[k], &new_nummodules)))
151  |                 continue;
152  | 
153  |             if( TCL_ERROR == checkConflict( interp, path, new_modulelist,
154  | 		new_nummodules)) {
155  |                 FreeList( new_modulelist, new_nummodules);
156  | 		goto unwind1;
157  |             }
158  | 
159  |             FreeList( new_modulelist, new_nummodules);
160  | 
161  | 	/**
162  | 	 **  If it isn't a directory, check the current one for to be the
163  | 	 **  required module file
164  | 	 **/
165  | 
166  |         } else {
167  | 
168  |             if( IsLoaded_ExactMatch( interp, modulelist[k], NULL, NULL) &&
169  |                 strcmp( g_current_module, modulelist[k])) {
170  | 
171  |                 /**
172  |                  **  Save the name of the offending module in a buffer
173  |                  **  for reporting purposes when we get back to the top.
174  |                  **/
175  | 
176  | 		if ((char *) NULL == stringer(error_module,MOD_BUFSIZE,
177  | 			modulelist[k], NULL))
178  | 		    if( OK != ErrorLogger( ERR_STRING, LOC,NULL))
179  | 			goto unwind1;
180  | 		goto unwind1;
181  |             }
182  | 
183  |         } /** if( directory) **/
184  |     } /** for **/
185  | 
186  | #if WITH_DEBUGGING_UTIL
187  |     ErrorLogger( NO_ERR_END, LOC, _proc_checkConflict, NULL);
188  | #endif
189  |     /**
190  |      ** free resources
191  |      **/
192  |     null_free((void *) &buffer);
193  | 
194  |     return( TCL_OK);			/** -------- EXIT (SUCCESS) -------> **/
195  | 
196  | unwind1:
197  |     null_free((void *) &buffer);
198  | unwind0:
199  |     return( TCL_ERROR);			/** -------- EXIT (FAILURE) -------> **/
200  | 
201  | } /** End of 'checkConflict' **/
202  | 
203  | /*++++
204  |  ** ** Function-Header ***************************************************** **
205  |  ** 									     **
206  |  **   Function:		cmdConflict					     **
207  |  ** 									     **
208  |  **   Description:	Callback function for 'confilct'		     **
209  |  ** 									     **
210  |  **   First Edition:	1991/10/23					     **
211  |  ** 									     **
212  |  **   Parameters:	ClientData	 client_data			     **
213  |  **			Tcl_Interp	*interp		According Tcl interp.**
214  |  **			int		 argc		Number of arguments  **
215  |  **			char		*argv[]		Argument array	     **
216  |  ** 									     **
217  |  **   Result:		int	TCL_OK		Successfull completion	     **
218  |  **				TCL_ERROR	Any error		     **
219  |  ** 									     **
220  |  **   Attached Globals:	g_flags		These are set up accordingly before  **
221  |  **					this function is called in order to  **
222  |  **					control everything		     **
223  |  ** 									     **
224  |  ** ************************************************************************ **
225  |  ++++*/
226  | 
227  | int	cmdConflict(	ClientData	 client_data,
228  | 	    		Tcl_Interp	*interp,
229  | 	    		int		 argc,
230  | 	    		CONST84 char 	*argv[])
231  | {
232  |     char	 **pathlist,		/** List of module-pathes	     **/
233  |     		 **modulelist;		/** List of modules		     **/
234  |     char	  *modulepath;		/** Contents of MODULEPATH	     **/
235  |     int		   i, j,		/** Loop counters		     **/
236  |    		   numpaths, nummodules;/** Size of the according arrays     **/
237  | 
238  | #if WITH_DEBUGGING_CALLBACK
239  |     ErrorLogger( NO_ERR_START, LOC, _proc_cmdConflict, NULL);
240  | #endif
241  | 
242  |     /**
243  |      **  Whatis mode
244  |      **/
245  | 
246  |     if( g_flags & (M_WHATIS | M_HELP))
247  | 	goto success0;
248  | 
249  |     /**
250  |      **  Check the parameters. Usage is 'conflict <module> [<module> ...]'
251  |      **/
252  | 
253  |     if( argc < 2)
254  | 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0],
255  | 	    "conflicting-modulefiles", NULL))
256  | 	    goto unwind0;
257  | 
258  |     /**
259  |      **  There will be no conflicts in case of switch or unload
260  |      **/
261  | 
262  |     if( g_flags & (M_REMOVE | M_SWITCH))
263  |         goto success0;
264  | 
265  |     /**
266  |      **  Load the MODULEPATH and split it into a list of paths. Assume success
267  |      **  if no list to be built...
268  |      **/
269  |     if((char *) NULL == (modulepath = xgetenv( "MODULEPATH")))
270  | 	if( OK != ErrorLogger( ERR_MODULE_PATH, LOC, NULL))
271  | 	    goto unwind0;
272  | 
273  |     if((char **) NULL==(pathlist=SplitIntoList(interp, modulepath, &numpaths)))
274  |         goto success1;
275  | 
276  |     /**
277  |      **  Non-persist mode?
278  |      **/
279  |     
280  |     if (g_flags & M_NONPERSIST) {
281  | 	return (TCL_OK);
282  |     }
283  | 
284  |     /**
285  |      **  Display?
286  |      **/
287  | 
288  |     if( g_flags & M_DISPLAY) {
289  | 	fprintf( stderr, "%s\t ", argv[ 0]);
290  | 	while( --argc)
291  | 	    fprintf( stderr, "%s ", *++argv);
292  | 	fprintf( stderr, "\n");
293  |         goto success2;
294  |     }
295  | 
296  |     /**
297  |      **  Now check/display all passed modules ...
298  |      **/
299  | 
300  |     for( i=1; i<argc && argv[i]; i++) {
301  |         for( j = 0; j < numpaths; j++) {
302  | 
303  |             if((char **)NULL == (modulelist = SortedDirList(interp,
304  | 			pathlist[j], (char *) argv[i], &nummodules)))
305  |                 continue;		/** not browseable		     **/
306  | 
307  | 	    /**
308  | 	     **  Actually checking for conflicts is done here
309  | 	     **/
310  |             if( TCL_ERROR == checkConflict( interp, pathlist[j], modulelist,
311  | 		nummodules))
312  | 		if( OK != ErrorLogger( ERR_CONFLICT, LOC, g_current_module,
313  | 		    error_module, NULL)) {
314  | 		    FreeList( modulelist, nummodules);
315  | 		    goto unwind2;
316  | 		}
317  | 
318  | 	    /**
319  | 	     **  Free the list of modules used in the loops body above.
320  | 	     **/
321  |             FreeList( modulelist, nummodules);
322  | 
323  |         } /** for( j) **/
324  |     } /** for( i) **/
325  | 
326  | #if WITH_DEBUGGING_CALLBACK
327  |     ErrorLogger( NO_ERR_END, LOC, _proc_cmdConflict, NULL);
328  | #endif
329  | 
330  |     /**
331  |      ** free resources
332  |      **/
333  | success2:
334  |     FreeList( pathlist, numpaths);
335  | success1:
336  |     null_free((void *) &modulepath);
337  | success0:
338  |     return( TCL_OK);			/** -------- EXIT (SUCCESS) -------> **/
339  | 
340  | unwind2:
341  |     FreeList( pathlist, numpaths);
342  | unwind1:
343  |     null_free((void *) &modulepath);
344  | unwind0:
345  |     return( TCL_ERROR);			/** -------- EXIT (FAILURE) -------> **/
346  | 
347  | } /** End of 'cmdConflict' **/
348  | 
349  | /*++++
350  |  ** ** Function-Header ***************************************************** **
351  |  ** 									     **
352  |  **   Function:		cmdPrereq					     **
353  |  ** 									     **
354  |  **   Description:	Callback function for 'prereq'			     **
355  |  ** 									     **
356  |  **   First Edition:	1991/10/23					     **
357  |  ** 									     **
358  |  **   Parameters:	ClientData	 client_data			     **
359  |  **			Tcl_Interp	*interp		According Tcl interp.**
360  |  **			int		 argc		Number of arguments  **
361  |  **			char		*argv[]		Argument array	     **
362  |  ** 									     **
363  |  **   Result:		int	TCL_OK		Successfull completion	     **
364  |  **				TCL_ERROR	Any error		     **
365  |  ** 									     **
366  |  **   Attached Globals:	g_flags		These are set up accordingly before  **
367  |  **					this function is called in order to  **
368  |  **					control everything		     **
369  |  ** 									     **
370  |  ** ************************************************************************ **
371  |  ++++*/
372  | 
373  | int	cmdPrereq(	ClientData	 client_data,
374  | 	    		Tcl_Interp	*interp,
375  | 	    		int		 argc,
376  | 	    		CONST84 char	*argv[])
377  | {
378  |     char	***savedlists = (char ***) NULL;
379  |     int		  *savedlens = (int *) NULL;
380  |     char	 **pathlist,
381  | 		 **modulelist,
382  | 		  *modulepath,
383  | 		  *notloaded_flag = (char *) argv[1];
384  |     int     	   i, j, k, numpaths, nummodules, listcnt = 0,
385  | 		   Result = TCL_OK;
386  |     char	   buffer[ MOD_BUFSIZE];
387  | 	
388  | #if WITH_DEBUGGING_CALLBACK
389  |     ErrorLogger( NO_ERR_START, LOC, _proc_cmdPrereq, NULL);
390  | #endif
391  | 
392  |     /** 
393  |      **  Parameter check. Usage is 'prereq <module> [<module> ...]'
394  |      **/
395  | 
396  |     if( argc < 2)
397  | 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0],
398  | 	    "prerequsite-modules", NULL))
399  | 	    goto unwind0;
400  | 
401  |     /**
402  |      **  There's no prerequisite check in case of removal
403  |      **/
404  | 
405  |     if( g_flags & (M_REMOVE | M_WHATIS))
406  |         goto success0;
407  | 
408  |   
409  |     /**
410  |      **  Non-persist mode?
411  |      **/
412  |     
413  |     if (g_flags & M_NONPERSIST) {
414  | 	return (TCL_OK);
415  |     }
416  | 
417  |     /**
418  |      **  Display mode
419  |      **/
420  | 
421  |     if( g_flags & M_DISPLAY) {
422  | 	fprintf( stderr, "%s\t ", argv[ 0]);
423  | 	while( --argc)
424  | 	    fprintf( stderr, "%s ", *++argv);
425  | 	fprintf( stderr, "\n");
426  |         goto success0;
427  |     }
428  | 
429  |     /**
430  |      **  Load the MODULEPATH and split it into a list of paths. Assume success
431  |      **  if no list to be built...
432  |      **/
433  |     if((char *) NULL == (modulepath = xgetenv( "MODULEPATH")))
434  | 	if( OK != ErrorLogger( ERR_MODULE_PATH, LOC, NULL))
435  | 	    goto unwind0;
436  | 
437  | #if WITH_DEBUGGING_CALLBACK_1
438  |     ErrorLogger( NO_ERR_DEBUG, LOC, "Got modulepath: '", modulepath, "'", NULL);
439  | #endif
440  | 
441  |     if((char **) NULL==(pathlist=SplitIntoList(interp, modulepath, &numpaths)))
442  |         goto success1;
443  | 
444  |     /**
445  |      **  Allocate memory for the lists of conflict modules
446  |      **/
447  |     if((char ***) NULL==(savedlists=(char***) malloc(numpaths * (argc - 1)
448  | 	* sizeof(char**))))
449  | 	if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
450  | 	    goto unwind1;
451  | 
452  |     if((int *) NULL == (savedlens = (int*) malloc(numpaths * (argc - 1)
453  | 	* sizeof( int))))
454  | 	if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
455  | 	    goto unwind2;
456  | 
457  |     /**
458  |      **  Check/Display all passed modules
459  |      **/
460  | 
461  | #if WITH_DEBUGGING_CALLBACK_1
462  |     ErrorLogger( NO_ERR_DEBUG, LOC, "Scanning all ", (sprintf( buffer, "%d",
463  | 	numpaths), buffer), "modulepaths", NULL);
464  | #endif
465  | 
466  |     for( i=1; i<argc && argv[i] && notloaded_flag; i++) {
467  |         for( j = 0; j < numpaths && notloaded_flag; j++) {
468  | 
469  |             if((char **) NULL == (modulelist = SortedDirList(interp,pathlist[j],
470  | 	        (char *) argv[i], &nummodules)))
471  |                 continue;
472  | 
473  | 	    /**
474  | 	     **  save the list of file to be printed in case of missing pre-
475  | 	     **  requisites or 
476  | 	     **/
477  | 
478  | #if WITH_DEBUGGING_CALLBACK_1
479  | 	    ErrorLogger( NO_ERR_DEBUG, LOC, "Save directory list. # = ",
480  | 		(sprintf( buffer, "%d", listcnt), buffer), NULL);
481  | #endif
482  | 
483  | 	    savedlens[ listcnt]    = nummodules;
484  | 	    savedlists[ listcnt++] = modulelist;
485  | 
486  | 	    /**
487  | 	     **  Now actually check if the prerequisites are fullfilled
488  | 	     **  The notloaded_flag controls the exit from both loops in case
489  | 	     **  a prerequisite is missing.
490  | 	     **/
491  | 
492  |             for( k=0; k < nummodules && notloaded_flag; k++) {
493  |                 if( !IsLoaded( interp, modulelist[k], NULL, NULL)) {
494  |                     notloaded_flag = (char *) argv[i];
495  |                 } else {
496  |                     notloaded_flag = NULL;
497  |                 }
498  |             }
499  |         } /** for( j) **/
500  |     } /** for( i) **/
501  | 
502  | #if WITH_DEBUGGING_CALLBACK_1
503  |     ErrorLogger( NO_ERR_DEBUG, LOC, "Done. Missing prerequisite: '",
504  | 	(notloaded_flag ? notloaded_flag : "none"), "'", NULL);
505  | #endif
506  | 
507  |     /**
508  |      **  Display an error message if this was *NOT* display mode and a
509  |      **  missing prerequisite has been found
510  |      **/
511  |     if( notloaded_flag) {
512  | 
513  | 	/**
514  | 	 **  Add the whole list of prerequired module files to the Tcl result
515  | 	 **  string
516  | 	 **/
517  | 	for( k=0; k<listcnt; k++) {
518  | 	    char **listptr = savedlists[k];
519  | 
520  | 	    *buffer = '\0';
521  | 	    for( i=0; listptr && i<savedlens[k]; i++, listptr++) {
522  | 		if ((char *) NULL == stringer(
523  | 			buffer + strlen(buffer), MOD_BUFSIZE-strlen(buffer),
524  | 			*listptr, " ", NULL))
525  | 		    if( OK != ErrorLogger( ERR_STRING, LOC,NULL)) {
526  | 	    		FreeList( savedlists[k], savedlens[k]);
527  | 			goto unwind2;
528  | 		    }
529  | 	    }
530  | 
531  | 	    FreeList( savedlists[k], savedlens[k]);
532  | 	}
533  | 
534  | 	buffer[strlen(buffer)-1] = '\0';	/* remove last blank */
535  | 
536  | 	if( OK != ErrorLogger( ERR_PREREQ, LOC, g_current_module, buffer, NULL))
537  | 	    Result = TCL_ERROR;	
538  | 
539  |     } else {
540  | 
541  | 	/**
542  | 	 **  We have to free the saved module names again
543  | 	 **/
544  | 
545  | 	for( k=0; k<listcnt; k++)
546  | 	    FreeList( savedlists[k], savedlens[k]);
547  | 
548  |     }
549  | 
550  |     /**
551  |      **  Free up the list of prerequisites and return ...
552  |      **/
553  | 
554  |     null_free((void *) &savedlens);
555  |     null_free((void *) &savedlists);
556  | 
557  | #if WITH_DEBUGGING_CALLBACK
558  |     ErrorLogger( NO_ERR_END, LOC, _proc_cmdPrereq, NULL);
559  | #endif
560  | 
561  | success1:
562  |     null_free((void *) &modulepath);
563  | success0:
564  |     return( Result);			/** -------- EXIT (Result)  -------> **/
565  | 
566  | unwind3:
567  |     null_free((void *) &savedlens);
568  | unwind2:
569  |     null_free((void *) &savedlists);
570  | unwind1:
571  |     null_free((void *) &modulepath);
572  | unwind0:
573  |     return( TCL_ERROR);			/** -------- EXIT (FAILURE) -------> **/
574  | } /** End of 'cmdPrereq' **/