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