Link with C++ linker
[oweals/cde.git] / cde / programs / dtimsstart / 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 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 /* @(#)$XConsortium: env.c /main/9 1996/10/30 05:57:27 pascale $ */
24
25 #include <pwd.h>
26 #include "xims.h"
27
28
29 typedef enum {
30     P_Shell,    /* posix shell */
31     K_Shell,    /* Korn shell */
32     C_Shell     /* C shell */
33 } ShellType;
34
35
36     /* local func */
37 static int      shell_type(/* shell */);
38
39 int     set_cmd_env()
40 {
41     int         ret = NoError;
42     char        **aliases = (char **)0;
43     char        *p;
44     UserEnv     *uenv = &userEnv;
45
46     if ((ret = get_user_environ()) != NoError)
47         return ret;
48
49     if ((ret = read_cmd_conf()) != NoError)
50         return ret;
51
52 # ifdef old_hpux
53     p = get_real_locale(uenv->locale, &aliases);
54     if (p) {
55         uenv->real_locale = NEWSTR(p);
56         uenv->locale_aliases = aliases;
57     }
58 # endif /* old_hpux */
59
60     expand_cmd_conf();
61
62     return ret;
63 }
64
65
66 int     get_user_environ()
67 {
68     int         ret = NoError;
69     char        buf[BUFSIZ], *p;
70     int         n;
71     UserEnv     *uenv = &userEnv;
72
73     ret = NoError;
74
75     CLR(&userEnv, UserEnv);
76
77     if ((p = getenv("LANG")) && *p)
78         uenv->locale = NEWSTR(p);
79     else
80         return ErrNoLocale;
81
82     /* find the CDE generic locale name */
83     if (find_CDE_locale_name() != NoError)
84         return ErrNoCDELocale;
85
86     if ((p = getenv("HOME")) && *p)
87         uenv->homedir = NEWSTR(p);
88     else {
89         if (OpMode != MODE_LIST && OpMode != MODE_REMCONF) {
90 #ifdef  ALLOW_NOHOME
91             p = "/var/tmp";
92             uenv->homedir = NEWSTR(p);
93 #else
94             ret = ErrNoHome;
95 #endif  /* ALLOW_NOHOME */
96         }
97     }
98
99     if ((p = Opt.DisplayName) && *p) {
100         strcpy(buf, "DISPLAY=");
101         strcat(buf, p);
102         putenv(NEWSTR(buf));
103     } else
104         p = getenv("DISPLAY");
105     if (p && *p)
106         uenv->displayname = NEWSTR(p);
107     else {
108         if (OpMode == MODE_START /* || OpMode == MODE_CURRENT */
109             || (OpMode == MODE_MODE && (OpFlag & USE_WINDOW_MASK)))
110             return ErrNoDisplay;
111     }
112
113     if (p = getenv("XMODIFIERS"))
114         uenv->xmodifiers = NEWSTR(p);
115     else
116         uenv->xmodifiers = NULL;
117
118     gethostname(buf, BUFSIZ);
119     uenv->hostname = NEWSTR(buf);
120
121     if (!(p = getlogin()))
122       {
123         struct passwd *pw;
124         pw = getpwuid(getuid());
125         p = pw->pw_name;
126       }
127     
128     uenv->username = NEWSTR(p);
129
130     n = 0;
131     if (p = std_dpy_str(uenv->displayname, &n))
132         uenv->displaydir = p;
133     else
134         uenv->displaydir = NEWSTR(uenv->displayname);
135     uenv->screen_num = n;
136
137     return ret;
138 }
139
140
141 int     expand_string(in_str, out_str, out_len, ims)
142     char        *in_str, *out_str;
143     int         out_len;
144     ImsConf     *ims;
145 {
146     register char       *p, *q, *ep;
147     char        str[20];
148     int         len = 0;
149     UserEnv     *uenv = &userEnv;
150     CmdConf     *conf = &Conf;
151
152     p = in_str; q = out_str;
153     if (*p == '~' && p[1] == '/') {
154         q = strcpyx(q, uenv->homedir);
155         *q++ = '/';
156         p += 2;
157         out_len -= q - out_str;
158     }
159     while (*p && out_len > 0) {
160         ep = NULL;
161         if (*p == '%') {
162             switch(p[1]) {
163
164                 case 'I':       ep = conf->imsConfDir; break;
165                 case 'R':       ep = conf->imsAppDir; break;
166                 case 'G':       ep = conf->imsLogDir; break;
167                 case 'g':       ep = conf->imsLogFile; break;
168                 case 'b':       ep = conf->imsDir; break;
169                 case 'S':       ep = conf->userImsDir; break;
170                 case 'T':       ep = conf->userTmpDir; break;
171                 case 'A':       ep = conf->userAltDir; break;
172                 case 'C':       ep = conf->dt->confDir; break;
173                 case 'U':       ep = conf->dt->userDir; break;
174 # ifdef old_hpux
175                 case 'V':       ep = conf->vue->confDir; break;
176                 case 'X':       ep = conf->vue->userDir; break;
177 # endif /* old_hpux */
178
179                 case 'L':       if (ep = uenv->real_locale)     break;
180                 case 'l':       ep = uenv->locale; break;
181                 case 'H':       ep = uenv->homedir; break;
182                 case 'u':       ep = uenv->username; break;
183                 case 'h':       ep = uenv->hostname; break;
184                 case 'D':       ep = uenv->displayname; break;
185                 case 'd':       ep = uenv->displaydir; break;
186
187                 case 'N':       if (ims && (ep = ims->servername2)) break;
188                 case 'n':       if (ims) ep = ims->servername; break;
189                 case 'c':       if (ims) ep = ims->classname; break;
190                 case 's':       sprintf(str, "%ld", (long) uenv->screen_num); 
191                                 if (str[0] != '\0')  ep = str;
192                                 break;
193                 case 'r':       ep = userSel.hostname; break;
194
195                 case '%':       p++;
196                 default:        DPR2(("expand_string: '%%%c' unknown\n"));
197                                 ep = 0; break;
198             }
199             if (ep) {
200                 if ((out_len -= (int) strlen(ep)) <= 0) break;
201                 q = strcpyx(q, ep);
202                 p += 2;
203                 continue;
204             }
205         }
206         if (--out_len <= 0)     break;
207         *q++ = *p++;
208     }
209
210     *q = 0;
211     len = q - out_str;
212
213     DPR3(("expand_string(\"%s\"):\t\"%s\"\n", in_str, out_str));
214
215     if (out_len <= 0) {
216         DPR(("expand_string(): buffer overflow (len=%d)\n", len));
217     }
218
219     return len;
220 }
221
222
223 static int      shell_type(shell)
224     char        *shell;
225 {
226     char        *p;
227     int         len;
228
229     if (!shell || !*shell) {
230         shell = getenv("SHELL");
231         if (!shell || !*shell)  return P_Shell;
232     }
233
234     if (strchr(p = shell, '/')) {
235         for (len = strlen(p); len > 1 && p[len - 1] == '/'; len--) ;
236         shell[len] = 0;
237         if (p = strrchr(shell, '/'))    shell = p + 1;
238     }
239     if (strstr(shell, "ksh") != NULL)
240         return K_Shell;
241     else if (strstr(shell, "csh") != NULL)
242         return C_Shell;
243
244     return P_Shell;
245 }
246
247
248 int     make_new_environ(oenv, sel)
249     OutEnv      *oenv;
250     UserSelection       *sel;
251 {
252     ImsConf     *ims;
253     EnvEnt      *ep, *ep2;
254     int         num, i;
255     int         proto;
256     char        *p, **pp;
257     char        buf[BUFSIZ], *bp;
258     char        *xmod, *xinput;
259     char        **setp, **unsetp;
260     bool        xmod_done, xinput_done;
261     RunEnv      *renv;
262
263     /* if (!oenv)       return ErrInternal; */
264     if (!sel)   sel = &userSel;
265
266     CLR(oenv, OutEnv);
267     renv = sel->renv;
268     ims = sel->ent->ims;
269     xmod = ENV_XMODIFIERS;
270     xmod_done = False;
271 # ifdef old_hpux
272     xinput = xhp_xinput_name(NULL);
273 # else
274     xinput = NULL;
275 # endif /* old_hpux */
276     xinput_done = (xinput) ? False : True;
277     proto = renv ? renv->proto : default_protocol(ims);
278
279     setp = unsetp = 0;
280     if (ims->env_set)   setp = parse_strlist(ims->env_set, ' ');
281     if (ims->env_unset) unsetp = parse_strlist(ims->env_unset, ' ');
282
283         /* set: ims->env_set, XMODIFIERS & X?INPUT */
284     num = 0;
285     if (setp)   for (pp = setp; *pp; pp++, num++) ;
286     ep = oenv->set = ALLOC(num + 2 + 1, EnvEnt);
287
288     for (i = 0; i < num && (p = setp[i]); i++)
289         if (strcmp(p, xmod) && strcmp(p, xinput)) {
290             ep->name = NEWSTR(p);
291             ep++;
292         }
293     if (renv && renv->im_mod) {
294         ep->name = NEWSTR(xmod);
295         bp = strcpyx(bp = buf, ENV_MOD_IM);     /* "@im=" */
296         bp = strcpyx(bp, renv->im_mod);
297         ep->value = NEWSTR(buf);
298         ep++;
299         xmod_done = True;
300     }
301 # ifdef old_hpux
302     if (!xinput_done && (proto == Proto_Xhp)) {
303 #ifdef  DEBUG
304         if (!ims->servername) {
305             DPR(("make_new_environ(): '%s' servername not defined\n",
306                                                         sel->name));
307         }
308 #endif
309         ep->name = NEWSTR(xinput);
310         ep->value = NEWSTR(ims->servername);
311         ep++;
312         xinput_done = True;
313     }
314 # endif /* old_hpux */
315     if (ep == oenv->set) {
316         FREE(oenv->set); oenv->set = (EnvEnt *)0;
317     } else
318         ep->name = NULL;
319
320         /* unset: XMODIFIERS & X?INPUT, ims->env_unset */
321     num = 0;
322     if (unsetp) for (pp = unsetp; *pp; pp++, num++) ;
323     ep = oenv->unset = ALLOC(num + 2 + 1, EnvEnt);
324
325     if (!xmod_done) {
326         ep->name = NEWSTR(xmod);
327         ep++;
328         xmod_done = True;
329     }
330 # ifdef old_hpux
331     if (!xinput_done) {
332         ep->name = NEWSTR(xinput);
333         ep++;
334         xinput_done = True;
335     }
336 # endif /* old_hpux */
337     for (i = 0; i < num && (p = unsetp[i]); i++) {
338         if (strcmp(p, xmod) == 0 || strcmp(p, xinput) == 0)
339             continue;
340         if (oenv->set) {
341             for (ep2 = oenv->set; ep2->name; ep2++)
342                 if (strcmp(p, ep2->name) == 0) {
343                     p = NULL;
344                     break;
345                 }
346         }
347         if (p) {
348             ep->name = NEWSTR(p);
349             ep++;
350         }
351     }
352     if (ep == oenv->unset) {
353         FREE(oenv->unset); oenv->unset = (EnvEnt *)0;
354     } else
355         ep->name = NULL;
356
357     FREE_LIST(setp);
358     FREE_LIST(unsetp);
359     FREE(xinput);
360
361     return NoError;
362 }
363
364 int     put_new_environ(oenv)   /* print modified environment variables */
365     OutEnv      *oenv;
366 {
367     EnvEnt      *ep;
368     char        tmpbuf[BUFSIZ], *bp, *vp;
369     int         typ = shell_type(Opt.ShellName);
370     int         len;
371
372     /* if (!oenv)                               return ErrInternal; */
373 #ifdef  DEBUG
374     if (DebugLvl >= 2)
375         pr_OutEnv(oenv);
376 #endif
377
378     if (!oenv->set && !oenv->unset)     return NoError;
379     tmpbuf[0] = 0;
380
381     if (typ == C_Shell) {       /* C-Shell format */
382         bp = strcpyx(tmpbuf, "set noglob;\n");
383         if (oenv->set) {
384             for (ep = oenv->set; ep->name; ep++) {
385                 if (!(vp = ep->value) && (vp = strchr(ep->name, '=')))
386                     *vp++ = '\0';
387                 sprintf(bp, "setenv %s '%s';\n", ep->name, vp);
388                 bp += strlen(bp);
389             }
390         }
391         if (oenv->unset) {
392             bp = strcpyx(bp, "unsetenv ");
393             for (ep = oenv->unset; ep->name; ep++) {
394                 *bp++= ' ';
395                 bp = strcpyx(bp, ep->name);
396             }
397         }
398         bp = strcpyx(bp, ";\nunset noglob;\n");
399     } else {                            /* B-Shell format */
400         bp = tmpbuf;
401         if (oenv->set) {
402             for (ep = oenv->set; ep->name; ep++) {
403                 if (!(vp = ep->value) && (vp = strchr(ep->name, '=')))
404                     *vp++ = '\0';
405                 sprintf(bp, "%s='%s';\n", ep->name, vp);
406                 bp += strlen(bp);
407             }
408             bp = strcpyx(bp, "export ");
409             for (ep = oenv->set; ep->name; ep++) {
410                 *bp++= ' ';
411                 bp = strcpyx(bp, ep->name);
412             }
413             bp = strcpyx(bp, ";\n");
414         }
415         if (oenv->unset) {
416             bp = strcpyx(bp, "unset ");
417             for (ep = oenv->unset; ep->name; ep++) {
418                 *bp++= ' ';
419                 bp = strcpyx(bp, ep->name);
420             }
421             bp = strcpyx(bp, ";\n");
422         }
423     }
424     len = bp - tmpbuf;
425
426     DPR3(("put_new_environ(len=%d):\t%s\n", len, tmpbuf));
427
428     if (len > 0)
429         write(1, tmpbuf, len);
430
431     return NoError;
432 }
433
434
435 int     set_remote_env(ptr, env_pass)
436     char        *ptr, *env_pass;
437 {
438     char        *bp = ptr, *ep;
439     char        **ls, **ls2, **pp, **pp2;
440     bool        dup_ent;
441
442     ls = ls2 = 0;
443     if (Conf.remote->passEnv
444                 && (ls = parse_strlist(Conf.remote->passEnv, ' '))) {
445         for (pp = ls; *pp; pp++)
446             if (ep = getenv(*pp)) {
447                 *bp++ = ' '; bp = strcpyx(bp, *pp); *bp++ = '=';
448                 *bp++ = '"'; bp = strcpyx(bp, ep); *bp++ = '"';
449             }
450     }
451     if (env_pass && (ls2 = parse_strlist(env_pass, ' '))) {
452         for (pp2 = ls2; *pp2; pp2++) {
453             dup_ent = False;
454             if (ls) {           /* eliminate duplicate entries */
455                 for (pp = ls; *pp; pp++)
456                     if (strcmp(*pp, *pp2) == 0) {
457                         dup_ent = True;
458                         break;
459                     }
460             }
461             if (!dup_ent && (ep = getenv(*pp2))) {
462                 *bp++ = ' '; bp = strcpyx(bp, *pp2); *bp++ = '=';
463                 *bp++ = '"'; bp = strcpyx(bp, ep); *bp++ = '"';
464             }
465         }
466         FREE_LIST(ls2);
467         ls2 = 0;
468     }
469     if (ls)     FREE_LIST(ls);
470     /* if (bp != ptr)   *bp++ = ' '; */
471     *bp = 0;
472
473     DPR2(("set_remote_env('%s' & '%s'):\n\t'%s'\n",
474                                         Conf.remote->passEnv, env_pass, ptr));
475     return bp - ptr;
476 }
477
478 # ifdef old_hpux
479 char    *xhp_xinput_name(locale)
480     char        *locale;
481 {
482     char        *xinput_name = "X@INPUT";
483     char        **pp, *p;
484     int         i, len;
485     XhpLocale   *xhp = Conf.xhp;
486     char        **ls;
487     char        typ = 0;
488
489     if (!xhp)           return NULL;
490     if (!locale)        locale = userEnv.locale;
491
492     for (i = 0; !typ && i < XHP_LANG_NUM; i++) {
493         if (!(ls = parse_strlist(xhp[i].locales, ' '))) continue;
494         for (pp = ls; *pp; pp++) {
495             if (locale[0] != (*pp)[0])  continue;
496             len = strlen(p = *pp);
497             if ((p[len - 1] == '*' && strncmp(locale, p, len - 1) == 0)
498                 || strcmp(locale, p) == 0) {
499                 typ = xhp[i].type;
500                 break;
501             }
502         }
503         FREE_LIST(ls);
504     }
505     if (!typ) {
506         DPR2(("xhp_xinput_name(%s): unknown locale\n", locale));
507         return NULL;
508     }
509
510     xinput_name[1] = typ;
511     return NEWSTR(xinput_name);
512 }
513
514
515 char    *get_real_locale(locale, aliases)
516     char        *locale, ***aliases;
517 {
518     int         i;
519     int         match_idx = -1;
520     LocaleAlias **alias = Conf.alias, *ap;
521     char        **ls, **pp;
522     char        *real_locale = NULL;
523
524     if (!locale || !alias)      return NULL;
525
526     for (i = 0; match_idx < 0 && (ap = alias[i]); i++) {
527         if (strcmp(ap->name, locale) == 0) {
528             match_idx = i;
529             if (aliases)
530                 ls = parse_strlist(ap->aliases, ' ');
531             break;
532         }
533         if (ls = parse_strlist(ap->aliases, ' ')) {
534             for (pp = ls; *pp; pp++)
535                 if (strcmp(locale, *pp) == 0) {
536                     match_idx = i;
537                     break;
538                 }
539             FREE_LIST(ls);
540             ls = (char **)NULL;
541         }
542     }
543
544     if (match_idx >= 0) {
545         real_locale = alias[match_idx]->name;
546         if (aliases) {
547             *aliases = ls;
548             ls = (char **)NULL;
549         }
550     } else {
551         real_locale = NULL;
552         if (aliases)    *aliases = (char **) NULL;
553     }
554     if (ls)     FREE_LIST(ls);
555
556     DPR(("get_real_locale(%s): real_locale=%s  aliases=%s\n",
557                 locale, real_locale, aliases ? *aliases : NULL));
558
559     return real_locale;
560 }
561
562 # endif /* old_hpux */