diff --git a/.gitattributes b/.gitattributes index 342f40d5d6743d058e55b78002417e46cf5c367c..6c2d5e3ed0dc65eeac693250f899c6b1e8585d54 100644 --- a/.gitattributes +++ b/.gitattributes @@ -411,6 +411,7 @@ testfont binary /src/rusage.h foreign_ident /src/signal_handler.c foreign_ident /src/signal_handler.h foreign_ident +/src/smartlink.c foreign_ident /src/stralloc.c foreign_ident /src/stralloc.h foreign_ident /src/stuff.c foreign_ident diff --git a/src/smartlink.c b/src/smartlink.c new file mode 100644 index 0000000000000000000000000000000000000000..e5765a04f0ac0ce1169acdd52216664321b7817c --- /dev/null +++ b/src/smartlink.c @@ -0,0 +1,289 @@ +/* + * $Id: smartlink.c,v 1.1 1999/03/06 01:54:44 grubba Exp $ + * + * smartlink - A smarter linker. + * Based on the /bin/sh script smartlink 1.23. + * + * Henrik Grubbström 1999-03-04 + */ + +/* NOTE: Use confdefs.h and not machine.h, since we are compiled by configure + */ +#include "confdefs.h" + +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif /* HAVE_STDLIB_H */ + +#ifdef HAVE_STRING_H +#include <string.h> +#endif /* HAVE_STRING_H */ + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif /* HAVE_SYS_STAT_H */ + +char *prog_name; + +void fatal(char *message) +{ + fprintf(stderr, "%s: %s", prog_name, message); + exit(1); +} + +/* Not terribly efficient, but... */ +int add_path(char *buffer, char *path) +{ + char *p = buffer - 1; + int len = strlen(path); + + do { + p++; + if (!strncmp(p, path, len) && (p[len] == ':')) { + return 0; + } + } while ((p = strchr(p, ':'))); + + strcat(buffer, path); + strcat(buffer, ":"); + + return 1; +} + +int main(int argc, char **argv) +{ + int i; + int buf_size; + char *path; + char *buffer; + char *lpath; + char *rpath; + int rpath_in_use = 0; + char *lp; + char *rp; + char *full_rpath; + char **new_argv; + char *ld_lib_path; + int new_argc; + int n32 = 0; + int linking = 1; /* Maybe */ + + prog_name = argv[0]; + + if (argc < 2) { + fatal("Too few arguments\n"); + } + + if (!strcmp(argv[1], "-v")) { + fprintf(stdout, + "$Id: smartlink.c,v 1.1 1999/03/06 01:54:44 grubba Exp $\n" + "Usage:\n" + "\t%s binary [args]\n", + argv[0]); + exit(0); + } + + if (putenv("LD_PXDB=/dev/null")) { + fatal("Out of memory (1)!\n"); + } + if (!getenv("SGI_ABI")) { + if (putenv("SGI_ABI=-n32")) { + fatal("Out of memory (2)!\n"); + } + } + + path = getenv("PATH"); + + buf_size = 0; + + if ((ld_lib_path = getenv("LD_LIBRARY_PATH"))) { + buf_size += strlen(ld_lib_path); + } + + for(i=0; i < argc; i++) { + buf_size += strlen(argv[i]); + } + + buf_size += 2*argc + 20; /* Some extra space */ + + if (path && !(buffer = malloc(strlen(path) + strlen(argv[1]) + 4))) { + fatal("Out of memory (2.5)!\n"); + } + + if (!(rpath = malloc(buf_size))) { + fatal("Out of memory (3)!\n"); + } + + if (!(lpath = malloc(buf_size))) { + fatal("Out of memory (4)!\n"); + } + + rpath[0] = 0; + lpath[0] = 0; + + /* 5 extra args should be enough... */ + if (!(new_argv = malloc(sizeof(char *)*(argc + 5)))) { + fatal("Out of memory (5)!\n"); + } + + new_argc = 0; + full_rpath = rpath; + +#ifdef USE_Wl + strcat(rpath, "-Wl,-rpath,"); + rpath += strlen(rpath); +#elif defined(USE_R) + strcat(rpath, "-R"); +#elif defined(USE_LD_LIBRARY_PATH) + strcat(rpath, "LD_LIBRARY_PATH="); +#endif /* defined(USE_Wl) || defined(USE_R) || defined(USE_LD_LIBRARY_PATH) */ + rpath += strlen(rpath); + + new_argv[new_argc++] = argv[1]; + + if (!strcmp(argv[1], "cpp")) { + /* Not linking */ + linking = 0; + } + + /* NOTE: Skip arg 1 */ + for(i=2; i<argc; i++) { + if (argv[i][0] == '-') { + if ((argv[i][1] == 'R') || (argv[i][1] == 'L')) { + /* -R & -L */ + if (argv[i][1] == 'L') { + if (!argv[i][2]) { + if (i+1 < argc) { + if (add_path(lpath, argv[i+1])) { + new_argv[new_argc++] = argv[i]; + new_argv[new_argc++] = argv[i+1]; + } + } + } else { + if (add_path(lpath, argv[i]+2)) { + new_argv[new_argc++] = argv[i]; + } + } + } + if (!argv[i][2]) { + i++; + if (i < argc) { + add_path(rpath, argv[i]); + rpath_in_use = 1; + } + } else { + add_path(rpath, argv[i] + 2); + rpath_in_use = 1; + } + continue; + } else if ((argv[i][1] == 'n') && (argv[i][2] == '3') && + (argv[i][3] == '2') && (!argv[i][4])) { + /* -n32 */ + n32 = 1; + continue; /* Skip */ + } else if (((argv[i][1] == 'c') || (argv[i][1] == 'E')) && + (!argv[i][2])) { + /* Not linking */ + linking = 0; + } + } + new_argv[new_argc++] = argv[i]; + } + + if (n32) { + i = new_argc++; + /* Note don't copy index 0 */ + while(--i) { + new_argv[i+1] = new_argv[i]; + } + new_argv[1] = "-n32"; + } + + if (ld_lib_path) { + char *p; + + while (p = strchr(ld_lib_path, ':')) { + *p = 0; + add_path(rpath, ld_lib_path); + *p = ':'; /* Make sure LD_LIBRARY_PATH isn't modified */ + ld_lib_path = p+1; + } + add_path(rpath, ld_lib_path); + + rpath_in_use = 1; + } + + if (rpath_in_use) { + /* Delete the terminating ':' */ + rpath[strlen(rpath) - 1] = 0; + +#ifdef USE_RPATH + new_argv[new_argc++] = "-rpath"; + new_argv[new_argc++] = rpath; +#elif defined(USE_Wl) + if (linking) { + new_argv[new_argc++] = full_rpath; + } +#elif defined(USE_R) + new_argv[new_argc++] = full_rpath; +#elif defined(USE_LD_LIBRARY_PATH) + if (putenv(full_rpath)) { + fatal("Out of memory (6)!"); + } + /* LD_LIBRARY_PATH + * LD_RUN_PATH + */ + memcpy(full_rpath + 4, "LD_RUN_PATH", 11); + if (putenv(full_rpath + 4)) { + fatal("Out of memory (7)!"); + } +#else +#error Unknown method +#endif + } + + new_argv[new_argc++] = NULL; + + if ((argv[1][0] != '/') && path) { + /* Perform a search in $PATH */ + struct stat stat_buf; + char *p; + while ((p = strchr(path, ':'))) { + *p = 0; + strcpy(buffer, path); + *p = ':'; /* Make sure PATH isn't modified */ + strcat(buffer, "/"); + strcat(buffer, argv[1]); + fprintf(stderr, "Trying %s...\n", buffer); + if (!stat(buffer, &stat_buf)) { + /* Found. */ + argv[1] = buffer; + break; + } + path = p + 1; + } + if (!p) { + strcpy(buffer, path); + strcat(buffer, "/"); + strcat(buffer, argv[1]); + fprintf(stderr, "Trying %s...\n", buffer); + if (!stat(buffer, &stat_buf)) { + /* Found */ + argv[1] = buffer; + } + } + } + + execv(argv[1], new_argv); + fprintf(stderr, "%s: exec of %s failed!\n", argv[0], argv[1]); + exit(1); +}