Example #1
0
File: lib.c Project: pfmoore/shimmy
static wchar_t *get_target(wchar_t *path, wchar_t *base, int type) {
    if (type == 0 && base == NULL) {
        /* Relative to base, if no base then shim location */
        base = my_dir();
    }
    else if (type == 1) {
        /* Relative to an exe on PATH */
        base = find_on_path(base);
    }
    else if (type == 2) {
        /* Relative to env variable */
        base = _wgetenv(base);
    }
    else if (type == 3) {
        /* Relative to registry entry */
        /* TODO: add this later */
    }
}
Example #2
0
int main(int argc, char **argv) {
    char *prog;
    char *dir, *dirup;
    char *p;
    char **args, **argp;
    char is_verbose = 0;
    char **argi, *arg;
    struct stat st;

    dir = find_on_path(argv[0]);
    if (!dir) {
        fdprint(2, "xstatic: error: could not find myself on $PATH\n");
        return 122;
    }
    dir = readlink_alloc_all(dir);
    for (p = dir + strlen(dir); p != dir && p[-1] != '/'; --p) {}
    if (p == dir) {
        strcpy(dir, ".");
    } else {
        for (; p != dir && p[-1] == '/'; --p) {}
        p[p == dir] = '\0';  /* Remove basename of dir. */
    }
    dirup = get_up_dir_alloc(dir);
    if (detect_linker(argv)) {  /* clang trampoline runs as as ld. */
        char is_static = 0;
        char **argli;  /* Where to add the -L flags. */

        /* All we do is exec()ing ld.bin with the following dropped from argv:
         *
         * -L/usr/lib...
         * -L/lib...
         * --hash-style=both (because not supported by old ld)
         * --build-id (because not supported by old ld)
         * -z relro (because it increases the binary size and it's useless for static)
         */
        check_ld_crtoarg(argv);
        argp = args = malloc(sizeof(*args) * (argc + 5));
        *argp++ = *argv;
        for (argi = argv + 1; (arg = *argi); ++argi) {
            if (0 == strcmp(arg, "--do-xstaticldv")) {
                is_verbose = 1;
            } else if (0 == strcmp(arg, "-static")) {
                is_static = 1;
            }
        }
        if (!is_static) {
            fdprint(2, "xstatic: error: missing -static\n");
            exit(1);
        }

        *argp++ = "-nostdlib";  /* No system directories to find .a files. */
        /* Find argli: in front of the last -L (which will be removed), but no
         * later than just before the first -l.
         */
        argli = NULL;
        for (argi = argv + 1; (arg = *argi); ++argi) {
            if (arg[0] == '-') {
                if (arg[1] == 'L') {  /* "-L". */
                    argli = argi;
                } else if (arg[1] == 'l') {  /* "-l". */
                    if (!argli) argli = argi;
                    break;
                }
            }
        }
        if (!argli) argli = argv + 1;

        for (argi = argv + 1; (arg = *argi); ++argi) {
            if (argi == argli) {
                char **argj;
                /* Add the user-specified link dirs first (just like non-xstatic). */
                for (argj = argv + 1; *argj; ++argj) {
                    if (0 == strncmp(*argj, "-=L", 3)) {
                        *argp++ = strdupcat("-L", "", *argj + 3);
                    }
                }
                /* We put xstaticcld with libgcc.a first, because clang puts
                 * /usr/lib/gcc/i486-linux-gnu/4.4 with libgcc.a before /usr/lib with
                 * libc.a .
                 *
                 * We add these -L flags even if compiler -nostdlib was specified,
                 * because non-xstatic compilers do the same.
                 */
                *argp++ = strdupcat("-L", dirup, "/xstaticcld");
                *argp++ = strdupcat("-L", dirup, "/xstaticusr/lib");
                argli = NULL;  /* Don't insert the -L flags again. */
            }
            if (0 == strcmp(arg, "-z") &&
                    argi[1] && 0 == strcmp(argi[1], "relro")) {
                /* Would increase size. */
                ++argi;  /* Omit both arguments: -z relro */
            } else if (arg[0] == '-' && arg[1] == 'L') {  /* "-L". */
                if (arg[2] == '\0' && argi[1]) ++argi;
                /* Omit -L... containing the system link dirs, the user-specified link
                 * dir flags were passed as -=L...
                 */
            } else if (0 == strncmp(arg, "-=L", 3)) {
                /* Omit -=L here, gets added at position argli. */
            } else if (
                0 == strcmp(arg, "-nostdlib") ||
                0 == strcmp(arg, "--do-xstaticcld") ||
                0 == strcmp(arg, "--do-xstaticldv") ||
                0 == strncmp(arg, "--hash-style=", 13) ||  /* Would increase size. */
                0 == strcmp(arg, "--build-id") ||
                0 == strncmp(arg, "--sysroot=", 10)) {
                /* Omit this argument. */
            } else {
                *argp++ = *argi;
            }
        }
        *argp = NULL;
        prog = strdupcat(argv[0], ".bin", "");  /* "ld.bin". */
        args[0] = prog;
        if (is_verbose) {
            fdprint(2, escape_argv("xstatic-ld: info: running ld:\n", args, "\n"));
        }
        execv(prog, args);
        fdprint(2, strdupcat("xstatic-ld: error: exec failed: ", prog, "\n"));
        return 120;
    }

    if (!argv[1] || 0 == strcmp(argv[1], "--help")) {
        fdprint(1, strdupcat(
                    "Usage: ", argv[0], " <gcc|g++|clang|clang++> [<compiler-arg>...]\n"
                    "Invokes the C/C++ compiler with -static against the xstatic uClibc.\n"
                ));
        return 1;
    }
    if (argv[1][0] == '-') {
        fdprint(2, "xstatic: error: please specify gcc|clang prog in 1st arg\n");
        return 1;
    }
    check_bflags(argv);
    check_xflags(argv);
    p = strdupcat(dirup, "/xstaticcld/ld.bin", "");
    if (0 != stat(p, &st) || !S_ISREG(st.st_mode)) {
file_missing:
        fdprint(2, strdupcat(
                    "xstatic: error: file missing, please install: ", p, "\n"));
        return 123;
    }
    p = strdupcat(dirup, "/xstaticusr/lib/libc.a", "");
    if (0 != stat(p, &st) || !S_ISREG(st.st_mode)) goto file_missing;
    p = strdupcat(dirup, "/xstaticusr/include/stdio.h", "");
    if (0 != stat(p, &st) || !S_ISREG(st.st_mode)) goto file_missing;
    p = strdupcat(dirup, "/xstaticusr/lib/crt1.o", "");
    if (0 != stat(p, &st) || !S_ISREG(st.st_mode)) goto file_missing;
    p = strdupcat(dirup, "/xstaticcld/crtbeginT.o", "");
    if (0 != stat(p, &st) || !S_ISREG(st.st_mode)) goto file_missing;
    prog = find_on_path(argv[1]);
    if (!prog) {
        fdprint(2, strdupcat(
                    "xstatic: error: compiler not found: ", argv[1], "\n"));
        return 119;
    }
    argv[1] = argv[0];
    ++argv;
    --argc;
    argp = args = malloc(sizeof(*args) * (argc + 20));
    *argp++ = prog;  /* Set destination argv[0]. */
    /* No need to check for -m64, check_bflags has already done that. */
    if (!argv[1] ||
            (!argv[2] &&
             (0 == strcmp(argv[1], "-v") || 0 == strcmp(argv[1], "-m32"))) ||
            (argv[2] && !argv[3] &&
             0 == strcmp(argv[1], "-m32") &&
             0 == strcmp(argv[2], "-v"))) {
        /* This changes the `Target: ...' of Clang to i386, but of GCC. */
        if (!argv[1] || (!argv[2] && 0 != strcmp(argv[1], "-m32"))) {
            *argp++ = "-m32";
        }
        /* Don't add any flags, because the user wants some version info, and with
         * `-Wl,... -v' gcc and clang won't display version info.
         */
        memcpy(argp, argv + 1, argc * sizeof(*argp));
    } else {
        char need_linker;
        char has_nostdinc, has_nostdincxx;
        lang_t lang;
        need_linker = detect_need_linker(argv);
        detect_nostdinc(argv, &has_nostdinc, &has_nostdincxx);
        detect_lang(prog, argv, &lang);

        /* When adding more arguments here, increase the args malloc count. */
        /* We don't need get_autodetect_archflag(argv), we always send "-m32". */
        *argp++ = "-m32";
        *argp++ = "-static";
        /* The linker would be ../xstaticcld/ld, which is also a trampoline binary
         * of ours.
         */
        *argp++ = strdupcat("-B", dirup, "/xstaticcld");
        /* This puts xstaticusr/include to the top of the include path, and keeps
         * the gcc or clang headers below that. Specifying --nostdinc (when
         * lang.is_compiling) would remove these compiler-specific headers (e.g.
         * stdarg.h), which we don't want removed, because libc headers depend
         * on them.
         *
         * TODO(pts): Make /usr/local/bin/clang also work.
         */
        *argp++ = strdupcat("--sysroot=", dirup,
                            lang.is_clang && is_dirprefix(prog, "/usr/bin") ?
                            "/xstaticclangempty" : "/xstaticempty");
        if (lang.is_compiling) {
            /*
             * Without this we get the following error compiling binutils 2.20.1:
             * chew.c:(.text+0x233f): undefined reference to `__stack_chk_fail'
             * We can't implement this in a compatible way, glibc gcc generates %gs:20,
             * uClibc-0.9.33 has symbol __stack_chk_guard.
             */
            *argp++ = "-fno-stack-protector";
            if (lang.is_cxx) {
                /* Glitch: It's not possible to disable the gcc warning ``cc1: warning:
                 * command line option "-nostdinc++" is valid for C++/ObjC++ but not
                 * for C'', there is no such clang warning. Example invocation (with
                 * both .c and .cc files): ``xstatic gcc -c -W -Wall -O2 co.c
                 * hello.cc''.
                 */
                *argp++ = "-nostdinc++";
                if (!has_nostdincxx) {
                    /* Clang has -cxx-isystem, which is a no-op when compiling C code,
                     * but it adds the directory after the regular -isystem. But we need
                     * the C++ headers in front of the C headers (because of conflicting
                     * files, e.g. complex.h, tgmath.h, fenv.h).
                     *
                     * So we don't use -cxx-isystem, but we use -isystem uniformly for
                     * Clang and GCC.
                     *
                     * A small glitch: if there are both C and C++ source files
                     * specified (because C source files mustn't have C++ headers on
                     * their include path), and a non-C++ compiler is used (e.g.
                     * ``xstatic gcc -c -W -Wall -O2 helloco.c hello.cc''), then
                     * `#include <vector>' in the .c file would find the C++ vector
                     * header, and fail with a confusing error message when parsing it.
                     */
                    *argp++ = "-isystem";
                    *argp++ = strdupcat(dirup, "/xstaticusr/c++include", "");
                    /* Regular g++ libstdc++ has non-backward and then backward. */
                    *argp++ = "-isystem";
                    *argp++ = strdupcat(dirup, "/xstaticusr/c++include/backward", "");
                }
            }
            if (!has_nostdinc) {
                *argp++ = "-isystem";
                *argp++ = strdupcat(dirup, "/xstaticusr/include", "");
            }
        }

        for (argi = argv + 1; (arg = *argi); ++argi) {
            if (0 == strcmp(arg, "-v")) {
                is_verbose = 1;
                *argp++ = arg;
            } else if (0 == strcmp(arg, "-static") ||
                       0 == strcmp(arg, "-xstatic") ||
                       0 == strcmp(arg, "--xstatic") ||
                       0 == strcmp(arg, "-nostdinc") ||
                       0 == strcmp(arg, "-nostdinc++") ||
                       0 == strcmp(arg, "-m32")) {
            } else if (arg[0] == '-' && arg[1] == 'L') {  /* "-L". */
                /* Convert -L to -=L in the linker command-line on which our ld wrapper
                 * code can trigger.
                 */
                if (arg[2] == '\0' && argi[1]) {
                    *argp++ = strdupcat("-Wl,-=L", "", *++argi);
                } else {
                    *argp++ = strdupcat("-Wl,-=L", "", arg + 2);
                }
            } else {
                *argp++ = arg;
            }
        }

        if (need_linker) {
            *argp++ = "-Wl,--do-xstaticcld";
            if (is_verbose) *argp++ = "-Wl,--do-xstaticldv";
        }
        *argp++ = NULL;
    }

    if (is_verbose) {
        fdprint(2, escape_argv("xstatic: info: running compiler:\n", args, "\n"));
    }
    execv(prog, args);
    fdprint(2, strdupcat("xstatic: error: exec failed: ", prog, "\n"));
    return 120;
}
Example #3
0
int main(int argc, char **argv) {
  char python_bin[PATH_MAX + 1], argv0_bin[PATH_MAX + 1], *p, *q;
  char prog_py[PATH_MAX + 1];
  const char *moreargv[ARGV_MAX + 1];
  int i;
  (void)argc;
  p = argv[0];
  q = NULL;
  while (*p != '\0') {
    if (*p++ == FILE_SEP) q = p;
  }
  if (q == NULL) {  // Try to find argv[0] on $PATH.
    p = argv[0];
    strncpy(argv0_bin, p, sizeof argv0_bin);
    q = NULL;
    while (*p != '\0') {
      if (*p++ == '.') q = p;
    }
    if (q == NULL) {
      argv0_bin[sizeof argv0_bin - 5] = '\0';
      strcat(argv0_bin, ".exe");
    } else {
      argv0_bin[sizeof argv0_bin - 1] = '\0';
    }
    find_on_path(argv0_bin, python_bin);
  } else {  // Put dirname(argv[0]) to python_bin.
    p = argv[0];
    --q;
    if (q - p > PATH_MAX) {
      q = p + PATH_MAX;
    }
    strncpy(python_bin, p, q - p);
    python_bin[q - p] = '\0';
  }

  if (python_bin[0] == '\0') {
    python_bin[0] = '.';
    python_bin[1] = '\0';
  }
  strcpy(prog_py, python_bin);

  i = strlen(python_bin);
  if (i + strlen(python_exe) > PATH_MAX) {
    i = PATH_MAX - strlen(python_exe);
  }
  python_bin[i] = FILE_SEP;
  strcpy(python_bin + i + 1, python_exe);

  i = strlen(prog_py);
  if (i + strlen(pdfsizeopt_py) > PATH_MAX) {
    i = PATH_MAX - strlen(pdfsizeopt_py);
  }
  prog_py[i] = FILE_SEP;
  strcpy(prog_py + i + 1, pdfsizeopt_py);

  moreargv[0] = "python26";
  moreargv[1] = prog_py;
  for (i = 1; argv[i] != NULL; ++i) {
    moreargv[i + 1] = argv[i];
  }
  moreargv[i + 1] = NULL;
  

  // execv(...) and P_OVERLAY don't work well in wine-1.2.2 and Windows XP,
  // because they make this process return before the started process finishes.
  i = spawnv(P_WAIT, python_bin, moreargv);
  if (i < 0) {
    fprintf(stderr, "error: could not start %s: %s\n",
            python_bin, strerror(errno));
    return 120;
  }
  return i;
}