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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <dlfcn.h> 28 #include <link.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <stdarg.h> 32 #include <libintl.h> 33 #include <locale.h> 34 #include <conv.h> 35 #include <msg.h> 36 37 void 38 locale() 39 { 40 static int localeinit = 0; 41 42 /* 43 * Defer localization overhead until a localized message, is required. 44 * For successful specific (32-bit or 64-bit) commands, none of this 45 * overhead should be incurred. 46 */ 47 if (localeinit++) 48 return; 49 50 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 51 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 52 } 53 54 const char * 55 _moe_msg(Msg mid) 56 { 57 return (gettext(MSG_ORIG(mid))); 58 } 59 60 /* 61 * Error messages from ld.so.1 are formatted as: 62 * 63 * ld.so.1: app-name: fatal: .... 64 * 65 * Here, we skip over these three components. Thus the message a little less 66 * hostile when displayed by moe(). Really, it would be nice to have some 67 * flexibility over what ld.so.1 displays. 68 */ 69 static char * 70 trim_msg(char *str) 71 { 72 char *ptr = str; 73 int cnt = 0; 74 75 /* 76 * Skip the first three components. 77 */ 78 while (*ptr) { 79 if (*ptr == ':') { 80 if (++cnt == 3) 81 break; 82 } 83 ptr++; 84 } 85 if (*ptr == '\0') 86 return (str); 87 else 88 return (ptr + 2); 89 } 90 91 #define ONLY32 1 92 #define ONLY64 2 93 94 static int 95 openlib(const char *prog, const char *name, int class, int silent, int verbose) 96 { 97 void *handle; 98 const char *modestr; 99 100 /* 101 * If the class of object is required, localize the prefix message. 102 */ 103 if (class) { 104 locale(); 105 #if defined(_LP64) 106 modestr = MSG_INTL(MSG_PRE_64); 107 #else 108 modestr = MSG_INTL(MSG_PRE_32); 109 #endif 110 } else 111 modestr = MSG_ORIG(MSG_STR_EMPTY); 112 113 114 /* 115 * Open the optimal object, and determine its full name from the 116 * returned handle. Borrow the internal mode, RTLD_CONFGEN, from 117 * crle(1). This flag allows us to process incomplete objects, as 118 * would occur if the object couldn't find its dependencies or relocate 119 * itself. 120 */ 121 if ((handle = dlmopen(LM_ID_NEWLM, name, 122 (RTLD_FIRST | RTLD_CONFGEN | RTLD_LAZY))) == 0) { 123 if (verbose) { 124 (void) fprintf(stderr, MSG_ORIG(MSG_FMT_VERBOSE), prog, 125 modestr, trim_msg(dlerror())); 126 (void) fflush(stderr); 127 } 128 return (1); 129 } 130 if (silent == 0) { 131 Link_map *lmp; 132 133 if (dlinfo(handle, RTLD_DI_LINKMAP, &lmp) == -1) { 134 if (verbose) { 135 (void) fprintf(stderr, 136 MSG_ORIG(MSG_FMT_VERBOSE), prog, modestr, 137 trim_msg(dlerror())); 138 (void) fflush(stderr); 139 } 140 return (1); 141 } 142 143 if (verbose) 144 (void) printf(MSG_ORIG(MSG_FMT_VERBOSE), prog, modestr, 145 lmp->l_name); 146 else 147 (void) printf(MSG_ORIG(MSG_FMT_SIMPLE), modestr, 148 lmp->l_name); 149 (void) fflush(stdout); 150 } 151 152 (void) dlclose(handle); 153 return (0); 154 } 155 156 int 157 /* ARGSUSED2 */ 158 main(int argc, char **argv, char **envp) 159 { 160 int var, verbose = 0, silent = 0, error = 0, mode = 0, class = 0; 161 char *prog; 162 163 if ((prog = strrchr(argv[0], '/')) == 0) 164 prog = argv[0]; 165 else 166 prog++; 167 168 opterr = 0; 169 while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 170 switch (var) { 171 case 'c': 172 class++; 173 break; 174 case '3': 175 #if !defined(_LP64) 176 if ((optarg[0] == '2') && (mode == 0)) 177 mode = ONLY32; 178 else 179 #endif 180 error++; 181 break; 182 case '6': 183 if ((optarg[0] == '4') && (mode == 0)) 184 mode = ONLY64; 185 else 186 error++; 187 break; 188 case 's': 189 if (verbose == 0) 190 silent++; 191 else 192 error++; 193 break; 194 case 'v': 195 if (silent == 0) 196 verbose++; 197 else 198 error++; 199 break; 200 case '?': 201 error++; 202 break; 203 default: 204 break; 205 } 206 } 207 if (error || ((argc - optind) == 0)) { 208 locale(); 209 (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), prog); 210 return (1); 211 } 212 if (silent) 213 class = 0; 214 215 /* 216 * Process any 32-bit expansion. 217 */ 218 #if !defined(_LP64) 219 if (mode != ONLY64) { 220 #endif 221 if (openlib(prog, argv[optind], class, silent, verbose) != 0) { 222 if (mode) 223 error++; 224 } 225 #if !defined(_LP64) 226 } 227 #endif 228 if (mode == ONLY32) 229 return (error); 230 231 /* 232 * Re-exec ourselves to process any 64-bit expansion. 233 */ 234 #if !defined(__sparcv9) && !defined(__amd64) 235 (void) conv_check_native(argv, envp); 236 #endif 237 return (error); 238 } 239