2 * Copyright (c) 1989 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4 * Copyright (c) 2001 - 2006, Tomasz Kłoczko
5 * Copyright (c) 2007 - 2009, Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Separated from setup.c. --marekm
39 #ident "$Id: setupenv.c 3034 2009-07-22 13:30:06Z nekral-guest $"
42 #include <sys/types.h>
46 #include "prototypes.h"
53 addenv_path (const char *varname, const char *dirname, const char *filename)
56 size_t len = strlen (dirname) + strlen (filename) + 2;
60 wlen = snprintf (buf, len, "%s/%s", dirname, filename);
61 assert (wlen == (int) len - 1);
63 addenv (varname, buf);
67 static void read_env_file (const char *filename)
71 char *cp, *name, *val;
73 fp = fopen (filename, "r");
77 while (fgets (buf, sizeof buf, fp) == buf) {
78 cp = strrchr (buf, '\n');
85 /* ignore whitespace and comments */
86 while (('\0' != *cp) && isspace (*cp)) {
89 if (('\0' == *cp) || ('#' == *cp)) {
93 * ignore lines which don't follow the name=value format
94 * (for example, the "export NAME" shell commands)
97 while (('\0' != *cp) && !isspace (*cp) && ('=' != *cp)) {
103 /* NUL-terminate the name */
107 #if 0 /* XXX untested, and needs rewrite with fewer goto's :-) */
109 (state, char_type) -> (state, action)
111 state: unquoted, single_quoted, double_quoted, escaped, double_quoted_escaped
112 char_type: normal, white, backslash, single, double
113 action: remove_curr, remove_curr_skip_next, remove_prev, finish XXX
117 /* remove the backslash */
119 /* skip over the next character */
123 } else if (*cp == '\'') {
124 /* remove the quote */
126 /* now within single quotes */
128 } else if (*cp == '"') {
129 /* remove the quote */
131 /* now within double quotes */
133 } else if (*cp == '\0') {
136 } else if (isspace (*cp)) {
137 /* unescaped whitespace - end of string */
146 /* remove the quote */
150 } else if (*cp == '\0') {
154 /* preserve everything within single quotes */
160 /* remove the quote */
164 } else if (*cp == '\\') {
166 /* if backslash followed by double quote, remove backslash
167 else skip over the backslash and following char */
169 remove_char (cp - 1);
174 eise if (*cp == '\0') {
178 /* preserve everything within double quotes */
184 * XXX - should handle quotes, backslash escapes, etc.
185 * like the shell does.
195 * change to the user's home directory
196 * set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
200 void setup_env (struct passwd *info)
208 * Change the current working directory to be the home directory
209 * of the user. It is a fatal error for this process to be unable
210 * to change to that directory. There is no "default" home
213 * We no longer do it as root - should work better on NFS-mounted
214 * home directories. Some systems default to HOME=/, so we make
215 * this a configurable option. --marekm
218 if (chdir (info->pw_dir) == -1) {
219 static char temp_pw_dir[] = "/";
221 if (!getdef_bool ("DEFAULT_HOME") || chdir ("/") == -1) {
222 fprintf (stderr, _("Unable to cd to '%s'\n"),
225 "unable to cd to `%s' for user `%s'\n",
226 info->pw_dir, info->pw_name));
230 (void) puts (_("No directory, logging in with HOME=/"));
231 info->pw_dir = temp_pw_dir;
235 * Create the HOME environmental variable and export it.
238 addenv ("HOME", info->pw_dir);
241 * Create the SHELL environmental variable and export it.
244 if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) {
245 static char temp_pw_shell[] = SHELL;
247 info->pw_shell = temp_pw_shell;
250 addenv ("SHELL", info->pw_shell);
253 * Export the user name. For BSD derived systems, it's "USER", for
254 * all others it's "LOGNAME". We set both of them.
257 addenv ("USER", info->pw_name);
258 addenv ("LOGNAME", info->pw_name);
261 * Create the PATH environmental variable and export it.
264 cp = getdef_str ((info->pw_uid == 0) ? "ENV_SUPATH" : "ENV_PATH");
267 /* not specified, use a minimal default */
268 addenv ("PATH=/bin:/usr/bin", NULL);
269 } else if (strchr (cp, '=')) {
270 /* specified as name=value (PATH=...) */
273 /* only value specified without "PATH=" */
279 * Create the MAIL environmental variable and export it. login.defs
283 if (getdef_bool ("MAIL_CHECK_ENAB")) {
284 cp = getdef_str ("MAIL_DIR");
286 addenv_path ("MAIL", cp, info->pw_name);
288 cp = getdef_str ("MAIL_FILE");
290 addenv_path ("MAIL", info->pw_dir, cp);
292 #if defined(MAIL_SPOOL_FILE)
293 addenv_path ("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
294 #elif defined(MAIL_SPOOL_DIR)
295 addenv_path ("MAIL", MAIL_SPOOL_DIR, info->pw_name);
302 * Read environment from optional config file. --marekm
304 envf = getdef_str ("ENVIRON_FILE");
306 read_env_file (envf);
308 #endif /* !USE_PAM */