xref: /onnv-gate/usr/src/cmd/sgs/crle/common/util.c (revision 9131:d7741cc87056)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*9131SRod.Evans@Sun.COM  * Common Development and Distribution License (the "License").
6*9131SRod.Evans@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*9131SRod.Evans@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * Utility functions
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate #include <libintl.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <dlfcn.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <alloca.h>
350Sstevel@tonic-gate #include "sgs.h"
360Sstevel@tonic-gate #include "rtc.h"
370Sstevel@tonic-gate #include "_crle.h"
380Sstevel@tonic-gate #include "msg.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * Add an environment string.  A list of environment variable descriptors is
420Sstevel@tonic-gate  * maintained so that duplicate definitions can be caught, the first one wins.
430Sstevel@tonic-gate  */
440Sstevel@tonic-gate int
addenv(Crle_desc * crle,const char * arg,unsigned int flags)450Sstevel@tonic-gate addenv(Crle_desc *crle, const char *arg, unsigned int flags)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	Env_desc	*env;
480Sstevel@tonic-gate 	char		*str;
490Sstevel@tonic-gate 	size_t		varsz, totsz = strlen(arg) + 1;
500Sstevel@tonic-gate 
510Sstevel@tonic-gate 	/*
520Sstevel@tonic-gate 	 * Determine "=" location so as to separated the variable name from
530Sstevel@tonic-gate 	 * its value.
540Sstevel@tonic-gate 	 */
550Sstevel@tonic-gate 	if ((str = strchr(arg, '=')) != NULL) {
56*9131SRod.Evans@Sun.COM 		Aliste	idx;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 		varsz = (size_t)(str - arg);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 		/*
610Sstevel@tonic-gate 		 * Traverse any existing environment variables to see if we've
620Sstevel@tonic-gate 		 * caught a duplicate.
630Sstevel@tonic-gate 		 */
64*9131SRod.Evans@Sun.COM 		for (APLIST_TRAVERSE(crle->c_env, idx, env)) {
650Sstevel@tonic-gate 			if ((env->e_varsz == varsz) &&
660Sstevel@tonic-gate 			    (strncmp(env->e_str, arg, varsz) == 0)) {
670Sstevel@tonic-gate 				/*
680Sstevel@tonic-gate 				 * If the user has already specified this string
690Sstevel@tonic-gate 				 * given them a warning, and ignore the new one.
700Sstevel@tonic-gate 				 */
710Sstevel@tonic-gate 				if ((env->e_flags & RTC_ENV_CONFIG) == 0) {
720Sstevel@tonic-gate 					(void) fprintf(stderr,
730Sstevel@tonic-gate 					    MSG_INTL(MSG_WARN_ENV),
740Sstevel@tonic-gate 					    crle->c_name, (int)varsz,
750Sstevel@tonic-gate 					    env->e_str);
760Sstevel@tonic-gate 					return (2);
770Sstevel@tonic-gate 				}
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 				/*
800Sstevel@tonic-gate 				 * Otherwise the original string must have been
810Sstevel@tonic-gate 				 * retrieved from a config file.  In this case
820Sstevel@tonic-gate 				 * allow the user to override it.
830Sstevel@tonic-gate 				 */
840Sstevel@tonic-gate 				free((void *)env->e_str);
850Sstevel@tonic-gate 				crle->c_strsize -= env->e_totsz;
860Sstevel@tonic-gate 				crle->c_strsize += totsz;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 				if ((env->e_str = strdup(arg)) == 0) {
890Sstevel@tonic-gate 					int err = errno;
900Sstevel@tonic-gate 					(void) fprintf(stderr,
910Sstevel@tonic-gate 					    MSG_INTL(MSG_SYS_MALLOC),
920Sstevel@tonic-gate 					    crle->c_name, strerror(err));
930Sstevel@tonic-gate 					return (0);
940Sstevel@tonic-gate 				}
950Sstevel@tonic-gate 				env->e_varsz = varsz;
960Sstevel@tonic-gate 				env->e_totsz = totsz;
970Sstevel@tonic-gate 				env->e_flags &= ~RTC_ENV_CONFIG;
980Sstevel@tonic-gate 				env->e_flags |= flags;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 				return (1);
1010Sstevel@tonic-gate 			}
1020Sstevel@tonic-gate 		}
1030Sstevel@tonic-gate 	} else {
104*9131SRod.Evans@Sun.COM 		Aliste	idx;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 		/*
1070Sstevel@tonic-gate 		 * Although this is just a plain environment definition (no "=")
1080Sstevel@tonic-gate 		 * and probably has no effect on ld.so.1 anyway, we might as
1090Sstevel@tonic-gate 		 * well make sure we're not duplicating the same string.
1100Sstevel@tonic-gate 		 */
111*9131SRod.Evans@Sun.COM 		for (APLIST_TRAVERSE(crle->c_env, idx, env)) {
1120Sstevel@tonic-gate 			if (env->e_varsz)
1130Sstevel@tonic-gate 				continue;
1140Sstevel@tonic-gate 			if (strcmp(env->e_str, arg) == 0) {
1150Sstevel@tonic-gate 				if ((env->e_flags & RTC_ENV_CONFIG) == 0) {
1160Sstevel@tonic-gate 					(void) fprintf(stderr,
1170Sstevel@tonic-gate 					    MSG_INTL(MSG_WARN_ENV),
1180Sstevel@tonic-gate 					    crle->c_name, (int)totsz,
1190Sstevel@tonic-gate 					    env->e_str);
1200Sstevel@tonic-gate 					return (2);
1210Sstevel@tonic-gate 				}
1220Sstevel@tonic-gate 				env->e_flags &= ~RTC_ENV_CONFIG;
1230Sstevel@tonic-gate 				env->e_flags |= flags;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 				return (1);
1260Sstevel@tonic-gate 			}
1270Sstevel@tonic-gate 		}
1280Sstevel@tonic-gate 		varsz = 0;
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	/*
1320Sstevel@tonic-gate 	 * Allocate a new environment descriptor.
1330Sstevel@tonic-gate 	 */
1340Sstevel@tonic-gate 	if (((env = malloc(sizeof (Env_desc))) == 0) ||
1350Sstevel@tonic-gate 	    ((env->e_str = strdup(arg)) == 0)) {
1360Sstevel@tonic-gate 		int err = errno;
1370Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
1380Sstevel@tonic-gate 		    crle->c_name, strerror(err));
1390Sstevel@tonic-gate 		return (0);
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 	env->e_varsz = varsz;
1420Sstevel@tonic-gate 	env->e_totsz = totsz;
1430Sstevel@tonic-gate 	env->e_flags = flags;
1440Sstevel@tonic-gate 
145*9131SRod.Evans@Sun.COM 	if (aplist_append(&(crle->c_env), env, AL_CNT_CRLE) == NULL)
1460Sstevel@tonic-gate 		return (0);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	/*
1490Sstevel@tonic-gate 	 * Update the number of environment variables found, and the string
1500Sstevel@tonic-gate 	 * table requirement.
1510Sstevel@tonic-gate 	 */
1520Sstevel@tonic-gate 	crle->c_envnum++;
1530Sstevel@tonic-gate 	crle->c_strsize += totsz;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	return (1);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate /*
1590Sstevel@tonic-gate  * Add a library path.  Multiple library paths are concatenated together into a
1600Sstevel@tonic-gate  * colon separated string suitable for runtime processing.  These colon
1610Sstevel@tonic-gate  * separated strings can also be passed in as arguments to addlib(), e.g.,
1620Sstevel@tonic-gate  * -l /usr/lib:/usr/local/lib.  This is enabled to make update easier.
1630Sstevel@tonic-gate  */
1640Sstevel@tonic-gate int
addlib(Crle_desc * crle,char ** lib,const char * args)1650Sstevel@tonic-gate addlib(Crle_desc *crle, char **lib, const char *args)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 	char		*str, *arg;
1680Sstevel@tonic-gate 	char		*lasts;
1690Sstevel@tonic-gate 	size_t		tlen = strlen(args) + 1;
1700Sstevel@tonic-gate 	const char	*colon = MSG_ORIG(MSG_STR_COLON);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	/*
1730Sstevel@tonic-gate 	 * Parse the argument for any ":" separated elements.
1740Sstevel@tonic-gate 	 */
1750Sstevel@tonic-gate 	str = alloca(tlen);
1760Sstevel@tonic-gate 	(void) strcpy(str, args);
1770Sstevel@tonic-gate 	arg = str;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	if ((arg = strtok_r(arg, colon, &lasts)) != NULL) {
1800Sstevel@tonic-gate 		do {
1810Sstevel@tonic-gate 			size_t	llen, alen = strlen(arg);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 			if (*lib) {
1840Sstevel@tonic-gate 				/*
1850Sstevel@tonic-gate 				 * Determine whether this argument exists in the
1860Sstevel@tonic-gate 				 * existing string buffer.
1870Sstevel@tonic-gate 				 */
1880Sstevel@tonic-gate 				if (((str = strstr(*lib, arg)) != NULL) &&
1890Sstevel@tonic-gate 				    (((str == *lib) ||
1900Sstevel@tonic-gate 				    (*(str - 1) == *colon)) &&
1910Sstevel@tonic-gate 				    (str += alen) &&
1920Sstevel@tonic-gate 				    ((*str == '\0') || (*str == *colon))))
1930Sstevel@tonic-gate 					continue;
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 				llen = strlen(*lib);
1960Sstevel@tonic-gate 				tlen = llen + 1;
1970Sstevel@tonic-gate 			} else {
1980Sstevel@tonic-gate 				/*
1990Sstevel@tonic-gate 				 * This is the first argument to be added.
2000Sstevel@tonic-gate 				 */
2010Sstevel@tonic-gate 				llen = 0;
2020Sstevel@tonic-gate 				tlen = 0;
2030Sstevel@tonic-gate 			}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 			/*
2060Sstevel@tonic-gate 			 * This is a new string, so add it to the buffer.  If
2070Sstevel@tonic-gate 			 * this is the first occurrence of a string the size is
2080Sstevel@tonic-gate 			 * simply the size of the string + a trailing null.
2090Sstevel@tonic-gate 			 * Otherwise the size is the old string + ":" + the
2100Sstevel@tonic-gate 			 * size of the new string + a trailing null.
2110Sstevel@tonic-gate 			 */
2120Sstevel@tonic-gate 			alen += 1;
2130Sstevel@tonic-gate 			tlen += alen;
2140Sstevel@tonic-gate 			if ((str = realloc((void *)*lib, tlen)) == 0) {
2150Sstevel@tonic-gate 				int err = errno;
2160Sstevel@tonic-gate 				(void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
2170Sstevel@tonic-gate 				    crle->c_name, strerror(err));
2180Sstevel@tonic-gate 				return (1);
2190Sstevel@tonic-gate 			}
2200Sstevel@tonic-gate 			if (llen == 0)
2210Sstevel@tonic-gate 				(void) strcpy(str, arg);
2220Sstevel@tonic-gate 			else {
2230Sstevel@tonic-gate 				/* LINTED */
2240Sstevel@tonic-gate 				(void) sprintf(&str[llen],
2250Sstevel@tonic-gate 				    MSG_ORIG(MSG_FMT_COLON), arg);
2260Sstevel@tonic-gate 			}
2270Sstevel@tonic-gate 			*lib = str;
2280Sstevel@tonic-gate 			crle->c_strsize += alen;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 		} while ((arg = strtok_r(NULL, colon, &lasts)) != NULL);
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	return (0);
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * -f option expansion.  Interpret its argument as a numeric or symbolic
2390Sstevel@tonic-gate  * representation of the dldump(3dl) flags.
2400Sstevel@tonic-gate  */
2410Sstevel@tonic-gate int
dlflags(Crle_desc * crle,const char * arg)2420Sstevel@tonic-gate dlflags(Crle_desc *crle, const char *arg)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	int		_flags;
2450Sstevel@tonic-gate 	char		*tok, *_arg;
2460Sstevel@tonic-gate 	char		*lasts;
2470Sstevel@tonic-gate 	const char	*separate = MSG_ORIG(MSG_MOD_SEPARATE);
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	/*
2500Sstevel@tonic-gate 	 * Scan the argument looking for allowable tokens.  First determine if
2510Sstevel@tonic-gate 	 * the string is numeric, otherwise try and parse any known flags.
2520Sstevel@tonic-gate 	 */
2530Sstevel@tonic-gate 	if ((_flags = (int)strtol(arg, (char **)NULL, 0)) != 0)
2540Sstevel@tonic-gate 		return (_flags);
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	if ((_arg = malloc(strlen(arg) + 1)) == 0)
2570Sstevel@tonic-gate 		return (0);
2580Sstevel@tonic-gate 	(void) strcpy(_arg, arg);
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if ((tok = strtok_r(_arg, separate, &lasts)) != NULL) {
261*9131SRod.Evans@Sun.COM 		/* BEGIN CSTYLED */
2620Sstevel@tonic-gate 		do {
2630Sstevel@tonic-gate 		    if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_RELATIVE)) == 0)
2640Sstevel@tonic-gate 			_flags |= RTLD_REL_RELATIVE;
2650Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_EXEC)) == 0)
2660Sstevel@tonic-gate 			_flags |= RTLD_REL_EXEC;
2670Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_DEPENDS)) == 0)
2680Sstevel@tonic-gate 			_flags |= RTLD_REL_DEPENDS;
2690Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_PRELOAD)) == 0)
2700Sstevel@tonic-gate 			_flags |= RTLD_REL_PRELOAD;
2710Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_SELF)) == 0)
2720Sstevel@tonic-gate 			_flags |= RTLD_REL_SELF;
2730Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_WEAK)) == 0)
2740Sstevel@tonic-gate 			_flags |= RTLD_REL_WEAK;
2750Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_ALL)) == 0)
2760Sstevel@tonic-gate 			_flags |= RTLD_REL_ALL;
2770Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_MEMORY)) == 0)
2780Sstevel@tonic-gate 			_flags |= RTLD_MEMORY;
2790Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_STRIP)) == 0)
2800Sstevel@tonic-gate 			_flags |= RTLD_STRIP;
2810Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_NOHEAP)) == 0)
2820Sstevel@tonic-gate 			_flags |= RTLD_NOHEAP;
2830Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_CONFGEN)) == 0)
2840Sstevel@tonic-gate 			_flags |= RTLD_CONFGEN;
2850Sstevel@tonic-gate 		    else {
2860Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_ARG_FLAGS),
2870Sstevel@tonic-gate 			    crle->c_name, tok);
2880Sstevel@tonic-gate 			free(_arg);
2890Sstevel@tonic-gate 			return (0);
2900Sstevel@tonic-gate 		    }
2910Sstevel@tonic-gate 		} while ((tok = strtok_r(NULL, separate, &lasts)) != NULL);
292*9131SRod.Evans@Sun.COM 		/* END CSTYLED */
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 	if (_flags == 0)
2950Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_ARG_FLAGS),
2960Sstevel@tonic-gate 		    crle->c_name, arg);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	free(_arg);
2990Sstevel@tonic-gate 	return (_flags);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate  * Internationalization interface for sgsmsg(1l) use.
3040Sstevel@tonic-gate  */
3050Sstevel@tonic-gate const char *
_crle_msg(Msg mid)3060Sstevel@tonic-gate _crle_msg(Msg mid)
3070Sstevel@tonic-gate {
3080Sstevel@tonic-gate 	return (gettext(MSG_ORIG(mid)));
3090Sstevel@tonic-gate }
310