118 lines
2.9 KiB
C
118 lines
2.9 KiB
C
/* @(#)ldd.c 1.1 94/10/31 SMI */
|
|
|
|
/*
|
|
* List Dynamic Dependencies
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <stdio.h>
|
|
#include <a.out.h>
|
|
#include <link.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/file.h>
|
|
|
|
char *nargv[] = {0, 0}; /* dummy argument vector */
|
|
|
|
char *malloc(); /* malloc return value */
|
|
|
|
main(argc, argv, envp)
|
|
int argc; /* count of arguments */
|
|
char *argv[]; /* argument values */
|
|
char *envp[]; /* array of environment strings */
|
|
{
|
|
unsigned int i, j; /* general temporaries */
|
|
int fd; /* file descriptor on targets */
|
|
int pid; /* child process id */
|
|
char **nenvp; /* new environment */
|
|
struct exec exec; /* template for inspecting target */
|
|
union wait status; /* dummy for wait() */
|
|
struct exec a;
|
|
|
|
/*
|
|
* Initial sanity check.
|
|
*/
|
|
if (argc <= 1) {
|
|
(void) fprintf(stderr, "Usage: ldd file ... \n");
|
|
exit(1);
|
|
}
|
|
(void) setlinebuf(stdout);
|
|
(void) setlinebuf(stderr);
|
|
|
|
/*
|
|
* Add an environment variable. Count the number of existing
|
|
* ones, and then allocate up a new vector of environment strings
|
|
* and add ours to it.
|
|
*/
|
|
for (i = 0; envp[i]; i++)
|
|
;
|
|
if ((nenvp = (char **)malloc((i + 2) * sizeof (char *))) == NULL) {
|
|
perror("ldd: out of memory for environment");
|
|
exit(1);
|
|
}
|
|
nenvp[0] = "LD_TRACE_LOADED_OBJECTS=placeholder";
|
|
for (j = 0; j < (i + 1); j++)
|
|
nenvp[j + 1] = envp[j];
|
|
|
|
/*
|
|
* For each argument, examine it and determine if it is an
|
|
* executable with a __DYNAMIC structure and an entry point.
|
|
* If it is, simply execute it and let the dynamic linker
|
|
* report its status.
|
|
*/
|
|
for (i = 1; i < argc; i++) {
|
|
if ((fd = open(argv[i], O_RDONLY)) == -1) {
|
|
fprintf(stderr, "ldd: %s unreadable: ", argv[1]);
|
|
perror("");
|
|
continue;
|
|
}
|
|
j = read(fd, (char *)&exec, sizeof (struct exec));
|
|
(void) close(fd);
|
|
if (j != sizeof (struct exec)) {
|
|
(void) fprintf(stderr, "ldd: %s: not an executable\n",
|
|
argv[i]);
|
|
continue;
|
|
}
|
|
if (N_BADMAG(exec)) {
|
|
(void) fprintf(stderr, "ldd: %s: not an executable\n",
|
|
argv[i]);
|
|
continue;
|
|
}
|
|
if (!exec.a_dynamic) {
|
|
(void) printf("%s: statically linked\n", argv[i]);
|
|
continue;
|
|
}
|
|
if (exec.a_entry == 0) {
|
|
(void) fprintf("%s: not an executable\n", argv[i]);
|
|
continue;
|
|
}
|
|
if ((pid = fork()) == 0) {
|
|
if (argc > 2)
|
|
(void) printf("%s:\n", argv[i]);
|
|
execve(argv[i], nargv, nenvp);
|
|
(void) fprintf(stderr,
|
|
"ldd: %s execution failed: ", argv[i]);
|
|
perror("");
|
|
continue;
|
|
} else
|
|
if (pid != -1) {
|
|
while (wait(&status) != pid)
|
|
;
|
|
if (status.w_T.w_Termsig)
|
|
(void) fprintf(stderr,
|
|
"ldd: %s execution failed due to signal %d %s\n",
|
|
argv[i],
|
|
status.w_T.w_Termsig,
|
|
status.w_T.w_Coredump ?
|
|
"(core dumped)" : "");
|
|
else if (status.w_T.w_Retcode)
|
|
(void) printf(stderr,
|
|
"ldd: %s execution failed: exit status %d\n",
|
|
argv[i],
|
|
status.w_T.w_Retcode);
|
|
} else
|
|
perror("ldd: fork() failed");
|
|
}
|
|
exit(0);
|
|
/*NOTREACHED*/
|
|
}
|