Answer:
a)
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
  
#define BUFSIZE 16
int main(){
    //pipe descriptors
    char msg[BUFSIZE];
    char buf[BUFSIZE];
    int pipefd[2];
    if(pipe(pipefd) == -1){
        //pipe creation error
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    //pipe creation successfull
    //write four messages
    sprintf(msg , "apple");
    write(pipefd[1], msg, BUFSIZE);
    printf("Written %s\n", msg);
    sprintf(msg , "boy");
    write(pipefd[1], msg, BUFSIZE);
    printf("Written %s\n", msg);
    sprintf(msg , "cat");
    write(pipefd[1], msg, BUFSIZE);
    printf("Written %s\n", msg);
    sprintf(msg , "dog");
    write(pipefd[1], msg, BUFSIZE);
    printf("Written %s\n", msg);
    //read
    read(pipefd[0], buf, BUFSIZE);
    printf("Read: %s\n", buf);
    read(pipefd[0], buf, BUFSIZE);
    printf("Read: %s\n", buf);
    read(pipefd[0], buf, BUFSIZE);
    printf("Read: %s\n", buf);
    read(pipefd[0], buf, BUFSIZE);
    printf("Read: %s\n", buf);
    close(pipefd[0]);
    close(pipefd[1]);
    return 0;
}
(b)
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<wait.h>
#define BUFSIZE 16
int main(){
    //pipe descriptors
    char msg[BUFSIZE];
    char buf[BUFSIZE];
    int pipefd[2];
    if(pipe(pipefd) == -1){
        //pipe creation error
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    //pipe creation successfull
    //write four messages
    if(fork() == 0){
        //this is child
        //close unused write end
        close(pipefd[1]);
        read(pipefd[0], buf, BUFSIZE);
        printf("This is child process reading first message. Content is %s\n", buf);
        read(pipefd[0], buf, BUFSIZE);
        printf("This is child process reading second message. Content is %s\n", buf);
        read(pipefd[0], buf, BUFSIZE);
        printf("This is child process reading third message. Content is %s\n", buf);
        read(pipefd[0], buf, BUFSIZE);
        printf("This is child process reading fourth message. Content is %s\n", buf);
        close(pipefd[0]);
        //exit from child
        exit(EXIT_SUCCESS);
    }
    //this is parent process
    //close unused read end
    close(pipefd[0]);
    sprintf(msg , "apple");
    printf("This is parent process. Writing first message into pipe\n");
    write(pipefd[1], msg, BUFSIZE);
    sprintf(msg , "boy");
    printf("This is parent process. Writing second message into pipe\n");
    write(pipefd[1], msg, BUFSIZE);
    sprintf(msg , "cat");
    printf("This is parent process. Writing third message into pipe\n");
    write(pipefd[1], msg, BUFSIZE);
    sprintf(msg , "dog");
    printf("This is parent process. Writing fourth message into pipe\n");
    write(pipefd[1], msg, BUFSIZE);
    close(pipefd[1]);
    //wait for child
    wait(NULL);
    return 0;
}
(c)
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<signal.h>
typedef struct sigaction Sigaction;
unsigned long long size = 0;
void alarmhandler(int sig){
    //alarm fired writing blocked
    printf("Write blocked after %llu characters\n", size);
    exit(EXIT_SUCCESS);
}
int main(){
    //pipe descriptors
    int pipefd[2];
    if(pipe(pipefd) == -1){
        //pipe creation error
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    //install handler
    sigset_t mask , prev;
    sigemptyset(&mask);
    sigaddset(&mask , SIGALRM);
    sigprocmask(SIG_BLOCK , &mask , &prev);
    Sigaction new_action;
    sigemptyset(&new_action.sa_mask);
    new_action.sa_flags = SA_RESTART;
    new_action.sa_handler = alarmhandler;
    sigaction(SIGALRM , &new_action , NULL);
    sigprocmask(SIG_SETMASK , &prev, NULL);
    while(1){
      
        //print size on multiple of 4
        if(size != 0 && size % 1024 == 0){
            printf("%llu characters in pipe\n", size);
        }
        //reset previous alarm
        alarm(0);
        //set new alarm for 5 seconds
        alarm(5);
        //write to pipe one character
        write(pipefd[1], "A", sizeof(char));
        size++;
    }
    return 0;
}
Explanation:
Output for a, b, c are pasted accordingly