4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #include <sys/types.h>
38 * This file contains functions for setting the environment for
39 * processes started by svc.startd.
43 #define DEF_PATH "PATH=/usr/sbin:/usr/bin"
45 static char *ENVFILE
= "/etc/default/init"; /* Default env. */
47 static char **glob_envp
; /* Array of environment strings */
48 static int glob_env_n
; /* Number of environment slots allocated. */
50 static char zonename
[ZONENAME_MAX
];
54 * A clone of the work init.c does to provide as much compatibility
55 * for startup scripts as possible.
63 int inquotes
, length
, wslength
;
64 char *tokp
, *cp1
, *cp2
;
68 glob_envp
= startd_alloc(sizeof (*glob_envp
) * glob_env_n
);
70 glob_envp
[0] = startd_alloc((unsigned)(strlen(DEF_PATH
)+2));
71 (void) strcpy(glob_envp
[0], DEF_PATH
);
73 if ((fp
= fopen(ENVFILE
, "r")) == NULL
) {
74 uu_warn("Cannot open %s. Environment not initialized.\n",
83 while (fgets(line
, MAXCMDL
- 1, fp
) != NULL
) {
87 length
= strlen(line
);
88 if (line
[length
- 1] == '\n')
89 line
[length
- 1] = '\0';
92 * Ignore blank or comment lines.
94 if (line
[0] == '#' || line
[0] == '\0' ||
95 (wslength
= strspn(line
, " \t\n")) == strlen(line
) ||
96 strchr(line
, '#') == line
+ wslength
)
100 * First make a pass through the line and change
101 * any non-quoted semi-colons to blanks so they
102 * will be treated as token separators below.
105 for (cp1
= line
; *cp1
!= '\0'; cp1
++) {
111 } else if (*cp1
== ';') {
118 * Tokens within the line are separated by blanks
119 * and tabs. For each token in the line which
120 * contains a '=' we strip out any quotes and then
121 * stick the token in the environment array.
123 if ((tokp
= strtok(line
, " \t")) == NULL
)
127 cp1
= strchr(tokp
, '=');
128 if (cp1
== NULL
|| cp1
== tokp
)
130 length
= strlen(tokp
);
131 while ((cp1
= strpbrk(tokp
, "\"\'")) != NULL
) {
132 for (cp2
= cp1
; cp2
< &tokp
[length
]; cp2
++)
138 * init already started us with this umask, and we
139 * handled it in startd.c, so just skip it.
141 if (strncmp(tokp
, "CMASK=", 6) == 0 ||
142 strncmp(tokp
, "SMF_", 4) == 0)
145 glob_envp
[i
] = startd_alloc((unsigned)(length
+ 1));
146 (void) strcpy(glob_envp
[i
], tokp
);
149 * Double the environment size whenever it is
152 if (++i
== glob_env_n
) {
154 newp
= startd_alloc(sizeof (*glob_envp
) *
156 (void) memcpy(newp
, glob_envp
,
157 sizeof (*glob_envp
) * glob_env_n
/ 2);
158 startd_free(glob_envp
,
159 sizeof (*glob_envp
) * glob_env_n
/ 2);
162 } while ((tokp
= strtok(NULL
, " \t")) != NULL
);
167 /* Append a null pointer to the environment array to mark its end. */
171 * Get the zonename once; it is used to set SMF_ZONENAME for methods.
173 (void) getzonenamebyid(getzoneid(), zonename
, sizeof (zonename
));
178 valid_env_var(const char *var
, const restarter_inst_t
*inst
, const char *path
)
180 char *cp
= strchr(var
, '=');
182 if (cp
== NULL
|| cp
== var
) {
184 log_instance(inst
, B_FALSE
, "Invalid environment "
185 "variable \"%s\".", var
);
187 } else if (strncmp(var
, "SMF_", 4) == 0) {
189 log_instance(inst
, B_FALSE
, "Invalid environment "
190 "variable \"%s\"; \"SMF_\" prefix is reserved.",
193 } else if (path
!= NULL
&& strncmp(var
, "PATH=", 5) == 0) {
201 find_dup(const char *var
, char **env
, const restarter_inst_t
*inst
)
206 for (p
= env
; *p
!= NULL
; p
++) {
207 assert((tmp
= strchr(*p
, '=')) != NULL
);
209 if (strncmp(*p
, var
, tmp
- *p
) == 0)
217 * The first entry in the array can be ignored when it is the
220 if (inst
!= NULL
&& p
!= env
&&
221 strncmp(*p
, DEF_PATH
, strlen(DEF_PATH
)) != 0) {
222 log_instance(inst
, B_FALSE
, "Ignoring duplicate "
223 "environment variable \"%s\".", *p
);
230 * Create an environment which is appropriate for spawning an SMF
231 * aware process. The new environment will consist of the values from
232 * the global environment as modified by the supplied (local) environment.
234 * In order to preserve the correctness of the new environment,
235 * various checks are performed on the local environment (init_env()
236 * is relied upon to ensure the global environment is correct):
238 * - All SMF_ entries are ignored. All SMF_ entries should be provided
240 * - Duplicates in the entry are eliminated.
241 * - Malformed entries are eliminated.
243 * Detected errors are logged as warnings to the appropriate instance
244 * logfile, since a single bad entry should not be enough to prevent
245 * an SMF_ functional environment from being created. The faulty entry
246 * is then ignored when building the environment.
248 * If env is NULL, then the return is an environment which contains
249 * all default values.
251 * If "path" is non-NULL, it will silently over-ride any previous
252 * PATH environment variable.
254 * NB: The returned env and strings are allocated using startd_alloc().
257 set_smf_env(char **env
, size_t env_sz
, const char *path
,
258 const restarter_inst_t
*inst
, const char *method
)
266 * Max. of glob_env, env, four SMF_ variables,
267 * path, and terminating NULL.
269 nenv_size
= glob_env_n
+ env_sz
+ 4 + 1 + 1;
271 nenv
= startd_zalloc(sizeof (char *) * nenv_size
);
276 sz
= strlen(path
) + 1;
277 *np
= startd_alloc(sz
);
278 (void) strlcpy(*np
, path
, sz
);
283 sz
= sizeof ("SMF_FMRI=") + strlen(inst
->ri_i
.i_fmri
);
284 *np
= startd_alloc(sz
);
285 (void) strlcpy(*np
, "SMF_FMRI=", sz
);
286 (void) strlcat(*np
, inst
->ri_i
.i_fmri
, sz
);
291 sz
= sizeof ("SMF_METHOD=") + strlen(method
);
292 *np
= startd_alloc(sz
);
293 (void) strlcpy(*np
, "SMF_METHOD=", sz
);
294 (void) strlcat(*np
, method
, sz
);
298 sz
= sizeof ("SMF_RESTARTER=") + strlen(SCF_SERVICE_STARTD
);
299 *np
= startd_alloc(sz
);
300 (void) strlcpy(*np
, "SMF_RESTARTER=", sz
);
301 (void) strlcat(*np
, SCF_SERVICE_STARTD
, sz
);
304 sz
= sizeof ("SMF_ZONENAME=") + strlen(zonename
);
305 *np
= startd_alloc(sz
);
306 (void) strlcpy(*np
, "SMF_ZONENAME=", sz
);
307 (void) strlcat(*np
, zonename
, sz
);
310 for (p
= glob_envp
; *p
!= NULL
; p
++) {
311 if (valid_env_var(*p
, inst
, path
)) {
313 *np
= startd_alloc(sz
);
314 (void) strlcpy(*np
, *p
, sz
);
320 for (p
= env
; *p
!= NULL
; p
++) {
323 if (!valid_env_var(*p
, inst
, path
))
326 if ((dup_pos
= find_dup(*p
, nenv
, inst
)) != NULL
) {
327 startd_free(*dup_pos
, strlen(*dup_pos
) + 1);
329 *dup_pos
= startd_alloc(sz
);
330 (void) strlcpy(*dup_pos
, *p
, sz
);
333 *np
= startd_alloc(sz
);
334 (void) strlcpy(*np
, *p
, sz
);