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 2009 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 return (1); 128 } 129 if (silent == 0) { 130 Link_map *lmp; 131 132 if (dlinfo(handle, RTLD_DI_LINKMAP, &lmp) == -1) { 133 if (verbose) 134 (void) fprintf(stderr, 135 MSG_ORIG(MSG_FMT_VERBOSE), prog, modestr, 136 trim_msg(dlerror())); 137 (void) fflush(stderr); 138 return (1); 139 } 140 141 if (verbose) 142 (void) printf(MSG_ORIG(MSG_FMT_VERBOSE), prog, modestr, 143 lmp->l_name); 144 else 145 (void) printf(MSG_ORIG(MSG_FMT_SIMPLE), modestr, 146 lmp->l_name); 147 (void) fflush(stdout); 148 } 149 150 (void) dlclose(handle); 151 return (0); 152 } 153 154 int 155 /* ARGSUSED2 */ 156 main(int argc, char **argv, char **envp) 157 { 158 int var, verbose = 0, silent = 0, error = 0, mode = 0, class = 0; 159 char *prog; 160 161 if ((prog = strrchr(argv[0], '/')) == 0) 162 prog = argv[0]; 163 else 164 prog++; 165 166 opterr = 0; 167 while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) { 168 switch (var) { 169 case 'c': 170 class++; 171 break; 172 case '3': 173 #if !defined(_LP64) 174 if ((optarg[0] == '2') && (mode == 0)) 175 mode = ONLY32; 176 else 177 #endif 178 error++; 179 break; 180 case '6': 181 if ((optarg[0] == '4') && (mode == 0)) 182 mode = ONLY64; 183 else 184 error++; 185 break; 186 case 's': 187 if (verbose == 0) 188 silent++; 189 else 190 error++; 191 break; 192 case 'v': 193 if (silent == 0) 194 verbose++; 195 else 196 error++; 197 break; 198 case '?': 199 error++; 200 break; 201 default: 202 break; 203 } 204 } 205 if (error || ((argc - optind) == 0)) { 206 locale(); 207 (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), prog); 208 return (1); 209 } 210 if (silent) 211 class = 0; 212 213 /* 214 * Process any 32-bit expansion. 215 */ 216 #if !defined(_LP64) 217 if (mode != ONLY64) { 218 #endif 219 if (openlib(prog, argv[optind], class, silent, verbose) != 0) { 220 if (mode) 221 error++; 222 } 223 #if !defined(_LP64) 224 } 225 #endif 226 if (mode == ONLY32) 227 return (error); 228 229 /* 230 * Re-exec ourselves to process any 64-bit expansion. 231 */ 232 #if !defined(__sparcv9) && !defined(__amd64) 233 (void) conv_check_native(argv, envp); 234 #endif 235 return (error); 236 } 237