4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
41 static char const *strdup_sym
= "strdup";
42 static char const *malloc_sym
= "malloc";
43 static char const *comma
= ",";
46 bugout(char const *call
)
48 (void) fprintf(stderr
,
49 dgettext(TEXT_DOMAIN
, "apptrace: %s failed\n"),
55 build_env_list(Liblist
**list
, char const *env
)
60 if ((envstr
= getenv(env
)) == NULL
)
63 if ((envstr
= strdup(envstr
)) == NULL
)
66 tok
= strtok(envstr
, comma
);
70 if ((lp
= malloc(sizeof (Liblist
))) == NULL
)
76 tok
= strtok(NULL
, comma
);
81 build_env_list1(Liblist
**list
, Liblist
**listend
, const char *env
)
86 if ((envstr
= getenv(env
)) == NULL
)
90 * It is possible that we have a single file name,
91 * in which case the subseqent loop will do nothing
93 if (strchr(envstr
, ',') == NULL
) {
94 appendlist(list
, listend
, envstr
, 1);
98 if ((envstr
= strdup(envstr
)) == NULL
)
101 tok
= strtok(envstr
, comma
);
102 while (tok
!= NULL
) {
103 appendlist(list
, listend
, tok
, 1);
104 tok
= strtok(NULL
, comma
);
110 env_to_intlist(Intlist
**list
, char const *env
)
115 if ((envstr
= getenv(env
)) == NULL
)
118 if ((envstr
= strdup(envstr
)) == NULL
)
121 for (tok
= strtok(envstr
, comma
);
123 tok
= strtok(NULL
, comma
)) {
127 if ((ip
= malloc(sizeof (Intlist
))) == NULL
)
130 if ((ip
->i_name
= strdup(tok
)) == NULL
)
140 appendlist(Liblist
**list
, Liblist
**listend
, const char *name
, int fatal
)
145 if (access(name
, R_OK
)) {
147 (void) fprintf(stderr
,
148 dgettext(TEXT_DOMAIN
,
149 "apptrace: %s: %s\n"),
157 if ((handle
= dlopen(name
, RTLD_LAZY
)) == NULL
) {
159 (void) fprintf(stderr
,
160 dgettext(TEXT_DOMAIN
,
161 "apptrace: dlopen on %s failed: %s\n"),
169 /* OK, so now add it to the end of the list */
170 if ((lp
= malloc(sizeof (Liblist
))) == NULL
)
173 if ((lp
->l_libname
= strdup(name
)) == NULL
)
175 lp
->l_handle
= handle
;
178 (*listend
)->l_next
= lp
;
185 * Called abibasename() to avoid clash with basename(3C)
186 * Incidentally, basename(3C) is destructive which is why
187 * we are not using it instead.
190 abibasename(const char *str
)
194 if ((p
= strrchr(str
, '/')) != NULL
)
197 return ((char *)str
);
201 check_list(Liblist
*list
, char const *str
)
203 char *basename1
, *basename2
, *p1
, *p2
;
209 if ((basename2
= strdup(abibasename(str
))) == NULL
)
211 if ((p2
= strchr(basename2
, '.')) != NULL
)
214 for (; list
; list
= list
->l_next
) {
215 /* Lose the dirname */
216 if ((basename1
= strdup(abibasename(list
->l_libname
))) == NULL
)
218 /* Lose the suffix */
219 if ((p1
= strchr(basename1
, '.')) != NULL
)
221 if (fnmatch(basename1
, basename2
, 0) == 0) {
234 check_intlist(Intlist
*list
, char const *iface
)
239 for (; list
!= NULL
; list
= list
->i_next
) {
240 if (fnmatch(list
->i_name
, iface
, 0) == 0)
248 checkenv(char const *env
)
252 if ((envstr
= getenv(env
)) == NULL
)
254 while (*envstr
== ' ')
262 build_interceptor_path(char *buf
, size_t l
, char const *path
)
270 /* Duplicate the path */
271 if ((p
= strdup(path
)) == NULL
)
274 /* Find the last slash, if there ain't one bug out */
275 if ((t
= strrchr(p
, '/')) == NULL
) {
281 * Wack the slash to a null byte.
284 * p now points to /A/B/C
285 * f is set to point to D.so.1
292 * As above except that in LP64 (for sparc) we'll get:
293 * /A/B/C/sparcv9/D.so.1
294 * thus p now points to:
296 * so we repeat the wack so that we get:
298 * and retain a pointer, m, to the machine dependent portion.
300 if ((t
= strrchr(p
, '/')) == NULL
) {
308 * Now we can build a path name.
309 * This path is only a guess that'll be checked later in appendlist().
310 * Some system libraries, like libc.so.1, reside in /lib while their
311 * corresponding abi_* counterparts reside in /usr/lib. The same is
312 * true for libraries like libc_psr.so.1 that reside in /platform
313 * rather than /usr/platform. To deal with this, we check whether
314 * the file in the direct path name we generate exists, and if not,
315 * we prepend "/usr" to it. This handles all existing cases.
317 ret
= snprintf(buf
, l
, "%s/abi/%s/abi_%s", p
, m
, f
);
318 if (access(buf
, R_OK
) != 0 && strncmp(buf
, "/usr/", 5) != 0)
319 ret
= snprintf(buf
, l
, "/usr%s/abi/%s/abi_%s", p
, m
, f
);
321 ret
= snprintf(buf
, l
, "%s/abi/abi_%s", p
, f
);
322 if (access(buf
, R_OK
) != 0 && strncmp(buf
, "/usr/", 5) != 0)
323 ret
= snprintf(buf
, l
, "/usr%s/abi/abi_%s", p
, f
);