1/*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27/* All Rights Reserved */
28
29
30#include <stdio.h>
31#include <limits.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <string.h>
35#include <fcntl.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <signal.h>
39#include <errno.h>
40#include <assert.h>
41#include <pkgdev.h>
42#include <pkginfo.h>
43#include <pkglocs.h>
44#include <locale.h>
45#include <libintl.h>
46#include <instzones_api.h>
47#include <pkglib.h>
48#include <install.h>
49#include <libinst.h>
50#include <libadm.h>
51#include <messages.h>
52
53static char *localeNames[] = {
54	"LC_CTYPE",
55	"LC_NUMERIC",
56	"LC_TIME",
57	"LC_COLLATE",
58	"LC_MESSAGES",
59	"LC_MONETARY",
60	"LC_ALL",
61	"LANG",
62	"TZ",
63	NULL
64};
65
66#define	NUM_LOCALE_TYPES	100
67
68static char	*envPtr[NUM_LOCALE_TYPES];
69
70/*
71 * extern declarations
72 */
73
74extern char	**environ;
75
76/*
77 * this is the initial and incremental allocation used to
78 * populate the environment "environ"
79 */
80
81#define	MALSIZ	64
82
83void
84putparam(char *param, char *value)
85{
86	char	*pt;
87	int	ptlen;
88	int	i, n;
89
90	/*
91	 * If the environment is NULL, allocate space for the
92	 * character pointers.
93	 */
94	if (environ == NULL) {
95		environ = (char **)calloc(MALSIZ, sizeof (char *));
96		if (environ == NULL) {
97			progerr(gettext(ERR_MEMORY), errno);
98			quit(99);
99		}
100	}
101
102	/*
103	 * If this parameter is already in place and it has a different
104	 * value, clear the old value by freeing the memory previously
105	 * allocated. Otherwise, we leave well-enough alone.
106	 */
107	n = strlen(param);
108	for (i = 0; environ[i]; i++) {
109		if (strncmp(environ[i], param, n) == 0 &&
110		    (environ[i][n] == '=')) {
111			if (strcmp((environ[i]) + n + 1, value) == 0)
112				return;
113			else {
114				free(environ[i]);
115				break;
116			}
117		}
118	}
119
120	/* Allocate space for the new environment entry. */
121	ptlen = (strlen(param)+strlen(value)+2)*(sizeof (char));
122	pt = (char *)calloc(strlen(param)+strlen(value)+2, sizeof (char));
123	if (pt == NULL) {
124		progerr(gettext(ERR_MEMORY), errno);
125		quit(99);
126	}
127
128	/*
129	 * Put the statement into the allocated space and point the
130	 * environment entry at it.
131	 */
132	(void) snprintf(pt, ptlen, "%s=%s", param, value);
133	if (environ[i]) {
134		environ[i] = pt;
135		return;
136	}
137
138	/*
139	 * With this parameter in place, if we're at the end of the
140	 * allocated environment then allocate more space.
141	 */
142	environ[i++] = pt;
143	if ((i % MALSIZ) == 0) {
144		environ = (char **)realloc((void *)environ,
145			(i+MALSIZ)*sizeof (char *));
146		if (environ == NULL) {
147			progerr(gettext(ERR_MEMORY), errno);
148			quit(1);
149		}
150	}
151
152	/* Terminate the environment properly. */
153	environ[i] = (char *)NULL;
154}
155
156/* bugid 4279039 */
157void
158getuserlocale(void)
159{
160	int i;
161
162	for (i = 0; (localeNames[i] != NULL) && (i < NUM_LOCALE_TYPES); i++) {
163		envPtr[i] = getenv(localeNames[i]);
164		if (envPtr[i]) {
165			putparam(localeNames[i], envPtr[i]);
166		}
167	}
168}
169
170/* bugid 4279039 */
171void
172putuserlocale(void)
173{
174	int i;
175
176	for (i = 0; (localeNames[i] != NULL) && (i < NUM_LOCALE_TYPES); i++) {
177		if (envPtr[i]) {
178			putparam(localeNames[i], envPtr[i]);
179		}
180	}
181}
182
183/*
184 * Name:	putConditionInfo
185 * Description:	put parent "condition" information to environment
186 * Arguments:	a_parentZoneName - name of the parent zone
187 *			== NULL - no name
188 *		a_parentZoneType - parent zone "type"
189 *			== NULL - no type
190 * Returns:	void
191 */
192
193void
194putConditionInfo(char *a_parentZoneName, char *a_parentZoneType)
195{
196	char	*p;
197	char	*pa;
198	SML_TAG	*tag = SML_TAG__NULL;
199	SML_TAG	*ntag;
200
201	/* entry debugging info */
202
203	echoDebug(DBG_PUTPARAM_PUTCONDINFO_ENTRY);
204
205	/*
206	 * create tag to hold condition information:
207	 * <environmentConditionInformation>
208	 * <parentZone zoneName=<?> zoneType=<?>/>
209	 * <currentZone zoneName=<?> zoneType=<?>/>
210	 * </environmentConditionInformation>
211	 */
212
213	tag = smlNewTag(TAG_COND_TOPLEVEL);
214
215	/*
216	 * information about pkgadd or pkgrm environment
217	 * <parentZone zoneName=<?> zoneType=<?>/>
218	 */
219
220	/* allocate tag for parent info */
221
222	ntag = smlNewTag(TAG_COND_PARENT_ZONE);
223
224	/* parent zone name */
225
226	smlSetParam(ntag, TAG_COND_ZONE_NAME,
227		a_parentZoneName ? a_parentZoneName : "");
228
229	/* parent zone info */
230
231	smlSetParam(ntag, TAG_COND_ZONE_TYPE,
232		a_parentZoneType ? a_parentZoneType : "");
233
234	/* add to top level tag */
235
236	(void) smlAddTag(&tag, -1, ntag);
237	free(ntag);
238
239	/*
240	 * information about pkginstall or pkgremove environment
241	 * <currentZone zoneName=<?> zoneType=<?>/>
242	 */
243
244	/* allocate tag for parent info */
245
246	ntag = smlNewTag(TAG_COND_CURRENT_ZONE);
247
248	/* current zone name */
249
250	p = z_get_zonename();
251	if ((p != NULL) && (*p != '\0')) {
252		smlSetParam(ntag, TAG_COND_ZONE_NAME, p);
253		free(p);
254	}
255
256	/* current zone type */
257
258	smlSetParam(ntag, TAG_COND_ZONE_TYPE,
259		z_running_in_global_zone() == B_TRUE ?
260			TAG_VALUE_GLOBAL_ZONE : TAG_VALUE_NONGLOBAL_ZONE);
261
262	/* add to top level tag */
263
264	(void) smlAddTag(&tag, -1, ntag);
265	free(ntag);
266
267	/*
268	 * done filling in tag - convert to string and place in environment
269	 */
270
271	p = smlConvertTagToString(tag);
272
273	/* convert all new-line characters to space */
274
275	for (pa = p; *pa != '\0'; pa++) {
276		if (*pa == '\n') {
277			*pa = ' ';
278		}
279	}
280
281	echoDebug(DBG_PUTPARAM_PUTCONDINFO_EXIT, p);
282
283	putparam(PKGCOND_GLOBAL_VARIABLE, p);
284}
285