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 + 2);
 
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);