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