yasar
yasar

Reputation: 13728

How to pass signals to child process

Title may be a little confusing, so let me explain. I am trying to write a simple shell to practice my programming. I have got the get a command, fork, exec loop working. However, when I press CTRL-C while child process is still executing, my shell terminates, instead of child process (but child process would keep running). Here is the main function:

int main()
{
    dynarray *args; /* pointer to a dynamic array */
    int bytes_read;
    size_t nbytes = 0;
    char *command;
    pid_t pid;
    printf("Enter command: ");
    while ((bytes_read = getline(&command, &nbytes, stdin)) != -1) {
        if (bytes_read == -1) {
            perror("getline");
            exit(EXIT_FAILURE);
        }
        pid = fork();
        if (pid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        else if (pid == 0) { /* child process */
            args = newdynarray();
            char *arg = strtok(command, " \n");
            while (arg != NULL) {
                addstring(args, arg);
                arg = strtok(NULL, " \n");
            }
            if (args->nval == 0) {
                freedynarray(args);
                continue;
            }

            addstring(args, NULL);
            char *fullpath = find_executable(args->strings[0]);
            if (fullpath == NULL) {
                fprintf(stderr, "Couldn't find executable: %s\n", command);
                exit(EXIT_FAILURE);
            }
            if (execv(fullpath, args->strings) == -1) {
                perror("execv");
                exit(EXIT_FAILURE);
            }
        } else {
            int status;
            waitpid(pid, &status, 0);
        }
        printf("Enter command: ");
    } 
    return 0;
}

I didn't include other parts, because I don't think they are relevant. How can I make my child process catch all the input from stdin until it terminates?

Upvotes: 0

Views: 2283

Answers (2)

mah
mah

Reputation: 39797

How can I make my child process catch all the input from stdin until it terminates? Signals generated from stdin keys (such as control C) will be sent to the last process to use stdin, so there's nothing you can do unless you can force your child to use the path.

Instead, you need to create a signal handler in your shell process to catch SIGINT (and others), and resend the signal (using the kill() function) to the process you want to receive it.

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 476930

You can register a signal handler for SIGINT in your parent process, and therein use kill(2) to send a signal to the child process, whose PID you should store somewhere.

Upvotes: 1

Related Questions