Build with debug symbols enabled.
[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 librararies 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 publically 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()
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()
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()
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 #else
428                         if (ptr = strstr(tempString, "/usr/bin/X11"))
429 #endif
430                         {
431                              /* 
432                               * Shorten the string in tempString
433                               * to the initial segment, up to the 
434                               * initial slash in "/usr/bin/X11"
435                               */
436                              if (ptr != tempString)
437                              {
438                                 /* 
439                                  * then put our dt string just ahead of 
440                                  * "/usr/bin/X11" in the new PATH 
441                                  */
442                                  *(ptr - 1) = NULL; 
443                                  sprintf(_postDtEnvironment.binPath,
444                                    "%s=%s:%s:%s",
445                                     BIN_PATH_ENVIRON,
446                                     tempString,
447                                     BIN_PATH_STRING,
448                                     ptr);
449                              }
450                              else
451                              {
452                                 /*
453                                  *  Turns out that "/usr/bin/X11"
454                                  *  is at the front of the PATH, so...
455                                  */
456                                 sprintf(_postDtEnvironment.binPath,
457                                     "%s=%s:%s",
458                                     BIN_PATH_ENVIRON,
459                                     BIN_PATH_STRING,
460                                     tempString);
461                             }
462
463                         }
464                         else if (ptr = strstr(tempString, "/usr/bin"))
465                         {
466                              /* 
467                               * Shorten the string in tempString
468                               * to the initial segment, up to the 
469                               * initial slash in "/usr/bin"
470                               */
471                              if (ptr != tempString)
472                              {
473                                 /* 
474                                  * then put our dt string just ahead of 
475                                  * "/usr/bin" in the new PATH 
476                                  */
477
478                                  *(ptr - 1) = NULL; 
479                                  sprintf(_postDtEnvironment.binPath,
480                                    "%s=%s:%s:%s",
481                                     BIN_PATH_ENVIRON,
482                                     tempString,
483                                     BIN_PATH_STRING,
484                                     ptr);
485                              }
486                              else
487                              {
488                                 /*
489                                  *  Turns out that "/usr/bin"
490                                  *  is at the front of the PATH, so...
491                                  */
492                                 sprintf(_postDtEnvironment.binPath,
493                                     "%s=%s:%s",
494                                     BIN_PATH_ENVIRON,
495                                     BIN_PATH_STRING,
496                                     tempString);
497                             }
498                         }
499                         else
500                         {
501                             /* 
502                              * Put our dt string on the front of the PATH 
503                              */
504                             sprintf(_postDtEnvironment.binPath,
505                                 "%s=%s:%s",
506                                 BIN_PATH_ENVIRON,
507                                 BIN_PATH_STRING,
508                                 tempString);
509                         }
510                     }
511
512                     _EnvAdd (BIN_PATH_ENVIRON, 
513                                _postDtEnvironment.binPath, 
514                                BV_BINPATH);
515                 }
516
517
518                 tempString = getenv(PM_PATH_ENVIRON);
519                 if (tempString)
520                 {
521                     bytes_needed =
522                       strlen(PM_PATH_ENVIRON) + strlen(tempString) + 2;
523
524                     _preDtEnvironment.pmPath = XtMalloc(bytes_needed);
525                     sprintf(_preDtEnvironment.pmPath,
526                         "%s=%s",
527                         PM_PATH_ENVIRON,
528                         tempString);
529                 }
530                 else
531                 {
532                     /* it doesn't exist, so generate a default value */
533                     _postDtEnvironment.pmPath = makeDefaultIconPmPath();
534                     _EnvAdd(PM_PATH_ENVIRON, _postDtEnvironment.pmPath,
535                         BV_PMPATH);
536                 }
537
538
539                 tempString = getenv(BM_PATH_ENVIRON);
540                 if (tempString)
541                 {
542                     bytes_needed =
543                       strlen(BM_PATH_ENVIRON) + strlen(tempString) + 2;
544
545                     _preDtEnvironment.bmPath = XtMalloc(bytes_needed);
546                     sprintf(_preDtEnvironment.bmPath,
547                         "%s=%s",
548                         BM_PATH_ENVIRON,
549                         tempString);
550                 }
551                 else
552                 {
553                     /* it doesn't exist, so generate a default value */
554                     _postDtEnvironment.bmPath = makeDefaultIconBmPath();
555                     _EnvAdd(BM_PATH_ENVIRON, _postDtEnvironment.bmPath,
556                         BV_BMPATH);
557                 }
558
559
560                 /* Do the admin for the NLSPATH env variable */
561                 tempString = getenv(NLS_PATH_ENVIRON);
562                 if (!tempString)
563                 {
564                     /* If it doesn't exist, set it to the CDE default */
565                     bytes_needed =
566                       strlen(NLS_PATH_ENVIRON) + strlen(NLS_PATH_STRING) + 2;
567
568                     _postDtEnvironment.nlsPath = XtMalloc(bytes_needed);
569                     sprintf(_postDtEnvironment.nlsPath,
570                         "%s=%s",
571                         NLS_PATH_ENVIRON,
572                         NLS_PATH_STRING);
573                 }
574                 else
575                 {
576                     /* If it does exist, store it away so it can be
577                      * restored afterwards.....
578                      */
579                     bytes_needed =
580                       strlen(NLS_PATH_ENVIRON) + strlen(tempString) + 2;
581
582                     _preDtEnvironment.nlsPath = XtMalloc(bytes_needed);
583                     sprintf(_preDtEnvironment.nlsPath,
584                         "%s=%s",
585                         NLS_PATH_ENVIRON,
586                         tempString);
587
588                     /* ... then append the CDE default to the existing
589                      * value
590                      */
591                     bytes_needed =
592                         strlen(NLS_PATH_ENVIRON) +
593                         strlen(tempString) +
594                         strlen(NLS_PATH_STRING) + 3;
595
596                     _postDtEnvironment.nlsPath = XtMalloc(bytes_needed);
597                     sprintf(_postDtEnvironment.nlsPath,
598                         "%s=%s:%s",
599                         NLS_PATH_ENVIRON,
600                         tempString,
601                         NLS_PATH_STRING);
602                 }
603
604                 _EnvAdd(NLS_PATH_ENVIRON, _postDtEnvironment.nlsPath,
605                            BV_NLSPATH);
606
607
608                 tempString = getenv(SYSTEM_APPL_PATH_ENVIRON);
609                 if (!tempString)
610                 {
611                     bytes_needed =
612                         strlen(SYSTEM_APPL_PATH_ENVIRON) +
613                         strlen(SYSTEM_APPL_PATH_STRING) + 2;
614
615                     _postDtEnvironment.sysApplPath = XtMalloc(bytes_needed);
616                     sprintf(_postDtEnvironment.sysApplPath,
617                         "%s=%s",
618                         SYSTEM_APPL_PATH_ENVIRON,
619                         SYSTEM_APPL_PATH_STRING);
620                 }
621                 else
622                 {
623                     bytes_needed =
624                       strlen(SYSTEM_APPL_PATH_ENVIRON) + strlen(tempString) + 2;
625
626                     _preDtEnvironment.sysApplPath = XtMalloc(bytes_needed);
627                     sprintf(_preDtEnvironment.sysApplPath,
628                         "%s=%s",
629                         SYSTEM_APPL_PATH_ENVIRON,
630                         tempString);
631
632                     bytes_needed =
633                         strlen(SYSTEM_APPL_PATH_ENVIRON) +
634                         strlen(tempString) +
635                         strlen(SYSTEM_APPL_PATH_STRING) + 3;
636
637                     _postDtEnvironment.sysApplPath = XtMalloc(bytes_needed);
638                     sprintf(_postDtEnvironment.sysApplPath,
639                         "%s=%s:%s",
640                         SYSTEM_APPL_PATH_ENVIRON,
641                         tempString,
642                         SYSTEM_APPL_PATH_STRING);
643                 }
644
645                 _EnvAdd (SYSTEM_APPL_PATH_ENVIRON,
646                            _postDtEnvironment.sysApplPath,
647                            BV_SYSAPPLPATH);
648
649                 environSetup = 1;
650                 returnValue = DT_ENV_SET;
651             }
652             else /* we've already been here -- do nothing */
653             {
654                 returnValue = DT_ENV_NO_OP;
655             }
656             break;
657
658         case  DT_ENV_RESTORE_PRE_DT:
659             if (environSetup) 
660             {
661                 if (_preDtEnvironment.nlsPath) {
662                     _EnvAdd (NLS_PATH_ENVIRON, 
663                                _preDtEnvironment.nlsPath,
664                                BV_NLSPATH);
665                 }
666                 else {
667                     _DtEnvRemove(NLS_PATH_ENVIRON, 0);
668                     envBitVector &= ~BV_NLSPATH;
669                 }
670
671                 if (_preDtEnvironment.sysApplPath) {
672                     _EnvAdd (SYSTEM_APPL_PATH_ENVIRON, 
673                                _preDtEnvironment.sysApplPath,
674                                BV_SYSAPPLPATH);
675                 }
676                 else {
677                     _DtEnvRemove(SYSTEM_APPL_PATH_ENVIRON, 0);
678                     envBitVector &= ~BV_SYSAPPLPATH;
679                 }
680
681                 if (_preDtEnvironment.pmPath) {
682                     _EnvAdd (PM_PATH_ENVIRON,
683                                _preDtEnvironment.pmPath,
684                                BV_PMPATH);
685                 }
686                 else {
687                     _DtEnvRemove(PM_PATH_ENVIRON, 0);
688                     envBitVector &= ~BV_PMPATH;
689                 }
690
691                 if (_preDtEnvironment.bmPath) {
692                     _EnvAdd (BM_PATH_ENVIRON,
693                                _preDtEnvironment.bmPath,
694                                BV_BMPATH);
695                 }
696                 else {
697                     _DtEnvRemove(BM_PATH_ENVIRON, 0);
698                     envBitVector &= ~BV_BMPATH;
699                 }
700
701                 returnValue = DT_ENV_RESTORE_PRE_DT;
702             }
703             else
704             {
705                 returnValue = DT_ENV_NO_OP;
706             }
707             break;
708
709         case DT_ENV_RESTORE_POST_DT:
710             if (environSetup) 
711             {
712
713                 if (_postDtEnvironment.nlsPath) {
714                     _EnvAdd (NLS_PATH_ENVIRON, 
715                                _postDtEnvironment.nlsPath,
716                                BV_NLSPATH);
717                 }
718
719                 if (_postDtEnvironment.pmPath) {
720                     _EnvAdd (PM_PATH_ENVIRON,
721                                _postDtEnvironment.pmPath,
722                                BV_PMPATH);
723                 }
724
725                 if (_postDtEnvironment.bmPath) {
726                     _EnvAdd (BM_PATH_ENVIRON,
727                                _postDtEnvironment.bmPath,
728                                BV_BMPATH);
729                 }
730
731                 if (_postDtEnvironment.sysApplPath) {
732                     _EnvAdd (SYSTEM_APPL_PATH_ENVIRON, 
733                                _postDtEnvironment.sysApplPath,
734                                BV_SYSAPPLPATH);
735                 }
736
737                 returnValue = DT_ENV_RESTORE_POST_DT;
738             }
739             else
740             {
741                 returnValue = DT_ENV_NO_OP;
742             }
743             break;
744
745         default:
746             /* do nothing */
747             break;
748     }
749
750     _DtSvcProcessUnlock();
751
752 #ifdef DEBUG
753         switch (mode) {
754         case DT_ENV_SET:
755                 printf("DT environment set:\n");
756                 printf("-------------------------------\n");
757                 break;
758
759         case DT_ENV_RESTORE_PRE_DT:
760                 printf("Pre-DT environment restored:\n");
761                 printf("-------------------------------\n");
762                 break;
763
764         case DT_ENV_RESTORE_POST_DT:
765                 printf("Post-DT environment restored:\n");
766                 printf("-------------------------------\n");
767                 break;
768
769         case DT_ENV_NO_OP:
770                 printf("No change from last invocation:\n");
771                 printf("-------------------------------\n");
772                 break;
773         }
774
775         tempString = getenv(BIN_PATH_ENVIRON);
776         printf("%s=|%s|\n", BIN_PATH_ENVIRON, tempString);
777         tempString = getenv(SYSTEM_APPL_PATH_ENVIRON);
778         printf("%s=|%s|\n", SYSTEM_APPL_PATH_ENVIRON, tempString);
779         tempString = getenv(NLS_PATH_ENVIRON);
780         printf("%s=|%s|\n", NLS_PATH_ENVIRON, tempString);
781         tempString = getenv(PM_PATH_ENVIRON);
782         printf("%s=|%s|\n", PM_PATH_ENVIRON, tempString);
783         tempString = getenv(BM_PATH_ENVIRON); 
784         printf("%s=|%s|\n", BM_PATH_ENVIRON, tempString);
785
786 #endif /* DEBUG */
787         return (returnValue);
788
789 } /* END OF FUNCTION _DtEnvControl */
790
791 /*****************************<->*************************************
792  *
793  *  _EnvAdd(char * str)
794  *
795  *
796  *  Description:
797  *  -----------
798  *  Adds the given string to the application's environment
799  *  If the existing environment variable string was allocated
800  *  by this application, the space is freed.
801  *
802  *  Inputs:
803  *  ------
804  *  envVar          The environment variable. E.g. NLSPATH
805  *  envVarSetting   The environment variable setting. 
806  *                  E.g. NLSPATH=/usr/lib/nls
807  *  bv_flag         The constant denoting which environment variable
808  *                  is being set.
809  * 
810  *****************************<->***********************************/
811 static void _EnvAdd
812   (
813    char * envVar,
814    char * envVarSetting,
815    unsigned int bv_flag
816   )
817 {
818   _DtSvcProcessLock();
819   if (envBitVector & bv_flag) {
820       register int i;
821       size_t envVarLen = strlen(envVar);
822       char *envPtr = NULL;
823
824     /* if we have previously put this environment variable out to the
825      * environment, we can retrieve it and reuse it rather than letting
826      * it disappear into the ether
827      */
828
829     for ( i = 0; environ[i] ; i++ )
830     {
831         if ( environ[i][0] == envVar[0]
832              && ( strlen(environ[i]) >= envVarLen )
833              && ( environ[i][envVarLen] == '=' ) 
834              && !strncmp(envVar,environ[i],envVarLen))
835         {
836                 envPtr = environ[i];
837                 break;
838         }
839     }
840     
841     if ( envPtr )
842     {
843             XtFree(envPtr);
844             envPtr = strdup(envVarSetting);
845             strcpy(envPtr,envVarSetting);
846             environ[i] = envPtr;
847     }
848     else
849     {
850             /* This should never happen */
851             putenv(strdup(envVarSetting));
852     }
853   }
854   else
855     putenv(strdup(envVarSetting));
856
857   envBitVector |= bv_flag;
858   _DtSvcProcessUnlock();
859 }
860
861 /*****************************<->*************************************
862  *
863  *  _DtEnvRemove(
864  *      char *str,
865  *      int length )
866  *
867  *
868  *  Description:
869  *  -----------
870  *  Removes the given string from the application's environment
871  *  Uses the char **extern environment string array.
872  *
873  *  Inputs:
874  *  ------
875  *  str         - the name of the variable to remove (e.g., "NLSPATH")
876  *  length      - the length of the variable--we compute it dynamically.
877  *
878  *  Returns:
879  *  --------
880  *  Returns a success code--"0" if the variable is found and removed.
881  *                          "1" if the variable isn't found.
882  * 
883  *****************************<->***********************************/
884 int
885 _DtEnvRemove(
886         char *str,
887         int length )
888 {
889         char **pEnviron, **pEnviron2 = environ;
890         char *p, *freeMe;
891         int temp;
892                          
893         int count  = 0;  /* count is the number of items in the */
894                          /* environ                             */
895         int index;   /* index will range from 0 to count - 1 */
896         size_t len;
897
898         if (!(len = strlen(str)))
899                 return(1);
900
901         pEnviron = pEnviron2;
902
903         p = *pEnviron;
904
905         while (p)
906         {
907                 pEnviron++;
908                 count++;
909                 p = *pEnviron;
910         }
911
912         pEnviron = pEnviron2;
913         p = *pEnviron;
914
915         for  (index = 0; index < count; index++)
916         {
917                 if (  p[0] == str[0] 
918                       && ( strlen(p) >= len )
919                       && ( p[len] == '=' )
920                       && !strncmp(p, str, len))
921                 {
922                     freeMe = pEnviron2[index];
923
924                     /* just move the last one into the gap - any
925                      * putenv destroyed the initial lexical ordering
926                      * anyway
927                      */
928
929                     pEnviron2[index] = pEnviron2[count - 1];
930                     pEnviron2[count - 1] = NULL;
931
932                     XtFree (freeMe);
933                     return(0);
934                 }
935                 pEnviron++;
936                 p = *pEnviron;
937         }
938         return(1);
939 }
940
941 #if 0
942 int
943 _EnvPrint( void )
944 {
945         char **p, *q;
946
947         p = (char **)(environ);
948
949         q = *p;
950
951         while (q)
952         {
953                 printf("%s\n", q);
954                 p++;
955                 q = *p;
956         }
957         return 0;
958 }
959 #endif
960
961 \f
962 /*************************************<->*************************************
963  *
964  *  _AddToPath (sPath, sDir)
965  *
966  *
967  *  Description:
968  *  -----------
969  *  Append a directory to a directory path. 
970  *
971  *  Inputs:
972  *  ------
973  *  sPath       - the old path (must be a pointer to malloc'ed memory)
974  *  sDir        - the directory to add to the path
975  *
976  *
977  *  Returns:
978  *  --------
979  *  A pointer to the new path if successful.
980  *  NULL on memory allocation failures.
981  *
982  *  Comment:
983  *  --------
984  *  This functions adds sDir to the path of directories already in
985  *  sPath. Each directory is separated by a colon (':'). The function
986  *  is designed to work off the heap. sPath should be a pointer into
987  *  the heap on entry, or NULL. If sPath is NULL, then new memory is
988  *  allocated and returned. If sPath is not NULL, the storage for sPath
989  *  is reallocated to include space for the new string. In this case,
990  *  the pointer returned may point to a different value than sPath
991  *  that was passed in. If the pointer returned is different than sPath,
992  *  then sPath is invalid and should be reassigned.
993  *
994  *************************************<->***********************************/
995 static char *
996 _AddToPath (
997         char * sPath,
998         char * sDir)
999 {
1000     char * sNew;
1001
1002     if (sPath != NULL)
1003     {
1004         sNew = XtRealloc (sPath, 1+strlen(sPath)+1+strlen(sDir));
1005     }
1006     else
1007     {
1008         sNew = XtMalloc (1+strlen(sPath)+1+strlen(sDir));
1009     }
1010
1011     strcat (sNew, ":");
1012     strcat (sNew, sDir);
1013
1014     return (sNew);
1015 }
1016
1017 \f
1018 /*************************************<->*************************************
1019  *
1020  *  _DtWsmSetBackdropSearchPath(screen, backdropPath, useMultiColorIcons)
1021  *
1022  *
1023  *  Description:
1024  *  -----------
1025  *  Append the specified directories to DTICONSEARCHPATH environment 
1026  *  variable.  This must be done before any icon lookup by XmGetPixmap.
1027  *  Each directory in backdropPath is modified so the backdrop file
1028  *  names can be matched (%B, %M, etc.).
1029  *
1030  *  _DtEnvControl( DT_ENV_RESTORE_PRE_DT ) will restore the original
1031  *  environment.
1032  *
1033  *  Inputs:
1034  *  ------
1035  *  screen              - screen of display 
1036  *  backdropPath        - a colon-separated list of directories
1037  *  useMultiColorIcons  - True if color backdrops are desired.
1038  *
1039  *  Returns:
1040  *  --------
1041  *  Returns a success code:   success: DT_ENV_SET
1042  *                            failure: DT_ENV_NO_OP
1043  *
1044  *************************************<->***********************************/
1045 int
1046 _DtWsmSetBackdropSearchPath (
1047         Screen  *screen,
1048         char    *backdropPath,
1049         Boolean  useMultiColorIcons)
1050
1051 {
1052     char *sBackDirs;
1053     char *sOldEnv;
1054     char *sNext;
1055     char *bm_pm_fmt = "%s/%%B.bm:%s/%%B.pm:%s/%%B";  
1056     char *pm_bm_fmt = "%s/%%B.pm:%s/%%B.bm:%s/%%B";  
1057     int fmtlen = strlen(pm_bm_fmt);
1058     int returnValue = DT_ENV_NO_OP;
1059     int bytes_needed;
1060     _Xstrtokparams strtok_buf;
1061
1062     /* for creating the name=value string */
1063     char postDtEnvironmentStringBuf[MAX_ENV_STRING]; 
1064     char *postDtEnvironmentString;
1065
1066     if (backdropPath == NULL) return (returnValue);
1067
1068     sOldEnv = getenv(PM_PATH_ENVIRON);
1069
1070     DtNlInitialize();
1071
1072     _DtSvcProcessLock();
1073     if (!sOldEnv)
1074     {
1075         /* 
1076          * The user has no existing value for this
1077          * environment variable.  Don't save it.
1078          * Just create the new DT environment.
1079          */
1080
1081         /* make a copy that we can modify locally */
1082         sBackDirs = strdup(backdropPath);
1083         strcpy (sBackDirs, backdropPath);
1084
1085         /*
1086          * Initialize path string
1087          */
1088         if (useMultiColorIcons)
1089           _postDtEnvironment.pmPath = makeDefaultIconPmPath();
1090         else
1091           _postDtEnvironment.pmPath = makeDefaultIconBmPath();
1092
1093         /* get first directory */
1094         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1095
1096         /* process each directory individually */
1097         while (sNext != NULL)
1098         {
1099             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1100             if (bytes_needed >= MAX_ENV_STRING)
1101               postDtEnvironmentString = XtMalloc(bytes_needed);
1102             else
1103               postDtEnvironmentString = postDtEnvironmentStringBuf;
1104
1105             if (useMultiColorIcons)
1106               sprintf(postDtEnvironmentString, pm_bm_fmt, sNext, sNext, sNext);
1107             else
1108               sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1109
1110             _postDtEnvironment.pmPath = 
1111               _AddToPath(_postDtEnvironment.pmPath, postDtEnvironmentString);
1112
1113             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1114             {
1115                 if (postDtEnvironmentString) XtFree(postDtEnvironmentString);
1116                 postDtEnvironmentString = NULL;
1117             }
1118
1119             /* get next directory */
1120             sNext = _XStrtok(NULL, ":", strtok_buf);
1121         }
1122
1123         XtFree (sBackDirs);
1124     }
1125     else
1126     {
1127         /* 
1128          * Save the old path if not previously saved
1129          */
1130         if (!_preDtEnvironment.pmPath)
1131         {
1132             bytes_needed = strlen(PM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1133             _preDtEnvironment.pmPath = XtMalloc(bytes_needed);
1134             sprintf(_preDtEnvironment.pmPath,"%s=%s", PM_PATH_ENVIRON, sOldEnv);
1135         }
1136
1137         /* make a copy that we can modify locally */
1138         sBackDirs = strdup(backdropPath);
1139         strcpy (sBackDirs, backdropPath);
1140
1141         /*
1142          * Initialize path environment string
1143          */
1144         bytes_needed = strlen(PM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1145         _postDtEnvironment.pmPath = XtMalloc(bytes_needed);
1146         sprintf(_postDtEnvironment.pmPath, "%s=%s",  PM_PATH_ENVIRON, sOldEnv);
1147
1148         /* get first directory */
1149         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1150
1151         /* process each directory individually */
1152         while (sNext != NULL)
1153         {
1154             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1155             if (bytes_needed >= MAX_ENV_STRING)
1156               postDtEnvironmentString = XtMalloc(bytes_needed);
1157             else
1158               postDtEnvironmentString = postDtEnvironmentStringBuf;
1159
1160             if (useMultiColorIcons)
1161               sprintf(postDtEnvironmentString, pm_bm_fmt, sNext, sNext, sNext);
1162             else
1163               sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1164
1165             _postDtEnvironment.pmPath = 
1166               _AddToPath(_postDtEnvironment.pmPath, postDtEnvironmentString);
1167
1168             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1169             {
1170                 if (postDtEnvironmentString) XtFree(postDtEnvironmentString);
1171                 postDtEnvironmentString = NULL;
1172             }
1173
1174             /* get next directory */
1175             sNext = _XStrtok(NULL, ":", strtok_buf);
1176         }
1177
1178         XtFree (sBackDirs);
1179     }
1180
1181     putenv(strdup(_postDtEnvironment.pmPath));
1182     envBitVector |= BV_PMPATH;
1183
1184
1185     /*
1186      * Now do the same thing for the bitmap lookup path
1187      */
1188     sOldEnv = getenv(BM_PATH_ENVIRON);
1189     if (!sOldEnv)
1190     {
1191         /* 
1192          * The user has no existing value for this
1193          * environment variable.  Don't save it.
1194          * Just create the new DT environment.
1195          */
1196
1197         /* make a copy that we can modify locally */
1198         sBackDirs = strdup(backdropPath);
1199         strcpy (sBackDirs, backdropPath);
1200
1201         /*
1202          * Initialize path string
1203          */
1204         _postDtEnvironment.bmPath = makeDefaultIconBmPath();
1205
1206         /* get first directory */
1207         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1208
1209         /* process each directory individually */
1210         while (sNext != NULL)
1211         {
1212             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1213             if (bytes_needed >= MAX_ENV_STRING)
1214               postDtEnvironmentString = XtMalloc(bytes_needed);
1215             else
1216               postDtEnvironmentString = postDtEnvironmentStringBuf;
1217
1218             sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1219
1220             _postDtEnvironment.bmPath = 
1221               _AddToPath(_postDtEnvironment.bmPath, postDtEnvironmentString);
1222
1223             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1224             {
1225                 if (postDtEnvironmentString) XtFree(postDtEnvironmentString);
1226                 postDtEnvironmentString = NULL;
1227             }
1228
1229             /* get next directory */
1230             sNext = _XStrtok(NULL, ":", strtok_buf);
1231         }
1232
1233         XtFree (sBackDirs);
1234     }
1235     else
1236     {
1237         /* 
1238          * Save the old path if not previously saved
1239          */
1240         if (!_preDtEnvironment.bmPath)
1241         {
1242             bytes_needed = strlen(BM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1243             _preDtEnvironment.pmPath = XtMalloc(bytes_needed);
1244             sprintf(_preDtEnvironment.pmPath,"%s=%s", BM_PATH_ENVIRON, sOldEnv);
1245         }
1246
1247         /* make a copy that we can modify locally */
1248         sBackDirs = strdup(backdropPath);
1249         strcpy (sBackDirs, backdropPath);
1250
1251         /*
1252          * Initialize path environment string
1253          */
1254         bytes_needed = strlen(BM_PATH_ENVIRON) + strlen(sOldEnv) + 2;
1255         _postDtEnvironment.bmPath = XtMalloc(bytes_needed);
1256         sprintf(_postDtEnvironment.bmPath, "%s=%s",  BM_PATH_ENVIRON, sOldEnv);
1257
1258         /* get first directory */
1259         sNext = _XStrtok(sBackDirs, ":", strtok_buf);
1260
1261         /* process each directory individually */
1262         while (sNext != NULL)
1263         {
1264             bytes_needed = (3 * (strlen(sNext) + fmtlen));
1265             if (bytes_needed >= MAX_ENV_STRING)
1266               postDtEnvironmentString = XtMalloc(bytes_needed);
1267             else
1268               postDtEnvironmentString = postDtEnvironmentStringBuf;
1269
1270             sprintf(postDtEnvironmentString, bm_pm_fmt, sNext, sNext, sNext);
1271
1272             _postDtEnvironment.bmPath = 
1273               _AddToPath(_postDtEnvironment.bmPath, postDtEnvironmentString);
1274
1275             if (postDtEnvironmentString != postDtEnvironmentStringBuf)
1276             {
1277                 if (postDtEnvironmentString) XtFree(postDtEnvironmentString);
1278                 postDtEnvironmentString = NULL;
1279             }
1280
1281             /* get next directory */
1282             sNext = _XStrtok(NULL, ":", strtok_buf);
1283         }
1284
1285         XtFree (sBackDirs);
1286     }
1287
1288     putenv(strdup(_postDtEnvironment.bmPath));
1289     envBitVector |= BV_BMPATH;
1290
1291     _DtSvcProcessUnlock();
1292     returnValue = DT_ENV_SET;
1293     return (returnValue);
1294
1295 } /* END OF FUNCTION _DtWsmSetBackdropSearchPath */
1296
1297 /*********************         eof   *************************/