/* @(#)ldd.c 1.1 94/10/31 SMI */ /* * List Dynamic Dependencies */ #include #include #include #include #include #include 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*/ }