434 lines
10 KiB
C
434 lines
10 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* @(#)$XConsortium: env.c /main/9 1996/10/30 05:57:27 pascale $ */
|
|
|
|
#include <pwd.h>
|
|
#include "xims.h"
|
|
|
|
|
|
int find_CDE_locale_name(void); /* from util.c */
|
|
|
|
typedef enum {
|
|
P_Shell, /* posix shell */
|
|
K_Shell, /* Korn shell */
|
|
C_Shell /* C shell */
|
|
} ShellType;
|
|
|
|
|
|
/* local func */
|
|
static int shell_type(/* shell */);
|
|
|
|
int set_cmd_env(void)
|
|
{
|
|
int ret = NoError;
|
|
char **aliases = (char **)0;
|
|
char *p;
|
|
UserEnv *uenv = &userEnv;
|
|
|
|
if ((ret = get_user_environ()) != NoError)
|
|
return ret;
|
|
|
|
if ((ret = read_cmd_conf()) != NoError)
|
|
return ret;
|
|
|
|
expand_cmd_conf();
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int get_user_environ(void)
|
|
{
|
|
int ret = NoError;
|
|
char buf[BUFSIZ], *p;
|
|
int n;
|
|
UserEnv *uenv = &userEnv;
|
|
|
|
ret = NoError;
|
|
|
|
CLR(&userEnv, UserEnv);
|
|
|
|
if ((p = getenv("LANG")) && *p)
|
|
uenv->locale = NEWSTR(p);
|
|
else
|
|
return ErrNoLocale;
|
|
|
|
/* find the CDE generic locale name */
|
|
if (find_CDE_locale_name() != NoError)
|
|
return ErrNoCDELocale;
|
|
|
|
if ((p = getenv("HOME")) && *p)
|
|
uenv->homedir = NEWSTR(p);
|
|
else {
|
|
if (OpMode != MODE_LIST && OpMode != MODE_REMCONF) {
|
|
#ifdef ALLOW_NOHOME
|
|
p = "/var/tmp";
|
|
uenv->homedir = NEWSTR(p);
|
|
#else
|
|
ret = ErrNoHome;
|
|
#endif /* ALLOW_NOHOME */
|
|
}
|
|
}
|
|
|
|
if ((p = Opt.DisplayName) && *p) {
|
|
strcpy(buf, "DISPLAY=");
|
|
strcat(buf, p);
|
|
putenv(XtNewString(buf));
|
|
} else
|
|
p = getenv("DISPLAY");
|
|
if (p && *p)
|
|
uenv->displayname = NEWSTR(p);
|
|
else {
|
|
if (OpMode == MODE_START /* || OpMode == MODE_CURRENT */
|
|
|| (OpMode == MODE_MODE && (OpFlag & USE_WINDOW_MASK)))
|
|
return ErrNoDisplay;
|
|
}
|
|
|
|
if (p = getenv("XMODIFIERS"))
|
|
uenv->xmodifiers = NEWSTR(p);
|
|
else
|
|
uenv->xmodifiers = NULL;
|
|
|
|
gethostname(buf, BUFSIZ);
|
|
uenv->hostname = NEWSTR(buf);
|
|
|
|
if (!(p = getlogin()))
|
|
{
|
|
struct passwd *pw;
|
|
pw = getpwuid(getuid());
|
|
p = pw->pw_name;
|
|
}
|
|
|
|
uenv->username = NEWSTR(p);
|
|
|
|
n = 0;
|
|
if (p = std_dpy_str(uenv->displayname, &n))
|
|
uenv->displaydir = p;
|
|
else
|
|
uenv->displaydir = NEWSTR(uenv->displayname);
|
|
uenv->screen_num = n;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int expand_string(char *in_str, char *out_str, int out_len, ImsConf *ims)
|
|
{
|
|
char *p, *q, *ep;
|
|
char str[20];
|
|
int len = 0;
|
|
UserEnv *uenv = &userEnv;
|
|
CmdConf *conf = &Conf;
|
|
|
|
p = in_str; q = out_str;
|
|
if (*p == '~' && p[1] == '/') {
|
|
q = strcpyx(q, uenv->homedir);
|
|
*q++ = '/';
|
|
p += 2;
|
|
out_len -= q - out_str;
|
|
}
|
|
while (*p && out_len > 0) {
|
|
ep = NULL;
|
|
if (*p == '%') {
|
|
switch(p[1]) {
|
|
|
|
case 'I': ep = conf->imsConfDir; break;
|
|
case 'R': ep = conf->imsAppDir; break;
|
|
case 'G': ep = conf->imsLogDir; break;
|
|
case 'g': ep = conf->imsLogFile; break;
|
|
case 'b': ep = conf->imsDir; break;
|
|
case 'S': ep = conf->userImsDir; break;
|
|
case 'T': ep = conf->userTmpDir; break;
|
|
case 'A': ep = conf->userAltDir; break;
|
|
case 'C': ep = conf->dt->confDir; break;
|
|
case 'U': ep = conf->dt->userDir; break;
|
|
case 'L': if (ep = uenv->real_locale) break;
|
|
case 'l': ep = uenv->locale; break;
|
|
case 'H': ep = uenv->homedir; break;
|
|
case 'u': ep = uenv->username; break;
|
|
case 'h': ep = uenv->hostname; break;
|
|
case 'D': ep = uenv->displayname; break;
|
|
case 'd': ep = uenv->displaydir; break;
|
|
|
|
case 'N': if (ims && (ep = ims->servername2)) break;
|
|
case 'n': if (ims) ep = ims->servername; break;
|
|
case 'c': if (ims) ep = ims->classname; break;
|
|
case 's': sprintf(str, "%ld", (long) uenv->screen_num);
|
|
if (str[0] != '\0') ep = str;
|
|
break;
|
|
case 'r': ep = userSel.hostname; break;
|
|
|
|
case '%': p++;
|
|
default: DPR2(("expand_string: '%%%c' unknown\n"));
|
|
ep = 0; break;
|
|
}
|
|
if (ep) {
|
|
if ((out_len -= (int) strlen(ep)) <= 0) break;
|
|
q = strcpyx(q, ep);
|
|
p += 2;
|
|
continue;
|
|
}
|
|
}
|
|
if (--out_len <= 0) break;
|
|
*q++ = *p++;
|
|
}
|
|
|
|
*q = 0;
|
|
len = q - out_str;
|
|
|
|
DPR3(("expand_string(\"%s\"):\t\"%s\"\n", in_str, out_str));
|
|
|
|
if (out_len <= 0) {
|
|
DPR(("expand_string(): buffer overflow (len=%d)\n", len));
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
static int shell_type(char *shell)
|
|
{
|
|
char *p;
|
|
int len;
|
|
|
|
if (!shell || !*shell) {
|
|
shell = getenv("SHELL");
|
|
if (!shell || !*shell) return P_Shell;
|
|
}
|
|
|
|
if (strchr(p = shell, '/')) {
|
|
for (len = strlen(p); len > 1 && p[len - 1] == '/'; len--) ;
|
|
shell[len] = 0;
|
|
if (p = strrchr(shell, '/')) shell = p + 1;
|
|
}
|
|
if (strstr(shell, "ksh") != NULL)
|
|
return K_Shell;
|
|
else if (strstr(shell, "csh") != NULL)
|
|
return C_Shell;
|
|
|
|
return P_Shell;
|
|
}
|
|
|
|
|
|
int make_new_environ(OutEnv *oenv, UserSelection *sel)
|
|
{
|
|
ImsConf *ims;
|
|
EnvEnt *ep, *ep2;
|
|
int num, i;
|
|
int proto;
|
|
char *p, **pp;
|
|
char buf[BUFSIZ], *bp;
|
|
char *xmod, *xinput;
|
|
char **setp, **unsetp;
|
|
bool xmod_done, xinput_done;
|
|
RunEnv *renv;
|
|
|
|
/* if (!oenv) return ErrInternal; */
|
|
if (!sel) sel = &userSel;
|
|
|
|
CLR(oenv, OutEnv);
|
|
renv = sel->renv;
|
|
ims = sel->ent->ims;
|
|
xmod = ENV_XMODIFIERS;
|
|
xmod_done = False;
|
|
xinput = NULL;
|
|
xinput_done = True;
|
|
proto = renv ? renv->proto : default_protocol(ims);
|
|
|
|
setp = unsetp = 0;
|
|
if (ims->env_set) setp = parse_strlist(ims->env_set, ' ');
|
|
if (ims->env_unset) unsetp = parse_strlist(ims->env_unset, ' ');
|
|
|
|
/* set: ims->env_set, XMODIFIERS & X?INPUT */
|
|
num = 0;
|
|
if (setp) for (pp = setp; *pp; pp++, num++) ;
|
|
ep = oenv->set = ALLOC(num + 2 + 1, EnvEnt);
|
|
|
|
for (i = 0; i < num && (p = setp[i]); i++)
|
|
if (strcmp(p, xmod) && (!xinput || strcmp(p, xinput))) {
|
|
ep->name = NEWSTR(p);
|
|
ep++;
|
|
}
|
|
if (renv && renv->im_mod) {
|
|
ep->name = NEWSTR(xmod);
|
|
bp = strcpyx(bp = buf, ENV_MOD_IM); /* "@im=" */
|
|
bp = strcpyx(bp, renv->im_mod);
|
|
ep->value = NEWSTR(buf);
|
|
ep++;
|
|
xmod_done = True;
|
|
}
|
|
if (ep == oenv->set) {
|
|
FREE(oenv->set); oenv->set = (EnvEnt *)0;
|
|
} else
|
|
ep->name = NULL;
|
|
|
|
/* unset: XMODIFIERS & X?INPUT, ims->env_unset */
|
|
num = 0;
|
|
if (unsetp) for (pp = unsetp; *pp; pp++, num++) ;
|
|
ep = oenv->unset = ALLOC(num + 2 + 1, EnvEnt);
|
|
|
|
if (!xmod_done) {
|
|
ep->name = NEWSTR(xmod);
|
|
ep++;
|
|
xmod_done = True;
|
|
}
|
|
for (i = 0; i < num && (p = unsetp[i]); i++) {
|
|
if (strcmp(p, xmod) == 0 || (xinput && (strcmp(p, xinput) == 0)))
|
|
continue;
|
|
if (oenv->set) {
|
|
for (ep2 = oenv->set; ep2->name; ep2++)
|
|
if (strcmp(p, ep2->name) == 0) {
|
|
p = NULL;
|
|
break;
|
|
}
|
|
}
|
|
if (p) {
|
|
ep->name = NEWSTR(p);
|
|
ep++;
|
|
}
|
|
}
|
|
if (ep == oenv->unset) {
|
|
FREE(oenv->unset); oenv->unset = (EnvEnt *)0;
|
|
} else
|
|
ep->name = NULL;
|
|
|
|
FREE_LIST(setp);
|
|
FREE_LIST(unsetp);
|
|
FREE(xinput);
|
|
|
|
return NoError;
|
|
}
|
|
|
|
/* print modified environment variables */
|
|
int put_new_environ(OutEnv *oenv)
|
|
{
|
|
EnvEnt *ep;
|
|
char tmpbuf[BUFSIZ], *bp, *vp;
|
|
int typ = shell_type(Opt.ShellName);
|
|
int len;
|
|
|
|
/* if (!oenv) return ErrInternal; */
|
|
#ifdef DEBUG
|
|
if (DebugLvl >= 2)
|
|
pr_OutEnv(oenv);
|
|
#endif
|
|
|
|
if (!oenv->set && !oenv->unset) return NoError;
|
|
tmpbuf[0] = 0;
|
|
|
|
if (typ == C_Shell) { /* C-Shell format */
|
|
bp = strcpyx(tmpbuf, "set noglob;\n");
|
|
if (oenv->set) {
|
|
for (ep = oenv->set; ep->name; ep++) {
|
|
if (!(vp = ep->value) && (vp = strchr(ep->name, '=')))
|
|
*vp++ = '\0';
|
|
sprintf(bp, "setenv %s '%s';\n", ep->name, vp);
|
|
bp += strlen(bp);
|
|
}
|
|
}
|
|
if (oenv->unset) {
|
|
bp = strcpyx(bp, "unsetenv ");
|
|
for (ep = oenv->unset; ep->name; ep++) {
|
|
*bp++= ' ';
|
|
bp = strcpyx(bp, ep->name);
|
|
}
|
|
}
|
|
bp = strcpyx(bp, ";\nunset noglob;\n");
|
|
} else { /* B-Shell format */
|
|
bp = tmpbuf;
|
|
if (oenv->set) {
|
|
for (ep = oenv->set; ep->name; ep++) {
|
|
if (!(vp = ep->value) && (vp = strchr(ep->name, '=')))
|
|
*vp++ = '\0';
|
|
sprintf(bp, "%s='%s';\n", ep->name, vp);
|
|
bp += strlen(bp);
|
|
}
|
|
bp = strcpyx(bp, "export ");
|
|
for (ep = oenv->set; ep->name; ep++) {
|
|
*bp++= ' ';
|
|
bp = strcpyx(bp, ep->name);
|
|
}
|
|
bp = strcpyx(bp, ";\n");
|
|
}
|
|
if (oenv->unset) {
|
|
bp = strcpyx(bp, "unset ");
|
|
for (ep = oenv->unset; ep->name; ep++) {
|
|
*bp++= ' ';
|
|
bp = strcpyx(bp, ep->name);
|
|
}
|
|
bp = strcpyx(bp, ";\n");
|
|
}
|
|
}
|
|
len = bp - tmpbuf;
|
|
|
|
DPR3(("put_new_environ(len=%d):\t%s\n", len, tmpbuf));
|
|
|
|
if (len > 0)
|
|
write(1, tmpbuf, len);
|
|
|
|
return NoError;
|
|
}
|
|
|
|
|
|
int set_remote_env(char *ptr, char *env_pass)
|
|
{
|
|
char *bp = ptr, *ep;
|
|
char **ls, **ls2, **pp, **pp2;
|
|
bool dup_ent;
|
|
|
|
ls = ls2 = 0;
|
|
if (Conf.remote->passEnv
|
|
&& (ls = parse_strlist(Conf.remote->passEnv, ' '))) {
|
|
for (pp = ls; *pp; pp++)
|
|
if (ep = getenv(*pp)) {
|
|
*bp++ = ' '; bp = strcpyx(bp, *pp); *bp++ = '=';
|
|
*bp++ = '"'; bp = strcpyx(bp, ep); *bp++ = '"';
|
|
}
|
|
}
|
|
if (env_pass && (ls2 = parse_strlist(env_pass, ' '))) {
|
|
for (pp2 = ls2; *pp2; pp2++) {
|
|
dup_ent = False;
|
|
if (ls) { /* eliminate duplicate entries */
|
|
for (pp = ls; *pp; pp++)
|
|
if (strcmp(*pp, *pp2) == 0) {
|
|
dup_ent = True;
|
|
break;
|
|
}
|
|
}
|
|
if (!dup_ent && (ep = getenv(*pp2))) {
|
|
*bp++ = ' '; bp = strcpyx(bp, *pp2); *bp++ = '=';
|
|
*bp++ = '"'; bp = strcpyx(bp, ep); *bp++ = '"';
|
|
}
|
|
}
|
|
FREE_LIST(ls2);
|
|
ls2 = 0;
|
|
}
|
|
if (ls) FREE_LIST(ls);
|
|
/* if (bp != ptr) *bp++ = ' '; */
|
|
*bp = 0;
|
|
|
|
DPR2(("set_remote_env('%s' & '%s'):\n\t'%s'\n",
|
|
Conf.remote->passEnv, env_pass, ptr));
|
|
return bp - ptr;
|
|
}
|