#define _GNU_SOURCE #include #include #include #include #include #include static int child(int argc, char* argv[]) { char **newargv = malloc(sizeof(char*) * argc); if (newargv == NULL) { perror("malloc"); return 1; } for (int i = 0; i < argc; i++) { newargv[i] = argv[i]; } newargv[argc] = NULL; execvp(newargv[0], newargv); perror("execvp"); return 1; } int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s [-p LD_PRELOAD] [-l LD_LIBRARY_PATH] [cmd args]\n", argv[0]); printf("\tset LD_PRELOAD to ld_preload and call execvp [cmd args]\n"); return 1; } int status, child_val; struct rusage r_usage; int i = 1; for (; i < argc; i++) { // Overwrite LD_PRELOAD. if (strncmp(argv[i], "-p", 2) == 0) { setenv("LD_PRELOAD", argv[i+1], 1); i++; // Overwrite LD_LIBRARY_PATH. } else if (strncmp(argv[i], "-l", 2) == 0) { setenv("LD_LIBRARY_PATH", argv[i+1], 1); i++; } else { break; } } pid_t child_pid = fork(); if (child_pid == 0) { return child(argc - i, &argv[i]); } else if (child_pid > 0) { /* Collect child */ wait4(child_pid, &status, 0, &r_usage); printf("child memory usage = %ld\n", r_usage.ru_maxrss); /* Get child status value */ if (WIFEXITED(status)) { child_val = WEXITSTATUS(status); exit(child_val); } } else { perror("fork"); } return 0; }