xref: /onnv-gate/usr/src/cmd/sgs/crle/common/util.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * Utility functions
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate #include <libintl.h>
33*0Sstevel@tonic-gate #include <stdio.h>
34*0Sstevel@tonic-gate #include <dlfcn.h>
35*0Sstevel@tonic-gate #include <string.h>
36*0Sstevel@tonic-gate #include <errno.h>
37*0Sstevel@tonic-gate #include <alloca.h>
38*0Sstevel@tonic-gate #include "sgs.h"
39*0Sstevel@tonic-gate #include "rtc.h"
40*0Sstevel@tonic-gate #include "_crle.h"
41*0Sstevel@tonic-gate #include "msg.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate /*
45*0Sstevel@tonic-gate  * Append an item to the specified list, and return a pointer to the list
46*0Sstevel@tonic-gate  * node created.
47*0Sstevel@tonic-gate  */
48*0Sstevel@tonic-gate Listnode *
49*0Sstevel@tonic-gate list_append(List * lst, const void * item)
50*0Sstevel@tonic-gate {
51*0Sstevel@tonic-gate 	Listnode *	lnp;
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate 	if ((lnp = malloc(sizeof (Listnode))) == (Listnode *)0)
54*0Sstevel@tonic-gate 		return (0);
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	lnp->data = (void *)item;
57*0Sstevel@tonic-gate 	lnp->next = NULL;
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	if (lst->head == NULL)
60*0Sstevel@tonic-gate 		lst->tail = lst->head = lnp;
61*0Sstevel@tonic-gate 	else {
62*0Sstevel@tonic-gate 		lst->tail->next = lnp;
63*0Sstevel@tonic-gate 		lst->tail = lst->tail->next;
64*0Sstevel@tonic-gate 	}
65*0Sstevel@tonic-gate 	return (lnp);
66*0Sstevel@tonic-gate }
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate /*
69*0Sstevel@tonic-gate  * Add an environment string.  A list of environment variable descriptors is
70*0Sstevel@tonic-gate  * maintained so that duplicate definitions can be caught, the first one wins.
71*0Sstevel@tonic-gate  */
72*0Sstevel@tonic-gate int
73*0Sstevel@tonic-gate addenv(Crle_desc *crle, const char *arg, unsigned int flags)
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	Env_desc	*env;
76*0Sstevel@tonic-gate 	char		*str;
77*0Sstevel@tonic-gate 	size_t		varsz, totsz = strlen(arg) + 1;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	/*
80*0Sstevel@tonic-gate 	 * Determine "=" location so as to separated the variable name from
81*0Sstevel@tonic-gate 	 * its value.
82*0Sstevel@tonic-gate 	 */
83*0Sstevel@tonic-gate 	if ((str = strchr(arg, '=')) != NULL) {
84*0Sstevel@tonic-gate 		Listnode *	lnp;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 		varsz = (size_t)(str - arg);
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 		/*
89*0Sstevel@tonic-gate 		 * Traverse any existing environment variables to see if we've
90*0Sstevel@tonic-gate 		 * caught a duplicate.
91*0Sstevel@tonic-gate 		 */
92*0Sstevel@tonic-gate 		for (LIST_TRAVERSE(&(crle->c_env), lnp, env)) {
93*0Sstevel@tonic-gate 			if ((env->e_varsz == varsz) &&
94*0Sstevel@tonic-gate 			    (strncmp(env->e_str, arg, varsz) == 0)) {
95*0Sstevel@tonic-gate 				/*
96*0Sstevel@tonic-gate 				 * If the user has already specified this string
97*0Sstevel@tonic-gate 				 * given them a warning, and ignore the new one.
98*0Sstevel@tonic-gate 				 */
99*0Sstevel@tonic-gate 				if ((env->e_flags & RTC_ENV_CONFIG) == 0) {
100*0Sstevel@tonic-gate 					(void) fprintf(stderr,
101*0Sstevel@tonic-gate 					    MSG_INTL(MSG_WARN_ENV),
102*0Sstevel@tonic-gate 					    crle->c_name, (int)varsz,
103*0Sstevel@tonic-gate 					    env->e_str);
104*0Sstevel@tonic-gate 					return (2);
105*0Sstevel@tonic-gate 				}
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 				/*
108*0Sstevel@tonic-gate 				 * Otherwise the original string must have been
109*0Sstevel@tonic-gate 				 * retrieved from a config file.  In this case
110*0Sstevel@tonic-gate 				 * allow the user to override it.
111*0Sstevel@tonic-gate 				 */
112*0Sstevel@tonic-gate 				free((void *)env->e_str);
113*0Sstevel@tonic-gate 				crle->c_strsize -= env->e_totsz;
114*0Sstevel@tonic-gate 				crle->c_strsize += totsz;
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 				if ((env->e_str = strdup(arg)) == 0) {
117*0Sstevel@tonic-gate 					int err = errno;
118*0Sstevel@tonic-gate 					(void) fprintf(stderr,
119*0Sstevel@tonic-gate 					    MSG_INTL(MSG_SYS_MALLOC),
120*0Sstevel@tonic-gate 					    crle->c_name, strerror(err));
121*0Sstevel@tonic-gate 					return (0);
122*0Sstevel@tonic-gate 				}
123*0Sstevel@tonic-gate 				env->e_varsz = varsz;
124*0Sstevel@tonic-gate 				env->e_totsz = totsz;
125*0Sstevel@tonic-gate 				env->e_flags &= ~RTC_ENV_CONFIG;
126*0Sstevel@tonic-gate 				env->e_flags |= flags;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 				return (1);
129*0Sstevel@tonic-gate 			}
130*0Sstevel@tonic-gate 		}
131*0Sstevel@tonic-gate 	} else {
132*0Sstevel@tonic-gate 		Listnode *	lnp;
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 		/*
135*0Sstevel@tonic-gate 		 * Although this is just a plain environment definition (no "=")
136*0Sstevel@tonic-gate 		 * and probably has no effect on ld.so.1 anyway, we might as
137*0Sstevel@tonic-gate 		 * well make sure we're not duplicating the same string.
138*0Sstevel@tonic-gate 		 */
139*0Sstevel@tonic-gate 		for (LIST_TRAVERSE(&(crle->c_env), lnp, env)) {
140*0Sstevel@tonic-gate 			if (env->e_varsz)
141*0Sstevel@tonic-gate 				continue;
142*0Sstevel@tonic-gate 			if (strcmp(env->e_str, arg) == 0) {
143*0Sstevel@tonic-gate 				if ((env->e_flags & RTC_ENV_CONFIG) == 0) {
144*0Sstevel@tonic-gate 					(void) fprintf(stderr,
145*0Sstevel@tonic-gate 					    MSG_INTL(MSG_WARN_ENV),
146*0Sstevel@tonic-gate 					    crle->c_name, (int)totsz,
147*0Sstevel@tonic-gate 					    env->e_str);
148*0Sstevel@tonic-gate 					return (2);
149*0Sstevel@tonic-gate 				}
150*0Sstevel@tonic-gate 				env->e_flags &= ~RTC_ENV_CONFIG;
151*0Sstevel@tonic-gate 				env->e_flags |= flags;
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 				return (1);
154*0Sstevel@tonic-gate 			}
155*0Sstevel@tonic-gate 		}
156*0Sstevel@tonic-gate 		varsz = 0;
157*0Sstevel@tonic-gate 	}
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 	/*
160*0Sstevel@tonic-gate 	 * Allocate a new environment descriptor.
161*0Sstevel@tonic-gate 	 */
162*0Sstevel@tonic-gate 	if (((env = malloc(sizeof (Env_desc))) == 0) ||
163*0Sstevel@tonic-gate 	    ((env->e_str = strdup(arg)) == 0)) {
164*0Sstevel@tonic-gate 		int err = errno;
165*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
166*0Sstevel@tonic-gate 		    crle->c_name, strerror(err));
167*0Sstevel@tonic-gate 		return (0);
168*0Sstevel@tonic-gate 	}
169*0Sstevel@tonic-gate 	env->e_varsz = varsz;
170*0Sstevel@tonic-gate 	env->e_totsz = totsz;
171*0Sstevel@tonic-gate 	env->e_flags = flags;
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	if (list_append(&(crle->c_env), env) == 0)
174*0Sstevel@tonic-gate 		return (0);
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	/*
177*0Sstevel@tonic-gate 	 * Update the number of environment variables found, and the string
178*0Sstevel@tonic-gate 	 * table requirement.
179*0Sstevel@tonic-gate 	 */
180*0Sstevel@tonic-gate 	crle->c_envnum++;
181*0Sstevel@tonic-gate 	crle->c_strsize += totsz;
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	return (1);
184*0Sstevel@tonic-gate }
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate /*
187*0Sstevel@tonic-gate  * Add a library path.  Multiple library paths are concatenated together into a
188*0Sstevel@tonic-gate  * colon separated string suitable for runtime processing.  These colon
189*0Sstevel@tonic-gate  * separated strings can also be passed in as arguments to addlib(), e.g.,
190*0Sstevel@tonic-gate  * -l /usr/lib:/usr/local/lib.  This is enabled to make update easier.
191*0Sstevel@tonic-gate  */
192*0Sstevel@tonic-gate int
193*0Sstevel@tonic-gate addlib(Crle_desc *crle, char **lib, const char *args)
194*0Sstevel@tonic-gate {
195*0Sstevel@tonic-gate 	char		*str, *arg;
196*0Sstevel@tonic-gate 	char		*lasts;
197*0Sstevel@tonic-gate 	size_t		tlen = strlen(args) + 1;
198*0Sstevel@tonic-gate 	const char	*colon = MSG_ORIG(MSG_STR_COLON);
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	/*
201*0Sstevel@tonic-gate 	 * Parse the argument for any ":" separated elements.
202*0Sstevel@tonic-gate 	 */
203*0Sstevel@tonic-gate 	str = alloca(tlen);
204*0Sstevel@tonic-gate 	(void) strcpy(str, args);
205*0Sstevel@tonic-gate 	arg = str;
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	if ((arg = strtok_r(arg, colon, &lasts)) != NULL) {
208*0Sstevel@tonic-gate 		do {
209*0Sstevel@tonic-gate 			size_t	llen, alen = strlen(arg);
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 			if (*lib) {
212*0Sstevel@tonic-gate 				/*
213*0Sstevel@tonic-gate 				 * Determine whether this argument exists in the
214*0Sstevel@tonic-gate 				 * existing string buffer.
215*0Sstevel@tonic-gate 				 */
216*0Sstevel@tonic-gate 				if (((str = strstr(*lib, arg)) != NULL) &&
217*0Sstevel@tonic-gate 				    (((str == *lib) ||
218*0Sstevel@tonic-gate 				    (*(str - 1) == *colon)) &&
219*0Sstevel@tonic-gate 				    (str += alen) &&
220*0Sstevel@tonic-gate 				    ((*str == '\0') || (*str == *colon))))
221*0Sstevel@tonic-gate 					continue;
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 				llen = strlen(*lib);
224*0Sstevel@tonic-gate 				tlen = llen + 1;
225*0Sstevel@tonic-gate 			} else {
226*0Sstevel@tonic-gate 				/*
227*0Sstevel@tonic-gate 				 * This is the first argument to be added.
228*0Sstevel@tonic-gate 				 */
229*0Sstevel@tonic-gate 				llen = 0;
230*0Sstevel@tonic-gate 				tlen = 0;
231*0Sstevel@tonic-gate 			}
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 			/*
234*0Sstevel@tonic-gate 			 * This is a new string, so add it to the buffer.  If
235*0Sstevel@tonic-gate 			 * this is the first occurrence of a string the size is
236*0Sstevel@tonic-gate 			 * simply the size of the string + a trailing null.
237*0Sstevel@tonic-gate 			 * Otherwise the size is the old string + ":" + the
238*0Sstevel@tonic-gate 			 * size of the new string + a trailing null.
239*0Sstevel@tonic-gate 			 */
240*0Sstevel@tonic-gate 			alen += 1;
241*0Sstevel@tonic-gate 			tlen += alen;
242*0Sstevel@tonic-gate 			if ((str = realloc((void *)*lib, tlen)) == 0) {
243*0Sstevel@tonic-gate 				int err = errno;
244*0Sstevel@tonic-gate 				(void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
245*0Sstevel@tonic-gate 				    crle->c_name, strerror(err));
246*0Sstevel@tonic-gate 				return (1);
247*0Sstevel@tonic-gate 			}
248*0Sstevel@tonic-gate 			if (llen == 0)
249*0Sstevel@tonic-gate 				(void) strcpy(str, arg);
250*0Sstevel@tonic-gate 			else {
251*0Sstevel@tonic-gate 				/* LINTED */
252*0Sstevel@tonic-gate 				(void) sprintf(&str[llen],
253*0Sstevel@tonic-gate 				    MSG_ORIG(MSG_FMT_COLON), arg);
254*0Sstevel@tonic-gate 			}
255*0Sstevel@tonic-gate 			*lib = str;
256*0Sstevel@tonic-gate 			crle->c_strsize += alen;
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 		} while ((arg = strtok_r(NULL, colon, &lasts)) != NULL);
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	return (0);
262*0Sstevel@tonic-gate }
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate /*
266*0Sstevel@tonic-gate  * -f option expansion.  Interpret its argument as a numeric or symbolic
267*0Sstevel@tonic-gate  * representation of the dldump(3dl) flags.
268*0Sstevel@tonic-gate  */
269*0Sstevel@tonic-gate int
270*0Sstevel@tonic-gate dlflags(Crle_desc *crle, const char *arg)
271*0Sstevel@tonic-gate {
272*0Sstevel@tonic-gate 	int		_flags;
273*0Sstevel@tonic-gate 	char		*tok, *_arg;
274*0Sstevel@tonic-gate 	char		*lasts;
275*0Sstevel@tonic-gate 	const char	*separate = MSG_ORIG(MSG_MOD_SEPARATE);
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	/*
278*0Sstevel@tonic-gate 	 * Scan the argument looking for allowable tokens.  First determine if
279*0Sstevel@tonic-gate 	 * the string is numeric, otherwise try and parse any known flags.
280*0Sstevel@tonic-gate 	 */
281*0Sstevel@tonic-gate 	if ((_flags = (int)strtol(arg, (char **)NULL, 0)) != 0)
282*0Sstevel@tonic-gate 		return (_flags);
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	if ((_arg = malloc(strlen(arg) + 1)) == 0)
285*0Sstevel@tonic-gate 		return (0);
286*0Sstevel@tonic-gate 	(void) strcpy(_arg, arg);
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 	if ((tok = strtok_r(_arg, separate, &lasts)) != NULL) {
289*0Sstevel@tonic-gate 		do {
290*0Sstevel@tonic-gate 		    if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_RELATIVE)) == 0)
291*0Sstevel@tonic-gate 			_flags |= RTLD_REL_RELATIVE;
292*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_EXEC)) == 0)
293*0Sstevel@tonic-gate 			_flags |= RTLD_REL_EXEC;
294*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_DEPENDS)) == 0)
295*0Sstevel@tonic-gate 			_flags |= RTLD_REL_DEPENDS;
296*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_PRELOAD)) == 0)
297*0Sstevel@tonic-gate 			_flags |= RTLD_REL_PRELOAD;
298*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_SELF)) == 0)
299*0Sstevel@tonic-gate 			_flags |= RTLD_REL_SELF;
300*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_WEAK)) == 0)
301*0Sstevel@tonic-gate 			_flags |= RTLD_REL_WEAK;
302*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_ALL)) == 0)
303*0Sstevel@tonic-gate 			_flags |= RTLD_REL_ALL;
304*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_MEMORY)) == 0)
305*0Sstevel@tonic-gate 			_flags |= RTLD_MEMORY;
306*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_STRIP)) == 0)
307*0Sstevel@tonic-gate 			_flags |= RTLD_STRIP;
308*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_NOHEAP)) == 0)
309*0Sstevel@tonic-gate 			_flags |= RTLD_NOHEAP;
310*0Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_CONFGEN)) == 0)
311*0Sstevel@tonic-gate 			_flags |= RTLD_CONFGEN;
312*0Sstevel@tonic-gate 		    else {
313*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_ARG_FLAGS),
314*0Sstevel@tonic-gate 			    crle->c_name, tok);
315*0Sstevel@tonic-gate 			free(_arg);
316*0Sstevel@tonic-gate 			return (0);
317*0Sstevel@tonic-gate 		    }
318*0Sstevel@tonic-gate 		} while ((tok = strtok_r(NULL, separate, &lasts)) != NULL);
319*0Sstevel@tonic-gate 	}
320*0Sstevel@tonic-gate 	if (_flags == 0)
321*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_ARG_FLAGS),
322*0Sstevel@tonic-gate 		    crle->c_name, arg);
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate 	free(_arg);
325*0Sstevel@tonic-gate 	return (_flags);
326*0Sstevel@tonic-gate }
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate /*
329*0Sstevel@tonic-gate  * Internationalization interface for sgsmsg(1l) use.
330*0Sstevel@tonic-gate  */
331*0Sstevel@tonic-gate const char *
332*0Sstevel@tonic-gate _crle_msg(Msg mid)
333*0Sstevel@tonic-gate {
334*0Sstevel@tonic-gate 	return (gettext(MSG_ORIG(mid)));
335*0Sstevel@tonic-gate }
336