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: 729617d8bb5db0ac3250d01b322bcee750b8c540 $";
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		Successful 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 
checkConflict(Tcl_Interp * interp,char * path,char ** modulelist,unsigned int nummodules)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 recursively 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		Successful 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 
cmdConflict(ClientData client_data,Tcl_Interp * interp,int argc,CONST84 char * argv[])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 	_colon)))
275         goto success1;
276 
277     /**
278      **  Non-persist mode?
279      **/
280 
281     if (g_flags & M_NONPERSIST) {
282 	return (TCL_OK);
283     }
284 
285     /**
286      **  Display?
287      **/
288 
289     if( g_flags & M_DISPLAY) {
290 	fprintf( stderr, "%s\t ", argv[ 0]);
291 	while( --argc)
292 	    fprintf( stderr, "%s ", *++argv);
293 	fprintf( stderr, "\n");
294         goto success2;
295     }
296 
297     /**
298      **  Now check/display all passed modules ...
299      **/
300 
301     for( i=1; i<argc && argv[i]; i++) {
302         for( j = 0; j < numpaths; j++) {
303 
304             if((char **)NULL == (modulelist = SortedDirList(interp,
305 			pathlist[j], (char *) argv[i], &nummodules)))
306                 continue;		/** not browseable		     **/
307 
308 	    /**
309 	     **  Actually checking for conflicts is done here
310 	     **/
311             if( TCL_ERROR == checkConflict( interp, pathlist[j], modulelist,
312 		nummodules))
313 		if( OK != ErrorLogger( ERR_CONFLICT, LOC, g_current_module,
314 		    error_module, NULL)) {
315 		    FreeList( modulelist, nummodules);
316 		    goto unwind2;
317 		}
318 
319 	    /**
320 	     **  Free the list of modules used in the loops body above.
321 	     **/
322             FreeList( modulelist, nummodules);
323 
324         } /** for( j) **/
325     } /** for( i) **/
326 
327 #if WITH_DEBUGGING_CALLBACK
328     ErrorLogger( NO_ERR_END, LOC, _proc_cmdConflict, NULL);
329 #endif
330 
331     /**
332      ** free resources
333      **/
334 success2:
335     FreeList( pathlist, numpaths);
336 success1:
337     null_free((void *) &modulepath);
338 success0:
339     return( TCL_OK);			/** -------- EXIT (SUCCESS) -------> **/
340 
341 unwind2:
342     FreeList( pathlist, numpaths);
343 unwind1:
344     null_free((void *) &modulepath);
345 unwind0:
346     return( TCL_ERROR);			/** -------- EXIT (FAILURE) -------> **/
347 
348 } /** End of 'cmdConflict' **/
349 
350 /*++++
351  ** ** Function-Header ***************************************************** **
352  ** 									     **
353  **   Function:		cmdPrereq					     **
354  ** 									     **
355  **   Description:	Callback function for 'prereq'			     **
356  ** 									     **
357  **   First Edition:	1991/10/23					     **
358  ** 									     **
359  **   Parameters:	ClientData	 client_data			     **
360  **			Tcl_Interp	*interp		According Tcl interp.**
361  **			int		 argc		Number of arguments  **
362  **			char		*argv[]		Argument array	     **
363  ** 									     **
364  **   Result:		int	TCL_OK		Successful completion	     **
365  **				TCL_ERROR	Any error		     **
366  ** 									     **
367  **   Attached Globals:	g_flags		These are set up accordingly before  **
368  **					this function is called in order to  **
369  **					control everything		     **
370  ** 									     **
371  ** ************************************************************************ **
372  ++++*/
373 
cmdPrereq(ClientData client_data,Tcl_Interp * interp,int argc,CONST84 char * argv[])374 int	cmdPrereq(	ClientData	 client_data,
375 	    		Tcl_Interp	*interp,
376 	    		int		 argc,
377 	    		CONST84 char	*argv[])
378 {
379     char	***savedlists = (char ***) NULL;
380     int		  *savedlens = (int *) NULL;
381     char	 **pathlist,
382 		 **modulelist,
383 		  *modulepath,
384 		  *notloaded_flag = (char *) argv[1];
385     int     	   i, j, k, numpaths, nummodules, listcnt = 0,
386 		   Result = TCL_OK;
387     char	   buffer[ MOD_BUFSIZE];
388 
389 #if WITH_DEBUGGING_CALLBACK
390     ErrorLogger( NO_ERR_START, LOC, _proc_cmdPrereq, NULL);
391 #endif
392 
393     /**
394      **  Parameter check. Usage is 'prereq <module> [<module> ...]'
395      **/
396 
397     if( argc < 2)
398 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0],
399 	    " prerequisite-modules", NULL))
400 	    goto unwind0;
401 
402     /**
403      **  There's no prerequisite check in case of removal
404      **/
405 
406     if( g_flags & (M_REMOVE | M_WHATIS))
407         goto success0;
408 
409 
410     /**
411      **  Non-persist mode?
412      **/
413 
414     if (g_flags & M_NONPERSIST) {
415 	return (TCL_OK);
416     }
417 
418     /**
419      **  Display mode
420      **/
421 
422     if( g_flags & M_DISPLAY) {
423 	fprintf( stderr, "%s\t ", argv[ 0]);
424 	while( --argc)
425 	    fprintf( stderr, "%s ", *++argv);
426 	fprintf( stderr, "\n");
427         goto success0;
428     }
429 
430     /**
431      **  Load the MODULEPATH and split it into a list of paths. Assume success
432      **  if no list to be built...
433      **/
434     if((char *) NULL == (modulepath = xgetenv( "MODULEPATH")))
435 	if( OK != ErrorLogger( ERR_MODULE_PATH, LOC, NULL))
436 	    goto unwind0;
437 
438 #if WITH_DEBUGGING_CALLBACK_1
439     ErrorLogger( NO_ERR_DEBUG, LOC, "Got modulepath: '", modulepath, "'", NULL);
440 #endif
441 
442     if((char **) NULL==(pathlist=SplitIntoList(interp, modulepath, &numpaths,
443 	_colon)))
444         goto success1;
445 
446     /**
447      **  Allocate memory for the lists of conflict modules
448      **/
449     if((char ***) NULL==(savedlists=(char***) module_malloc(numpaths * (argc-1)
450 	* sizeof(char**))))
451 	if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
452 	    goto unwind1;
453 
454     if((int *) NULL == (savedlens = (int*) module_malloc(numpaths * (argc-1)
455 	* sizeof( int))))
456 	if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
457 	    goto unwind2;
458 
459     /**
460      **  Check/Display all passed modules
461      **/
462 
463 #if WITH_DEBUGGING_CALLBACK_1
464     ErrorLogger( NO_ERR_DEBUG, LOC, "Scanning all ", (sprintf( buffer, "%d",
465 	numpaths), buffer), "modulepaths", NULL);
466 #endif
467 
468     for( i=1; i<argc && argv[i] && notloaded_flag; i++) {
469         for( j = 0; j < numpaths && notloaded_flag; j++) {
470 
471             if((char **) NULL == (modulelist = SortedDirList(interp,pathlist[j],
472 	        (char *) argv[i], &nummodules)))
473                 continue;
474 
475 	    /**
476 	     **  save the list of file to be printed in case of missing pre-
477 	     **  requisites or
478 	     **/
479 
480 #if WITH_DEBUGGING_CALLBACK_1
481 	    ErrorLogger( NO_ERR_DEBUG, LOC, "Save directory list. # = ",
482 		(sprintf( buffer, "%d", listcnt), buffer), NULL);
483 #endif
484 
485 	    savedlens[ listcnt]    = nummodules;
486 	    savedlists[ listcnt++] = modulelist;
487 
488 	    /**
489 	     **  Now actually check if the prerequisites are fullfilled
490 	     **  The notloaded_flag controls the exit from both loops in case
491 	     **  a prerequisite is missing.
492 	     **/
493 
494             for( k=0; k < nummodules && notloaded_flag; k++) {
495                 if( !IsLoaded( interp, modulelist[k], NULL, NULL)) {
496                     notloaded_flag = (char *) argv[i];
497                 } else {
498                     notloaded_flag = NULL;
499                 }
500             }
501         } /** for( j) **/
502     } /** for( i) **/
503 
504 #if WITH_DEBUGGING_CALLBACK_1
505     ErrorLogger( NO_ERR_DEBUG, LOC, "Done. Missing prerequisite: '",
506 	(notloaded_flag ? notloaded_flag : "none"), "'", NULL);
507 #endif
508 
509     /**
510      **  Display an error message if this was *NOT* display mode and a
511      **  missing prerequisite has been found
512      **/
513     if( notloaded_flag) {
514 
515 	/**
516 	 **  Add the whole list of prerequired module files to the Tcl result
517 	 **  string
518 	 **/
519 	for( k=0; k<listcnt; k++) {
520 	    char **listptr = savedlists[k];
521 
522 	    *buffer = '\0';
523 	    for( i=0; listptr && i<savedlens[k]; i++, listptr++) {
524 		if ((char *) NULL == stringer(
525 			buffer + strlen(buffer), MOD_BUFSIZE-strlen(buffer),
526 			*listptr, " ", NULL))
527 		    if( OK != ErrorLogger( ERR_STRING, LOC,NULL)) {
528 	    		FreeList( savedlists[k], savedlens[k]);
529 			goto unwind2;
530 		    }
531 	    }
532 
533 	    FreeList( savedlists[k], savedlens[k]);
534 	}
535 
536 	buffer[strlen(buffer)-1] = '\0';	/* remove last blank */
537 
538 	if( OK != ErrorLogger( ERR_PREREQ, LOC, g_current_module, buffer, NULL))
539 	    Result = TCL_ERROR;
540 
541     } else {
542 
543 	/**
544 	 **  We have to free the saved module names again
545 	 **/
546 
547 	for( k=0; k<listcnt; k++)
548 	    FreeList( savedlists[k], savedlens[k]);
549 
550     }
551 
552     /**
553      **  Free up the list of prerequisites and return ...
554      **/
555 
556     null_free((void *) &savedlens);
557     null_free((void *) &savedlists);
558 
559 #if WITH_DEBUGGING_CALLBACK
560     ErrorLogger( NO_ERR_END, LOC, _proc_cmdPrereq, NULL);
561 #endif
562 
563 success1:
564     null_free((void *) &modulepath);
565 success0:
566     return( Result);			/** -------- EXIT (Result)  -------> **/
567 
568 unwind3:
569     null_free((void *) &savedlens);
570 unwind2:
571     null_free((void *) &savedlists);
572 unwind1:
573     null_free((void *) &modulepath);
574 unwind0:
575     return( TCL_ERROR);			/** -------- EXIT (FAILURE) -------> **/
576 } /** End of 'cmdPrereq' **/
577