#Esercizio 5
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#define CHILD_PID 0
#define FAILED_FORK -1
#define PIPE_READ_END 0
#define PIPE_WRITE_END 1
#define FAILED_PIPE_CREATION -1
static void check_fork_succesfull_executed(pid_t pid);
static void check_pipe_succesfull_created(int pipe_code);
static int read_integer();
int main()
{
pid_t child_a, child_b;
int pipe_1_fd[2], pipe_2_fd[2];
// open two pipes
int pipe_1_creation_code = pipe(pipe_1_fd);
check_pipe_succesfull_created(pipe_1_creation_code);
int pipe_2_creation_code = pipe(pipe_2_fd);
check_pipe_succesfull_created(pipe_2_creation_code);
child_a = fork();
check_fork_succesfull_executed(child_a);
if (child_a == CHILD_PID)
{
/* Child A code */
int n_0_100;
char wrong_num_msg[] = "[!] Not a valid number in 0 100\nPlease provide one:";
// close unused pipe ends
close(pipe_2_fd[PIPE_WRITE_END]);
close(pipe_2_fd[PIPE_READ_END]);
close(pipe_1_fd[PIPE_READ_END]);
// wait for a number
printf("Enter a number between 0-100: ");
do
{
n_0_100 = read_integer(wrong_num_msg);
if (n_0_100 < 0 || n_0_100 > 100)
{
puts(wrong_num_msg);
}
} while (n_0_100 < 0 || n_0_100 > 100);
// write number to pipe and exit
char buffer[sizeof(int)];
sprintf(buffer, "%d", n_0_100);
write(pipe_1_fd[PIPE_WRITE_END], buffer, sizeof(int));
exit(EXIT_SUCCESS);
}
else
{
child_b = fork();
check_fork_succesfull_executed(child_b);
if (child_b == CHILD_PID)
{
/* Child B code */
//close unused pipes
close(pipe_1_fd[PIPE_WRITE_END]);
close(pipe_1_fd[PIPE_READ_END]);
close(pipe_2_fd[PIPE_WRITE_END]);
// read child 1 integer received from parent
char buffer[sizeof(int)];
ssize_t read_bytes = read(pipe_2_fd[PIPE_READ_END], buffer, sizeof(int));
// print received buffer
printf("I'm child two %ld and i received this number: %s\n", (long)getpid(), buffer);
exit(EXIT_SUCCESS);
}
else
{
/* Parent Code */
// close unused pipes
close(pipe_1_fd[PIPE_WRITE_END]);
close(pipe_2_fd[PIPE_READ_END]);
// read child 1 integer from pipe
char buffer[sizeof(int)];
ssize_t read_bytes = read(pipe_1_fd[PIPE_READ_END], buffer, sizeof(int));
// write it to child 2 pipe
write(pipe_2_fd[PIPE_WRITE_END], buffer, sizeof(int));
exit(EXIT_SUCCESS);
}
}
}
static void check_fork_succesfull_executed(pid_t pid)
{
if (pid == FAILED_FORK)
{
puts("[!] Fork call failed");
exit(EXIT_FAILURE);
}
}
static void check_pipe_succesfull_created(int pipe_code)
{
if (pipe_code == FAILED_PIPE_CREATION)
{
puts("[!] Pipe creation failed");
exit(EXIT_FAILURE);
}
}
#define READ_INT_BUF_SIZE 1024 // use 1KiB just to be sure
static int read_integer(char *wrong_int_msg)
{
int a;
char buf[READ_INT_BUF_SIZE];
do
{
if (!fgets(buf, READ_INT_BUF_SIZE, stdin))
{
// reading input failed, give up:
puts("[!] Error: cannot read input");
return EXIT_FAILURE;
}
// have some input, convert it to integer:
a = atoi(buf);
if (a == 0)
{
puts(wrong_int_msg);
}
} while (a == 0); // repeat until we got a valid number
return a;
}