Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at devShellTools-shell 79 lines 2.4 kB view raw
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. 5 6#include <stdio.h> 7#include <stdlib.h> 8#include <string.h> 9#include <unistd.h> 10 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 14 15extern char **environ; 16 17int 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; 22 } 23 24 size_t environ_count = 0; 25 for (char **cur = environ; *cur != NULL; ++cur) { 26 environ_count++; 27 } 28 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(); 35 } 36 37 new_argv[0] = TARGET_QEMU; 38 new_argv[1] = "-0"; 39 new_argv[2] = argv[2]; 40 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(); 47 } 48 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; 55 } 56 } 57 new_environ[new_environc] = NULL; 58 59 size_t new_arg_start = new_argc; 60 new_argc += argc - 3 + 2; // [ "--", full_binary_path ] 61 62 if (argc > 3) { 63 memcpy(&new_argv[new_arg_start + 2], &argv[3], (argc - 3) * sizeof(char**)); 64 } 65 66 new_argv[new_arg_start] = "--"; 67 new_argv[new_arg_start + 1] = argv[1]; 68 new_argv[new_argc] = NULL; 69 70#ifdef DEBUG 71 for (size_t i = 0; i < new_argc; ++i) { 72 fprintf(stderr, "argv[%zu] = %s\n", i, new_argv[i]); 73 } 74#endif 75 76 return execve(new_argv[0], new_argv, new_environ); 77} 78 79// vim: et:ts=4:sw=4