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
 
 
116
115
  if(name != NULL){
 
117
116
    copy_name = strdup(name);
 
118
117
    if(copy_name == NULL){
 
124
 
  *new_plugin = (plugin){ .name = copy_name,
 
127
 
                          .next = plugin_list };
 
 
122
  *new_plugin = (plugin) { .name = copy_name,
 
 
125
                           .next = plugin_list };
 
129
127
  new_plugin->argv = malloc(sizeof(char *) * 2);
 
130
128
  if(new_plugin->argv == NULL){
 
 
381
377
  error_t parse_opt(int key, char *arg, __attribute__((unused))
 
382
 
                    struct argp_state *state){
 
 
378
                    struct argp_state *state) {
 
385
380
    case 'g':                   /* --global-options */
 
388
 
        while((plugin_option = strsep(&arg, ",")) != NULL){
 
389
 
          if(plugin_option[0] == '\0'){
 
 
383
        while((p = strsep(&arg, ",")) != NULL){
 
392
 
          if(not add_argument(getplugin(NULL), plugin_option)){
 
 
387
          if(not add_argument(getplugin(NULL), p)){
 
393
388
            perror("add_argument");
 
394
389
            return ARGP_ERR_UNKNOWN;
 
 
407
402
    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)){
 
 
404
        char *p_name = strsep(&arg, ":");
 
 
405
        if(p_name[0] == '\0' or arg == NULL){
 
 
408
        char *opt = strsep(&arg, ":");
 
 
409
        if(opt[0] == '\0' or opt == NULL){
 
 
413
        while((p = strsep(&opt, ",")) != NULL){
 
 
417
          if(not add_argument(getplugin(p_name), p)){
 
416
418
            perror("add_argument");
 
417
419
            return ARGP_ERR_UNKNOWN;
 
 
463
465
      /* This is already done by parse_opt_config_file() */
 
465
467
    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){
 
 
468
      ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars);
 
 
469
      if(ret < 1 or tmpmax != (uid_t)tmpmax
 
 
470
         or arg[numchars] != '\0'){
 
470
471
        fprintf(stderr, "Bad user ID number: \"%s\", using %"
 
471
472
                PRIdMAX "\n", arg, (intmax_t)uid);
 
 
476
477
    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){
 
 
478
      ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars);
 
 
479
      if(ret < 1 or tmpmax != (gid_t)tmpmax
 
 
480
         or arg[numchars] != '\0'){
 
481
481
        fprintf(stderr, "Bad group ID number: \"%s\", using %"
 
482
482
                PRIdMAX "\n", arg, (intmax_t)gid);
 
 
511
511
     ignores everything but the --config-file option. */
 
512
512
  error_t parse_opt_config_file(int key, char *arg,
 
513
513
                                __attribute__((unused))
 
514
 
                                struct argp_state *state){
 
 
514
                                struct argp_state *state) {
 
516
516
    case 'g':                   /* --global-options */
 
517
517
    case 'G':                   /* --global-env */
 
518
518
    case 'o':                   /* --options-for */
 
 
959
958
       from one of them */
 
960
959
    for(plugin *proc = plugin_list; proc != NULL;){
 
961
960
      /* Is this process completely done? */
 
962
 
      if(proc->completed and proc->eof){
 
 
961
      if(proc->eof and proc->completed){
 
963
962
        /* Only accept the plugin output if it exited cleanly */
 
964
963
        if(not WIFEXITED(proc->status)
 
965
964
           or WEXITSTATUS(proc->status) != 0){
 
966
965
          /* Bad exit by plugin */
 
969
968
            if(WIFEXITED(proc->status)){
 
970
 
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] exited with"
 
971
 
                      " status %d\n", proc->name,
 
972
 
                      (intmax_t) (proc->pid),
 
 
969
              fprintf(stderr, "Plugin %" PRIdMAX " exited with status"
 
 
970
                      " %d\n", (intmax_t) (proc->pid),
 
973
971
                      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),
 
 
972
            } else if(WIFSIGNALED(proc->status)) {
 
 
973
              fprintf(stderr, "Plugin %" PRIdMAX " killed by signal"
 
 
974
                      " %d\n", (intmax_t) (proc->pid),
 
978
975
                      WTERMSIG(proc->status));
 
979
976
            } else if(WCOREDUMP(proc->status)){
 
980
 
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] dumped"
 
981
 
                      " core\n", proc->name, (intmax_t) (proc->pid));
 
 
977
              fprintf(stderr, "Plugin %" PRIdMAX " dumped core\n",
 
 
978
                      (intmax_t) (proc->pid));
 
985
982
          /* Remove the plugin */
 
986
983
          FD_CLR(proc->fd, &rfds_all);
 
988
985
          /* Block signal while modifying process_list */
 
989
986
          ret = sigprocmask(SIG_BLOCK, &sigchld_action.sa_mask, NULL);