#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);
}
}