1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <afblib/outbuf_printf.h>

/* function to be executed by a worker,
   where id is an integer in [0, # workers)
   and fd the writing end of the pipeline */
typedef void (*JobHandler)(unsigned int id, int fd);

typedef struct Worker {
   pid_t pid;
   int fd; /* reading end of the pipeline */
} Worker;

bool spawn_workers(Worker workers[], unsigned int number_of_workers,
      JobHandler handler) {
   for (unsigned int i = 0; i < number_of_workers; ++i) {
      int pipefds[2];
      if (pipe(pipefds) < 0) return false;
      pid_t child = fork();
      if (child < 0) return false;
      if (child == 0) {
	 close(pipefds[0]);
	 for (unsigned int j = 0; j < i; ++j) {
	    close(workers[i].fd);
	 }
	 handler(i, pipefds[1]);
	 exit(0);
      }
      close(pipefds[1]);
      workers[i] = (Worker) {
	 .pid = child,
	 .fd = pipefds[0],
      };
   }
   return true;
}

void do_sth(unsigned int id, int fd) {
   outbuf out = {fd};
   outbuf_printf(&out, "Greetings from worker %u!\n", id);
   outbuf_flush(&out);
}

bool copy(int in, int out) {
   char buf[8192];
   ssize_t nbytes;
   while ((nbytes = read(in, buf, sizeof buf)) > 0) {
      ssize_t written = 0;
      while (written < nbytes) {
	 ssize_t count = write(out, buf + written, nbytes - written);
	 if (count <= 0) return false;
	 written += count;
      }
   }
   return nbytes == 0;
}

#define WORKERS (10)

int main() {
   Worker workers[WORKERS];
   if (!spawn_workers(workers, WORKERS, do_sth)) {
      perror("spawn_workers"); exit(1);
   }
   for (unsigned int i = 0; i < WORKERS; ++i) {
      copy(workers[i].fd, 1); close(workers[i].fd);
      int wstat; waitpid(workers[i].pid, &wstat, 0);
   }
}