/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to plugin-runner.c

  • Committer: Teddy Hogeborn
  • Date: 2021-02-04 17:59:45 UTC
  • mto: This revision was merged to the branch mainline in revision 406.
  • Revision ID: teddy@recompile.se-20210204175945-8druo6d88ipc1z58
Fix issue with french translation

Initial white space was missing in both msgid and msgstr of the french
translation, leading to checking tools reporing an incomplete
translation.  The string is a raw key id, and therefore did not need
translation, so this was never a user-visible issue.

* debian/po/fr.po: Add missing whitespace to the id and translation
  for msgid " ${key_id}".

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Mandos plugin runner - Run Mandos plugins
4
4
 *
5
 
 * Copyright © 2008-2014 Teddy Hogeborn
6
 
 * Copyright © 2008-2014 Björn Påhlsson
7
 
 * 
8
 
 * This program is free software: you can redistribute it and/or
9
 
 * modify it under the terms of the GNU General Public License as
10
 
 * published by the Free Software Foundation, either version 3 of the
11
 
 * License, or (at your option) any later version.
12
 
 * 
13
 
 * This program is distributed in the hope that it will be useful, but
 
5
 * Copyright © 2008-2021 Teddy Hogeborn
 
6
 * Copyright © 2008-2021 Björn Påhlsson
 
7
 * 
 
8
 * This file is part of Mandos.
 
9
 * 
 
10
 * Mandos is free software: you can redistribute it and/or modify it
 
11
 * under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation, either version 3 of the License, or
 
13
 * (at your option) any later version.
 
14
 * 
 
15
 * Mandos is distributed in the hope that it will be useful, but
14
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
18
 * General Public License for more details.
17
19
 * 
18
20
 * You should have received a copy of the GNU General Public License
19
 
 * along with this program.  If not, see
20
 
 * <http://www.gnu.org/licenses/>.
 
21
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
21
22
 * 
22
23
 * Contact the authors at <mandos@recompile.se>.
23
24
 */
24
25
 
25
 
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), getline(),
26
 
                                   O_CLOEXEC, pipe2() */
 
26
#define _GNU_SOURCE             /* strchrnul(), TEMP_FAILURE_RETRY(),
 
27
                                   getline(), asprintf(), O_CLOEXEC,
 
28
                                   scandirat(), pipe2() */
 
29
#include <argp.h>               /* argp_program_version,
 
30
                                   argp_program_bug_address,
 
31
                                   struct argp_option,
 
32
                                   struct argp_state, argp_error(),
 
33
                                   ARGP_NO_EXIT, argp_state_help,
 
34
                                   ARGP_HELP_STD_HELP,
 
35
                                   ARGP_HELP_USAGE, ARGP_HELP_EXIT_OK,
 
36
                                   ARGP_KEY_ARG, ARGP_ERR_UNKNOWN,
 
37
                                   struct argp, argp_parse(),
 
38
                                   ARGP_IN_ORDER, ARGP_NO_HELP */
 
39
#include <stdbool.h>            /* bool, false, true */
 
40
#include <sys/types.h>          /* pid_t, sig_atomic_t, uid_t, gid_t,
 
41
                                   getuid(), setgid(), setuid() */
27
42
#include <stddef.h>             /* size_t, NULL */
28
 
#include <stdlib.h>             /* malloc(), exit(), EXIT_SUCCESS,
29
 
                                   realloc() */
30
 
#include <stdbool.h>            /* bool, true, false */
31
 
#include <stdio.h>              /* fileno(), fprintf(),
32
 
                                   stderr, STDOUT_FILENO, fclose() */
33
 
#include <sys/types.h>          /* fstat(), struct stat, waitpid(),
34
 
                                   WIFEXITED(), WEXITSTATUS(), wait(),
35
 
                                   pid_t, uid_t, gid_t, getuid(),
36
 
                                   getgid() */
37
 
#include <sys/select.h>         /* fd_set, select(), FD_ZERO(),
38
 
                                   FD_SET(), FD_ISSET(), FD_CLR */
39
 
#include <sys/wait.h>           /* wait(), waitpid(), WIFEXITED(),
40
 
                                   WEXITSTATUS(), WTERMSIG(),
41
 
                                   WCOREDUMP() */
42
 
#include <sys/stat.h>           /* struct stat, fstat(), S_ISREG() */
43
 
#include <iso646.h>             /* and, or, not */
44
 
#include <dirent.h>             /* struct dirent, scandirat() */
45
 
#include <unistd.h>             /* fcntl(), F_GETFD, F_SETFD,
46
 
                                   FD_CLOEXEC, write(), STDOUT_FILENO,
47
 
                                   struct stat, fstat(), close(),
48
 
                                   setgid(), setuid(), S_ISREG(),
49
 
                                   faccessat() pipe2(), fork(),
50
 
                                   _exit(), dup2(), fexecve(), read()
51
 
                                */
 
43
#include <iso646.h>             /* or, and, not */
 
44
#include <string.h>             /* strcmp(), strdup(), strchrnul(),
 
45
                                   strncmp(), strlen(), strcpy(),
 
46
                                   strsep(), strchr(), strsignal() */
 
47
#include <stdlib.h>             /* malloc(), free(), reallocarray(),
 
48
                                   realloc(), EXIT_SUCCESS */
 
49
#include <errno.h>              /* errno, EINTR, ENOMEM, ECHILD,
 
50
                                   error_t, EINVAL, EMFILE, ENFILE,
 
51
                                   ENOENT, ESRCH */
 
52
#include <stdint.h>             /* SIZE_MAX */
 
53
#define _GNU_SOURCE             /* strchrnul(), TEMP_FAILURE_RETRY(),
 
54
                                   getline(), asprintf(), O_CLOEXEC,
 
55
                                   scandirat(), pipe2() */
 
56
#include <unistd.h>             /* TEMP_FAILURE_RETRY(), ssize_t,
 
57
                                   write(), STDOUT_FILENO, uid_t,
 
58
                                   gid_t, getuid(), fchown(), close(),
 
59
                                   symlink(), setgid(), setuid(),
 
60
                                   faccessat(), X_OK, pipe(), pipe2(),
 
61
                                   fork(), _exit(), dup2(), fexecve(),
 
62
                                   read(), getpass() */
52
63
#include <fcntl.h>              /* fcntl(), F_GETFD, F_SETFD,
53
 
                                   FD_CLOEXEC, openat(), scandirat(),
54
 
                                   pipe2() */
55
 
#include <string.h>             /* strsep, strlen(), strsignal(),
56
 
                                   strcmp(), strncmp() */
57
 
#include <errno.h>              /* errno */
58
 
#include <argp.h>               /* struct argp_option, struct
59
 
                                   argp_state, struct argp,
60
 
                                   argp_parse(), ARGP_ERR_UNKNOWN,
61
 
                                   ARGP_KEY_END, ARGP_KEY_ARG,
62
 
                                   error_t */
63
 
#include <signal.h>             /* struct sigaction, sigemptyset(),
64
 
                                   sigaddset(), sigaction(),
65
 
                                   sigprocmask(), SIG_BLOCK, SIGCHLD,
66
 
                                   SIG_UNBLOCK, kill(), sig_atomic_t
67
 
                                */
68
 
#include <errno.h>              /* errno, EBADF */
69
 
#include <inttypes.h>           /* intmax_t, PRIdMAX, strtoimax() */
 
64
                                   FD_CLOEXEC, open(), O_RDONLY,
 
65
                                   O_CLOEXEC, openat() */
 
66
#include <sys/wait.h>           /* waitpid(), WNOHANG, WIFEXITED(),
 
67
                                   WEXITSTATUS(), WIFSIGNALED(),
 
68
                                   WTERMSIG(), wait() */
 
69
#include <error.h>              /* error() */
 
70
#include <stdio.h>              /* FILE, fprintf(), fopen(),
 
71
                                   getline(), fclose(), EOF,
 
72
                                   asprintf(), stderr */
 
73
#include <dirent.h>             /* struct dirent, scandirat(),
 
74
                                   alphasort() */
 
75
#include <sys/stat.h>           /* struct stat, fstat(), S_ISDIR(),
 
76
                                   lstat(), S_ISREG() */
 
77
#include <sys/select.h>         /* fd_set, FD_ZERO(), FD_SETSIZE,
 
78
                                   FD_SET(), select(), FD_CLR(),
 
79
                                   FD_ISSET() */
 
80
#include <signal.h>             /* struct sigaction, SA_NOCLDSTOP,
 
81
                                   sigemptyset(), sigaddset(),
 
82
                                   SIGCHLD, sigprocmask(), SIG_BLOCK,
 
83
                                   SIG_UNBLOCK, kill(), SIGTERM */
70
84
#include <sysexits.h>           /* EX_OSERR, EX_USAGE, EX_IOERR,
71
85
                                   EX_CONFIG, EX_UNAVAILABLE, EX_OK */
72
 
#include <errno.h>              /* errno */
73
 
#include <error.h>              /* error() */
74
 
#include <fnmatch.h>            /* fnmatch() */
 
86
#include <inttypes.h>           /* intmax_t, strtoimax(), PRIdMAX */
 
87
#include <fnmatch.h>            /* fnmatch(), FNM_FILE_NAME,
 
88
                                   FNM_PERIOD, FNM_NOMATCH */
75
89
 
76
90
#define BUFFER_SIZE 256
77
91
 
78
92
#define PDIR "/lib/mandos/plugins.d"
 
93
#define PHDIR "/lib/mandos/plugin-helpers"
79
94
#define AFILE "/conf/conf.d/mandos/plugin-runner.conf"
80
95
 
81
96
const char *argp_program_version = "plugin-runner " VERSION;
178
193
  /* Resize the pointed-to array to hold one more pointer */
179
194
  char **new_array = NULL;
180
195
  do {
181
 
    new_array = realloc(*array, sizeof(char *)
182
 
                        * (size_t) ((*len) + 2));
 
196
#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26)
 
197
    new_array = reallocarray(*array, (size_t)((*len) + 2),
 
198
                             sizeof(char *));
 
199
#else
 
200
    if(((size_t)((*len) + 2)) > (SIZE_MAX / sizeof(char *))){
 
201
      /* overflow */
 
202
      new_array = NULL;
 
203
      errno = ENOMEM;
 
204
    } else {
 
205
      new_array = realloc(*array, (size_t)((*len) + 2)
 
206
                          * sizeof(char *));
 
207
    }
 
208
#endif
183
209
  } while(new_array == NULL and errno == EINTR);
184
210
  /* Malloc check */
185
211
  if(new_array == NULL){
312
338
__attribute__((nonnull))
313
339
static void free_plugin(plugin *plugin_node){
314
340
  
315
 
  for(char **arg = plugin_node->argv; *arg != NULL; arg++){
 
341
  for(char **arg = (plugin_node->argv)+1; *arg != NULL; arg++){
316
342
    free(*arg);
317
343
  }
 
344
  free(plugin_node->name);
318
345
  free(plugin_node->argv);
319
346
  for(char **env = plugin_node->environ; *env != NULL; env++){
320
347
    free(*env);
347
374
 
348
375
int main(int argc, char *argv[]){
349
376
  char *plugindir = NULL;
 
377
  char *pluginhelperdir = NULL;
350
378
  char *argfile = NULL;
351
379
  FILE *conffp;
352
380
  struct dirent **direntries = NULL;
414
442
      .doc = "Group ID the plugins will run as", .group = 3 },
415
443
    { .name = "debug", .key = 132,
416
444
      .doc = "Debug mode", .group = 4 },
 
445
    { .name = "plugin-helper-dir", .key = 133,
 
446
      .arg = "DIRECTORY",
 
447
      .doc = "Specify a different plugin helper directory",
 
448
      .group = 2 },
417
449
    /*
418
450
     * These reproduce what we would get without ARGP_NO_HELP
419
451
     */
545
577
    case 132:                   /* --debug */
546
578
      debug = true;
547
579
      break;
 
580
    case 133:                   /* --plugin-helper-dir */
 
581
      free(pluginhelperdir);
 
582
      pluginhelperdir = strdup(arg);
 
583
      if(pluginhelperdir != NULL){
 
584
        errno = 0;
 
585
      }
 
586
      break;
548
587
      /*
549
588
       * These reproduce what we would get without ARGP_NO_HELP
550
589
       */
551
590
    case '?':                   /* --help */
552
591
      state->flags &= ~(unsigned int)ARGP_NO_EXIT; /* force exit */
553
592
      argp_state_help(state, state->out_stream, ARGP_HELP_STD_HELP);
 
593
      __builtin_unreachable();
554
594
    case -3:                    /* --usage */
555
595
      state->flags &= ~(unsigned int)ARGP_NO_EXIT; /* force exit */
556
596
      argp_state_help(state, state->out_stream,
557
597
                      ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
 
598
      __builtin_unreachable();
558
599
    case 'V':                   /* --version */
559
600
      fprintf(state->out_stream, "%s\n", argp_program_version);
560
601
      exit(EXIT_SUCCESS);
570
611
      if(arg[0] == '\0'){
571
612
        break;
572
613
      }
 
614
#if __GNUC__ >= 7
 
615
      __attribute__((fallthrough));
 
616
#else
 
617
          /* FALLTHROUGH */
 
618
#endif
573
619
    default:
574
620
      return ARGP_ERR_UNKNOWN;
575
621
    }
601
647
    case 130:                   /* --userid */
602
648
    case 131:                   /* --groupid */
603
649
    case 132:                   /* --debug */
 
650
    case 133:                   /* --plugin-helper-dir */
604
651
    case '?':                   /* --help */
605
652
    case -3:                    /* --usage */
606
653
    case 'V':                   /* --version */
686
733
        
687
734
        custom_argc += 1;
688
735
        {
689
 
          char **new_argv = realloc(custom_argv, sizeof(char *)
690
 
                                    * ((unsigned int)
691
 
                                       custom_argc + 1));
 
736
#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26)
 
737
          char **new_argv = reallocarray(custom_argv, (size_t)custom_argc + 1,
 
738
                                         sizeof(char *));
 
739
#else
 
740
          char **new_argv = NULL;
 
741
          if(((size_t)custom_argc + 1) > (SIZE_MAX / sizeof(char *))){
 
742
            /* overflow */
 
743
            errno = ENOMEM;
 
744
          } else {
 
745
            new_argv = realloc(custom_argv, ((size_t)custom_argc + 1)
 
746
                               * sizeof(char *));
 
747
          }
 
748
#endif
692
749
          if(new_argv == NULL){
693
 
            error(0, errno, "realloc");
 
750
            error(0, errno, "reallocarray");
694
751
            exitstatus = EX_OSERR;
695
752
            free(new_arg);
696
753
            free(org_line);
761
818
    goto fallback;
762
819
  }
763
820
  
 
821
  {
 
822
    char *pluginhelperenv;
 
823
    bool bret = true;
 
824
    ret = asprintf(&pluginhelperenv, "MANDOSPLUGINHELPERDIR=%s",
 
825
                   pluginhelperdir != NULL ? pluginhelperdir : PHDIR);
 
826
    if(ret != -1){
 
827
      bret = add_environment(getplugin(NULL), pluginhelperenv, true);
 
828
    }
 
829
    if(ret == -1 or not bret){
 
830
      error(0, errno, "Failed to set MANDOSPLUGINHELPERDIR"
 
831
            " environment variable to \"%s\" for all plugins\n",
 
832
            pluginhelperdir != NULL ? pluginhelperdir : PHDIR);
 
833
    }
 
834
    if(ret != -1){
 
835
      free(pluginhelperenv);
 
836
    }
 
837
  }
 
838
  
764
839
  if(debug){
765
 
    for(plugin *p = plugin_list; p != NULL; p=p->next){
 
840
    for(plugin *p = plugin_list; p != NULL; p = p->next){
766
841
      fprintf(stderr, "Plugin: %s has %d arguments\n",
767
842
              p->name ? p->name : "Global", p->argc - 1);
768
843
      for(char **a = p->argv; *a != NULL; a++){
777
852
  
778
853
  if(getuid() == 0){
779
854
    /* Work around Debian bug #633582:
780
 
       <http://bugs.debian.org/633582> */
 
855
       <https://bugs.debian.org/633582> */
781
856
    int plugindir_fd = open(/* plugindir or */ PDIR, O_RDONLY);
782
857
    if(plugindir_fd == -1){
783
858
      if(errno != ENOENT){
795
870
          }
796
871
        }
797
872
      }
798
 
      TEMP_FAILURE_RETRY(close(plugindir_fd));
 
873
      close(plugindir_fd);
 
874
    }
 
875
 
 
876
    /* Work around Debian bug #981302
 
877
       <https://bugs.debian.org/981302> */
 
878
    if(lstat("/dev/fd", &st) != 0 and errno == ENOENT){
 
879
      ret = symlink("/proc/self/fd", "/dev/fd");
 
880
      if(ret == -1){
 
881
        error(0, errno, "Failed to create /dev/fd symlink");
 
882
      }
799
883
    }
800
884
  }
801
885
  
860
944
    return 1;
861
945
  }
862
946
  
863
 
#ifdef __GLIBC__
864
 
#if __GLIBC_PREREQ(2, 15)
865
947
  int numplugins = scandirat(dir_fd, ".", &direntries, good_name,
866
948
                             alphasort);
867
 
#else  /* not __GLIBC_PREREQ(2, 15) */
868
 
  int numplugins = scandir(plugindir != NULL ? plugindir : PDIR,
869
 
                           &direntries, good_name, alphasort);
870
 
#endif  /* not __GLIBC_PREREQ(2, 15) */
871
 
#else   /* not __GLIBC__ */
872
 
  int numplugins = scandir(plugindir != NULL ? plugindir : PDIR,
873
 
                           &direntries, good_name, alphasort);
874
 
#endif  /* not __GLIBC__ */
875
949
  if(numplugins == -1){
876
950
    error(0, errno, "Could not scan plugin dir");
877
951
    direntries = NULL;
887
961
    int plugin_fd = openat(dir_fd, direntries[i]->d_name, O_RDONLY);
888
962
    if(plugin_fd == -1){
889
963
      error(0, errno, "Could not open plugin");
 
964
      free(direntries[i]);
890
965
      continue;
891
966
    }
892
967
    ret = (int)TEMP_FAILURE_RETRY(fstat(plugin_fd, &st));
893
968
    if(ret == -1){
894
969
      error(0, errno, "stat");
895
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
970
      close(plugin_fd);
 
971
      free(direntries[i]);
896
972
      continue;
897
973
    }
898
974
    
906
982
                plugindir != NULL ? plugindir : PDIR,
907
983
                direntries[i]->d_name);
908
984
      }
909
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
985
      close(plugin_fd);
 
986
      free(direntries[i]);
910
987
      continue;
911
988
    }
912
989
    
913
990
    plugin *p = getplugin(direntries[i]->d_name);
914
991
    if(p == NULL){
915
992
      error(0, errno, "getplugin");
916
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
993
      close(plugin_fd);
 
994
      free(direntries[i]);
917
995
      continue;
918
996
    }
919
997
    if(p->disabled){
921
999
        fprintf(stderr, "Ignoring disabled plugin \"%s\"\n",
922
1000
                direntries[i]->d_name);
923
1001
      }
924
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
1002
      close(plugin_fd);
 
1003
      free(direntries[i]);
925
1004
      continue;
926
1005
    }
927
1006
    {
960
1039
    if(ret == -1){
961
1040
      error(0, errno, "pipe");
962
1041
      exitstatus = EX_OSERR;
 
1042
      free(direntries[i]);
963
1043
      goto fallback;
964
1044
    }
965
1045
    if(pipefd[0] >= FD_SETSIZE){
966
1046
      fprintf(stderr, "pipe()[0] (%d) >= FD_SETSIZE (%d)", pipefd[0],
967
1047
              FD_SETSIZE);
968
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
969
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1048
      close(pipefd[0]);
 
1049
      close(pipefd[1]);
970
1050
      exitstatus = EX_OSERR;
 
1051
      free(direntries[i]);
971
1052
      goto fallback;
972
1053
    }
973
1054
#ifndef O_CLOEXEC
975
1056
    ret = set_cloexec_flag(pipefd[0]);
976
1057
    if(ret < 0){
977
1058
      error(0, errno, "set_cloexec_flag");
978
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
979
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1059
      close(pipefd[0]);
 
1060
      close(pipefd[1]);
980
1061
      exitstatus = EX_OSERR;
 
1062
      free(direntries[i]);
981
1063
      goto fallback;
982
1064
    }
983
1065
    ret = set_cloexec_flag(pipefd[1]);
984
1066
    if(ret < 0){
985
1067
      error(0, errno, "set_cloexec_flag");
986
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
987
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1068
      close(pipefd[0]);
 
1069
      close(pipefd[1]);
988
1070
      exitstatus = EX_OSERR;
 
1071
      free(direntries[i]);
989
1072
      goto fallback;
990
1073
    }
991
1074
#endif  /* not O_CLOEXEC */
996
1079
    if(ret < 0){
997
1080
      error(0, errno, "sigprocmask");
998
1081
      exitstatus = EX_OSERR;
 
1082
      free(direntries[i]);
999
1083
      goto fallback;
1000
1084
    }
1001
1085
    /* Starting a new process to be watched */
1007
1091
      error(0, errno, "fork");
1008
1092
      TEMP_FAILURE_RETRY(sigprocmask(SIG_UNBLOCK,
1009
1093
                                     &sigchld_action.sa_mask, NULL));
1010
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1011
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1094
      close(pipefd[0]);
 
1095
      close(pipefd[1]);
1012
1096
      exitstatus = EX_OSERR;
 
1097
      free(direntries[i]);
1013
1098
      goto fallback;
1014
1099
    }
1015
1100
    if(pid == 0){
1041
1126
      /* no return */
1042
1127
    }
1043
1128
    /* Parent process */
1044
 
    TEMP_FAILURE_RETRY(close(pipefd[1])); /* Close unused write end of
1045
 
                                             pipe */
1046
 
    TEMP_FAILURE_RETRY(close(plugin_fd));
 
1129
    close(pipefd[1]);           /* Close unused write end of pipe */
 
1130
    close(plugin_fd);
1047
1131
    plugin *new_plugin = getplugin(direntries[i]->d_name);
1048
1132
    if(new_plugin == NULL){
1049
1133
      error(0, errno, "getplugin");
1054
1138
        error(0, errno, "sigprocmask");
1055
1139
      }
1056
1140
      exitstatus = EX_OSERR;
 
1141
      free(direntries[i]);
1057
1142
      goto fallback;
1058
1143
    }
 
1144
    free(direntries[i]);
1059
1145
    
1060
1146
    new_plugin->pid = pid;
1061
1147
    new_plugin->fd = pipefd[0];
1062
 
    
 
1148
 
 
1149
    if(debug){
 
1150
      fprintf(stderr, "Plugin %s started (PID %" PRIdMAX ")\n",
 
1151
              new_plugin->name, (intmax_t) (new_plugin->pid));
 
1152
    }
 
1153
 
1063
1154
    /* Unblock SIGCHLD so signal handler can be run if this process
1064
1155
       has already completed */
1065
1156
    ret = (int)TEMP_FAILURE_RETRY(sigprocmask(SIG_UNBLOCK,
1071
1162
      goto fallback;
1072
1163
    }
1073
1164
    
1074
 
#if defined (__GNUC__) and defined (__GLIBC__)
1075
 
#if not __GLIBC_PREREQ(2, 16)
1076
 
#pragma GCC diagnostic push
1077
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1078
 
#endif
1079
 
#endif
1080
 
    FD_SET(new_plugin->fd, &rfds_all); /* Spurious warning from
1081
 
                                          -Wconversion in GNU libc
1082
 
                                          before 2.16 */
1083
 
#if defined (__GNUC__) and defined (__GLIBC__)
1084
 
#if not __GLIBC_PREREQ(2, 16)
1085
 
#pragma GCC diagnostic pop
1086
 
#endif
1087
 
#endif
 
1165
    FD_SET(new_plugin->fd, &rfds_all);
1088
1166
    
1089
1167
    if(maxfd < new_plugin->fd){
1090
1168
      maxfd = new_plugin->fd;
1093
1171
  
1094
1172
  free(direntries);
1095
1173
  direntries = NULL;
1096
 
  TEMP_FAILURE_RETRY(close(dir_fd));
 
1174
  close(dir_fd);
1097
1175
  dir_fd = -1;
1098
1176
  free_plugin(getplugin(NULL));
1099
1177
  
1139
1217
                      (intmax_t) (proc->pid),
1140
1218
                      WTERMSIG(proc->status),
1141
1219
                      strsignal(WTERMSIG(proc->status)));
1142
 
            } else if(WCOREDUMP(proc->status)){
1143
 
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] dumped"
1144
 
                      " core\n", proc->name, (intmax_t) (proc->pid));
1145
1220
            }
1146
1221
          }
1147
1222
          
1148
1223
          /* Remove the plugin */
1149
 
#if defined (__GNUC__) and defined (__GLIBC__)
1150
 
#if not __GLIBC_PREREQ(2, 16)
1151
 
#pragma GCC diagnostic push
1152
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1153
 
#endif
1154
 
#endif
1155
 
          FD_CLR(proc->fd, &rfds_all); /* Spurious warning from
1156
 
                                          -Wconversion in GNU libc
1157
 
                                          before 2.16 */
1158
 
#if defined (__GNUC__) and defined (__GLIBC__)
1159
 
#if not __GLIBC_PREREQ(2, 16)
1160
 
#pragma GCC diagnostic pop
1161
 
#endif
1162
 
#endif
 
1224
          FD_CLR(proc->fd, &rfds_all);
1163
1225
          
1164
1226
          /* Block signal while modifying process_list */
1165
1227
          ret = (int)TEMP_FAILURE_RETRY(sigprocmask
1205
1267
      }
1206
1268
      
1207
1269
      /* This process has not completed.  Does it have any output? */
1208
 
#if defined (__GNUC__) and defined (__GLIBC__)
1209
 
#if not __GLIBC_PREREQ(2, 16)
1210
 
#pragma GCC diagnostic push
1211
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1212
 
#endif
1213
 
#endif
1214
 
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){ /* Spurious
1215
 
                                                         warning from
1216
 
                                                         -Wconversion
1217
 
                                                         in GNU libc
1218
 
                                                         before
1219
 
                                                         2.16 */
1220
 
#if defined (__GNUC__) and defined (__GLIBC__)
1221
 
#if not __GLIBC_PREREQ(2, 16)
1222
 
#pragma GCC diagnostic pop
1223
 
#endif
1224
 
#endif
 
1270
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){
1225
1271
        /* This process had nothing to say at this time */
1226
1272
        proc = proc->next;
1227
1273
        continue;
1297
1343
  free(direntries);
1298
1344
  
1299
1345
  if(dir_fd != -1){
1300
 
    TEMP_FAILURE_RETRY(close(dir_fd));
 
1346
    close(dir_fd);
1301
1347
  }
1302
1348
  
1303
1349
  /* Kill the processes */
1323
1369
  free_plugin_list();
1324
1370
  
1325
1371
  free(plugindir);
 
1372
  free(pluginhelperdir);
1326
1373
  free(argfile);
1327
1374
  
1328
1375
  return exitstatus;