62
62
#include <signal.h>             /* struct sigaction, sigemptyset(),
 
63
63
                                   sigaddset(), sigaction(),
 
64
64
                                   sigprocmask(), SIG_BLOCK, SIGCHLD,
 
65
 
                                   SIG_UNBLOCK, kill() */
 
 
65
                                   SIG_UNBLOCK, kill(), sig_atomic_t
 
66
67
#include <errno.h>              /* errno, EBADF */
 
67
 
#include <inttypes.h>           /* intmax_t, SCNdMAX, PRIdMAX,  */
 
 
68
#include <inttypes.h>           /* intmax_t, PRIdMAX, strtoimax() */
 
69
70
#define BUFFER_SIZE 256
 
 
123
 
  *new_plugin = (plugin) { .name = copy_name,
 
126
 
                           .next = plugin_list };
 
 
124
  *new_plugin = (plugin){ .name = copy_name,
 
 
127
                          .next = plugin_list };
 
128
129
  new_plugin->argv = malloc(sizeof(char *) * 2);
 
129
130
  if(new_plugin->argv == NULL){
 
 
378
381
  error_t parse_opt(int key, char *arg, __attribute__((unused))
 
379
 
                    struct argp_state *state) {
 
 
382
                    struct argp_state *state){
 
381
385
    case 'g':                   /* --global-options */
 
384
 
        while((p = strsep(&arg, ",")) != NULL){
 
 
388
        while((plugin_option = strsep(&arg, ",")) != NULL){
 
 
389
          if(plugin_option[0] == '\0'){
 
388
 
          if(not add_argument(getplugin(NULL), p)){
 
 
392
          if(not add_argument(getplugin(NULL), plugin_option)){
 
389
393
            perror("add_argument");
 
390
394
            return ARGP_ERR_UNKNOWN;
 
 
403
407
    case 'o':                   /* --options-for */
 
405
 
        char *p_name = strsep(&arg, ":");
 
406
 
        if(p_name[0] == '\0' or arg == NULL){
 
409
 
        char *opt = strsep(&arg, ":");
 
410
 
        if(opt[0] == '\0' or opt == NULL){
 
414
 
        while((p = strsep(&opt, ",")) != NULL){
 
418
 
          if(not add_argument(getplugin(p_name), p)){
 
 
409
        char *plugin_name = strsep(&arg, ":");
 
 
410
        if(plugin_name[0] == '\0'){
 
 
414
        while((plugin_option = strsep(&arg, ",")) != NULL){
 
 
415
          if(not add_argument(getplugin(plugin_name), plugin_option)){
 
419
416
            perror("add_argument");
 
420
417
            return ARGP_ERR_UNKNOWN;
 
 
466
463
      /* This is already done by parse_opt_config_file() */
 
468
465
    case 130:                   /* --userid */
 
469
 
      ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars);
 
470
 
      if(ret < 1 or tmpmax != (uid_t)tmpmax
 
471
 
         or arg[numchars] != '\0'){
 
 
467
      tmpmax = strtoimax(arg, &tmp, 10);
 
 
468
      if(errno != 0 or tmp == arg or *tmp != '\0'
 
 
469
         or tmpmax != (uid_t)tmpmax){
 
472
470
        fprintf(stderr, "Bad user ID number: \"%s\", using %"
 
473
471
                PRIdMAX "\n", arg, (intmax_t)uid);
 
 
478
476
    case 131:                   /* --groupid */
 
479
 
      ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars);
 
480
 
      if(ret < 1 or tmpmax != (gid_t)tmpmax
 
481
 
         or arg[numchars] != '\0'){
 
 
478
      tmpmax = strtoimax(arg, &tmp, 10);
 
 
479
      if(errno != 0 or tmp == arg or *tmp != '\0'
 
 
480
         or tmpmax != (gid_t)tmpmax){
 
482
481
        fprintf(stderr, "Bad group ID number: \"%s\", using %"
 
483
482
                PRIdMAX "\n", arg, (intmax_t)gid);
 
 
512
511
     ignores everything but the --config-file option. */
 
513
512
  error_t parse_opt_config_file(int key, char *arg,
 
514
513
                                __attribute__((unused))
 
515
 
                                struct argp_state *state) {
 
 
514
                                struct argp_state *state){
 
517
516
    case 'g':                   /* --global-options */
 
518
517
    case 'G':                   /* --global-env */
 
519
518
    case 'o':                   /* --options-for */
 
 
959
959
       from one of them */
 
960
960
    for(plugin *proc = plugin_list; proc != NULL;){
 
961
961
      /* Is this process completely done? */
 
962
 
      if(proc->eof and proc->completed){
 
 
962
      if(proc->completed and proc->eof){
 
963
963
        /* Only accept the plugin output if it exited cleanly */
 
964
964
        if(not WIFEXITED(proc->status)
 
965
965
           or WEXITSTATUS(proc->status) != 0){
 
966
966
          /* Bad exit by plugin */
 
969
969
            if(WIFEXITED(proc->status)){
 
970
 
              fprintf(stderr, "Plugin %" PRIdMAX " exited with status"
 
971
 
                      " %d\n", (intmax_t) (proc->pid),
 
 
970
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] exited with"
 
 
971
                      " status %d\n", proc->name,
 
 
972
                      (intmax_t) (proc->pid),
 
972
973
                      WEXITSTATUS(proc->status));
 
973
 
            } else if(WIFSIGNALED(proc->status)) {
 
974
 
              fprintf(stderr, "Plugin %" PRIdMAX " killed by signal"
 
975
 
                      " %d\n", (intmax_t) (proc->pid),
 
 
974
            } else if(WIFSIGNALED(proc->status)){
 
 
975
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] killed by"
 
 
976
                      " signal %d\n", proc->name,
 
 
977
                      (intmax_t) (proc->pid),
 
976
978
                      WTERMSIG(proc->status));
 
977
979
            } else if(WCOREDUMP(proc->status)){
 
978
 
              fprintf(stderr, "Plugin %" PRIdMAX " dumped core\n",
 
979
 
                      (intmax_t) (proc->pid));
 
 
980
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] dumped"
 
 
981
                      " core\n", proc->name, (intmax_t) (proc->pid));
 
983
985
          /* Remove the plugin */
 
984
986
          FD_CLR(proc->fd, &rfds_all);
 
986
988
          /* Block signal while modifying process_list */
 
987
989
          ret = sigprocmask(SIG_BLOCK, &sigchld_action.sa_mask, NULL);