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