Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / spc-env.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  * File:         spc-env.c $TOG: spc-env.c /main/9 1998/04/10 08:27:04 mgreess $
25  * Language:     C
26  *
27  * (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
28  *
29  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
30  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
31  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
32  * (c) Copyright 1993, 1994 Novell, Inc.                                *
33  */
34
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
38
39 #include <SPC/spcP.h>
40
41 #include <bms/MemoryMgr.h> 
42 #include "DtSvcLock.h"
43
44 #include <XlationSvc.h>
45 #include <LocaleXlate.h>
46
47 /* External declarations */
48
49 extern XeString official_hostname;  /* from spc-net.c */
50
51 /*----------------------------------------------------------------------+*/
52 XeString SPC_Getenv(XeString var,
53                     XeString *envp)
54 /*----------------------------------------------------------------------+*/
55 {
56
57   int len;
58   XeString *envidx;
59   XeString idx;
60   
61   /* First, check that we have real values */
62   
63   if(!var || !envp || !*envp)
64     return(XeString_NULL);
65
66   /* Look for '=' */
67
68   idx=strchr(var, Equal);
69   
70   if(idx==0)
71     /* No '='.  Just use the entire var string */
72     len=strlen(var);
73   else
74     /* found '='.  Diddle pointers to get index of var */
75     len=(strchr(var, Equal))-var;
76   
77   for(envidx=envp; *envidx; envidx++) {
78     if(!strncmp(*envidx, var, len))
79       /* Found a match. Return value part */
80       return(*envidx+len+1);
81   }
82
83   return(XeString_NULL);
84
85 }
86
87 /*
88  **
89  ** The purpose of SPC_Putenv is to maintain the environment pointers
90  ** associated with a given channel.  It differs from the normal putenv
91  ** routine in the following ways:
92  **   1. It copies its arguments (and frees any arguments which get a "hit")
93  **   2. It takes an environment pointer which will be used to store the
94  **      new value.  This new pointer may change (via realloc).
95  **
96  ** Note: This routine makes a number of assumptions:
97  **   1. The envp pointer was allocated via malloc.
98  **   2. That it is okay to ignore error conditions.  In particular,
99  **      it will ignore incorrect pointers (which is okay, as this
100  **      guy is an internal routine which means that these pointers
101  **      have been already checked), and it will ignore syntax errors
102  **      in the passed value.  The latter ignore may be slightly
103  **      problematical, but it happens.
104  **   3. That memory allocation errors cause the program to bomb.
105  **
106 */
107
108 /*----------------------------------------------------------------------+*/
109 XeString *SPC_Putenv(XeString val,
110                      XeString *envp)
111 /*----------------------------------------------------------------------+*/
112
113 {
114   int len, newsize;
115   XeString *envptr;
116   char *pch;
117   int remove_command = 0;
118 #ifdef NLS16
119    int          is_multibyte = 0;
120 #endif /* NLS16 */
121
122 #ifdef NLS16
123    if (MB_CUR_MAX > 1)
124       is_multibyte = 1;
125    else
126       is_multibyte = 0;
127 #endif /* NLS16 */
128
129   /* Again, check for real values */
130
131   if(!val || !envp) {
132     return(envp);
133   }
134
135   /* Look for '=' */
136
137   len=(strchr(val, (XeChar)'='))-val;
138   if(len<0) {
139     /* 
140      * This string doesn't contain an '='.  This may be OK if
141      * the string contains a 'remove environment variable' keyword.  
142      * If this keyword is found, treat it like a variable and
143      * the SPC daemon will find it and remove it from the
144      * environment before it exec's a subprocess.
145      *
146      * If the string contains some white space before the variable
147      * or keyword, skip the white space.
148      */
149      pch = val;
150      while (
151 #ifdef NLS16
152             (!is_multibyte || (mblen (pch, MB_CUR_MAX) == 1)) &&
153 #endif
154             isspace ((u_char)*pch))
155               pch++;
156      if (*pch == '\000')
157        return (envp);
158      if (strncmp (pch, SPC_REMOVE_VAR, strlen (SPC_REMOVE_VAR)))
159        return(envp);
160      remove_command = 1;
161      val = pch;
162      len = strlen (SPC_REMOVE_VAR);
163   }
164   
165   for(envptr=envp; *envptr; envptr++) {
166     if(!strncmp(*envptr, val, len) && !remove_command) {
167       /* Found a match. Replace this value with the one passed */
168       free(*envptr);
169       *envptr=SPC_copy_string(val);
170       return(envp);
171     }
172   }
173   
174   /* No match. We need to expand this env pointer, and stash the
175      new value at the end */
176   
177   len=envptr-envp;
178   
179   /* calculate new size needed:
180      len=ptr to null element
181      newsize=len+2 (one for NULL, one for new element)
182      */
183   
184   newsize=(len+2)*sizeof(XeString *);
185   
186   /* Expand envp.  This is a potentially expensive operation, if the
187      realloc routine is not smart. */
188   
189   if(!(envp=(XeString *)realloc((char *)envp, newsize))) {
190     SPC_Error(SPC_Out_Of_Memory);
191     exit(1);
192   }
193   
194   /* Okay.  We got the new memory.  Stash the new variable into it &
195      return the new envp.*/
196   
197   envp[len]=SPC_copy_string(val);
198   envp[len+1]=XeChar_NULL;
199
200   return(envp);
201   
202 }
203
204 /*----------------------------------------------------------------------+*/
205 XeString *SPC_Add_Env_File(XeString filename,
206                            XeString *envp)
207 /*----------------------------------------------------------------------+*/
208 {
209
210   FILE *f;
211   int n;
212   XeChar fbuffer[BUFSIZ];
213
214   if(!filename)
215     return(envp);
216
217   /* Open stream */
218
219   if(!(f=fopen(filename, "r")))
220     return(envp);
221
222   while(fgets(fbuffer, BUFSIZ, f)) {
223     n=strlen(fbuffer);
224     if(fbuffer[n-1]==Newline)
225       fbuffer[--n]=Pad;  /* get rid of the extra newline */
226
227     /* Should we skip this line? */
228
229     if(n==XeChar_NULL || fbuffer[0]==Pad || fbuffer[0]==Pound) continue;
230
231     envp=SPC_Putenv(fbuffer, envp);
232   }
233
234   fclose(f);
235
236   return(envp);
237 }
238   
239 /*----------------------------------------------------------------------+*/
240 XeString *SPC_Create_Default_Envp(XeString *old_envp)
241 /*----------------------------------------------------------------------+*/
242 {
243
244   XeString *envp;
245   XeChar *display;
246   XeString envVar;
247   XeString sys_env_path = NULL;
248   
249   if(old_envp)
250     envp=old_envp;
251   else {
252     envp=(XeString *)XeMalloc(sizeof(XeString) * DEFAULT_ENVP_SIZE);
253     envp[0]=XeChar_NULL;
254   }
255   
256   if(!(envVar=getenv("DISPLAY"))) 
257     {
258     display = (XeChar *)malloc(
259                         (strlen(official_hostname) + 11) * sizeof(XeChar));
260     if (display != (XeChar *)NULL)
261       sprintf(display, "DISPLAY=%s:0", official_hostname);
262     }
263   else
264     {
265     display = (XeChar *)malloc((strlen(envVar) + 9) * sizeof(XeChar));
266     if (display != (XeChar *)NULL)
267       sprintf(display, "DISPLAY=%s", envVar);
268     }
269  
270   if (display != (XeChar *)NULL)
271     { 
272     envp=SPC_Putenv(display, envp);
273     free(display);
274     }
275
276   /*
277    *  Should we pick a default value for LANG (e.g. "C")?
278    *  For now we ignore it if it is not already set.
279    */
280   if ((envVar = getenv("LANG")) != (XeString)NULL)
281   {
282     XeChar *langBuf;
283
284     if ((langBuf = (XeChar *)malloc((strlen(envVar) + 6) * sizeof(XeChar)))
285         != (XeChar *)NULL)
286     {
287       sprintf(langBuf, "LANG=%s", envVar);
288       envp = SPC_Putenv(langBuf, envp);
289
290       free(langBuf);
291     }
292   }
293
294   /* 
295    * First add the installed environment file.
296    */
297   sys_env_path = (XeString) malloc (strlen(SPCD_ENV_INSTALL_DIRECTORY) +
298                                     strlen(SPCD_ENV_FILE) + 3);
299   (void) sprintf (sys_env_path, "%s/%s", 
300                   SPCD_ENV_INSTALL_DIRECTORY,
301                   SPCD_ENV_FILE);
302   envp=SPC_Add_Env_File(sys_env_path, envp);
303
304   /*
305    * Next add the configured environment file.
306    */
307   sys_env_path = (XeString) realloc (sys_env_path,
308                                      strlen(SPCD_ENV_CONFIG_DIRECTORY) +
309                                      strlen(SPCD_ENV_FILE) + 3);
310   (void) sprintf (sys_env_path, "%s/%s", 
311                   SPCD_ENV_CONFIG_DIRECTORY,
312                   SPCD_ENV_FILE);
313   envp=SPC_Add_Env_File(sys_env_path, envp);
314
315   /*
316    * Now add the user environment file
317    */
318   _DtSvcProcessLock();
319   envp=SPC_Add_Env_File(spc_user_environment_file, envp);
320   _DtSvcProcessUnlock();
321
322   free(sys_env_path);
323   
324   return(envp);
325 }
326
327 /* Final cleanup of environment pointer */
328
329 /*----------------------------------------------------------------------+*/
330 XeString *SPC_Fixup_Environment(XeString *envp,
331                                 SPC_Channel_Ptr channel)
332 /*----------------------------------------------------------------------+*/
333 {
334   if(!envp)
335     return(envp);
336
337   if (IS_REMOTE(channel))
338   {
339     XeString disp, myLang;
340
341     disp=SPC_Getenv((XeString)"DISPLAY", envp);
342
343     /* I don't particularly like hard coding these values here.
344        I have been bitten before by doing so, and probably will again... */
345     if (!strncmp(disp, (XeString)"unix", 4) ||
346         !strncmp(disp, (XeString)"local", 5) ||
347         !strncmp(disp, (XeString)":", 1))
348     {
349       XeChar *dispBuf = NULL;
350       XeString screenptr;
351       XeChar null=XeChar_NULL;
352
353       dispBuf =
354         (XeChar*) malloc(MAXHOSTNAMELEN + sizeof((XeString)"DISPLAY=:0.0") + 1);
355       if (dispBuf)
356       {
357           screenptr=strchr(disp, Colon);
358           sprintf(dispBuf, "DISPLAY=%s%s",
359                   official_hostname,
360                   screenptr ? screenptr : &null);
361
362           envp=SPC_Putenv(dispBuf, envp);
363           free(dispBuf);
364       }
365     }
366
367     myLang = SPC_Getenv((XeString)"LANG", envp);
368     if (myLang)
369     {
370       _DtXlateDb db = NULL;
371       char platform[_DtPLATFORM_MAX_LEN];
372       int execVer;
373       int compVer;
374       char *stdLang;
375       XeChar *langBuf;
376
377       if (_DtLcxOpenAllDbs(&db) == 0)
378       {
379         if ((_DtXlateGetXlateEnv(db, platform, &execVer, &compVer) == 0) &&
380             (_DtLcxXlateOpToStd(db, platform, compVer, DtLCX_OPER_SETLOCALE,
381                                 myLang, &stdLang, NULL, NULL, NULL) == 0))
382         {
383           if ((langBuf = (XeChar *)malloc((strlen(stdLang) + 6) *
384                                           sizeof(XeChar)))
385               != (XeChar *)NULL)
386           {
387             sprintf(langBuf, "LANG=%s", stdLang);
388             envp = SPC_Putenv(langBuf, envp);
389             free(langBuf);
390           }
391
392           free(stdLang);
393         }
394
395         _DtLcxCloseDb(&db);
396       }
397     }
398   }
399
400   return(envp);
401 }
402
403 /*----------------------------------------------------------------------+*/
404 XeString *SPC_Merge_Envp(XeString *dest_envp,
405                          XeString *source_envp)
406 /*----------------------------------------------------------------------+*/
407 {
408
409   if(!dest_envp || !source_envp)
410     return(dest_envp);
411   for(; *source_envp; source_envp++)
412     dest_envp=SPC_Putenv(*source_envp, dest_envp);
413   
414   return(dest_envp);
415 }
416
417 /*----------------------------------------------------------------------+*/
418 void SPC_Free_Envp(XeString *envp)
419 /*----------------------------------------------------------------------+*/
420 {
421   XeString *envptr=envp;
422
423   if(!envptr)
424     return;
425   
426   while (*envptr)
427     free(*envptr++);
428
429   free((char *)envp);
430 }