#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>

// Define a structure for process nodes
typedef struct ProcessNode {
    unsigned long pid;
    unsigned long ppid;
    long elapsed_time;
    int isDefunct;
    int defunct_children_count;
    struct ProcessNode *next;
} ProcessNode;

// Function prototypes
ProcessNode *create_process(unsigned long pid, unsigned long ppid, long elapsed_time, int isDefunct);
void insert_process(ProcessNode **head, ProcessNode *new_process);
void read_processes(ProcessNode **head);
int process_exists(ProcessNode *head, unsigned long pid);
ProcessNode *get_process(ProcessNode *head, unsigned long pid);
void terminate_parents(ProcessNode *head, unsigned long root_pid, int option1, int option2, unsigned long exclude_pid);

// Main function
int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, “Usage: deftreeminus [root_process] [OPTION1] [OPTION2] [-processid]\n”);
        return 1;
    }

    ProcessNode *head = NULL;

    read_processes(&head);

    unsigned long root_pid = strtoul(argv[1], NULL, 10);
    if (!process_exists(head, root_pid)) {
        fprintf(stderr, “Invalid root process.\n”);
        return 1;
    }

    unsigned long exclude_pid = 0;
    int option1 = 0;
    int option2 = 0;
    if (argc > 3) {
        if (argv[argc - 1][0] == ‘-’) {
            exclude_pid = strtoul(argv[argc - 1] + 1, NULL, 10);
            if (!process_exists(head, exclude_pid)) {
                fprintf(stderr, “Invalid exclude process ID.\n”);
                return 1;
            }
        }
        if (strcmp(argv[2], “-t”) == 0) {
            option1 = 1;
        } else if (strcmp(argv[2], “-b”) == 0) {
            option1 = 2;
        } else {
            fprintf(stderr, “Invalid OPTION1 value.\n”);
            return 1;
        }

        option2 = atoi(argv[3]);
        if (option2 < 1) {
            fprintf(stderr, “Invalid OPTION2 value.\n”);
            return 1;
        }
    }

    terminate_parents(head, root_pid, option1, option2, exclude_pid);

    return 0;
}

// Function to create a process node
ProcessNode *create_process(unsigned long pid, unsigned long ppid, long elapsed_time, int isDefunct) {
    ProcessNode *process = malloc(sizeof(ProcessNode));
    process->pid = pid;
    process->ppid = ppid;
    process->elapsed_time = elapsed_time;
    process->isDefunct = isDefunct;
    process->defunct_children_count = 0;
    process->next = NULL;
    return process;
}

// Function to insert a process node into the process list
void insert_process(ProcessNode **head, ProcessNode *new_process) {
    new_process->next = *head;
    *head = new_process;
}

// Function to read process information from the /proc directory
void read_processes(ProcessNode **head) {
    DIR *proc_dir;
    struct dirent *dir;
    FILE *fp;
    unsigned long pid, ppid;
    int isDefunct;
    char status, buffer[128];

    proc_dir = opendir(“/proc”);

    if (proc_dir == NULL) {
        perror(“Cannot open /proc directory”);
        return;
    }

    while ((dir = readdir(proc_dir)) != NULL) {
        pid = strtoul(dir->d_name, NULL, 10);

        //read the status file
        snprintf(buffer, sizeof(buffer), “/proc/%lu/status”, pid);
        fp = fopen(buffer, “r”);
        if (fp != NULL) {
            isDefunct = 0;
            struct stat stat_buf;
            stat(buffer, &stat_buf);
            long elapsed_time = (time(NULL) - stat_buf.st_ctime) / 60;

            while (fscanf(fp, “%s”, buffer) != EOF) {
                if (strcmp(buffer, “PPid:”) == 0) {
                    fscanf(fp, “%lu”, &ppid);
                } else if (strcmp(buffer, “State:”) == 0) {
                    fscanf(fp, " %c", &status);
                    if (status == ‘Z’) {
                        isDefunct = 1;
                    }
                }
            }
            ProcessNode *new_process = create_process(pid, ppid, elapsed_time, isDefunct);
            insert_process(head, new_process);
            fclose(fp);
        }
    }

    closedir(proc_dir);

    // Calculate defunct_children_count for each process
    ProcessNode *current = *head;
    while (current != NULL) {
        if (current->isDefunct) {
            ProcessNode *parent = get_process(*head, current->ppid);
            if (parent != NULL) {
                parent->defunct_children_count++;
            }
        }
        current = current->next;
    }
}

// Function to check if a process exists in the process list
int process_exists(ProcessNode *head, unsigned long pid) {
    while (head != NULL) {
        if (head->pid == pid) {
            return 1;
        }
        head = head->next;
    }
    return 0;
}

// Function to get a process from the process list by PID
ProcessNode *get_process(ProcessNode *head, unsigned long pid) {
    while (head != NULL) {
        if (head->pid == pid) {
            return head;
        }
        head = head->next;
    }
    return NULL;
}

// Function to forcefully terminate parent processes of defunct processes in the process tree
void terminate_parents(ProcessNode *head, unsigned long root_pid, int option1, int option2, unsigned long exclude_pid) {
    ProcessNode *current = head;
    while (current != NULL) {
        if (current->isDefunct && current->ppid != exclude_pid && process_exists(head, current->ppid)) {
            ProcessNode *parent = get_process(head, current->ppid);
            if (parent != NULL && parent->pid != root_pid && parent->pid != getpid()) {
                int terminate = 1;
                if (option1 == 1) { // OPTION1: -t
                    terminate = parent->elapsed_time > option2;
                } else if (option1 == 2) { // OPTION1: -b
                    terminate = parent->defunct_children_count >= option2;
                }

                if (terminate) {
                    printf(“Terminating parent process with PID: %lu\n”, parent->pid);
                    kill(parent->pid, SIGKILL);
                }
            }
        }
        current = current->next;
    }
}

change the code implementation to make it more simpler