vfork_and_exec.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6. #include <unistd.h>
  7. int main(int argc, const char** argv, const char** envp) {
  8. pid_t child_pid;
  9. /* duplicate STDOUT into newfd and pass it as exec_victim argument
  10. * (it will be inherited by exec_victim) */
  11. int newfd = dup(1);
  12. if (newfd < 0) {
  13. perror("dup failed");
  14. return 1;
  15. }
  16. char fd_argv[12];
  17. snprintf(fd_argv, 12, "%d", newfd);
  18. char* const new_argv[] = {"./exec_victim", fd_argv, NULL};
  19. /* set environment variable to test that it is inherited by exec_victim */
  20. int ret = setenv("IN_EXECVE", "1", 1);
  21. if (ret < 0) {
  22. perror("setenv failed");
  23. return 1;
  24. }
  25. child_pid = vfork();
  26. if (child_pid == 0) {
  27. /* child performs execve(exec_victim) */
  28. execv(new_argv[0], new_argv);
  29. perror("execve failed");
  30. return 1;
  31. } else if (child_pid > 0) {
  32. /* parent waits for child termination */
  33. int status;
  34. pid_t pid = wait(&status);
  35. if (pid < 0) {
  36. perror("wait failed");
  37. return 1;
  38. }
  39. if (WIFEXITED(status))
  40. printf("child exited with status: %d\n", WEXITSTATUS(status));
  41. } else {
  42. /* error */
  43. perror("fork failed");
  44. return 1;
  45. }
  46. puts("test completed successfully");
  47. return 0;
  48. }