////////////////////////////////////////////////////////
// Source: https://russianblogs.com/article/74521821640/
////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/wait.h>

int usage(int ver){
    printf("borndefunct 1.0\n"); if(ver) return EXIT_SUCCESS;
    printf("Copyright (c) 2023 Alex Kuryakin daqgroup@mail.ru\n");
    printf("borndefunct - parent process which born a child defunct (zombie) process.\n");
    printf("Parent process forks, wait nc (5) seconds and countdown np (300) seconds.\n");
    printf("Child process wait nc (5) seconds, die and becomes defunct Zombie.\n");
    printf("This tool uses for testing purposes.\n");
    printf("usage:\n");
    printf(" borndefunct [np] [nc]\n");
    printf("  np - number of parent loops, default 300\n");
    printf("  nc - number of child  loops, default 5\n");
    return EXIT_SUCCESS;
}

int main(int argc,char **argv){
    int np=300;
    int nc=5;
    if(argc>1){ if(strcmp(argv[1],"-h")==0) return usage(0); }
    if(argc>1){ if(strcmp(argv[1],"--help")==0) return usage(0); }
    if(argc>1){ if(strcmp(argv[1],"--version")==0) return usage(1); }
    if(argc>1){ if(atoi(argv[1])>0) np=atoi(argv[1]); }
    if(argc>2){ if(atoi(argv[2])>0) nc=atoi(argv[2]); }
    pid_t pid=fork();
    if(pid==-1) {
        printf("could not fork\n");
        return EXIT_FAILURE;
    }
    else if(pid==0) {
        printf("child  pid is %d\n",getpid());
        int i=nc;
        while(i>0) {
            printf("\rchild  countdown %-10d",i);
            fflush(stdout);
            sleep(1);
            i--;
        }
        printf("\rchild  is over and became defunct Zombie.\n");
        fflush(stdout);
    }else if(pid>0) {
        printf("parent pid is %d\n",getpid());
        sleep(nc+1);
        int i=np;
        while(i>0) {
            printf("\rparent countdown %-10d",i);
            fflush(stdout);
            sleep(1);
            i--;
        }
        int status=0; pid_t wpid=waitpid(pid,&status,WNOHANG);
        if (wpid == -1) { perror("\nwaitpid failed"); exit(EXIT_FAILURE); }
        if (WIFEXITED(status)) { printf("\rchild exited (status %d)\n", WEXITSTATUS(status)); }
        if (WIFSIGNALED(status)) { printf("\rchild killed (signal %d)\n", WTERMSIG(status)); }
        if (WIFSTOPPED(status)) { printf("\rchild stopped (signal %d)\n", WSTOPSIG(status)); }
        printf("\rparent is over and clean his child defunct Zombie.\n");
        fflush(stdout);
    }
    return EXIT_SUCCESS;
}
