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