ocamlPackages.cpdf: 2.7.1 → 2.8 (#376363)
[NixPkgs.git] / pkgs / applications / virtualization / qemu / binfmt-p-wrapper.c
blobf956768862eca437e21c05a0331dd3619784903a
1 // This is a tiny wrapper that converts the extra arv[0] argument
2 // from binfmt-misc with the P flag enabled to QEMU parameters.
3 // It also prevents LD_* environment variables from being applied
4 // to QEMU itself.
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
11 #ifndef TARGET_QEMU
12 #error "Define TARGET_QEMU to be the path to the qemu-user binary (e.g., -DTARGET_QEMU=\"/full/path/to/qemu-riscv64\")"
13 #endif
15 extern char **environ;
17 int main(int argc, char *argv[]) {
18 if (argc < 3) {
19 fprintf(stderr, "%s: This should be run as the binfmt interpreter with the P flag\n", argv[0]);
20 fprintf(stderr, "%s: My preconfigured qemu-user binary: %s\n", argv[0], TARGET_QEMU);
21 return 1;
24 size_t environ_count = 0;
25 for (char **cur = environ; *cur != NULL; ++cur) {
26 environ_count++;
29 size_t new_argc = 3;
30 size_t new_argv_alloc = argc + 2 * environ_count + 2; // [ "-E", env ] for each LD_* env + [ "-0", argv0 ]
31 char **new_argv = (char**)malloc((new_argv_alloc + 1) * sizeof(char*));
32 if (!new_argv) {
33 fprintf(stderr, "FATAL: Failed to allocate new argv array\n");
34 abort();
37 new_argv[0] = TARGET_QEMU;
38 new_argv[1] = "-0";
39 new_argv[2] = argv[2];
41 // Pass all LD_ env variables as -E and strip them in `new_environ`
42 size_t new_environc = 0;
43 char **new_environ = (char**)malloc((environ_count + 1) * sizeof(char*));
44 if (!new_environ) {
45 fprintf(stderr, "FATAL: Failed to allocate new environ array\n");
46 abort();
49 for (char **cur = environ; *cur != NULL; ++cur) {
50 if (strncmp("LD_", *cur, 3) == 0) {
51 new_argv[new_argc++] = "-E";
52 new_argv[new_argc++] = *cur;
53 } else {
54 new_environ[new_environc++] = *cur;
57 new_environ[new_environc] = NULL;
59 size_t new_arg_start = new_argc;
60 new_argc += argc - 3 + 2; // [ "--", full_binary_path ]
62 if (argc > 3) {
63 memcpy(&new_argv[new_arg_start + 2], &argv[3], (argc - 3) * sizeof(char**));
66 new_argv[new_arg_start] = "--";
67 new_argv[new_arg_start + 1] = argv[1];
68 new_argv[new_argc] = NULL;
70 #ifdef DEBUG
71 for (size_t i = 0; i < new_argc; ++i) {
72 fprintf(stderr, "argv[%zu] = %s\n", i, new_argv[i]);
74 #endif
76 return execve(new_argv[0], new_argv, new_environ);
79 // vim: et:ts=4:sw=4