TFBReaper.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #define _DEFAULT_SOURCE
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/prctl.h>
  5. #include <sys/syscall.h>
  6. #include <string.h>
  7. int main(int argc, char *argv[])
  8. {
  9. // Gather the command line arguments for the pass-through.
  10. int count = argc - 1;
  11. int *sizes = malloc(sizeof(int) * count);
  12. int total_size = 0;
  13. for( int i = 1; i < argc; i++ ) {
  14. sizes[i - 1] = strlen(argv[i]);
  15. total_size += sizes[i - 1];
  16. }
  17. char *result = malloc(sizeof(char) * total_size + count);
  18. char *ptr = result;
  19. for( int i = 1; i < argc; i++ ) {
  20. memcpy(ptr, argv[i], sizes[i - 1]);
  21. ptr[sizes[i - 1]] = ' ';
  22. ptr += sizes[i - 1] + 1;
  23. }
  24. *ptr = '\0';
  25. free(sizes);
  26. // Here is the magic. This sets any child processes to
  27. // use THIS process as a 'subreaper'. What that means is
  28. // even if the process uses the fork-exit technicque for
  29. // running a daemon (which normally orphans the process
  30. // and causes init(1) to adopt it, which is problematic
  31. // for TFB because we cannot then generally kill the
  32. // process since it has lost all context available to us)
  33. // the child process will have the parent id of THIS
  34. // process, allowing us to kill all the processes started
  35. // by the suite in this way generally.
  36. //
  37. // See: http://man7.org/linux/man-pages/man2/prctl.2.html
  38. prctl(PR_SET_CHILD_SUBREAPER,1);
  39. // This invokes whatever was passed as arguments to TFBReaper
  40. // on the system. This program is merely a pass-through to
  41. // a shell with the subreaper stuff enabled.
  42. int ret = system(result);
  43. // We need to wait forever; the suite will clean this
  44. // process up later.
  45. if (ret == 0) {
  46. for(;;) {
  47. // Pause to keep us from spiking CPU; whenever a signal
  48. // occurs (except SIGTERM etc which will kill this process)
  49. // just iterate and pause again.
  50. pause();
  51. }
  52. }
  53. // If the scripts failed, we should return that code.
  54. return ret;
  55. }