xref: /illumos-gate/usr/src/cmd/sgs/crle/common/util.c (revision 8285fe28)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
557ef7aa9SRod Evans  * Common Development and Distribution License (the "License").
657ef7aa9SRod Evans  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2257ef7aa9SRod Evans  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Utility functions
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate #include <libintl.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <dlfcn.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <alloca.h>
357c478bd9Sstevel@tonic-gate #include "sgs.h"
367c478bd9Sstevel@tonic-gate #include "rtc.h"
377c478bd9Sstevel@tonic-gate #include "_crle.h"
387c478bd9Sstevel@tonic-gate #include "msg.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * Add an environment string.  A list of environment variable descriptors is
427c478bd9Sstevel@tonic-gate  * maintained so that duplicate definitions can be caught, the first one wins.
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate int
addenv(Crle_desc * crle,const char * arg,unsigned int flags)457c478bd9Sstevel@tonic-gate addenv(Crle_desc *crle, const char *arg, unsigned int flags)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate 	Env_desc	*env;
487c478bd9Sstevel@tonic-gate 	char		*str;
497c478bd9Sstevel@tonic-gate 	size_t		varsz, totsz = strlen(arg) + 1;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate 	/*
527c478bd9Sstevel@tonic-gate 	 * Determine "=" location so as to separated the variable name from
537c478bd9Sstevel@tonic-gate 	 * its value.
547c478bd9Sstevel@tonic-gate 	 */
557c478bd9Sstevel@tonic-gate 	if ((str = strchr(arg, '=')) != NULL) {
5657ef7aa9SRod Evans 		Aliste	idx;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 		varsz = (size_t)(str - arg);
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 		/*
617c478bd9Sstevel@tonic-gate 		 * Traverse any existing environment variables to see if we've
627c478bd9Sstevel@tonic-gate 		 * caught a duplicate.
637c478bd9Sstevel@tonic-gate 		 */
6457ef7aa9SRod Evans 		for (APLIST_TRAVERSE(crle->c_env, idx, env)) {
657c478bd9Sstevel@tonic-gate 			if ((env->e_varsz == varsz) &&
667c478bd9Sstevel@tonic-gate 			    (strncmp(env->e_str, arg, varsz) == 0)) {
677c478bd9Sstevel@tonic-gate 				/*
687c478bd9Sstevel@tonic-gate 				 * If the user has already specified this string
697c478bd9Sstevel@tonic-gate 				 * given them a warning, and ignore the new one.
707c478bd9Sstevel@tonic-gate 				 */
717c478bd9Sstevel@tonic-gate 				if ((env->e_flags & RTC_ENV_CONFIG) == 0) {
727c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
737c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_WARN_ENV),
747c478bd9Sstevel@tonic-gate 					    crle->c_name, (int)varsz,
757c478bd9Sstevel@tonic-gate 					    env->e_str);
767c478bd9Sstevel@tonic-gate 					return (2);
777c478bd9Sstevel@tonic-gate 				}
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 				/*
807c478bd9Sstevel@tonic-gate 				 * Otherwise the original string must have been
817c478bd9Sstevel@tonic-gate 				 * retrieved from a config file.  In this case
827c478bd9Sstevel@tonic-gate 				 * allow the user to override it.
837c478bd9Sstevel@tonic-gate 				 */
847c478bd9Sstevel@tonic-gate 				free((void *)env->e_str);
857c478bd9Sstevel@tonic-gate 				crle->c_strsize -= env->e_totsz;
867c478bd9Sstevel@tonic-gate 				crle->c_strsize += totsz;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 				if ((env->e_str = strdup(arg)) == 0) {
897c478bd9Sstevel@tonic-gate 					int err = errno;
907c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
917c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_SYS_MALLOC),
927c478bd9Sstevel@tonic-gate 					    crle->c_name, strerror(err));
937c478bd9Sstevel@tonic-gate 					return (0);
947c478bd9Sstevel@tonic-gate 				}
957c478bd9Sstevel@tonic-gate 				env->e_varsz = varsz;
967c478bd9Sstevel@tonic-gate 				env->e_totsz = totsz;
977c478bd9Sstevel@tonic-gate 				env->e_flags &= ~RTC_ENV_CONFIG;
987c478bd9Sstevel@tonic-gate 				env->e_flags |= flags;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 				return (1);
1017c478bd9Sstevel@tonic-gate 			}
1027c478bd9Sstevel@tonic-gate 		}
1037c478bd9Sstevel@tonic-gate 	} else {
10457ef7aa9SRod Evans 		Aliste	idx;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 		/*
1077c478bd9Sstevel@tonic-gate 		 * Although this is just a plain environment definition (no "=")
1087c478bd9Sstevel@tonic-gate 		 * and probably has no effect on ld.so.1 anyway, we might as
1097c478bd9Sstevel@tonic-gate 		 * well make sure we're not duplicating the same string.
1107c478bd9Sstevel@tonic-gate 		 */
11157ef7aa9SRod Evans 		for (APLIST_TRAVERSE(crle->c_env, idx, env)) {
1127c478bd9Sstevel@tonic-gate 			if (env->e_varsz)
1137c478bd9Sstevel@tonic-gate 				continue;
1147c478bd9Sstevel@tonic-gate 			if (strcmp(env->e_str, arg) == 0) {
1157c478bd9Sstevel@tonic-gate 				if ((env->e_flags & RTC_ENV_CONFIG) == 0) {
1167c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
1177c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_WARN_ENV),
1187c478bd9Sstevel@tonic-gate 					    crle->c_name, (int)totsz,
1197c478bd9Sstevel@tonic-gate 					    env->e_str);
1207c478bd9Sstevel@tonic-gate 					return (2);
1217c478bd9Sstevel@tonic-gate 				}
1227c478bd9Sstevel@tonic-gate 				env->e_flags &= ~RTC_ENV_CONFIG;
1237c478bd9Sstevel@tonic-gate 				env->e_flags |= flags;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 				return (1);
1267c478bd9Sstevel@tonic-gate 			}
1277c478bd9Sstevel@tonic-gate 		}
1287c478bd9Sstevel@tonic-gate 		varsz = 0;
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	/*
1327c478bd9Sstevel@tonic-gate 	 * Allocate a new environment descriptor.
1337c478bd9Sstevel@tonic-gate 	 */
134*8285fe28SToomas Soome 	if (((env = malloc(sizeof (Env_desc))) == NULL) ||
135*8285fe28SToomas Soome 	    ((env->e_str = strdup(arg)) == NULL)) {
1367c478bd9Sstevel@tonic-gate 		int err = errno;
1377c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
1387c478bd9Sstevel@tonic-gate 		    crle->c_name, strerror(err));
139*8285fe28SToomas Soome 		free(env);
1407c478bd9Sstevel@tonic-gate 		return (0);
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 	env->e_varsz = varsz;
1437c478bd9Sstevel@tonic-gate 	env->e_totsz = totsz;
1447c478bd9Sstevel@tonic-gate 	env->e_flags = flags;
1457c478bd9Sstevel@tonic-gate 
14657ef7aa9SRod Evans 	if (aplist_append(&(crle->c_env), env, AL_CNT_CRLE) == NULL)
1477c478bd9Sstevel@tonic-gate 		return (0);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/*
1507c478bd9Sstevel@tonic-gate 	 * Update the number of environment variables found, and the string
1517c478bd9Sstevel@tonic-gate 	 * table requirement.
1527c478bd9Sstevel@tonic-gate 	 */
1537c478bd9Sstevel@tonic-gate 	crle->c_envnum++;
1547c478bd9Sstevel@tonic-gate 	crle->c_strsize += totsz;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	return (1);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate  * Add a library path.  Multiple library paths are concatenated together into a
1617c478bd9Sstevel@tonic-gate  * colon separated string suitable for runtime processing.  These colon
1627c478bd9Sstevel@tonic-gate  * separated strings can also be passed in as arguments to addlib(), e.g.,
1637c478bd9Sstevel@tonic-gate  * -l /usr/lib:/usr/local/lib.  This is enabled to make update easier.
1647c478bd9Sstevel@tonic-gate  */
1657c478bd9Sstevel@tonic-gate int
addlib(Crle_desc * crle,char ** lib,const char * args)1667c478bd9Sstevel@tonic-gate addlib(Crle_desc *crle, char **lib, const char *args)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	char		*str, *arg;
1697c478bd9Sstevel@tonic-gate 	char		*lasts;
1707c478bd9Sstevel@tonic-gate 	size_t		tlen = strlen(args) + 1;
1717c478bd9Sstevel@tonic-gate 	const char	*colon = MSG_ORIG(MSG_STR_COLON);
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	/*
1747c478bd9Sstevel@tonic-gate 	 * Parse the argument for any ":" separated elements.
1757c478bd9Sstevel@tonic-gate 	 */
1767c478bd9Sstevel@tonic-gate 	str = alloca(tlen);
1777c478bd9Sstevel@tonic-gate 	(void) strcpy(str, args);
1787c478bd9Sstevel@tonic-gate 	arg = str;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	if ((arg = strtok_r(arg, colon, &lasts)) != NULL) {
1817c478bd9Sstevel@tonic-gate 		do {
1827c478bd9Sstevel@tonic-gate 			size_t	llen, alen = strlen(arg);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 			if (*lib) {
1857c478bd9Sstevel@tonic-gate 				/*
1867c478bd9Sstevel@tonic-gate 				 * Determine whether this argument exists in the
1877c478bd9Sstevel@tonic-gate 				 * existing string buffer.
1887c478bd9Sstevel@tonic-gate 				 */
1897c478bd9Sstevel@tonic-gate 				if (((str = strstr(*lib, arg)) != NULL) &&
1907c478bd9Sstevel@tonic-gate 				    (((str == *lib) ||
1917c478bd9Sstevel@tonic-gate 				    (*(str - 1) == *colon)) &&
1927c478bd9Sstevel@tonic-gate 				    (str += alen) &&
1937c478bd9Sstevel@tonic-gate 				    ((*str == '\0') || (*str == *colon))))
1947c478bd9Sstevel@tonic-gate 					continue;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 				llen = strlen(*lib);
1977c478bd9Sstevel@tonic-gate 				tlen = llen + 1;
1987c478bd9Sstevel@tonic-gate 			} else {
1997c478bd9Sstevel@tonic-gate 				/*
2007c478bd9Sstevel@tonic-gate 				 * This is the first argument to be added.
2017c478bd9Sstevel@tonic-gate 				 */
2027c478bd9Sstevel@tonic-gate 				llen = 0;
2037c478bd9Sstevel@tonic-gate 				tlen = 0;
2047c478bd9Sstevel@tonic-gate 			}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 			/*
2077c478bd9Sstevel@tonic-gate 			 * This is a new string, so add it to the buffer.  If
2087c478bd9Sstevel@tonic-gate 			 * this is the first occurrence of a string the size is
2097c478bd9Sstevel@tonic-gate 			 * simply the size of the string + a trailing null.
2107c478bd9Sstevel@tonic-gate 			 * Otherwise the size is the old string + ":" + the
2117c478bd9Sstevel@tonic-gate 			 * size of the new string + a trailing null.
2127c478bd9Sstevel@tonic-gate 			 */
2137c478bd9Sstevel@tonic-gate 			alen += 1;
2147c478bd9Sstevel@tonic-gate 			tlen += alen;
2157c478bd9Sstevel@tonic-gate 			if ((str = realloc((void *)*lib, tlen)) == 0) {
2167c478bd9Sstevel@tonic-gate 				int err = errno;
2177c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
2187c478bd9Sstevel@tonic-gate 				    crle->c_name, strerror(err));
2197c478bd9Sstevel@tonic-gate 				return (1);
2207c478bd9Sstevel@tonic-gate 			}
2217c478bd9Sstevel@tonic-gate 			if (llen == 0)
2227c478bd9Sstevel@tonic-gate 				(void) strcpy(str, arg);
2237c478bd9Sstevel@tonic-gate 			else {
2247c478bd9Sstevel@tonic-gate 				/* LINTED */
2257c478bd9Sstevel@tonic-gate 				(void) sprintf(&str[llen],
2267c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_FMT_COLON), arg);
2277c478bd9Sstevel@tonic-gate 			}
2287c478bd9Sstevel@tonic-gate 			*lib = str;
2297c478bd9Sstevel@tonic-gate 			crle->c_strsize += alen;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 		} while ((arg = strtok_r(NULL, colon, &lasts)) != NULL);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	return (0);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate  * -f option expansion.  Interpret its argument as a numeric or symbolic
2407c478bd9Sstevel@tonic-gate  * representation of the dldump(3dl) flags.
2417c478bd9Sstevel@tonic-gate  */
2427c478bd9Sstevel@tonic-gate int
dlflags(Crle_desc * crle,const char * arg)2437c478bd9Sstevel@tonic-gate dlflags(Crle_desc *crle, const char *arg)
2447c478bd9Sstevel@tonic-gate {
2457c478bd9Sstevel@tonic-gate 	int		_flags;
2467c478bd9Sstevel@tonic-gate 	char		*tok, *_arg;
2477c478bd9Sstevel@tonic-gate 	char		*lasts;
2487c478bd9Sstevel@tonic-gate 	const char	*separate = MSG_ORIG(MSG_MOD_SEPARATE);
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	/*
2517c478bd9Sstevel@tonic-gate 	 * Scan the argument looking for allowable tokens.  First determine if
2527c478bd9Sstevel@tonic-gate 	 * the string is numeric, otherwise try and parse any known flags.
2537c478bd9Sstevel@tonic-gate 	 */
2547c478bd9Sstevel@tonic-gate 	if ((_flags = (int)strtol(arg, (char **)NULL, 0)) != 0)
2557c478bd9Sstevel@tonic-gate 		return (_flags);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	if ((_arg = malloc(strlen(arg) + 1)) == 0)
2587c478bd9Sstevel@tonic-gate 		return (0);
2597c478bd9Sstevel@tonic-gate 	(void) strcpy(_arg, arg);
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if ((tok = strtok_r(_arg, separate, &lasts)) != NULL) {
26257ef7aa9SRod Evans 		/* BEGIN CSTYLED */
2637c478bd9Sstevel@tonic-gate 		do {
2647c478bd9Sstevel@tonic-gate 		    if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_RELATIVE)) == 0)
2657c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_RELATIVE;
2667c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_EXEC)) == 0)
2677c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_EXEC;
2687c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_DEPENDS)) == 0)
2697c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_DEPENDS;
2707c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_PRELOAD)) == 0)
2717c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_PRELOAD;
2727c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_SELF)) == 0)
2737c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_SELF;
2747c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_WEAK)) == 0)
2757c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_WEAK;
2767c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_ALL)) == 0)
2777c478bd9Sstevel@tonic-gate 			_flags |= RTLD_REL_ALL;
2787c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_MEMORY)) == 0)
2797c478bd9Sstevel@tonic-gate 			_flags |= RTLD_MEMORY;
2807c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_STRIP)) == 0)
2817c478bd9Sstevel@tonic-gate 			_flags |= RTLD_STRIP;
2827c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_NOHEAP)) == 0)
2837c478bd9Sstevel@tonic-gate 			_flags |= RTLD_NOHEAP;
2847c478bd9Sstevel@tonic-gate 		    else if (strcmp(tok, MSG_ORIG(MSG_MOD_REL_CONFGEN)) == 0)
2857c478bd9Sstevel@tonic-gate 			_flags |= RTLD_CONFGEN;
2867c478bd9Sstevel@tonic-gate 		    else {
2877c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_ARG_FLAGS),
2887c478bd9Sstevel@tonic-gate 			    crle->c_name, tok);
2897c478bd9Sstevel@tonic-gate 			free(_arg);
2907c478bd9Sstevel@tonic-gate 			return (0);
2917c478bd9Sstevel@tonic-gate 		    }
2927c478bd9Sstevel@tonic-gate 		} while ((tok = strtok_r(NULL, separate, &lasts)) != NULL);
29357ef7aa9SRod Evans 		/* END CSTYLED */
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 	if (_flags == 0)
2967c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_ARG_FLAGS),
2977c478bd9Sstevel@tonic-gate 		    crle->c_name, arg);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	free(_arg);
3007c478bd9Sstevel@tonic-gate 	return (_flags);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate  * Internationalization interface for sgsmsg(1l) use.
3057c478bd9Sstevel@tonic-gate  */
3067c478bd9Sstevel@tonic-gate const char *
_crle_msg(Msg mid)3077c478bd9Sstevel@tonic-gate _crle_msg(Msg mid)
3087c478bd9Sstevel@tonic-gate {
3097c478bd9Sstevel@tonic-gate 	return (gettext(MSG_ORIG(mid)));
3107c478bd9Sstevel@tonic-gate }
311