798ce64c25e13564da090ac9f34b732ce545680c
[oweals/cde.git] / cde / lib / DtSvc / DtUtil2 / EnvControl.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /****************************<+>*************************************
24  ********************************************************************
25  **
26  **   File:     EnvControl.c
27  **
28  **   $TOG: EnvControl.c /main/21 1999/01/28 17:59:53 mgreess $
29  **
30  **   Project:  DtSvc Runtime Library
31  **
32  **   Description: Get/Set the client's shell environment
33  **
34  **(c) Copyright 1992,1993,1994 by Hewlett-Packard Company
35  **(c) Copyright 1993,1994 International Business Machines Corp.
36  **(c) Copyright 1993,1994 Sun Microsystems, Inc.
37  **(c) Copyright 1993,1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
38  **
39  ********************************************************************
40  ****************************<+>*************************************/
41 #include <stdlib.h>
42 #include <stdio.h>
43 #define X_INCLUDE_STRING_H
44 #define XOS_USE_XT_LOCKING
45 #include <X11/Xos_r.h>
46 #include <X11/Intrinsic.h>
47 #include <X11/Xatom.h>
48 #include <Dt/DtosP.h>
49 #include <Dt/DtNlUtils.h>
50 #include "EnvControlP.h"
51 #include "EnvControlI.h"
52 #include "DtSvcLock.h"
53
54 extern char **environ;
55
56  /* 
57   *  We assume that the following fields of these static structures
58   *  are initialized at runtime to NULL pointers.
59   */
60 static struct environStruct _postDtEnvironment;
61 static struct environStruct _preDtEnvironment;
62
63 /* envBitVector is used to determine whether an environment
64  * variable has been put to the environment by the application.
65  * The flag values are in EnvControlI.h.
66  */
67 static unsigned int envBitVector = 0;
68
69 static void _EnvAdd (char *, char *, unsigned int);
70
71
72 /****************************************************************
73 * NOTES on an application's environ(5):
74
75 * The environment variable is an array of NULL-terminated strings.
76 * char **environ is defined in crt.o and is publicly extern-ed to
77 * all applications.  There is one such variable per UN*X application.
78
79 * To deference an environment string, as in the debugger, use:
80
81 *        environ[0] -- environ[n-1], where n is the number of
82 *        name=value pairs.
83
84 * E.g, in xdb:
85
86 *        >p environ[0]
87
88 * You must manually malloc() space to keep a specific environment string
89 * around.
90
91 * putenv() is useless at NULLing out an environment variable.  It will
92 * create a new value and will replace an existing value; however,
93 * in terms of getting rid of an environment variable, putenv() will only
94 * replace it with a NULL string ("") rather than freeing the space 
95 * for it and NULLing the pointer.  Afterwards, getenv() will return
96 * the NULL string rather than a NULL pointer, and hence give "incorrect"
97 * information to an application querying for a non-set environment
98 * variable.  
99 *
100 * E.g., there's a big difference between the following pairs 
101 * to XmGetPixmap():
102
103 *         XBMLANGPATH=""
104
105 *         --and--
106
107 *         XBMLANGPATH=<null pointer>
108
109 * The first will cause XmGetPixmap() to look nowhere for an icon image;
110 * the second will cause a lookup in all the default locations, which
111 * is what you want.
112
113 * Bottom line is that you have to NULL out an unneeded environ manually.
114
115 * The environment array is able to be jerked any which way you'd like,
116 * using direct string/pointer manipulations.  However, for safety:
117 * make a local copy of **environ.
118
119 ********************************************************************/
120
121
122
123 /*
124  * Common suffixes for icon pixmap and icon bitmap paths.  Each array must end
125  * with a null pointer.  Note: the unusual string concatenation is necessary
126  * in order to prevent expansion of SCCS id keywords.
127  */
128
129 static const char *iconPmSuffixes[] = {
130     "%B" "%M.pm",
131     "%B" "%M.bm",
132     "%B",
133     NULL
134 };
135
136 static const char *iconBmSuffixes[] = {
137     "%B" "%M.bm",
138     "%B" "%M.pm",
139     "%B",
140     NULL
141 };
142
143
144 /*
145  * makeDefaultIconPath
146  * 
147  * Construct the icon pixmap or bitmap search path by constructing the values
148  * from the home directory, and then appending the system default path.  The
149  * output is of the form "var=value", suitable for passing to putenv().
150  *
151  * Output:
152  *
153  * outbuf       A pointer to the memory to receive the output value.  This
154  *              must be large enough to accommodate the largest anticipated
155  *              environment variable; no bounds checking is done!
156  * 
157  * Inputs:
158  * 
159  * varname      The environment variable name.
160  * basedefault  The default value to be appended to the end.
161  * suffixes     An array of suffixes used in constructing the path elements in
162  *              the user's home directory.  Must have a trailing NULL pointer.
163  */
164 static char *
165 makeDefaultIconPath(
166         const char      *varname,
167         const char      *basedefault,
168         const char      **suffixes)
169 {
170         char            *fmt = "%s/.dt/icons/%s:";
171         char            *homedir;
172         char            *outbuf;
173         int             bytes_needed, fmt_bytes, homedir_bytes;
174
175         bytes_needed = strlen(varname) + strlen(basedefault) + 2;
176
177         homedir = getenv("HOME");
178         if (NULL != homedir)
179         {
180             homedir_bytes = strlen(homedir);
181             fmt_bytes = strlen(fmt);
182             for ( ; *suffixes ; ++suffixes)
183               bytes_needed += (homedir_bytes + fmt_bytes + strlen(*suffixes));
184         }
185
186         outbuf = XtMalloc(bytes_needed);
187         (void)sprintf(outbuf, "%s=", varname);
188         if (homedir != NULL)
189         {
190             char *temp = XtMalloc(bytes_needed);
191
192             for ( ; *suffixes ; ++suffixes)
193             {
194                 (void)sprintf(temp, fmt, homedir, *suffixes);
195                 (void)strcat(outbuf, temp);
196             }
197
198             if (temp) XtFree(temp);
199         }
200         (void)strcat(outbuf, basedefault);
201
202         return outbuf;
203 }
204
205
206 /*
207  * Construct a default value for XMICONSEARCHPATH into outbuf.
208  */
209 static char *
210 makeDefaultIconPmPath(void)
211 {
212     static char *defaultIconPmPath = NULL;
213
214     if (NULL == defaultIconPmPath)
215       defaultIconPmPath =
216         makeDefaultIconPath(PM_PATH_ENVIRON, DTPMSYSDEFAULT, iconPmSuffixes);
217     
218     return XtNewString(defaultIconPmPath);
219 }
220
221
222 /*
223  * Construct a default value for XMICONBMSEARCHPATH into outbuf.
224  */
225 static char *
226 makeDefaultIconBmPath(void)
227 {
228     static char *defaultIconBmPath = NULL;
229
230     if (NULL == defaultIconBmPath)
231       defaultIconBmPath =
232         makeDefaultIconPath(BM_PATH_ENVIRON, DTBMSYSDEFAULT, iconBmSuffixes);
233     
234     return XtNewString(defaultIconBmPath);
235 }
236
237
238 /*****************************<->*************************************
239  *
240  *  _DtEnvSessionManager ()
241  *
242  *
243  *  Description:
244  *  -----------
245  *  Sets the SESSION_MANAGER environment variable if not already set.
246  *
247  *  Inputs:
248  *  ------
249  *  NONE
250  *
251  *  Returns:
252  *  --------
253  *  void
254  * 
255  *****************************<->***********************************/
256 void
257 _DtEnvSessionManager(void)
258 {
259 #define SESSION_MANAGER "SESSION_MANAGER"
260     char *session_manager = getenv(SESSION_MANAGER);
261     if (NULL == session_manager)
262     {
263         Display *display;
264         Atom sm_atom;
265
266         display = XOpenDisplay(NULL);
267         if (NULL != display)
268         {
269             sm_atom = XInternAtom(display, SESSION_MANAGER, True);
270             if (None != sm_atom)
271             {
272                 Atom actual_type;
273                 unsigned long nitems, leftover;
274                 int actual_format;
275
276                 if (Success == XGetWindowProperty(
277                                 display, XDefaultRootWindow(display),
278                                 sm_atom, 0L, 256, False, XA_STRING,
279                                 &actual_type, &actual_format,
280                                 &nitems, &leftover,
281                                 (unsigned char **) &session_manager))
282                 {
283                     if (NULL != session_manager && None != actual_format)
284                     {
285                         char *envstr;
286                         envstr = (char*) malloc(
287                                                 strlen(SESSION_MANAGER) +
288                                                 strlen(session_manager) + 2);
289                         sprintf(
290                                 envstr, "%s=%s",
291                                 SESSION_MANAGER,
292                                 session_manager);
293                         putenv(envstr);
294                         XtFree(session_manager);
295                     }
296                 }
297             }
298             XCloseDisplay(display);
299         }
300     }
301 }
302
303 /*****************************<->*************************************
304  *
305  *  _DtEnvControl ( int mode )
306  *
307  *
308  *  Description:
309  *  -----------
310  *  Gets/Sets the application's environment 
311  *
312  *  Inputs:
313  *  ------
314  *  mode        - the command to the function; e.g., to set the
315  *                DT environment, to restore the originial env., etc.
316  *
317  *  Returns:
318  *  --------
319  *  Returns a success code--usually just the value of the original
320  *  mode parameter.  If an error occurs, returns DT_ENV_NO_OP.
321  * 
322  *****************************<->***********************************/
323 int
324 _DtEnvControl(
325         int mode )
326 {
327     static int environSetup = 0;
328
329     char *tempString;  
330     char *ptr; /* used for indexing into the $PATH */
331     int returnValue = DT_ENV_NO_OP;
332     int bytes_needed;
333
334     _DtSvcProcessLock();
335     switch (mode) {
336
337         case DT_ENV_SET:
338             if (!environSetup)  /* first time through */
339             {
340                 /*
341                  * Make sure the SESSION_MANAGER variable is set.
342                  */
343                 _DtEnvSessionManager();
344
345                 /*
346                  * Set up DT environment in the application 
347                  * environment, while stashing the old environment
348                  * in the _preDtEnvironment structure 
349                  *
350                  * Note: this code will not check for duplicate
351                  * environment values--it will append or prepend
352                  * the DT environment values regardless of what's
353                  * in the current environment.
354                  *
355                  *  Of the form:
356                  *
357                  *  PATH = /opt/dt/bin :  originalPath
358                  *  %s  %s    %s        %s    %s
359                  *
360                  *
361                  *  XBMLANGPATH = originalPath : dtPath
362                  *        %s    %s    %s       %s    %s
363                  *
364                  *  Note: Of all the environmental vars, ONLY $PATH
365                  *  is jammed with the DT value first.
366                  *
367                  *  Check for NULL environment strings before the sprintf
368                  *
369                  */
370
371                 /*
372                  * Get the application's original environment 
373                  * to save it in the _preDtEnvironment structure 
374                  *
375                  * We save in the _preDtEnvironment structure
376                  * only existing (non-NULL getenv()) values.
377                  *
378                  */
379
380                 /*
381                  * Prepend BIN_PATH_STRING to the PATH component.
382                  */
383                 tempString = getenv(BIN_PATH_ENVIRON);
384
385                 /*
386                  *  First, ensure that BIN_PATH_STRING isn't already there.
387                  */
388                 if (!tempString || !(strstr(tempString, BIN_PATH_STRING)))
389                 {
390                     if (!tempString)
391                     {
392                         /* 
393                          * No existing PATH environment variable.
394                          * Just create the new DT environment.
395                          */
396                         bytes_needed =
397                           strlen(BIN_PATH_ENVIRON) + strlen(BIN_PATH_STRING) +2;
398
399                         _postDtEnvironment.binPath = XtMalloc(bytes_needed);
400                         sprintf(_postDtEnvironment.binPath,
401                                 "%s=%s",
402                                 BIN_PATH_ENVIRON,
403                                 BIN_PATH_STRING);
404                     }
405                     else
406                     {
407                         /*
408                          * Save the existing PATH.
409                          */
410                         bytes_needed =
411                           strlen(BIN_PATH_ENVIRON) + strlen(tempString) + 2;
412
413                         _preDtEnvironment.binPath = XtMalloc(bytes_needed);
414                         sprintf(_preDtEnvironment.binPath,
415                                 "%s=%s",
416                                 BIN_PATH_ENVIRON,
417                                 tempString);
418
419                         bytes_needed =
420                                 strlen(tempString) +
421                                 strlen(BIN_PATH_ENVIRON) +
422                                 strlen(BIN_PATH_STRING) + 4;
423
424                         _postDtEnvironment.binPath = XtMalloc(bytes_needed);
425 #ifdef sun
426                         if ((ptr = strstr(tempString, "/usr/openwin/bin")))
427 #elif defined(CSRG_BASED)
428                         if ((ptr = strstr(tempString, "/usr/X11R6/bin")))
429 #elif defined(__linux__)
430                         if ((ptr = strstr(tempString, "/usr/bin")))
431 #else
432                         if ((ptr = strstr(tempString, "/usr/bin/X11")))
433 #endif
434                         {
435                              /* 
436                               * Shorten the string in tempString
437                               * to the initial segment, up to the 
438                               * initial slash in "/usr/bin/X11"
439                               */
440                              if (ptr != tempString)
441                              {
442                                 /* 
443                                  * then put our dt string just ahead of 
444                                  * "/usr/bin/X11" in the new PATH 
445                                  */
446                                  *(ptr - 1) = '\0'; 
447                                  sprintf(_postDtEnvironment.binPath,
448                                    "%s=%s:%s:%s",
449                                     BIN_PATH_ENVIRON,
450                                     tempString,
451                                     BIN_PATH_STRING,
452                                     ptr);
453                              }
454                              else
455                              {
456                                 /*
457                                  *  Turns out that "/usr/bin/X11"
458                                  *  is at the front of the PATH, so...
459                                  */
460                                 sprintf(_postDtEnvironment.binPath,
461                                     "%s=%s:%s",
462                                     BIN_PATH_ENVIRON,
463                                     BIN_PATH_STRING,
464                                     tempString);
465                             }
466
467                         }
468                         else if (ptr = strstr(tempString, "/usr/bin"))
469                         {
470                              /* 
471                               * Shorten the string in tempString
472                               * to the initial segment, up to the 
473                               * initial slash in "/usr/bin"
474                               */
475                              if (ptr != tempString)
476                              {
477                                 /* 
478                                  * then put our dt string just ahead of 
479                                  * "/usr/bin" in the new PATH 
480                                  */
481
482                                  *(ptr - 1) = '\0'; 
483                                  sprintf(_postDtEnvironment.binPath,
484                                    "%s=%s:%s:%s",
485                                     BIN_PATH_ENVIRON,
486                                     tempString,
487                                     BIN_PATH_STRING,
488                                     ptr);
489                              }
490                              else
491                              {
492                                 /*
493                                  *  Turns out that "/usr/bin"
494                                  *  is at the front of the PATH, so...
495                                  */
496                                 sprintf(_postDtEnvironment.binPath,
497                                     "%s=%s:%s",
498                                     BIN_PATH_ENVIRON,
499                                     BIN_PATH_STRING,
500                                     tempString);
501                             }
502                         }
503                         else
504                         {
505                             /* 
506                              * Put our dt string on the front of the PATH 
507                              */
508                             sprintf(_postDtEnvironment.binPath,
509                                 "%s=%s:%s",
510                                 BIN_PATH_ENVIRON,
511                                 BIN_PATH_STRING,
512                                 tempString);
513                         }
514                     }
515
516                     _EnvAdd (BIN_PATH_ENVIRON, 
517                                _postDtEnvironment.binPath, 
518                                BV_BINPATH);
519                 }
520
521
522                 tempString = getenv(PM_PATH_ENVIRON);
523                 if (tempString)
524                 {
525                     bytes_needed =
526                       strlen(PM_PATH_ENVIRON) + strlen(tempString) + 2;
527
528                     _preDtEnvironment.pmPath = XtMalloc(bytes_needed);
529                     sprintf(_preDtEnvironment.pmPath,
530                         "%s=%s",
531                         PM_PATH_ENVIRON,
532                         tempString);
533                 }
534                 else
535                 {
536                     /* it doesn't exist, so generate a default value */
537                     _postDtEnvironment.pmPath = makeDefaultIconPmPath();
538                     _EnvAdd(PM_PATH_ENVIRON, _postDtEnvironment.pmPath,
539                         BV_PMPATH);
540                 }
541
542
543                 tempString = getenv(BM_PATH_ENVIRON);
544                 if (tempString)
545                 {
546                     bytes_needed =
547                       strlen(BM_PATH_ENVIRON) + strlen(tempString) + 2;
548
549                     _preDtEnvironment.bmPath = XtMalloc(bytes_needed);
550                     sprintf(_preDtEnvironment.bmPath,
551                         "%s=%s",
552                         BM_PATH_ENVIRON,
553                         tempString);
554                 }
555                 else
556                 {
557                     /* it doesn't exist, so generate a default value */
558                     _postDtEnvironment.bmPath = makeDefaultIconBmPath();
559                     _EnvAdd(BM_PATH_ENVIRON, _postDtEnvironment.bmPath,
560                         BV_BMPATH);
561                 }
562
563
564                 /* Do the admin for the NLSPATH env variable */
565                 tempString = getenv(NLS_PATH_ENVIRON);
566                 if (!tempString)
567                 {
568                     /* If it doesn't exist, set it to the CDE default */
569                     bytes_needed =
570                       strlen(NLS_PATH_ENVIRON) + strlen(NLS_PATH_STRING) + 2;
571
572                     _postDtEnvironment.nlsPath = XtMalloc(bytes_needed);
573                     sprintf(_postDtEnvironment.nlsPath,
574                         "%s=%s",
575                         NLS_PATH_ENVIRON,
576                         NLS_PATH_STRING);
577                 }
578                 else
579                 {
580                     /* If it does exist, store it away so it can be
581                      * restored afterwards.....
582                      */
583                     bytes_needed =
584                       strlen(NLS_PATH_ENVIRON) + strlen(tempString) + 2;
585
586                     _preDtEnvironment.nlsPath = XtMalloc(bytes_needed);
587                     sprintf(_preDtEnvironment.nlsPath,
588                         "%s=%s",
589                         NLS_PATH_ENVIRON,
590                         tempString);
591
592                     /* ... then append the CDE default to the existing
593                      * value
594                      */
595                     bytes_needed =
596                         strlen(NLS_PATH_ENVIRON) +
597                         strlen(tempString) +
598                         strlen(NLS_PATH_STRING) + 3;
599
600                     _postDtEnvironment.nlsPath = XtMalloc(bytes_needed);
601                     sprintf(_postDtEnvironment.nlsPath,
602                         "%s=%s:%s",
603                         NLS_PATH_ENVIRON,
604                         tempString,
605                         NLS_PATH_STRING);
606                 }
607
608                 _EnvAdd(NLS_PATH_ENVIRON, _postDtEnvironment.nlsPath,
609                            BV_NLSPATH);
610
611
612                 tempString = getenv(SYSTEM_APPL_PATH_ENVIRON);
613                 if (!tempString)
614                 {
615                     bytes_needed =
616                         strlen(SYSTEM_APPL_PATH_ENVIRON) +
617                         strlen(SYSTEM_APPL_PATH_STRING) + 2;
618
619                     _postDtEnvironment.sysApplPath = XtMalloc(bytes_needed);
620                     sprintf(_postDtEnvironment.sysApplPath,
621                         "%s=%s",
622                         SYSTEM_APPL_PATH_ENVIRON,
623                         SYSTEM_APPL_PATH_STRING);
624                 }
625                 else
626                 {
627                     bytes_needed =
628                       strlen(SYSTEM_APPL_PATH_ENVIRON) + strlen(tempString) + 2;
629
630                     _preDtEnvironment.sysApplPath = XtMalloc(bytes_needed);
631                     sprintf(_preDtEnvironment.sysApplPath,
632                         "%s=%s",
633                         SYSTEM_APPL_PATH_ENVIRON,
634                         tempString);
635
636                     bytes_needed =
637                         strlen(SYSTEM_APPL_PATH_ENVIRON) +
638                         strlen(tempString) +
639                         strlen(SYSTEM_APPL_PATH_STRING) + 3;
640
641                     _postDtEnvironment.sysApplPath = XtMalloc(bytes_needed);
642                     sprintf(_postDtEnvironment.sysApplPath,
643                         "%s=%s:%s",
644                         SYSTEM_APPL_PATH_ENVIRON,
645                         tempString,
646                         SYSTEM_APPL_PATH_STRING);
647                 }
648
649                 _EnvAdd (SYSTEM_APPL_PATH_ENVIRON,
650                            _postDtEnvironment.sysApplPath,
651                            BV_SYSAPPLPATH);
652
653                 environSetup = 1;
654                 returnValue = DT_ENV_SET;
655             }
656             else /* we've already been here -- do nothing */
657             {
658                 returnValue = DT_ENV_NO_OP;
659             }
660             break;
661
662         case  DT_ENV_RESTORE_PRE_DT:
663             if (environSetup) 
664             {
665                 if (_preDtEnvironment.nlsPath) {
666                     _EnvAdd (NLS_PATH_ENVIRON, 
667                                _preDtEnvironment.nlsPath,
668                                BV_NLSPATH);
669                 }
670                 else {
671                     _DtEnvRemove(NLS_PATH_ENVIRON, 0);
672                     envBitVector &= ~BV_NLSPATH;
673                 }
674
675                 if (_preDtEnvironment.sysApplPath) {
676                     _EnvAdd (SYSTEM_APPL_PATH_ENVIRON, 
677                                _preDtEnvironment.sysApplPath,
678                                BV_SYSAPPLPATH);
679                 }
680                 else {
681                     _DtEnvRemove(SYSTEM_APPL_PATH_ENVIRON, 0);
682                     envBitVector &= ~BV_SYSAPPLPATH;
683                 }
684
685                 if (_preDtEnvironment.pmPath) {
686                     _EnvAdd (PM_PATH_ENVIRON,
687                                _preDtEnvironment.pmPath,
688                                BV_PMPATH);
689                 }
690                 else {
691                     _DtEnvRemove(PM_PATH_ENVIRON, 0);
692                     envBitVector &= ~BV_PMPATH;
693                 }
694
695                 if (_preDtEnvironment.bmPath) {
696                     _EnvAdd (BM_PATH_ENVIRON,
697                                _preDtEnvironment.bmPath,
698                                BV_BMPATH);
699                 }
700                 else {
701                     _DtEnvRemove(BM_PATH_ENVIRON, 0);
702                     envBitVector &= ~BV_BMPATH;
703                 }
704
705                 returnValue = DT_ENV_RESTORE_PRE_DT;
706             }
707             else
708             {
709                 returnValue = DT_ENV_NO_OP;
710             }
711             break;
712
713         case DT_ENV_RESTORE_POST_DT:
714             if (environSetup) 
715             {
716
717                 if (_postDtEnvironment.nlsPath) {
718                     _EnvAdd (NLS_PATH_ENVIRON, 
719                                _postDtEnvironment.nlsPath,
720                                BV_NLSPATH);
721                 }
722
723                 if (_postDtEnvironment.pmPath) {
724                     _EnvAdd (PM_PATH_ENVIRON,
725                                _postDtEnvironment.pmPath,
726                                BV_PMPATH);
727                 }
728
729                 if (_postDtEnvironment.bmPath) {
730                     _EnvAdd (BM_PATH_ENVIRON,
731                                _postDtEnvironment.bmPath,
732                                BV_BMPATH);
733                 }
734
735                 if (_postDtEnvironment.sysApplPath) {
736                     _EnvAdd (SYSTEM_APPL_PATH_ENVIRON, 
737                                _postDtEnvironment.sysApplPath,
738                                BV_SYSAPPLPATH);
739                 }
740
741                 returnValue = DT_ENV_RESTORE_POST_DT;
742             }
743             else
744             {
745                 returnValue = DT_ENV_NO_OP;
746             }
747             break;
748
749         default:
750             /* do nothing */
751             break;
752     }
753
754     _DtSvcProcessUnlock();
755
756 #ifdef DEBUG
757         switch (mode) {
758         case DT_ENV_SET:
759                 printf("DT environment set:\n");
760                 printf("-------------------------------\n");
761                 break;
762
763         case DT_ENV_RESTORE_PRE_DT:
764                 printf("Pre-DT environment restored:\n");
765                 printf("-------------------------------\n");
766                 break;
767
768         case DT_ENV_RESTORE_POST_DT:
769                 printf("Post-DT environment restored:\n");
770                 printf("-------------------------------\n");
771                 break;
772
773         case DT_ENV_NO_OP:
774                 printf("No change from last invocation:\n");
775                 printf("-------------------------------\n");
776                 break;
777         }
778
779         tempString = getenv(BIN_PATH_ENVIRON);
780         printf("%s=|%s|\n", BIN_PATH_ENVIRON, tempString);
781         tempString = getenv(SYSTEM_APPL_PATH_ENVIRON);
782         printf("%s=|%s|\n", SYSTEM_APPL_PATH_ENVIRON, tempString);
783         tempString = getenv(NLS_PATH_ENVIRON);
784         printf("%s=|%s|\n", NLS_PATH_ENVIRON, tempString);
785         tempString = getenv(PM_PATH_ENVIRON);
786         printf("%s=|%s|\n", PM_PATH_ENVIRON, tempString);
787         tempString = getenv(BM_PATH_ENVIRON); 
788         printf("%s=|%s|\n", BM_PATH_ENVIRON, tempString);
789
790 #endif /* DEBUG */
791         return (returnValue);
792
793 } /* END OF FUNCTION _DtEnvControl */
794
795 /*****************************<->*************************************
796  *
797  *  _EnvAdd(char * str)
798  *
799  *
800  *  Description:
801  *  -----------
802  *  Adds the given string to the application's environment
803  *  If the existing environment variable string was allocated
804  *  by this application, the space is freed.
805  *
806  *  Inputs:
807  *  ------
808  *  envVar          The environment variable. E.g. NLSPATH
809  *  envVarSetting   The environment variable setting. 
810  *                  E.g. NLSPATH=/usr/lib/nls
811  *  bv_flag         The constant denoting which environment variable
812  *                  is being set.
813  * 
814  *****************************<->***********************************/
815 static void _EnvAdd
816   (
817    char * envVar,
818    char * envVarSetting,
819    unsigned int bv_flag
820   )
821 {
822   _DtSvcProcessLock();
823   if (envBitVector & bv_flag) {
824 #if defined(CSRG_BASED) || defined(__linux__)
825       setenv(envVar, envVarSetting + strlen(envVar) + 1, 1);
826 #else
827
828       register int i;
829       size_t envVarLen = strlen(envVar);
830       char *envPtr = NULL;
831
832     /* if we have previously put this environment variable out to the
833      * environment, we can retrieve it and reuse it rather than letting
834      * it disappear into the ether
835      */
836
837     for ( i = 0; environ[i] ; i++ )
838     {
839         if ( environ[i][0] == envVar[0]
840              && ( strlen(environ[i]) >= envVarLen )
841              && ( environ[i][envVarLen] == '=' ) 
842              && !strncmp(envVar,environ[i],envVarLen))
843         {
844                 envPtr = environ[i];
845                 break;
846         }
847     }
848     
849     if ( envPtr )
850     {
851             XtFree(envPtr);
852             envPtr = strdup(envVarSetting);
853             strcpy(envPtr,envVarSetting);
854             environ[i] = envPtr;
855     }
856     else
857     {
858             /* This should never happen */
859             putenv(strdup(envVarSetting));
860     }
861 #endif /* linux || CSRG_BASED */
862   }
863   else
864     putenv(strdup(envVarSetting));
865
866   envBitVector |= bv_flag;
867   _DtSvcProcessUnlock();
868 }
869
870 /*****************************<->*************************************
871  *
872  *  _DtEnvRemove(
873  *      char *str,
874  *      int length )
875  *
876  *
877  *  Description:
878  *  -----------
879  *  Removes the given string from the application's environment
880  *  Uses the char **extern environment string array.
881  *
882  *  Inputs:
883  *  ------
884  *  str         - the name of the variable to remove (e.g., "NLSPATH")
885  *  length      - the length of the variable--we compute it dynamically.
886  *
887  *  Returns:
888  *  --------
889  *  Returns a success code--"0" if the variable is found and removed.
890  *                          "1" if the variable isn't found.
891  * 
892  *****************************<->***********************************/
893 int
894 _DtEnvRemove(
895         char *str,
896         int length )
897 {
898         char **pEnviron, **pEnviron2 = environ;
899         char *p, *freeMe;
900         int temp;
901                          
902         int count  = 0;  /* count is the number of items in the */
903                          /* environ                             */
904         int index;   /* index will range from 0 to count - 1 */
905         size_t len;
906
907         if (!(len = strlen(str)))
908                 return(1);
909
910         pEnviron = pEnviron2;
911
912         p = *pEnviron;
913
914         while (p)
915         {
916                 pEnviron++;
917                 count++;
918                 p = *pEnviron;
919         }
920
921         pEnviron = pEnviron2;
922         p = *pEnviron;
923
924         for  (index = 0; index < count; index++)
925         {
926                 if (  p[0] == str[0] 
927                       && ( strlen(p) >= len )
928                       && ( p[len] == '=' )
929                       && !strncmp(p, str, len))
930                 {
931 #if defined(__linux__) || defined(CSRG_BASED)
932                   /* JET - 2/19/99
933                      It seems much safer to let libc worry about this
934                      rather than try to do it ourselves.  
935                      */
936
937                   unsetenv(str);
938 #else
939
940                     freeMe = pEnviron2[index];
941
942                     /* just move the last one into the gap - any
943                      * putenv destroyed the initial lexical ordering
944                      * anyway
945                      */
946
947                     pEnviron2[index] = pEnviron2[count - 1];
948                     pEnviron2[count - 1] = NULL;
949
950                     XtFree (freeMe);
951 #endif /* linux || CSRG_BASED */
952                     return(0);
953                 }
954                 pEnviron++;
955                 p = *pEnviron;
956         }
957         return(1);
958 }
959
960 #if 0
961 int
962 _EnvPrint( void )
963 {
964         char **p, *q;
965
966         p = (char **)(environ);
967
968         q = *p;
969
970         while (q)
971         {
972                 printf("%s\n", q);
973                 p++;
974                 q = *p;
975         }
976         return 0;
977 }
978 #endif
979
980 \f
981 /*************************************<->*************************************
982  *
983  *  _AddToPath (sPath, sDir)
984  *
985  *
986  *  Description:
987  *  -----------
988  *  Append a directory to a directory path. 
989  *
990  *  Inputs:
991  *  ------
992  *  sPath       - the old path (must be a pointer to malloc'ed memory)
993  *  sDir        - the directory to add to the path
994  *
995  *
996  *  Returns:
997  *  --------
998  *  A pointer to the new path if successful.
999  *  NULL on memory allocation failures.
1000  *
1001  *  Comment:
1002  *  --------
1003  *  This functions adds sDir to the path of directories already in
1004  *  sPath. Each directory is separated by a colon (':'). The function
1005  *  is designed to work off the heap. sPath should be a pointer into
1006  *  the heap on entry, or NULL. If sPath is NULL, then new memory is
1007  *  allocated and returned. If sPath is not NULL, the storage for sPath
1008  *  is reallocated to include space for the new string. In this case,
1009  *  the pointer returned may point to a different value than sPath
1010  *  that was passed in. If the pointer returned is different than sPath,
1011  *  then sPath is invalid and should be reassigned.
1012  *
1013  *************************************<->***********************************/
1014 static char *
1015 _AddToPath (
1016         char * sPath,
1017         char * sDir)
1018 {
1019     char * sNew;
1020
1021     if (sPath != NULL)
1022     {
1023         sNew = XtRealloc (sPath, strlen(sPath) + 1 + strlen(sDir) + 1);
1024     }
1025     else
1026     {
1027         sNew = XtMalloc (1 + strlen(sDir) + 1);
1028     }
1029
1030     strcat (sNew, ":");
1031     strcat (sNew, sDir);
1032
1033     return (sNew);
1034 }
1035
1036 \f
1037 /*************************************<->*************************************
1038  *
1039  *  _DtWsmSetBackdropSearchPath(screen, backdropPath, useMultiColorIcons)
1040  *
1041  *
1042  *  Description:
1043  *  -----------
1044  *  Append the specified directories to DTICONSEARCHPATH environment 
1045  *  variable.  This must be done before any icon lookup by XmGetPixmap.
1046  *  Each directory in backdropPath is modified so the backdrop file
1047  *  names can be matched (%B, %M, etc.).
1048  *
1049  *  _DtEnvControl( DT_ENV_RESTORE_PRE_DT ) will restore the original
1050  *  environment.
1051  *
1052  *  Inputs:
1053  *  ------
1054  *  screen              - screen of display 
1055  *  backdropPath        - a colon-separated list of directories
1056  *  useMultiColorIcons  - True if color backdrops are desired.
1057  *
1058  *  Returns:
1059  *  --------
1060  *  Returns a success code:   success: DT_ENV_SET
1061  *                            failure: DT_ENV_NO_OP
1062  *
1063  *************************************<->***********************************/
1064 int
1065 _DtWsmSetBackdropSearchPath (
1066         Screen  *screen,
1067         char    *backdropPath,
1068         Boolean  useMultiColorIcons)
1069
1070 {
1071     char *sBackDirs;
1072     char *sOldEnv;
1073     char *sNext;
1074     char *bm_pm_fmt = "%s/%%B.bm:%s/%%B.pm:%s/%%B";  
1075     char *pm_bm_fmt = "%s/%%B.pm:%s/%%B.bm:%s/%%B";  
1076     int fmtlen = strlen(pm_bm_fmt);
1077     int returnValue = DT_ENV_NO_OP;
1078     int bytes_needed;
1079     _Xstrtokparams strtok_buf;
1080
1081     /* for creating the name=value string */
1082     char postDtEnvironmentStringBuf[MAX_ENV_STRING]; 
1083     char *postDtEnvironmentString;
1084
1085     if (backdropPath == NULL) return (returnValue);
1086
1087     sOldEnv = getenv(PM_PATH_ENVIRON);
1088
1089     DtNlInitialize();
1090
1091     _DtSvcProcessLock();
1092     if (!sOldEnv)
1093     {
1094         /* 
1095          * The user has no existing value for this
1096          * environment variable.  Don't save it.
1097          * Just create the new DT environment.
1098          */
1099
1100         /* make a copy that we can modify locally */
1101         sBackDirs = strdup(backdropPath);
1102         strcpy (sBackDirs, backdropPath);
1103
1104         /*
1105          * Initialize path string
1106          */
1107         if (useMultiColorIcons)
1108           _postDtEnvironment.pmPath = makeDefaultIconPmPath();
1109         else
1110           _postDtEnvironment.pmPath = makeDefaultIconBmPath();
1111
1112         /* get first directory */
1113         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1114
1115         /* process each directory individually */
1116         while (sNext != NULL)
1117         {
1118             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1119             if (bytes_needed >= MAX_ENV_STRING)
1120               postDtEnvironmentString = XtMalloc(bytes_needed);
1121             else
1122               postDtEnvironmentString = postDtEnvironmentStringBuf;
1123
1124             if (useMultiColorIcons)
1125               sprintf(postDtEnvironmentString, pm_bm_fmt, sNext, sNext, sNext);
1126             else
1127               sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1128
1129             _postDtEnvironment.pmPath = 
1130               _AddToPath(_postDtEnvironment.pmPath, postDtEnvironmentString);
1131
1132             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1133             {
1134                 if (postDtEnvironmentString) XtFree(postDtEnvironmentString);
1135                 postDtEnvironmentString = NULL;
1136             }
1137
1138             /* get next directory */
1139             sNext = _XStrtok(NULL, ":", strtok_buf);
1140         }
1141
1142         XtFree (sBackDirs);
1143     }
1144     else
1145     {
1146         /* 
1147          * Save the old path if not previously saved
1148          */
1149         if (!_preDtEnvironment.pmPath)
1150         {
1151             bytes_needed = strlen(PM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1152             _preDtEnvironment.pmPath = XtMalloc(bytes_needed);
1153             sprintf(_preDtEnvironment.pmPath,"%s=%s", PM_PATH_ENVIRON, sOldEnv);
1154         }
1155
1156         /* make a copy that we can modify locally */
1157         sBackDirs = strdup(backdropPath);
1158         strcpy (sBackDirs, backdropPath);
1159
1160         /*
1161          * Initialize path environment string
1162          */
1163         bytes_needed = strlen(PM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1164         _postDtEnvironment.pmPath = XtMalloc(bytes_needed);
1165         sprintf(_postDtEnvironment.pmPath, "%s=%s",  PM_PATH_ENVIRON, sOldEnv);
1166
1167         /* get first directory */
1168         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1169
1170         /* process each directory individually */
1171         while (sNext != NULL)
1172         {
1173             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1174             if (bytes_needed >= MAX_ENV_STRING)
1175               postDtEnvironmentString = XtMalloc(bytes_needed);
1176             else
1177               postDtEnvironmentString = postDtEnvironmentStringBuf;
1178
1179             if (useMultiColorIcons)
1180               sprintf(postDtEnvironmentString, pm_bm_fmt, sNext, sNext, sNext);
1181             else
1182               sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1183
1184             _postDtEnvironment.pmPath = 
1185               _AddToPath(_postDtEnvironment.pmPath, postDtEnvironmentString);
1186
1187             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1188             {
1189                 XtFree(postDtEnvironmentString);
1190                 postDtEnvironmentString = NULL;
1191             }
1192
1193             /* get next directory */
1194             sNext = _XStrtok(NULL, ":", strtok_buf);
1195         }
1196
1197         XtFree (sBackDirs);
1198     }
1199
1200     putenv(strdup(_postDtEnvironment.pmPath));
1201     envBitVector |= BV_PMPATH;
1202
1203
1204     /*
1205      * Now do the same thing for the bitmap lookup path
1206      */
1207     sOldEnv = getenv(BM_PATH_ENVIRON);
1208     if (!sOldEnv)
1209     {
1210         /* 
1211          * The user has no existing value for this
1212          * environment variable.  Don't save it.
1213          * Just create the new DT environment.
1214          */
1215
1216         /* make a copy that we can modify locally */
1217         sBackDirs = strdup(backdropPath);
1218         strcpy (sBackDirs, backdropPath);
1219
1220         /*
1221          * Initialize path string
1222          */
1223         _postDtEnvironment.bmPath = makeDefaultIconBmPath();
1224
1225         /* get first directory */
1226         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1227
1228         /* process each directory individually */
1229         while (sNext != NULL)
1230         {
1231             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1232             if (bytes_needed >= MAX_ENV_STRING)
1233               postDtEnvironmentString = XtMalloc(bytes_needed);
1234             else
1235               postDtEnvironmentString = postDtEnvironmentStringBuf;
1236
1237             sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1238
1239             _postDtEnvironment.bmPath = 
1240               _AddToPath(_postDtEnvironment.bmPath, postDtEnvironmentString);
1241
1242             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1243             {
1244                 if (postDtEnvironmentString) XtFree(postDtEnvironmentString);
1245                 postDtEnvironmentString = NULL;
1246             }
1247
1248             /* get next directory */
1249             sNext = _XStrtok(NULL, ":", strtok_buf);
1250         }
1251
1252         XtFree (sBackDirs);
1253     }
1254     else
1255     {
1256         /* 
1257          * Save the old path if not previously saved
1258          */
1259         if (!_preDtEnvironment.bmPath)
1260         {
1261             bytes_needed = strlen(BM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1262             _preDtEnvironment.pmPath = XtMalloc(bytes_needed);
1263             sprintf(_preDtEnvironment.pmPath,"%s=%s", BM_PATH_ENVIRON, sOldEnv);
1264         }
1265
1266         /* make a copy that we can modify locally */
1267         sBackDirs = strdup(backdropPath);
1268         strcpy (sBackDirs, backdropPath);
1269
1270         /*
1271          * Initialize path environment string
1272          */
1273         bytes_needed = strlen(BM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1274         _postDtEnvironment.bmPath = XtMalloc(bytes_needed);
1275         sprintf(_postDtEnvironment.bmPath, "%s=%s",  BM_PATH_ENVIRON, sOldEnv);
1276
1277         /* get first directory */
1278         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1279
1280         /* process each directory individually */
1281         while (sNext != NULL)
1282         {
1283             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1284             if (bytes_needed >= MAX_ENV_STRING)
1285               postDtEnvironmentString = XtMalloc(bytes_needed);
1286             else
1287               postDtEnvironmentString = postDtEnvironmentStringBuf;
1288
1289             sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1290
1291             _postDtEnvironment.bmPath = 
1292               _AddToPath(_postDtEnvironment.bmPath, postDtEnvironmentString);
1293
1294             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1295             {
1296                 XtFree(postDtEnvironmentString);
1297                 postDtEnvironmentString = NULL;
1298             }
1299
1300             /* get next directory */
1301             sNext = _XStrtok(NULL, ":", strtok_buf);
1302         }
1303
1304         XtFree (sBackDirs);
1305     }
1306
1307     putenv(strdup(_postDtEnvironment.bmPath));
1308     envBitVector |= BV_BMPATH;
1309
1310     _DtSvcProcessUnlock();
1311     returnValue = DT_ENV_SET;
1312     return (returnValue);
1313
1314 } /* END OF FUNCTION _DtWsmSetBackdropSearchPath */
1315
1316 /*********************         eof   *************************/