Example #1
0
int main(int argc, char *argv[]) {
  if (argc == 1) {
    fprintf(stderr, "please supply at least one command to run\n");
    return 1;
  }

  install_term_and_int_handlers();

  pid_t cmds[MAX_CMDS];
  int n_cmds = 0;
  {
    char **cmd_end = argv + argc;
    char **arg_it = argv + 1;

    int wait_on_command = 1;
    int wait_on_all_commands = 1;

    // TODO: parse more commands, including -h/--help with getopt
    if (! strcmp(*arg_it, "-f")) {
      ++arg_it;
      wait_on_all_commands = 0;
    }

    char **cmd_begin = arg_it;

    for (; arg_it < cmd_end; ++arg_it) {
      if (! strcmp(*arg_it, SEP)) {
        *arg_it = 0; // replace with null to terminate when passed to execvp
        if (wait_on_command)
          cmds[n_cmds++] = run_proc(cmd_begin);
        else
          run_proc(cmd_begin);

        cmd_begin = arg_it + 1;
        wait_on_command = wait_on_all_commands;
      }
    }

    if (cmd_begin < cmd_end) {
      if (wait_on_command)
        cmds[n_cmds++] = run_proc(cmd_begin);
      else
        run_proc(cmd_begin);

      wait_on_command = wait_on_all_commands;
    }
  }

  int error_code = wait_for_requested_commands_to_exit(n_cmds, cmds);
  remove_term_and_int_handlers();
  alarm(WAIT_FOR_PROC_DEATH_TIMEOUT);
  kill(0, SIGTERM);
  wait_for_all_processes_to_exit(error_code);

# ifndef NDEBUG
  fprintf(stderr, "all processes exited cleanly\n");
# endif
  return error_code;
}
Example #2
0
static void parse_argv(ChildProcs *child_procs, Opts *opts, int argc, char *argv[]) {
  child_procs->n_cmds = 1;

  char **args_end = argv + argc;

  for (char **i = argv + 1; i < args_end; ++i) {
    if (! strcmp(*i, SEP))
      ++child_procs->n_cmds;
  }

  child_procs->cmds = calloc(child_procs->n_cmds, sizeof(Cmd));
  *opts = (Opts) { .signal_everything = false };
  parse_cmd_args(opts, child_procs->cmds, argv + 1, args_end);

  char **arg_it = child_procs->cmds->args;

  int cmd_idx = 0;
  for (; arg_it < args_end; ++arg_it) {
    if (! strcmp(*arg_it, SEP)) {
      *arg_it = 0; // replace with null to terminate when passed to execvp

      if (arg_it + 1 == args_end) {
        fprintf(stderr, "command must follow `---'\n");
        exit(1);
      }

      parse_cmd_args(opts, child_procs->cmds + (++cmd_idx), arg_it + 1, args_end);
      Cmd *cmd = child_procs->cmds + cmd_idx;
      arg_it = cmd->args - 1;
    }
  }
}

int main(int argc, char *argv[]) {
  if (argc == 1) {
    fprintf(stderr, "please supply at least one command to run\n");
    return 1;
  }

  ChildProcs child_procs;
  Opts opts;
  parse_argv(&child_procs, &opts, argc, argv);

  int n_watch_cmds = 0;
  for (int i = 0; i < child_procs.n_cmds; ++i)  {
    if (child_procs.cmds[i].watch)
      ++n_watch_cmds;
  }

  // if -f hasn't been used then watch every command
  if (0 == n_watch_cmds) {
    for (int i = 0; i < child_procs.n_cmds; ++i) {
      if (! child_procs.cmds[i].configuring) {
        ++n_watch_cmds;
        child_procs.cmds[i].watch = true;
      }
    }
  }

  Cmd **watch_cmds = calloc(n_watch_cmds, sizeof(Cmd *));
  {
    int watch_cmd_end = 0;
    for (int i = 0; i < child_procs.n_cmds; ++i) {
      if (child_procs.cmds[i].watch)
        watch_cmds[watch_cmd_end++] = child_procs.cmds + i;
    }
  }

  install_term_and_int_handlers();

  int error_code;
  run_configure_cmds(child_procs.n_cmds, child_procs.cmds);

  if (running) {
    run_cmds(child_procs.n_cmds, child_procs.cmds);
    error_code = wait_for_requested_commands_to_exit(n_watch_cmds, watch_cmds);
    remove_term_and_int_handlers();
    alarm(WAIT_FOR_PROC_DEATH_TIMEOUT);
    kill(opts.signal_everything ? -1 : 0, SIGTERM);
    wait_for_all_processes_to_exit(error_code);

    DPRINTF("all processes exited cleanly");
  }

  free(watch_cmds);
  free(child_procs.cmds);
  return error_code;
}