Droid
Droid

Reputation: 121

Is there any way I can stop my signal handler from resending the signal every 5 mins?

I'm trying to create a signal handler for a shell that I'm creating, that would send a message Background job done only once after 5 seconds using a SIGLARM and alarm() by calling a signal handler that contains the message:

Here are the relevant codes first:

This is my signal handler:

void alarm_handler(int signo) {
    printf("Background job Done\n");
}

This is the bit of my code dealing with alarms and my attempt to end the calling of the signal after one signal was called in order to avoid an infinte loop of calling signals:


                             if (runInBackground == 1) {
                                if(newcurr == 0){
                                    addJob(pid, buffernew, 0, 1);
                                    struct sigaction sar;
                                    sar.sa_flags = 0;
                                    sigemptyset(&sar.sa_mask);
                                    sar.sa_handler = alarm_handler;
                                    if (sigaction(SIGALRM, &sar, NULL) == -1) {
                                        perror("sigaction");
                                        exit(1);
                                    }
                                    alarm(5);
                                }
                                newcurr = newcurr + 1;
                                printf("\n%d\n", newcurr);
                            } 


I tried to debug and see what my code is doing and also run a background process, and this is what I get:

Starting IC shell
icsh $ sleep 4 &

1
icsh $ Background job Done

1
icsh $ Background job Done

1
icsh $ Background job Done

1
icsh $ 

So my code basically waits for 5 seconds via alarm(5) and keeps on printing endlessly instead of just once (I hope you see my attempt to solve the recurrence now).

Here is my full code if that is needed (You can skip the first 2 functions as those are not relevant to this question. Since the code is long, I've indicated where the most relevant functions are using --------- SOME COMMENT ------------ method:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <ctype.h>
#include <sys/wait.h>
#include <sys/time.h>

#define MAX_CMD_BUFFER 255
int executeScriptFile(const char *filename) {
    char buffer[MAX_CMD_BUFFER];
    char last_command[MAX_CMD_BUFFER] = "";
    int script_exit_code = 0;
    FILE *script_file = fopen(filename, "r");

    while (fgets(buffer, MAX_CMD_BUFFER, script_file) != NULL) {
        buffer[strcspn(buffer, "\n")] = '\0';

        if (strlen(buffer) == 0) {
            continue;
        }
        if (strncmp(buffer, "echo $?", 7) == 0) {
            printf("%d\n", script_exit_code);
        } else if (strncmp(buffer, "echo ", 5) == 0) {
            printf("%s\n", buffer + 5);
            strcpy(last_command, buffer);
        } else if (strcmp(buffer, "!!") == 0) {
            if (strlen(last_command) > 0) {
                FILE *command_output = popen(last_command, "r");
                if (command_output != NULL) {
                    char output_buffer[MAX_CMD_BUFFER];
                    while (fgets(output_buffer, MAX_CMD_BUFFER, command_output) != NULL) {
                        printf("%s", output_buffer);
                    }
                    pclose(command_output);
                } else {
                    printf("Error executing previous command\n");
                }
            } else {
                printf("No previous command\n");
            }
        } else if (strncmp(buffer, "exit ", 5) == 0) {
            int exit_code = atoi(buffer + 5);
            if (exit_code >= 0 && exit_code <= 255) {
                script_exit_code = exit_code;
            }
        } else {
            int command_exit_code = system(buffer);
            script_exit_code = WEXITSTATUS(command_exit_code);
            strcpy(last_command, buffer);
        }
    }

    fclose(script_file);
    return script_exit_code;
}

int script_exit_code = 0; // Global variable to store exit code

// Define global variables for foreground job tracking
int inForegroundMode = 0;
pid_t foregroundProcessGroup = -1;

void handleRedirection(char *buffer) {
        char *before_gt = strtok(buffer, ">");
        char *after_gt = strtok(NULL, ">");

        if (before_gt != NULL) {
            char cmd_copy[MAX_CMD_BUFFER];

            strncpy(cmd_copy, before_gt, sizeof(cmd_copy));
            cmd_copy[sizeof(cmd_copy) - 1] = '\0';

            if (after_gt != NULL) {
                char *trimmed_after_gt = strtok(after_gt, " \t\n");

                if (trimmed_after_gt != NULL) {
                    int file_exists = access(trimmed_after_gt, F_OK);

                    if (file_exists) {
                        FILE *file = fopen(trimmed_after_gt, "a");
                        if (file != NULL) {
                            FILE *pipe = popen(cmd_copy, "r");
                            if (pipe != NULL) {
                                char output_buffer[MAX_CMD_BUFFER];
                                memset(output_buffer, 0, sizeof(output_buffer));
                                while (fgets(output_buffer, sizeof(output_buffer), pipe) != NULL) {
                                    fprintf(file, "%s", output_buffer);
                                }
                                pclose(pipe);
                            }
                            fclose(file);
                        }
                    } else {
                        FILE *file = fopen(trimmed_after_gt, "w");
                        if (file != NULL) {
                            FILE *pipe = popen(cmd_copy, "r");
                            if (pipe != NULL) {
                                char output_buffer[MAX_CMD_BUFFER];
                                memset(output_buffer, 0, sizeof(output_buffer));
                                while (fgets(output_buffer, sizeof(output_buffer), pipe) != NULL) {
                                    fprintf(file, "%s", output_buffer);
                                }
                                pclose(pipe);
                            }
                            fclose(file);
                        }
                    }
                }
            }
        }
}
#define MAX_JOB_LIST 1000

struct JobInfo {
    int jobID;
    pid_t pid;
    char *commands;
    int isStopped;
    char *processStatus;
};

struct JobInfo jobList[MAX_JOB_LIST];
int jobID = 0;
int foregroundJob = 0;

void addJob(pid_t pid, char *command, int isStopped, int runInBackground) {
    if (jobID < MAX_JOB_LIST) {
        jobID++;
        jobList[jobID].jobID = jobID;
        jobList[jobID].commands = command;
        jobList[jobID].pid = pid;

        if (runInBackground == 1) {
            jobList[jobID].isStopped = isStopped;
            jobList[jobID].processStatus = "Running in Background";
        } else {
            foregroundJob = 1; 
            jobList[jobID].isStopped = isStopped;
            jobList[jobID].processStatus = "Running";
        }
    }
}



void listJobs() {
    for (int i = 1; i <= jobID; i++) {
        if (strcmp(jobList[i].processStatus, "Terminated") != 0) {
            printf("[%d] %d %s\n", jobList[i].jobID, jobList[i].pid,
                jobList[i].processStatus);
        }
    }
}
int contnue = 0;
bool char1 = true;
char newbuffer[MAX_CMD_BUFFER];
volatile sig_atomic_t signalreceived = 0;
volatile sig_atomic_t signal_received = 0;

char buffer[MAX_CMD_BUFFER];
int commandRunning = 0; 

struct JobInfo newJobList[MAX_JOB_LIST];

void sighandler(int sig_num) {
    if (signalreceived == 0) {
        signalreceived = sig_num;
        char1 = false;

        contnue = 0;
        signal_received = sig_num;
        int execute = 0;

        if (signal_received == SIGINT) {
            if (execute == 0) {
                for (int i = 1; i <= jobID; i++) {
                    if (strcmp(jobList[i].processStatus, "Running") == 0) {
                            foregroundJob = 1;
                    }

                    printf("\n");

                    if (foregroundJob) {
                        if (strcmp(jobList[i].processStatus, "Running") == 0) {
                            kill(jobList[i].pid, SIGINT);
                            printf("Job %d (%d) KILLED\n", jobList[i].jobID, jobList[i].pid);
                            jobList[i].processStatus = "Terminated";
                        }
                    }
                }
            execute++;
            }
        } else if (signal_received == SIGTSTP) {
            if (foregroundJob && commandRunning && (execute == 0)) {

                killpg(getpgrp(), SIGTSTP);
                tcsetpgrp(STDIN_FILENO, getpgrp());

                for (int i = 1; i <= jobID; i++) {
                    if (jobList[i].pid == getpid()) {

                        jobList[i].isStopped = 1;
                        jobList[i].processStatus = "Stopped";
                        printf("[%d] Stopped\n", jobList[i].jobID);
                        
                        break;
                    }
                }
                inForegroundMode = 1;
                execute++;
            } else {
                printf("\nNo current foreground job is SUSPENDED.\n");
            }
        }
        foregroundJob = 0;
    }
}
//----------------------Here is my signal handler ------------------------------------------------
void alarm_handler(int signo) {
    printf("Background job Done\n");
}
//------------------------------------------------------------------------------------------------
int main(int argc, char *argv[]) {
    char last_input[MAX_CMD_BUFFER];
    char last_command[MAX_CMD_BUFFER];
    signal(SIGALRM, alarm_handler);

    struct sigaction sa;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = sighandler;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTSTP, &sa, NULL);


    if (argc == 2) {
        int scriptExitCode = executeScriptFile(argv[1]);
        return scriptExitCode;
    }
    int curr = 0;
    int newcurr = curr;
    printf("Starting IC shell\n");

    while (contnue == 0) {
        printf("icsh $ ");
        fgets(buffer, MAX_CMD_BUFFER, stdin);
        strcpy(newbuffer, buffer);

        buffer[strcspn(buffer, "\n")] = '\0';
        if(char1){
            if (strlen(buffer) == 0) {
                continue;
            }
            if (strchr(buffer, '>')) {
                char buffer_copy[MAX_CMD_BUFFER];
                strcpy(buffer_copy, buffer);
                strcpy(last_command, buffer);
                handleRedirection(buffer_copy);
            }
            strcpy(last_input, buffer);

            if (strncmp(buffer, "echo ", 5) == 0) {
                if (strchr(buffer, '>')) {
                    char buffer_copy[MAX_CMD_BUFFER];
                    strcpy(buffer_copy, buffer);
                    strcpy(last_command, buffer);
                    handleRedirection(buffer_copy);
    
                } else {
                    printf("%s\n", buffer + 5);
                    strcpy(last_command, buffer);
                }
            }
            else if ((strncmp(buffer, "!!", 2) == 0) || (strncmp(buffer, "echo !!", 7) == 0)) {
                char *str = last_command;
                char *p = buffer;
                int consecutive = 0;
                while (strncmp(p, "!!", 2) == 0 || (isspace(p[0]) && strncmp(p + 1, "!!", 2) == 0)) {
                    if (strncmp(p, "!!", 2) == 0) {
                        consecutive++;
                    }
                    p += 2;
                    while (isspace(*p)) {
                        p++;
                    }
                }
                while (consecutive > 0) {
                    if (strlen(str) > 0) {
                        printf("%s\n", str);
                        system(str);
                    } else {
                        printf("No previous command\n");
                    }
                    consecutive--;
                }
            } else if (strncmp(buffer, "exit ", 5) == 0) {

                int exit_code = atoi(buffer + 5);
                if (exit_code >= 0 && exit_code <= 255) {
                    printf("bye\n");
                    return exit_code; // Exit the shell with the specified exit code
                } else 
                {
                    printf("Exit code must be in the range 0-255\n");
                }
            } else if (strncmp(buffer, "jobs", 4) == 0) {

                listJobs();

            } else {
                char *found = strchr(buffer, '>');
                newcurr = curr;

                if(found == NULL){
                    char buffernew[MAX_CMD_BUFFER];
                    strcpy(buffernew, buffer);

                    int len = strlen(buffernew);
                    commandRunning = 1;

                    pid_t pid = fork();
                    int c = 0; 

                    if (pid == 0) {
                        // Child process
                        signal(SIGTSTP, SIG_DFL);
                        signal(SIGINT, SIG_DFL);

                        // Check for '&' in the child process
                        int runInBackground = 0;
                        if (buffernew[len - 1] == '&') {
                            
                            buffernew[len - 1] = '\0'; 
                            len--; 
                            runInBackground = 1;
                        }

                        char *args[MAX_CMD_BUFFER];
                        int arg_count = 0;
                        char *token = strtok(buffernew, " ");
                        while (token != NULL) {
                            args[arg_count] = token;
                            arg_count++;
                            token = strtok(NULL, " ");
                        }
                        args[arg_count] = NULL;

                        foregroundProcessGroup = pid;
                        foregroundJob = 1;
                        execvp(args[0], args);
                    } else {
                            int status;
                            int runInBackground = 0;
                            int foregroundJob = 0;
                            int ampersandIndex = -1;
                            for (int i = 0; i < len; i++) {
                                if (buffernew[i] == '&') {
                                    ampersandIndex = i; 
                                    break; 
                                }
                            }
                            if(ampersandIndex > 0){ 
                                runInBackground = 1;
                            } else {
                                foregroundJob = 1;
                            }
  //---------------------------- Here is where my problem is ---------------------------------
                            if (runInBackground == 1) {
                                if(newcurr == 0){
                                    addJob(pid, buffernew, 0, 1);
                                    struct sigaction sar;
                                    sar.sa_flags = 0;
                                    sigemptyset(&sar.sa_mask);
                                    sar.sa_handler = alarm_handler;
                                    if (sigaction(SIGALRM, &sar, NULL) == -1) {
                                        perror("sigaction");
                                        exit(1);
                                    }
                                    alarm(5);
                                }
                                newcurr = newcurr + 1;
                                printf("\n%d\n", newcurr);
//---------------------------- -------------------------------- ---------------------------------
                            } else {
                                addJob(pid, buffer, 0, 0); 
                                waitpid(pid, &status, 0);
                                foregroundProcessGroup = getpgrp();
                                tcsetpgrp(STDIN_FILENO, foregroundProcessGroup);
                            }
                            runInBackground = 0;
                            foregroundJob = 0;
                            commandRunning = 0; 
                            c = 0;
                        }
                }
            }
            if (strcmp(buffer, "!!") != 0) {
                char *p = buffer;
                int consecutive = 0;

                while (strncmp(p, "!!", 2) == 0 || (isspace(p[0]) && strncmp(p + 1, "!!", 2) == 0)) {
                    if (strncmp(p, "!!", 2) == 0) {
                        consecutive++;
                    }
                    p += 2;
                    while (isspace(*p)) {
                        p++;
                    }
                }

                if (consecutive == 0) {
                    strcpy(last_command, buffer);
                }
            } 
            if (newcurr > 1){
                newcurr = 1;
            }
        }
        char1 = true;
    }
    curr = 0;
    printf("\nAccessed outermost\n");
    return 0;
}                      
     

Upvotes: 0

Views: 90

Answers (0)

Related Questions