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' **/