summaryrefslogtreecommitdiff
path: root/sys-devel/gcc-config/files/wrapper-1.5.2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys-devel/gcc-config/files/wrapper-1.5.2.c')
-rw-r--r--sys-devel/gcc-config/files/wrapper-1.5.2.c315
1 files changed, 0 insertions, 315 deletions
diff --git a/sys-devel/gcc-config/files/wrapper-1.5.2.c b/sys-devel/gcc-config/files/wrapper-1.5.2.c
deleted file mode 100644
index ca1e84fb..00000000
--- a/sys-devel/gcc-config/files/wrapper-1.5.2.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright 1999-2011 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.5.2.c,v 1.2 2011/06/18 18:46:23 vapier Exp $
- * Author: Martin Schlemmer <azarah@gentoo.org>
- * az's lackey: Mike Frysinger <vapier@gentoo.org>
- */
-
-#ifdef DEBUG
-# define USE_DEBUG 1
-#else
-# define USE_DEBUG 0
-#endif
-
-#include <errno.h>
-#include <libgen.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#define GCC_CONFIG "/usr/bin/gcc-config"
-#define ENVD_BASE "/etc/env.d/05gcc"
-
-#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
-
-/* basename(3) is allowed to modify memory */
-#undef basename
-#define basename(path) \
-({ \
- char *__path = path; \
- char *__ret = strrchr(__path, '/'); \
- __ret ? __ret + 1 : __path; \
-})
-
-struct wrapper_data {
- const char *name;
- char *fullname, *bin, *path;
-};
-
-static const struct {
- const char *alias;
- const char *target;
-} wrapper_aliases[] = {
- { "cc", "gcc" },
- { "f77", "gfortran" },
- { "f95", "gfortran" },
-};
-
-#define wrapper_warn(fmt, ...) fprintf(stderr, "%s" fmt "\n", "gcc-config: ", ## __VA_ARGS__)
-#define wrapper_err(fmt, ...) ({ wrapper_warn("%s" fmt, "error: ", ## __VA_ARGS__); exit(1); })
-#define wrapper_errp(fmt, ...) wrapper_err(fmt ": %s", ## __VA_ARGS__, strerror(errno))
-#define wrapper_dbg(fmt, ...) ({ if (USE_DEBUG) wrapper_warn(fmt, ## __VA_ARGS__); })
-
-#define xmemwrap(func, proto, use) \
-static void *x ## func proto \
-{ \
- void *ret = func use; \
- if (!ret) \
- wrapper_err(#func "%s", ": out of memory"); \
- return ret; \
-}
-xmemwrap(malloc, (size_t size), (size))
-xmemwrap(strdup, (const char *s), (s))
-
-/* 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;
- char str[PATH_MAX + 1];
- size_t path_len = strlen(path);
- size_t len = path_len + strlen(data->name) + 2;
-
- if (sizeof(str) < len)
- wrapper_warn("path too long: %s", path);
-
- strcpy(str, path);
- str[path_len] = '/';
- str[path_len+1] = '\0';
- strcat(str, 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
- */
- if (strcmp(str, data->fullname) != 0 &&
- strstr(str, "/gcc-bin/") != NULL &&
- stat(str, &sbuf) == 0 &&
- (S_ISREG(sbuf.st_mode) || S_ISLNK(sbuf.st_mode)))
- {
- wrapper_dbg("%s: found in %s", data->name, path);
- data->bin = xstrdup(str);
- return 1;
- }
-
- wrapper_dbg("%s: did not find in %s", data->name, path);
- return 0;
-}
-
-static int find_target_in_path(struct wrapper_data *data)
-{
- char *token = NULL, *state = NULL;
- char *str;
-
- if (data->path == NULL)
- return 0;
-
- /* Make a copy since strtok_r will modify path */
- str = xstrdup(data->path);
-
- /* 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 ... */
- token = strtok_r(str, ":", &state);
- while (token != NULL) {
- if (check_for_target(token, data))
- return 1;
- token = strtok_r(NULL, ":", &state);
- }
-
- wrapper_dbg("%s: did not find in PATH", data->name);
- 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, int cross_compile)
-{
- FILE *envfile = NULL;
- char *token = NULL, *state;
- char str[PATH_MAX + 1];
- char *strp = str;
- char envd_file[PATH_MAX + 1];
-
- if (!cross_compile) {
- /* for the sake of speed, we'll keep a symlink around for
- * the native compiler. #190260
- */
- snprintf(envd_file, sizeof(envd_file)-1, "/etc/env.d/gcc/.NATIVE");
- } else {
- char *ctarget, *end = strrchr(data->name, '-');
- if (end == NULL)
- return 0;
- ctarget = xstrdup(data->name);
- ctarget[end - data->name] = '\0';
- snprintf(envd_file, PATH_MAX, "%s-%s", ENVD_BASE, ctarget);
- free(ctarget);
- }
-
- envfile = fopen(envd_file, "r");
- if (envfile == NULL)
- return 0;
-
- while (fgets(strp, PATH_MAX, envfile) != NULL) {
- /* Keep reading ENVD_FILE until we get a line that
- * starts with 'GCC_PATH=' ... keep 'PATH=' around
- * for older gcc versions.
- */
- if (strncmp(strp, "GCC_PATH=", strlen("GCC_PATH=")) &&
- strncmp(strp, "PATH=", strlen("PATH=")))
- continue;
-
- token = strtok_r(strp, "=", &state);
- if ((token != NULL) && token[0])
- /* The second token should be the value of PATH .. */
- token = strtok_r(NULL, "=", &state);
- else
- goto bail;
-
- if ((token != NULL) && token[0]) {
- strp = token;
- /* A bash variable may be unquoted, quoted with " or
- * quoted with ', so extract the value without those ..
- */
- token = strtok(strp, "\n\"\'");
-
- while (token != NULL) {
- if (check_for_target(token, data)) {
- fclose(envfile);
- return 1;
- }
-
- token = strtok(NULL, "\n\"\'");
- }
- }
-
- strp = str;
- }
-
- bail:
- fclose(envfile);
- return (cross_compile ? 0 : find_target_in_envd(data, 1));
-}
-
-static void find_wrapper_target(struct wrapper_data *data)
-{
- if (find_target_in_path(data))
- return;
-
- if (find_target_in_envd(data, 0))
- return;
-
- /* Only our wrapper is in PATH, so get the CC path using
- * gcc-config and execute the real binary in there ...
- */
- FILE *inpipe = popen(GCC_CONFIG " --get-bin-path", "r");
- if (inpipe == NULL)
- wrapper_errp("could not open pipe");
-
- char str[PATH_MAX + 1];
- if (fgets(str, PATH_MAX, inpipe) == 0)
- wrapper_errp("could not get compiler binary path");
-
- /* chomp! */
- size_t plen = strlen(str);
- if (str[plen-1] == '\n')
- str[plen-1] = '\0';
-
- data->bin = xmalloc(plen + 1 + strlen(data->name) + 1);
- sprintf(data->bin, "%s/%s", str, data->name);
-
- 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[PATH_MAX + 1], str[PATH_MAX + 1];
- char *str2 = dname_data, *dname = dname_data;
- size_t len = 0;
-
- if (data->bin == NULL)
- return;
-
- if (data->path == NULL)
- return;
-
- snprintf(str2, PATH_MAX + 1, "%s", data->bin);
-
- if ((dname = dirname(str2)) == NULL)
- return;
-
- /* Make a copy since strtok_r will modify path */
- snprintf(str, PATH_MAX + 1, "%s", data->path);
-
- token = strtok_r(str, ":", &state);
-
- /* Check if we already appended our bin location to PATH */
- if ((token != NULL) && token[0])
- if (!strcmp(token, dname))
- return;
-
- len = strlen(dname) + strlen(data->path) + 2 + strlen("PATH") + 1;
-
- newpath = xmalloc(len);
- memset(newpath, 0, len);
-
- snprintf(newpath, len, "PATH=%s:%s", dname, data->path);
- putenv(newpath);
-}
-
-int main(int argc, char *argv[])
-{
- struct wrapper_data data;
-
- memset(&data, 0, sizeof(data));
-
- if (getenv("PATH"))
- data.path = xstrdup(getenv("PATH"));
-
- /* What should we find ? */
- data.name = basename(argv[0]);
-
- /* Allow for common compiler names like cc->gcc */
- size_t i;
- for (i = 0; i < ARRAY_SIZE(wrapper_aliases); ++i)
- if (!strcmp(data.name, wrapper_aliases[i].alias))
- data.name = wrapper_aliases[i].target;
-
- /* What is the full name of our wrapper? */
- data.fullname = xmalloc(strlen(data.name) + sizeof("/usr/bin/") + 1);
- sprintf(data.fullname, "/usr/bin/%s", data.name);
-
- find_wrapper_target(&data);
-
- modify_path(&data);
-
- free(data.path);
- data.path = NULL;
-
- /* Set argv[0] to the correct binary, else gcc can't find internal headers
- * http://bugs.gentoo.org/8132
- */
- argv[0] = data.bin;
-
- /* Ok, lets do it one more time ... */
- execv(data.bin, argv);
-
- /* shouldn't have made it here if things worked ... */
- wrapper_err("could not run/locate '%s'", data.name);
-
- return 123;
-}