/* Author: Wietse Venema */ #include "bsd_locl.h" RCSID("$Id: sysv_environ.c,v 1.23 1997/12/14 23:50:44 assar Exp $"); #ifdef HAVE_ULIMIT_H #include #endif #ifndef UL_SETFSIZE #define UL_SETFSIZE 2 #endif #include "sysv_default.h" /* * Set */ static void read_etc_environment (void) { FILE *f; char buf[BUFSIZ]; f = fopen(_PATH_ETC_ENVIRONMENT, "r"); if (f) { char *val; while (fgets (buf, sizeof(buf), f) != NULL) { if (buf[0] == '\n' || buf[0] == '#') continue; buf[strlen(buf) - 1] = '\0'; val = strchr (buf, '='); if (val == NULL) continue; *val = '\0'; setenv(buf, val + 1, 1); } fclose (f); } } /* * Environment variables that are preserved (but may still be overruled by * other means). Only TERM and TZ appear to survive (SunOS 5.1). These are * typically inherited from the ttymon process. */ static struct preserved { char *name; char *value; } preserved[] = { {"TZ", 0}, {"TERM", 0}, {0}, }; /* * Environment variables that are not preserved and that cannot be specified * via commandline or stdin. Except for the LD_xxx (runtime linker) stuff, * the list applies to most SYSV systems. The manpage mentions only that * SHELL and PATH are censored. HOME, LOGNAME and MAIL are always * overwritten; they are in the list to make the censoring explicit. */ static struct censored { char *prefix; int length; } censored[] = { {"SHELL=", sizeof("SHELL=") - 1}, {"HOME=", sizeof("HOME=") - 1}, {"LOGNAME=", sizeof("LOGNAME=") - 1}, {"MAIL=", sizeof("MAIL=") - 1}, {"CDPATH=", sizeof("CDPATH=") - 1}, {"IFS=", sizeof("IFS=") - 1}, {"PATH=", sizeof("PATH=") - 1}, {"LD_", sizeof("LD_") - 1}, {0}, }; /* sysv_newenv - set up final environment after logging in */ void sysv_newenv(int argc, char **argv, struct passwd *pwd, char *term, int pflag) { unsigned umask_val; char buf[BUFSIZ]; int count = 0; struct censored *cp; struct preserved *pp; /* Preserve a selection of the environment. */ for (pp = preserved; pp->name; pp++) pp->value = getenv(pp->name); /* * Note: it is a bad idea to assign a static array to the global environ * variable. Reason is that putenv() can run into problems when it tries * to realloc() the environment table. Instead, we just clear environ[0] * and let putenv() work things out. */ if (!pflag && environ) environ[0] = 0; /* Restore preserved environment variables. */ for (pp = preserved; pp->name; pp++) if (pp->value) setenv(pp->name, pp->value, 1); /* The TERM definition from e.g. rlogind can override an existing one. */ if (term[0]) setenv("TERM", term, 1); /* * Environment definitions from the command line overrule existing ones, * but can be overruled by definitions from stdin. Some variables are * censored. * * Omission: we do not support environment definitions from stdin. */ #define STREQN(x,y,l) (x[0] == y[0] && strncmp(x,y,l) == 0) while (argc && *argv) { if (strchr(*argv, '=') == 0) { snprintf(buf, sizeof(buf), "L%d", count++); setenv(buf, *argv, 1); } else { for (cp = censored; cp->prefix; cp++) if (STREQN(*argv, cp->prefix, cp->length)) break; if (cp->prefix == 0) putenv(*argv); } argc--, argv++; } /* PATH is always reset. */ setenv("PATH", pwd->pw_uid ? default_path : default_supath, 1); /* Undocumented: HOME, MAIL and LOGNAME are always reset (SunOS 5.1). */ setenv("HOME", pwd->pw_dir, 1); { char *sep = "/"; if(KRB4_MAILDIR[strlen(KRB4_MAILDIR) - 1] == '/') sep = ""; roken_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL); } setenv("MAIL", buf, 1); setenv("LOGNAME", pwd->pw_name, 1); setenv("USER", pwd->pw_name, 1); /* * Variables that may be set according to specifications in the defaults * file. HZ and TZ are set only if they are still uninitialized. * * Extension: when ALTSHELL=YES, we set the SHELL variable even if it is * /bin/sh. */ if (strcasecmp(default_altsh, "YES") == 0) setenv("SHELL", pwd->pw_shell, 1); if (default_hz) setenv("HZ", default_hz, 0); if (default_timezone) setenv("TZ", default_timezone, 0); /* Non-environment stuff. */ if (default_umask) { if (sscanf(default_umask, "%o", &umask_val) == 1 && umask_val) umask(umask_val); } #ifdef HAVE_ULIMIT if (default_ulimit) { long limit_val; if (sscanf(default_ulimit, "%ld", &limit_val) == 1 && limit_val) if (ulimit(UL_SETFSIZE, limit_val) < 0) warn ("ulimit(UL_SETFSIZE, %ld)", limit_val); } #endif read_etc_environment(); }