1
#include <stdio.h>      /* popen, fileno */
 
 
2
#include <iso646.h>     /* and, or, not */
 
 
3
#include <sys/types.h>  /* DIR, opendir, stat, struct stat, waitpid,
 
 
4
                           WIFEXITED, WEXITSTATUS, wait */
 
 
5
#include <sys/wait.h>   /* wait */
 
 
6
#include <dirent.h>     /* DIR, opendir */
 
 
7
#include <sys/stat.h>   /* stat, struct stat */
 
 
8
#include <unistd.h>     /* stat, struct stat, chdir */
 
 
9
#include <stdlib.h>     /* EXIT_FAILURE */
 
 
10
#include <sys/select.h> /* fd_set, select, FD_ZERO, FD_SET, FD_ISSET */
 
 
11
#include <string.h>     /* strlen, strcpy, strcat */
 
 
12
#include <stdbool.h>    /* true */
 
 
13
#include <sys/wait.h>   /* waitpid, WIFEXITED, WEXITSTATUS */
 
 
14
#include <errno.h>      /* errno */
 
 
18
typedef struct process{
 
 
27
#define BUFFER_SIZE 256
 
 
29
int main(int argc, char *argv[]){
 
 
30
  char plugindir[] = "plugins.d";
 
 
31
  size_t d_name_len, plugindir_len = sizeof(plugindir)-1;
 
 
37
  process *process_list = NULL;
 
 
39
  dir = opendir(plugindir);
 
 
42
    fprintf(stderr, "Can not open directory\n");
 
 
51
    // All directory entries have been processed
 
 
56
    d_name_len = strlen(dirst->d_name);
 
 
58
    // Ignore dotfiles and backup files
 
 
59
    if (dirst->d_name[0] == '.'
 
 
60
        or dirst->d_name[d_name_len - 1] == '~'){
 
 
64
    char *filename = malloc(d_name_len + plugindir_len + 1);
 
 
65
    strcpy(filename, plugindir);
 
 
66
    strcat(filename, "/");
 
 
67
    strcat(filename, dirst->d_name);    
 
 
71
    if (S_ISREG(st.st_mode) and (access(filename, X_OK) == 0)){
 
 
72
      // Starting a new process to be watched
 
 
73
      process *new_process = malloc(sizeof(process));
 
 
76
      new_process->pid = fork();
 
 
77
      if(new_process->pid == 0){
 
 
78
        /* this is the child process */
 
 
80
        close(pipefd[0]);       /* close unused read end of pipe */
 
 
81
        dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */
 
 
82
        /* create a new modified argument list */
 
 
83
        char **new_argv = malloc(sizeof(char *) * argc + 1);
 
 
84
        new_argv[0] = filename;
 
 
85
        for(int i = 1; i < argc; i++){
 
 
86
          new_argv[i] = argv[i];
 
 
88
        new_argv[argc] = NULL;
 
 
89
        if(execv(filename, new_argv) < 0){
 
 
96
      close(pipefd[1]);         /* close unused write end of pipe */
 
 
97
      new_process->fd = pipefd[0];
 
 
98
      new_process->buffer = malloc(BUFFER_SIZE);
 
 
99
      if (new_process->buffer == NULL){
 
 
103
      new_process->buffer_size = BUFFER_SIZE;
 
 
104
      new_process->buffer_length = 0;
 
 
105
      FD_SET(new_process->fd, &rfds_orig);
 
 
107
      if (maxfd < new_process->fd){
 
 
108
        maxfd = new_process->fd;
 
 
112
      new_process->next = process_list;
 
 
113
      process_list = new_process;
 
 
119
  if (process_list != NULL){
 
 
121
      fd_set rfds = rfds_orig;
 
 
122
      int select_ret = select(maxfd+1, &rfds, NULL, NULL, NULL);
 
 
123
      if (select_ret == -1){
 
 
127
        for(process *process_itr = process_list; process_itr != NULL;
 
 
128
            process_itr = process_itr->next){
 
 
129
          if(FD_ISSET(process_itr->fd, &rfds)){
 
 
130
            if(process_itr->buffer_length + BUFFER_SIZE
 
 
131
               > process_itr->buffer_size){
 
 
132
                process_itr->buffer = realloc(process_itr->buffer,
 
 
133
                                              process_itr->buffer_size
 
 
135
                if (process_itr->buffer == NULL){
 
 
139
                process_itr->buffer_size += BUFFER_SIZE;
 
 
141
            ret = read(process_itr->fd, process_itr->buffer
 
 
142
                       + process_itr->buffer_length, BUFFER_SIZE);
 
 
143
            process_itr->buffer_length+=ret;
 
 
146
              /* wait for process exit */
 
 
148
              waitpid(process_itr->pid, &status, 0);
 
 
149
              if(WIFEXITED(status) and WEXITSTATUS(status) == 0){
 
 
150
                write(STDOUT_FILENO, process_itr->buffer,
 
 
151
                      process_itr->buffer_length);
 
 
154
                FD_CLR(process_itr->fd, &rfds_orig);
 
 
164
  for(process *process_itr = process_list; process_itr != NULL;
 
 
165
      process_itr = process_itr->next){
 
 
166
    close(process_itr->fd);
 
 
167
    kill(process_itr->pid, SIGTERM);
 
 
168
    free(process_itr->buffer);