#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>

#if defined(__i386__)
    #define LD "/lib/ld-linux.so.2"
#elif defined(__x86_64__)
    #define LD "/lib64/ld-linux-x86-64.so.2"
#else
    #error "expected x86"
#endif

static void execve_wrapper(const char *pgm, char *argv[], char *envp[])
{
    printf("execve(\"%s\", {", pgm);
    for (int i = 0; argv[i]; i++) {
        printf("\"%s\"%s", argv[i], (argv[i + 1]) ? ", " : "});\n\n");
    }
    fflush(stdout);
    execve(pgm, argv, envp);
    perror("execve()");
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[], char *envp[])
{
    char self[1024];
    size_t rc = readlink("/proc/self/exe", self, sizeof(self));
    if (rc == -1) {
        perror("readlink()");
        exit(EXIT_FAILURE);
    }
    self[rc] = '\0';

    printf("/proc/self/exe -> %s\n", self);
    for (int i = 0; i < argc; i++) {
        printf("argv[%i] = \"%s\"\n", i, argv[i]);
    }

    if (argc < 2) {
        puts("Мы не можем доверять argv[0], там может быть любой мусор");
        execve_wrapper(self, (char *[]){"C:\\WINDOWS\\NOTEPAD.EXE", "stage=ld", NULL}, envp);
    } else if (strcmp(argv[1], "stage=ld") == 0) {
        puts("Но /proc/self/exe мы тоже не можем доверять");
        execve_wrapper(LD, (char *[]){LD, self, "stage=done", NULL}, envp);
    } else if (strcmp(argv[1], "stage=done") == 0) {
        return 0;
    }
}
