#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <string>
#include <vector>

#include <sys/signalfd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>

using std::map;
using std::set;
using std::string;
using std::vector;


void dfs ( int pid, map <int, vector <int> > &tree, set <int> &result, bool &change ) {
  if (result.count (pid) == 0) {
    int r = kill (pid, SIGSTOP);
    if (r != 0) {
      fprintf (stderr, "killall failed (process disappeared?): SIGSTOP to %d: %m\n", pid);
    }
    change = true;
    result.insert (pid);
  }
  for (auto x: tree[pid])
    dfs (x, tree, result, change);
}


set <int> killall_list ( int pid ) {
  int r;
  set <int> pids_to_kill;
  while (true) {
    bool change = false;
    map <int, vector <int> > tree;

    DIR *dir = opendir ("/proc");
    if (!dir) {
      fprintf (stderr, "killall failed: opendir failed: %m\n");
      break;
    }
    struct dirent *ent;
    while ((ent = readdir (dir))) {
      string name = ent->d_name;
      bool proc = true;
      for (auto c: name)
        if (!('0' <= c && c <= '9'))
          proc = false;
      if (!proc)
        continue;
      name = "/proc/" + name + "/stat";
      FILE *stat = fopen (name.c_str (), "r");
      if (!stat) {
        // process suddenly disappeared, it could be other process in system, forget it
        // fprintf (stderr, "killall failed: open (%s) failed: %m\n", name.c_str ());
        continue;
      }
      int my_pid, ppid;
      static char nonce1[1 << 18];
      char nonce2;
      r = fscanf (stat, "%d%s %c%d", &my_pid, nonce1, &nonce2, &ppid);
      if (r == 3) {
        // process with bad name, nothing to do with it
        continue;
      }
      if (r != 4) {
        fprintf (stderr, "killall failed: [pid #%s] fscanf (..) failed: [r=%d] %m\n", name.c_str(), r);
        continue;
      }
      fclose (stat);
      tree[ppid].push_back (my_pid);
    }

    dfs (pid, tree, pids_to_kill, change);

    if (!change)
      break;
  }
  return pids_to_kill;
}

void killall_do ( set <int> pids_to_kill ) {
  for (auto child: pids_to_kill) {
    int r = kill (child, SIGKILL);
    if (r != 0)
      fprintf (stderr, "kill failed: SIGKILL to %d: %m\n", child);
  }
}

int main ( int argc, char **argv ) {
  int r;
  int pid = fork ();
  if (pid < 0) {
    fprintf (stderr, "check failed: fork (): %m\n");
    printf ("CF\n");
    return 1;
  }

  if (pid == 0) {
    assert (argv[argc] == 0);
    r = execv (argv[1], argv + 1);
    assert (false);
    exit (1);
    return 1;
  }

  sigset_t mask;
  sigemptyset (&mask);
  sigaddset (&mask, SIGCHLD);
  
  r = sigprocmask (SIG_BLOCK, &mask, NULL);
  assert (r == 0);

  int sfd = signalfd (-1, &mask, 0);
  assert (sfd >= 0);

  static char buffer[2048];
  r = read (sfd, buffer, 2048);
  assert (r > 0);

  set <int> pid_list = killall_list (pid);
  int wstatus;
  r = waitpid (pid, &wstatus, 0);
  if (r != pid) {
    fprintf (stderr, "check failed: waitpid (): %m\n");
    killall_do (pid_list);
    printf ("CF\n");
    return 1;
  }

  if (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) == 0)
    return 0;

  int status = -1;
  if (WIFSIGNALED (wstatus)) {
    fprintf (stderr, "check failed: master exited with signal: %d\n", WTERMSIG (wstatus));
    status = 1;
  } else if (WIFEXITED (wstatus)) {
    status = WEXITSTATUS (wstatus);
    fprintf (stderr, "check failed: master exited with non-zero code: %d\n", status);
  } else {
    fprintf (stderr, "check failed: master exited with something strange: %d\n", wstatus);
    status = 1;
  }

  killall_do (pid_list);
  printf ("CF\n");
  return status;
}

