diff options
author | Martin Schlemmer <azarah@gentoo.org> | 2004-10-26 18:15:30 +0000 |
---|---|---|
committer | Martin Schlemmer <azarah@gentoo.org> | 2004-10-26 18:15:30 +0000 |
commit | 341c4e913202ac9cb335c77c8d08adef8aca7292 (patch) | |
tree | ee573aca02c1ef0ecbc1370133bc8e129e32e133 /sys-devel | |
parent | fix digest (diff) | |
download | historical-341c4e913202ac9cb335c77c8d08adef8aca7292.tar.gz historical-341c4e913202ac9cb335c77c8d08adef8aca7292.tar.bz2 historical-341c4e913202ac9cb335c77c8d08adef8aca7292.zip |
Add GCCBITS support to wrapper.
Diffstat (limited to 'sys-devel')
-rw-r--r-- | sys-devel/gcc-config/ChangeLog | 5 | ||||
-rw-r--r-- | sys-devel/gcc-config/Manifest | 21 | ||||
-rw-r--r-- | sys-devel/gcc-config/files/wrapper-1.4.3.c | 355 |
3 files changed, 365 insertions, 16 deletions
diff --git a/sys-devel/gcc-config/ChangeLog b/sys-devel/gcc-config/ChangeLog index de55b294681c..17256f31abf2 100644 --- a/sys-devel/gcc-config/ChangeLog +++ b/sys-devel/gcc-config/ChangeLog @@ -1,6 +1,9 @@ # ChangeLog for sys-devel/gcc-config # Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/ChangeLog,v 1.63 2004/10/26 04:05:36 vapier Exp $ +# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/ChangeLog,v 1.64 2004/10/26 18:15:30 azarah Exp $ + + 26 Oct 2004; Martin Schlemmer <azarah@gentoo.org> +files/wrapper-1.4.3.c: + Add GCCBITS support to wrapper. *gcc-config-1.3.7-r1 (25 Oct 2004) diff --git a/sys-devel/gcc-config/Manifest b/sys-devel/gcc-config/Manifest index 3db14aa4766c..9fdade7fbe57 100644 --- a/sys-devel/gcc-config/Manifest +++ b/sys-devel/gcc-config/Manifest @@ -1,19 +1,10 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -MD5 861796d7d51aeec305d01854d330deac ChangeLog 11944 MD5 39c5ae73589a762c88b6e689f54b8831 gcc-config-1.3.6-r3.ebuild 2611 -MD5 9a09f8d531c582e78977dbfd96edc1f2 metadata.xml 164 +MD5 12a6abe6a3a2ed48dfb04a1eba513218 ChangeLog 12055 MD5 f39b187735cf78d94d6e47228edf7e95 gcc-config-1.3.7-r1.ebuild 2211 -MD5 d41d8cd98f00b204e9800998ecf8427e files/digest-gcc-config-1.3.6-r3 0 -MD5 f9ac19eaceaad00963038bc3d3d11b98 files/gcc-config-1.3.6 10163 +MD5 9a09f8d531c582e78977dbfd96edc1f2 metadata.xml 164 MD5 1bc5a05334c1d92a5aa3ed9614e465ea files/gcc-config-1.3.7 11225 -MD5 e64a89abafa7f6f7d16c2540fb0edcf4 files/wrapper-1.4.2.c 7381 +MD5 d41d8cd98f00b204e9800998ecf8427e files/digest-gcc-config-1.3.6-r3 0 MD5 d41d8cd98f00b204e9800998ecf8427e files/digest-gcc-config-1.3.7-r1 0 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.9.10 (GNU/Linux) - -iD8DBQFBfc0vHTu7gpaalycRAht0AKCN4yaBglAdphrBjD4TqDLDnl1sfwCg0A8I -nQ+GfTeb4hTh74dXWy1bRmY= -=FHc4 ------END PGP SIGNATURE----- +MD5 2902e905147ff6ba0703f0f72660aa9a files/wrapper-1.4.3.c 8434 +MD5 e64a89abafa7f6f7d16c2540fb0edcf4 files/wrapper-1.4.2.c 7381 +MD5 f9ac19eaceaad00963038bc3d3d11b98 files/gcc-config-1.3.6 10163 diff --git a/sys-devel/gcc-config/files/wrapper-1.4.3.c b/sys-devel/gcc-config/files/wrapper-1.4.3.c new file mode 100644 index 000000000000..30067a9d4c48 --- /dev/null +++ b/sys-devel/gcc-config/files/wrapper-1.4.3.c @@ -0,0 +1,355 @@ +/* + * Copyright 1999-2004 Gentoo Foundation + * Distributed under the terms of the GNU General Public License v2 + * $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/files/wrapper-1.4.3.c,v 1.1 2004/10/26 18:15:30 azarah Exp $ + * Author: Martin Schlemmer <azarah@gentoo.org> + */ + +/* Define if need of debugging */ +#undef WRAPPER_DEBUG + +#define _REENTRANT +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <unistd.h> +#include <wait.h> +#include <libgen.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> + +#define GCC_CONFIG "/usr/bin/gcc-config" + +#ifndef CC_PROFILE +# define ENVD_FILE "/etc/env.d/05gcc" +#else +# define ENVD_FILE "/etc/env.d/gcc/" CC_PROFILE +#endif + +#define CODESIZE_STR_LEN (sizeof(char) * (3 + strlen(gccbits))) +#define TMP_STR_LEN (sizeof(char) * 32 * 1024) + +struct wrapper_data { + char name[MAXPATHLEN + 1]; + char fullname[MAXPATHLEN + 1]; + char bin[MAXPATHLEN + 1]; + char tmp[MAXPATHLEN + 1]; + + char *path; +}; + +static const char *wrapper_strerror(int err, struct wrapper_data *data) +{ + strerror_r(err, data->tmp, sizeof(data->tmp)); + return data->tmp; +} + +static void wrapper_exit(char *msg, ...) +{ + va_list args; + fprintf(stderr, "gcc-config error: "); + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + exit(1); +} + +/* check_for_target checks in path for the file we are seeking + * it returns 1 if found (with data->bin setup), 0 if not and + * negative on error + */ +static int check_for_target(char *path, struct wrapper_data *data) +{ + struct stat sbuf; + int result = 0; + char str[MAXPATHLEN + 1]; + size_t len = strlen(path) + strlen(data->name) + 2; + + snprintf(str, len, "%s/%s", path, data->name); + + /* Stat possible file to check that + * 1) it exist and is a regular file, and + * 2) it is not the wrapper itself, and + * 3) it is in a /gcc-bin/ directory tree + */ + result = stat(str, &sbuf); + if ((0 == result) && + ((sbuf.st_mode & S_IFREG) || (sbuf.st_mode & S_IFLNK)) && + (0 != strcmp(str, data->fullname)) && + (0 != strstr(str, "/gcc-bin/"))) { + + strncpy(data->bin, str, MAXPATHLEN); + data->bin[MAXPATHLEN] = 0; + result = 1; + } + else + result = 0; + + return result; +} + +static int find_target_in_path(struct wrapper_data *data) +{ + char *token = NULL, *state; + char str[MAXPATHLEN + 1]; + + if (NULL == data->path) return 0; + + /* Make a copy since strtok_r will modify path */ + snprintf(str, MAXPATHLEN + 1, "%s", data->path); + + token = strtok_r(str, ":", &state); + + /* Find the first file with suitable name in PATH. The idea here is + * that we do not want to bind ourselfs to something static like the + * default profile, or some odd environment variable, but want to be + * able to build something with a non default gcc by just tweaking + * the PATH ... */ + while ((NULL != token) && (strlen(token) > 0)) { + + if (check_for_target(token, data)) + return 1; + + token = strtok_r(NULL, ":", &state); + } + + return 0; +} + +/* find_target_in_envd parses /etc/env.d/05gcc, and tries to + * extract PATH, which is set to the current profile's bin + * directory ... + */ +static int find_target_in_envd(struct wrapper_data *data) +{ + FILE *envfile = NULL; + char *token = NULL, *state; + char str[MAXPATHLEN + 1]; + char *strp = str; + + if (NULL == data->path) return 0; + + envfile = fopen(ENVD_FILE, "r"); + if (NULL == envfile) + return 0; + + while (0 != fgets(strp, MAXPATHLEN, envfile)) { + + /* Keep reading ENVD_FILE until we get a line that + * starts with 'PATH=' + */ + if (((strp) && (strlen(strp) > strlen("PATH=")) && + 0 == strncmp("PATH=", strp, strlen("PATH=")))) { + + token = strtok_r(strp, "=", &state); + if ((NULL != token) && (strlen(token) > 0)) + /* The second token should be the value of PATH .. */ + token = strtok_r(NULL, "=", &state); + else { + fclose(envfile); + return 0; + } + + if ((NULL != token) && (strlen(token) > 0)) { + + strp = token; + /* A bash variable may be unquoted, quoted with " or + * quoted with ', so extract the value without those .. + */ + token = strsep(&strp, "\n\"\'"); + + while (NULL != token) { + + if (check_for_target(token, data)) { + + fclose(envfile); + return 1; + } + + token = strsep(&strp, "\n\"\'"); + } + } + + } + strp = str; + } + + fclose(envfile); + + return 0; +} + +static void find_wrapper_target(struct wrapper_data *data) +{ + FILE *inpipe = NULL; + char str[MAXPATHLEN + 1]; + +#ifndef CC_PROFILE + if (find_target_in_path(data)) + return; +#endif + + if (find_target_in_envd(data)) + return; + + /* Only our wrapper is in PATH, so + get the CC path using gcc-config and + execute the real binary in there... */ +#ifndef CC_PROFILE + inpipe = popen(GCC_CONFIG " --get-bin-path", "r"); +#else + inpipe = popen(GCC_CONFIG " --get-bin-path " CC_PROFILE, "r"); +#endif + if (NULL == inpipe) + wrapper_exit( + "Could not open pipe: %s\n", + wrapper_strerror(errno, data)); + + if (0 == fgets(str, MAXPATHLEN, inpipe)) + wrapper_exit( + "Could not get compiler binary path: %s\n", + wrapper_strerror(errno, data)); + + strncpy(data->bin, str, sizeof(data->bin) - 1); + data->bin[strlen(data->bin) - 1] = '/'; + strncat(data->bin, data->name, sizeof(data->bin) - 1); + data->bin[MAXPATHLEN] = 0; + + pclose(inpipe); +} + +/* This function modifies PATH to have gcc's bin path appended */ +static void modify_path(struct wrapper_data *data) +{ + char *newpath = NULL, *token = NULL, *state; + char dname_data[MAXPATHLEN + 1], str[MAXPATHLEN + 1]; + char *str2 = dname_data, *dname = dname_data; + size_t len = 0; + + if (NULL == data->bin) + return; + + snprintf(str2, MAXPATHLEN + 1, "%s", data->bin); + + if (NULL == (dname = dirname(str2))) + return; + + if (NULL == data->path) + return; + + /* Make a copy since strtok_r will modify path */ + snprintf(str, MAXPATHLEN + 1, "%s", data->path); + + token = strtok_r(str, ":", &state); + + /* Check if we already appended our bin location to PATH */ + if ((NULL != token) && (strlen(token) > 0)) { + if (0 == strcmp(token, dname)) + return; + } + + len = strlen(dname) + strlen(data->path) + 2; + + newpath = (char *)malloc(len); + if (NULL == newpath) + wrapper_exit("out of memory\n"); + memset(newpath, 0, len); + + snprintf(newpath, len, "%s:%s", dname, data->path); + setenv("PATH", newpath, 1); + + if (newpath) + free(newpath); + newpath = NULL; +} + +int main(int argc, char **argv) +{ + struct wrapper_data *data; + size_t size; + char *myargv[argc + 2]; + char *path, *gccbits, *codesize; +#ifdef WRAPPER_DEBUG + char *tmpstr; +#endif + int result = 0, i; + + data = alloca(sizeof(*data)); + if (NULL == data) + wrapper_exit("%s wrapper: out of memory\n", argv[0]); + memset(data, 0, sizeof(*data)); + + path = getenv("PATH"); + if (NULL != path) { + data->path = strdup(getenv("PATH")); + if (NULL == data->path) + wrapper_exit("%s wrapper: out of memory\n", argv[0]); + } + + /* What should we find ? */ + strcpy(data->name, basename(argv[0])); + + /* cc calls "/full/path/to/gcc" ... */ + if (0 == strcmp(data->name, "cc")) + strcpy(data->name, "gcc"); + + /* What is the full name of our wrapper? */ + size = sizeof(data->fullname); + result = snprintf(data->fullname, size, "/usr/bin/%s", data->name); + if ((-1 == result) || (result > size)) + wrapper_exit("invalid wrapper name: \"%s\"\n", data->name); + + find_wrapper_target(data); + + modify_path(data); + + if (data->path) + free(data->path); + data->path = NULL; + + for (i = 0;i < argc;i++) + myargv[i] = argv[i]; + + myargv[argc + 1] = NULL; + + /* Add '-m$GCCBITS' to argv */ + gccbits = getenv("GCCBITS"); + if (NULL != gccbits + /* Make sure we have something remotely valid */ + && strlen(gccbits) >= 2) { + codesize = (char *)alloca(CODESIZE_STR_LEN); + snprintf(codesize, CODESIZE_STR_LEN, "-m%s", gccbits); + myargv[argc] = codesize; + } else { + /* Nothing to add, so just set to NULL */ + myargv[argc] = NULL; + } + + /* Set argv[0] to the correct binary, else gcc do not find internal + * headers, etc (bug #8132). */ + myargv[0] = data->bin; + +#ifndef WRAPPER_DEBUG + /* Ok, do it ... */ + if (execv(data->bin, myargv) < 0) + wrapper_exit("Could not run/locate \"%s\"\n", data->name); +#else + tmpstr = (char *)alloca(TMP_STR_LEN); + tmpstr = strndup(myargv[0], TMP_STR_LEN); + for (i = 1;i < (argc + 2);i++) { + if (NULL != myargv[i]) { + strncat(tmpstr, " ", TMP_STR_LEN - strlen(tmpstr)); + strncat(tmpstr, myargv[i], TMP_STR_LEN - strlen(tmpstr)); + } + } + printf("%s\n", tmpstr); +#endif + + return 0; +} + |