cdesktopenv/cde/programs/dtimsstart/env.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;
}