1 | /*****
2 | ** ** Module Header ******************************************************* **
3 | ** **
4 | ** Modules Revision 3.0 **
5 | ** Providing a flexible user environment **
6 | ** **
7 | ** File: cmdPath.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 path manipulation routines. Much of the heart of **
14 | ** Modules is contained in this file. These routines **
15 | ** are responsible for adding and removing directories **
16 | ** from given PATH-like variables. **
17 | ** **
18 | ** Exports: cmdSetPath **
19 | ** cmdRemovePath **
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: cmdPath.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 | #ifdef HAS_SYS_PARAM_H
42 | #include <sys/param.h>
43 | #endif
44 |
45 | /** ************************************************************************ **/
46 | /** LOCAL DATATYPES **/
47 | /** ************************************************************************ **/
48 |
49 | /** not applicable **/
50 |
51 | /** ************************************************************************ **/
52 | /** CONSTANTS **/
53 | /** ************************************************************************ **/
54 |
55 | #ifdef MAXPATHLEN
56 | #define PATH_BUFLEN MAXPATHLEN
57 | #else
58 | #define PATH_BUFLEN 1024
59 | #endif
60 |
61 | /** ************************************************************************ **/
62 | /** MACROS **/
63 | /** ************************************************************************ **/
64 |
65 | #define _TCLCHK(a) \
66 | {if (*(a)->result) ErrorLogger(ERR_EXEC,LOC,(a)->result,NULL);}
67 |
68 | /** ************************************************************************ **/
69 | /** LOCAL DATA **/
70 | /** ************************************************************************ **/
71 |
72 | static char module_name[] = "cmdPath.c"; /** File name of this module **/
73 |
74 | #if WITH_DEBUGGING_CALLBACK
75 | static char _proc_cmdSetPath[] = "cmdSetPath";
76 | static char _proc_cmdRemovePath[] = "cmdRemovePath";
77 | static char _proc_Remove_Path[] = "Remove_Path";
78 | #endif
79 |
80 | static char buffer[ PATH_BUFLEN];
81 |
82 | /** ************************************************************************ **/
83 | /** PROTOTYPES **/
84 | /** ************************************************************************ **/
85 |
86 | static int Remove_Path( Tcl_Interp *interp, char *variable, char *item,
87 | char *sw_marker);
88 |
89 |
90 | /*++++
91 | ** ** Function-Header ***************************************************** **
92 | ** **
93 | ** Function: cmdSetPath **
94 | ** **
95 | ** Description: Add the passed value (argv[2]) to the specified vari-**
96 | ** able (argv[1]). argv[0] specifies, if the variable **
97 | ** is to be appended or prepended. Each directory in **
98 | ** the path is checked to see whether it is already **
99 | ** in the path. If so it is not added. **
100 | ** **
101 | ** First Edition: 1991/10/23 **
102 | ** **
103 | ** Parameters: ClientData client_data **
104 | ** Tcl_Interp *interp According Tcl interp.**
105 | ** int argc Number of arguments **
106 | ** char *argv[] Argument array **
107 | ** **
108 | ** Result: int TCL_OK Successfull completion **
109 | ** TCL_ERROR Any error **
110 | ** **
111 | ** Attached Globals: g_flags These are set up accordingly before **
112 | ** this function is called in order to **
113 | ** control everything **
114 | ** **
115 | ** ************************************************************************ **
116 | ++++*/
117 |
118 | int cmdSetPath( ClientData client_data,
119 | Tcl_Interp *interp,
120 | int argc,
121 | CONST84 char *argv[])
122 | {
123 | Tcl_RegExp chkexpPtr; /** Regular expression for **/
124 | /** marker checking **/
125 | char *oldpath, /** Old value of 'var' **/
126 | *newpath, /** New value of 'var' **/
127 | *sw_marker = APP_SW_MARKER, /** arbitrary default **/
128 | *startp=NULL, *endp=NULL, /** regexp match endpts **/
129 | *qualifiedpath, /** List of dirs which
130 | aren't already in path **/
131 | **pathlist; /** List of dirs **/
132 | int append = 1, /** append or prepend **/
133 | numpaths, /** number of dirs in path **/
134 | qpathlen, /** qualifiedpath length **/
135 | x; /** loop index **/
136 |
137 | #if WITH_DEBUGGING_CALLBACK
138 | ErrorLogger( NO_ERR_START, LOC, _proc_cmdSetPath, NULL);
139 | #endif
140 |
141 | /**
142 | ** Whatis mode?
143 | **/
144 | if( g_flags & (M_WHATIS | M_HELP))
145 | goto success0;
146 |
147 | /**
148 | ** Check arguments. There should be give 3 args:
149 | ** argv[0] - prepend/append
150 | ** argv[1] - varname
151 | ** argv[2] - value
152 | **/
153 | if(argc != 3)
154 | if( OK != ErrorLogger(ERR_USAGE, LOC, argv[0],"path-variable directory",
155 | NULL))
156 | goto unwind0;
157 |
158 | /**
159 | ** Should this guy be removed from the variable ... If yes, do so!
160 | **/
161 | if(g_flags & M_REMOVE)
162 | return( cmdRemovePath(client_data, interp, argc, argv)); /** ----> **/
163 |
164 | /**
165 | ** prepend or append. The default is append.
166 | **/
167 | if( !( append = !!strncmp( argv[0], "pre", 3)))
168 | sw_marker = PRE_SW_MARKER;
169 |
170 | /**
171 | ** Non-persist mode?
172 | **/
173 |
174 | if (g_flags & M_NONPERSIST) {
175 | return (TCL_OK);
176 | }
177 |
178 | /**
179 | ** Display only ... ok, let's do so!
180 | **/
181 | if(g_flags & M_DISPLAY) {
182 | fprintf( stderr, "%s\t ", argv[ 0]);
183 | while( --argc)
184 | fprintf( stderr, "%s ", *++argv);
185 | fprintf( stderr, "\n");
186 | goto success0;
187 | }
188 |
189 | /**
190 | ** Get the old value of the variable. MANPATH defaults to "/usr/man".
191 | ** Put a \ in front of each '.' and '+'.
192 | ** (this is an intentional memory leak)
193 | **/
194 | oldpath = (char *) Tcl_GetVar2( interp, "env", argv[1], TCL_GLOBAL_ONLY);
195 | _TCLCHK(interp)
196 |
197 | if( oldpath == NULL)
198 | oldpath = !strcmp( argv[1], "MANPATH") ? "/usr/man" : "";
199 |
200 | /**
201 | ** Split the new path into its components directories so each
202 | ** directory can be checked to see whether it is already in the
203 | ** existing path.
204 | **/
205 | if( !( pathlist = SplitIntoList( interp, (char *) argv[2], &numpaths)))
206 | goto unwind0;
207 |
208 | /**
209 | ** Some space for the list of paths which
210 | ** are not already in the existing path.
211 | **/
212 | if((char *) NULL == (qualifiedpath = stringer(NULL,0, argv[2], ":", NULL)))
213 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
214 | goto unwind1;
215 |
216 | qpathlen = strlen(qualifiedpath)+1;
217 | *qualifiedpath = '\0'; /** make sure null for later **/
218 |
219 | for( x = 0; x < numpaths; x++) {
220 |
221 | cleanse_path( pathlist[x], buffer, PATH_BUFLEN);
222 |
223 | /**
224 | ** Check to see if path is already in this path variable.
225 | ** It could be at the
226 | ** beginning ... ^path:
227 | ** middle ... :path:
228 | ** end ... :path$
229 | ** only one ... ^path$
230 | **/
231 | if((char *) NULL == (newpath = stringer(NULL,0,
232 | "(^", buffer, ":)|(:", buffer, ":)|(:",
233 | buffer, "$)|(^", buffer, "$)",NULL)))
234 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
235 | goto unwind2;
236 |
237 | chkexpPtr = Tcl_RegExpCompile(interp, newpath);
238 | _TCLCHK(interp)
239 | null_free((void *) &newpath);
240 |
241 | /**
242 | ** If the directory is not already in the path,
243 | ** add it to the qualified path.
244 | **/
245 | if( !Tcl_RegExpExec(interp, chkexpPtr, oldpath, oldpath))
246 | if ((char *) NULL ==
247 | stringer(qualifiedpath + strlen(qualifiedpath),
248 | qpathlen - strlen(qualifiedpath),
249 | pathlist[x], ":", NULL))
250 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
251 | goto unwind2;
252 |
253 | } /** End of loop that checks for
254 | ** already existent path
255 | **/
256 | /**
257 | ** If all of the directories in the new path already exist,
258 | ** exit doing nothing.
259 | **/
260 | if( ! *qualifiedpath)
261 | goto success1;
262 |
263 | /* remove trailing ':' */
264 | qualifiedpath[strlen(qualifiedpath) - 1] = '\0';
265 |
266 | /**
267 | ** Some space for our newly created path.
268 | ** We size at the oldpath plus the addition.
269 | **/
270 | if((char *)NULL == (newpath = stringer(NULL, strlen( oldpath) +
271 | strlen(qualifiedpath) + 2,NULL)))
272 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
273 | goto unwind2;
274 | *newpath = '\0';
275 |
276 | /**
277 | ** Easy job to do, if the old path has not been set up so far ...
278 | **/
279 | if( !strcmp( oldpath, "")) {
280 | strcpy( newpath, qualifiedpath);
281 |
282 | /**
283 | ** Otherwise we have to take care on prepending vs. appending ...
284 | ** If there is a append or prepend marker within the variable (see
285 | ** modules_def.h) the changes are made according to this markers. Other-
286 | ** wise append and prepend will be relative to the strings begin or end.
287 | **/
288 |
289 | } else {
290 |
291 | Tcl_RegExp markexpPtr = Tcl_RegExpCompile(interp, sw_marker);
292 | _TCLCHK(interp)
293 |
294 | strcpy( newpath, oldpath);
295 |
296 | if( Tcl_RegExpExec(interp, markexpPtr, oldpath, oldpath)) {
297 | _TCLCHK(interp)
298 | Tcl_RegExpRange(markexpPtr, 0,
299 | (CONST84 char **) &startp, (CONST84 char **) &endp);
300 |
301 | /**
302 | ** Append/Prepend marker found
303 | **/
304 | if( append) {
305 | char ch = *endp;
306 | *endp = '\0';
307 | strcpy(newpath, oldpath);
308 | if (newpath[strlen(newpath)-1] != ':') strcat(newpath, ":");
309 | strcat(newpath, qualifiedpath);
310 | *endp = ch;
311 | strcat(newpath, endp);
312 | } else {
313 | char ch = *startp;
314 | *startp = '\0';
315 | strcpy(newpath, oldpath);
316 | if (newpath[strlen(newpath)-1] != ':') strcat(newpath, ":");
317 | strcpy(newpath, qualifiedpath);
318 | if (*oldpath != ':') strcat(newpath, ":");
319 | strcat(newpath, oldpath);
320 | *startp = ch;
321 | strcat(newpath, startp);
322 | }
323 |
324 | } else {
325 |
326 | /**
327 | ** No marker set
328 | **/
329 | if( !append) {
330 | strcpy(newpath, qualifiedpath);
331 | if (*oldpath != ':') strcat(newpath, ":");
332 | strcat(newpath, oldpath);
333 | } else {
334 | strcpy(newpath, oldpath);
335 | if (newpath[strlen(newpath)-1] != ':') strcat(newpath, ":");
336 | strcat(newpath, qualifiedpath);
337 | }
338 |
339 | } /** if( marker) **/
340 |
341 | } /** if( strcmp) **/
342 |
343 | /**
344 | ** Now the new value to be set resides in 'newpath'. Set it up.
345 | **/
346 | moduleSetenv( interp, (char *) argv[1], newpath, 1);
347 | _TCLCHK(interp)
348 |
349 | #if WITH_DEBUGGING_CALLBACK
350 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdSetPath, NULL);
351 | #endif
352 |
353 | /**
354 | ** Free resources
355 | **/
356 | null_free((void *) &newpath);
357 | success1:
358 | null_free((void *) &qualifiedpath);
359 | FreeList( pathlist, numpaths);
360 | success0:
361 | return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/
362 |
363 | unwind2:
364 | null_free((void *) &qualifiedpath);
365 | unwind1:
366 | FreeList( pathlist, numpaths);
367 | unwind0:
368 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
369 |
370 | } /** End of 'cmdSetPath' **/
371 |
372 | /*++++
373 | ** ** Function-Header ***************************************************** **
374 | ** **
375 | ** Function: cmdRemovePath **
376 | ** **
377 | ** Description: Remove the passed value (argv[2]) from the specified **
378 | ** variable (argv[1]). In case of switching this pro- **
379 | ** cedure removes markers from the path, too. argv[0] **
380 | ** specifies, if the append- or prepend-marker is af- **
381 | ** fected **
382 | ** **
383 | ** First Edition: 1991/10/23 **
384 | ** **
385 | ** Parameters: ClientData client_data **
386 | ** Tcl_Interp *interp According Tcl interp.**
387 | ** int argc Number of arguments **
388 | ** char *argv[] Argument array **
389 | ** **
390 | ** Result: int TCL_OK Successfull completion **
391 | ** TCL_ERROR Any error **
392 | ** **
393 | ** Attached Globals: g_flags These are set up accordingly before **
394 | ** this function is called in order to **
395 | ** control everything **
396 | ** **
397 | ** ************************************************************************ **
398 | ++++*/
399 |
400 | int cmdRemovePath( ClientData client_data,
401 | Tcl_Interp *interp,
402 | int argc,
403 | CONST84 char *argv[])
404 | {
405 | char *sw_marker = APP_SW_MARKER; /** arbitrary default **/
406 | char **pathlist; /** List of dirs **/
407 | int numpaths; /** number of dirs in path **/
408 | int x; /** loop index **/
409 |
410 |
411 | #if WITH_DEBUGGING_CALLBACK
412 | ErrorLogger( NO_ERR_START, LOC, _proc_cmdRemovePath, NULL);
413 | #endif
414 |
415 | /**
416 | ** Check arguments. There should be give 3 args:
417 | ** argv[0] - prepend/append/remove-path
418 | ** argv[1] - varname
419 | ** argv[2] - value
420 | **/
421 | if(argc != 3)
422 | if( OK != ErrorLogger(ERR_USAGE,LOC,argv[0],"path-variable directory",
423 | NULL))
424 | goto unwind0;
425 |
426 |
427 | /**
428 | ** Non-persist mode?
429 | **/
430 |
431 | if (g_flags & M_NONPERSIST) {
432 | return (TCL_OK);
433 | }
434 |
435 | /**
436 | ** Display only ... ok, let's do so!
437 | **/
438 | if(g_flags & M_DISPLAY) {
439 | fprintf( stderr, "%s\t ", argv[ 0]);
440 | while( --argc)
441 | fprintf( stderr, "%s ", *++argv);
442 | fprintf( stderr, "\n");
443 | goto success0;
444 | }
445 |
446 | /**
447 | ** prepend or append. The default is append.
448 | **/
449 | if( ! strncmp( argv[0], "pre", 3))
450 | sw_marker = PRE_SW_MARKER;
451 |
452 | /**
453 | ** For switch state3, we're looking to remove the markers.
454 | **/
455 | if( g_flags & M_SWSTATE3)
456 | argv[2] = sw_marker;
457 |
458 | /**
459 | ** Split the path into its components so each item can be removed
460 | ** individually from the variable.
461 | **/
462 | if( !( pathlist = SplitIntoList( interp, (char *) argv[2], &numpaths)))
463 | goto unwind0;
464 |
465 | /**
466 | ** Remove each item individually
467 | **/
468 | for( x = 0; x < numpaths; x++)
469 | if(TCL_OK != Remove_Path(interp,(char *) argv[1],pathlist[x],sw_marker))
470 | goto unwind1;
471 |
472 | #if WITH_DEBUGGING_CALLBACK
473 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdRemovePath, NULL);
474 | #endif
475 |
476 | /**
477 | ** Free resources
478 | **/
479 | FreeList(pathlist, numpaths);
480 |
481 | success0:
482 | return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/
483 |
484 | unwind1:
485 | FreeList(pathlist, numpaths);
486 | unwind0:
487 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
488 |
489 | } /** End of 'cmdRemovePath' **/
490 |
491 | /*++++
492 | ** ** Function-Header ***************************************************** **
493 | ** **
494 | ** Function: Remove_Path **
495 | ** **
496 | ** Description: This function actually does the work of removing **
497 | ** the item from the path. It is done this way to **
498 | ** support multiple items (often directories) **
499 | ** separated by colons in the variable value. **
500 | ** **
501 | ** First Edition: 2001/08/08 **
502 | ** **
503 | ** Parameters: Tcl_Interp *interp According Tcl interp.**
504 | ** char *variable Variable from which **
505 | ** to remove item **
506 | ** char *item Item to remove **
507 | ** char *sw_marker Switch marker **
508 | ** **
509 | ** Result: int TCL_OK Successfull completion **
510 | ** TCL_ERROR Any error **
511 | ** **
512 | ** Attached Globals: g_flags These are set up accordingly before **
513 | ** this function is called in order to **
514 | ** control everything **
515 | ** **
516 | ** ************************************************************************ **
517 | ++++*/
518 |
519 | static int Remove_Path( Tcl_Interp *interp,
520 | char *variable,
521 | char *item,
522 | char *sw_marker)
523 | {
524 | char *oldpath, /** Old value of 'var' **/
525 | *tmppath, /** Temp. buffer for 'var' **/
526 | *searchpath,
527 | *startp=NULL, *endp=NULL; /** regexp match endpts **/
528 | int start_offset = 0, /** match offsets **/
529 | end_offset = 0,
530 | path_len = 0; /** length of unmatched path **/
531 | Tcl_RegExp regexpPtr = (Tcl_RegExp) NULL,
532 | begexpPtr = (Tcl_RegExp) NULL,
533 | midexpPtr = (Tcl_RegExp) NULL,
534 | endexpPtr = (Tcl_RegExp) NULL,
535 | onlyexpPtr = (Tcl_RegExp) NULL,
536 | markexpPtr = (Tcl_RegExp) NULL;
537 |
538 | #if WITH_DEBUGGING_CALLBACK
539 | ErrorLogger( NO_ERR_START, LOC, _proc_Remove_Path, NULL);
540 | #endif
541 |
542 | /**
543 | ** Get the current value of the "PATH" environment variable
544 | **/
545 | if( NULL == (tmppath = (char *) Tcl_GetVar2( interp, "env", variable,
546 | TCL_GLOBAL_ONLY))) {
547 | _TCLCHK(interp)
548 | return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/
549 | }
550 |
551 | /**
552 | ** We want to make a local copy of old path because we're going
553 | ** to be butchering it and the environ one doesn't need to be
554 | ** changed in this manner.
555 | ** Put a \ in front of each . and + in the passed value to remove.
556 | **/
557 | if((char *) NULL == (oldpath = stringer(NULL,0, tmppath, NULL)))
558 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
559 | goto unwind0;
560 | path_len = strlen(oldpath);
561 | cleanse_path( item, buffer, PATH_BUFLEN);
562 |
563 | /**
564 | ** Now we need to find it in the path variable. So, we create
565 | ** space enough to build search expressions.
566 | **/
567 | if((char *) NULL == (searchpath = stringer(NULL,0,"^", buffer, ":", NULL)))
568 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
569 | goto unwind1;
570 |
571 | /**
572 | ** This section searches for the oldpath in the PATH variable.
573 | ** There are four cases because the colons must be used as markers
574 | ** in order to guarantee that a partial match isn't being found.
575 | **
576 | ** The start_offset and end_offset variables indicate how much to
577 | ** cut or not to cut off of each end of the located
578 | ** string. They differ for each case...beginning of
579 | ** the path, middle of the path, end of the path,
580 | ** and for the only path.
581 | **
582 | ** This is to ensure the colons get cut off properly.
583 | **/
584 |
585 | begexpPtr = Tcl_RegExpCompile(interp, searchpath);
586 | _TCLCHK(interp)
587 |
588 | if( Tcl_RegExpExec(interp, begexpPtr, oldpath, oldpath) > 0) {
589 | _TCLCHK(interp)
590 | regexpPtr = begexpPtr;
591 |
592 | /**
593 | ** Copy from the beginning of the startp to one
594 | ** character before endp
595 | **/
596 |
597 | Tcl_RegExpRange(begexpPtr, 0,
598 | (CONST84 char **) &startp, (CONST84 char **) &endp);
599 | start_offset = 0; end_offset = -1;
600 | path_len -= (endp - startp - 1);
601 |
602 | } else {
603 |
604 | *searchpath = ':'; /* :buffer: */
605 | midexpPtr = Tcl_RegExpCompile(interp, searchpath);
606 | _TCLCHK(interp)
607 |
608 | if( Tcl_RegExpExec(interp, midexpPtr, oldpath, oldpath) > 0) {
609 | _TCLCHK(interp)
610 | regexpPtr = midexpPtr;
611 |
612 | /**
613 | ** Copy from one character after stringp[0] to one
614 | ** character before endp[0]
615 | **/
616 |
617 | Tcl_RegExpRange(midexpPtr, 0,
618 | (CONST84 char **) &startp, (CONST84 char **) &endp);
619 | start_offset = 1; end_offset = -1;
620 | path_len -= (endp - startp - 2);
621 |
622 | } else {
623 |
624 | searchpath[strlen(searchpath)-1] = '$'; /* :buffer$ */
625 | endexpPtr = Tcl_RegExpCompile(interp, searchpath);
626 | _TCLCHK(interp)
627 |
628 | if( Tcl_RegExpExec(interp, endexpPtr, oldpath, oldpath) > 0) {
629 | _TCLCHK(interp)
630 | regexpPtr = endexpPtr;
631 |
632 | /**
633 | ** Copy from one character after stringp[0]
634 | ** through endp[0]
635 | **/
636 |
637 | Tcl_RegExpRange(endexpPtr, 0,
638 | (CONST84 char **) &startp, (CONST84 char **) &endp);
639 | start_offset = 0; end_offset = 0;
640 | path_len -= (endp - startp - 1);
641 |
642 | } else {
643 |
644 | *searchpath = '^'; /* ^buffer$ */
645 | onlyexpPtr = Tcl_RegExpCompile(interp, searchpath);
646 | _TCLCHK(interp)
647 |
648 | if(Tcl_RegExpExec(interp, onlyexpPtr, oldpath, oldpath) > 0) {
649 | _TCLCHK(interp)
650 |
651 | /**
652 | ** In this case, I should go ahead and unset the variable
653 | ** from the environment because I'm removing the very last
654 | ** path.
655 | **
656 | ** First I'm going to clear the variable from the
657 | ** setenvHashTable just in case its already been altered
658 | ** and had a significant value at the time. It's very
659 | ** possible that I'm removing the only two or three paths
660 | ** from this variable. If that's the case, then all the
661 | ** earlier paths were marked for output in this hashTable.
662 | **
663 | ** Secondly, I actually mark the the environment variable
664 | ** to be unset when output.
665 | **/
666 | clear_hash_value( setenvHashTable, variable);
667 | moduleUnsetenv( interp, variable);
668 |
669 | /**
670 | ** moduleUnsetenv doesn't unset the variable in the Tcl
671 | ** space because the $env variable might need to be
672 | ** used again in the modulefile for locating other
673 | ** paths. BUT, since this was a path-type environment
674 | ** variable, the user is expecting this to be empty
675 | ** after removing the only remaining path. So, I set
676 | ** the variable empty here.
677 | **/
678 | (void) Tcl_SetVar2( interp, "env", variable, "",
679 | TCL_GLOBAL_ONLY);
680 | _TCLCHK(interp)
681 | null_free((void *) &searchpath);
682 | goto success1;
683 | }
684 | }
685 | }
686 | }
687 | null_free((void *) &searchpath);
688 |
689 | /**
690 | ** If I couldn't find it assume it wasn't there
691 | ** and return.
692 | **/
693 | if( !regexpPtr)
694 | goto success1;
695 |
696 | markexpPtr = Tcl_RegExpCompile(interp, sw_marker);
697 | _TCLCHK(interp)
698 |
699 | /**
700 | ** In state1, we're actually replacing old paths with
701 | ** the markers for future appends and prepends.
702 | **
703 | ** We only want to do this once to mark the location
704 | ** the module was formed around.
705 | **/
706 | if((g_flags & M_SWSTATE1) && ! (Tcl_RegExpExec(interp,
707 | markexpPtr, oldpath, oldpath) > 0)) {
708 |
709 | /**
710 | ** If I don't have enough space to replace the oldpath with the
711 | ** marker, then I must create space for the marker and thus
712 | ** recreate the PATH variable.
713 | **/
714 | char* newenv;
715 | int newlen = path_len + strlen(sw_marker) + 1;
716 |
717 | if((char *) NULL==(newenv = stringer(NULL, newlen ,NULL) ))
718 | if( OK != ErrorLogger( ERR_STRING, LOC, NULL))
719 | goto unwind1;
720 |
721 | *(startp + start_offset) = '\0';
722 |
723 | if(*(endp + end_offset) == '\0') {
724 | (void) stringer(newenv, newlen, oldpath,":",sw_marker,NULL);
725 | } else {
726 | (void) stringer(newenv, newlen, oldpath,sw_marker,
727 | endp + end_offset, NULL);
728 | }
729 |
730 | /**
731 | ** Just store the value with the marker into the environment. I'm not
732 | ** checking if it changed because the only case that a PATH-type
733 | ** variable will be unset is when I remove the only path remaining in
734 | ** the variable. So, using moduleSetenv is not necessary here.
735 | **/
736 | Tcl_SetVar2( interp, "env", variable, newenv, TCL_GLOBAL_ONLY);
737 | _TCLCHK(interp)
738 | null_free((void *) &newenv);
739 |
740 | } else { /** SW_STATE1 **/
741 |
742 | /**
743 | ** We must be in SW_STATE3 or not in SW_STATE at all.
744 | ** Removing the marker should be just like removing any other path.
745 | **/
746 | strcpy( startp + start_offset, endp);
747 |
748 | /**
749 | ** Cache the set. Clear the variable from the unset table just
750 | ** in case it was previously unset.
751 | **/
752 | store_hash_value( setenvHashTable, variable, oldpath);
753 | clear_hash_value( unsetenvHashTable, variable);
754 |
755 | /**
756 | ** Store the new PATH value into the environment.
757 | **/
758 | Tcl_SetVar2( interp, "env", variable, oldpath, TCL_GLOBAL_ONLY);
759 | _TCLCHK(interp)
760 |
761 | } /** ! SW_STATE1 **/
762 |
763 | #if WITH_DEBUGGING_CALLBACK
764 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdRemovePath, NULL);
765 | #endif
766 |
767 | /**
768 | ** Free what has been used and return on success
769 | **/
770 | success1:
771 | null_free((void *) &oldpath);
772 | success0:
773 | return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/
774 |
775 | unwind1:
776 | null_free((void *) &oldpath);
777 | unwind0:
778 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
779 |
780 | } /** End of 'Remove_Path' **/