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