Aleksandar Čolović
Aleksandar Čolović

Reputation: 71

Bash input "read" stays open after Ctrl+C

TLDR:

read function doesn't stop reading the input after being killed by Ctrl + C, instead it waits for user input at the end of another function that comes after the one it was in.

DESCRIPTION:

So I have a loop menu style script with multiple functions, one for every option in a menu.

Now the issue in one of my functions I have these lines:

printf "Enter your choice: "
read var_boxChoice

After the "Enter your choice: " dialog pops-up and the read function starts waiting for the user input, I use the Ctrl + C keys to kill the function (which is trapped with trap 'f_menu' SIGINT command above the main menu function, so it wouldn't kill the whole script) and then I get transfered to main menu (as intended).

After that I select another function which has just this code in it:

    clear
    printf "Feature is not yet implemented! \nReturning to the main menu in 5 seconds."
    sleep 5

And then the problem occurs. Instead of once again going back to main menu, after the sleep 5 is done, the read function from the first function awaits for the user input. I know this to be the case because of the input error handling mechanism tells me that the read comes from the first function.

What do I do? How do I kill the input?

I am afraid I can't post more of the code, so I apologize ahead.

Thanks!

EDIT:

For the folks who wanted the entire code, here is the mini example I remade just for that purpose.

#!/bin/bash

var_answer1 = 0
var_answer2 = 0

f_blah1(){
    printf "Whatever 1"
    sleep 2
}

f_blah2(){
    printf "Whatever 2"
    sleep 2
}

f_option1(){
    clear
    printf "====================================================================\n"
    printf "What do you want to do?\n"
    printf "====================================================================\n"
    printf "1) Do this\n"
    printf "2) Do that\n"
    printf "====================================================================\n"
    printf "Enter your choice: "
    read var_answer2
    printf "====================================================================\n\n"
    sleep 1

    if [ "$var_answer2" -eq "1" ]; then
        f_blah1
    elif [ "$var_answer2" -eq "2" ]; then
        f_blah2
    else
        clear
        printf "====================================================================\n"
        printf "'$var_boxChoice' is not a viable answer!\nYou can only enter numbers 1 and 2!\n";
        printf "====================================================================\n"
        sleep 3
    fi
}

f_option2(){
    clear
    printf "Meh. I'm sleeping for 5 seconds. Then I'll return to main."
    sleep 5
}

trap 'f_menu' SIGINT

f_menu(){
    clear
    printf "====================================================================\n"
    printf "Select an option:\n"
    printf "====================================================================\n"
    printf "1) Option 1\n"
    printf "2) Option 2\n"
    printf "3) Quit\n"
    printf "====================================================================\n"
    printf "Enter your choice: "
    read var_answer1
    printf "====================================================================\n\n"
    sleep 0.5

    if [ "$var_answer1" -eq "1" ]; then
        f_option1
    elif [ "$var_answer1" -eq "2" ]; then
        f_option2
    elif [ "$var_answer1" -eq "3" ]; then
        printf "====================================================================\n"
        printf "Quitting the app... Thanks for using it!\n"
        printf "====================================================================\n"
        sleep 3
        clear
        exit
    else
        clear
        printf "====================================================================\n"
        printf "'$var_answer' is not a viable answer!\nYou can only enter numbers 1-3!\n";
        printf "====================================================================\n"
        sleep 2
    fi
}

while [ 1 > 0 ]
do 
    f_menu
done

Upvotes: 0

Views: 1154

Answers (1)

Barmar
Barmar

Reputation: 781210

Your trap is simply calling f_menu recursively. When it returns, you go back to where you were when the signal happened, which is in the read command.

I tried putting

trap 'continue' SIGINT

in the while loop, but that didn't work well. After typing Control-c I had to press Return for it to work.

The solution I found was to put

trap 'return' SIGINT

in each of the functions that displays a menu.

#!/bin/bash

var_answer1 = 0
var_answer2 = 0

f_blah1(){
    printf "Whatever 1"
}

f_blah2(){
    printf "Whatever 2"
}

f_option1(){
    trap 'return' SIGINT
    printf "====================================================================\n"
    printf "What do you want to do?\n"
    printf "====================================================================\n"
    printf "1) Do this\n"
    printf "2) Do that\n"
    printf "====================================================================\n"
    printf "Enter your choice: "
    read var_answer2
    printf "====================================================================\n\n"

    if [ "$var_answer2" -eq "1" ]; then
        f_blah1
    elif [ "$var_answer2" -eq "2" ]; then
        f_blah2
    else
        printf "====================================================================\n"
        printf "'$var_boxChoice' is not a viable answer!\nYou can only enter numbers 1 and 2!\n";
        printf "====================================================================\n"
    fi
}

f_option2(){
    printf "Meh. I'm sleeping for 5 seconds. Then I'll return to main.\n"
}

f_menu(){
    trap 'return' SIGINT
    printf "====================================================================\n"
    printf "Select an option:\n"
    printf "====================================================================\n"
    printf "1) Option 1\n"
    printf "2) Option 2\n"
    printf "3) Quit\n"
    printf "====================================================================\n"
    printf "Enter your choice: "
    read var_answer1
    printf "====================================================================\n\n"

    if [ "$var_answer1" -eq "1" ]; then
        f_option1
    elif [ "$var_answer1" -eq "2" ]; then
        f_option2
    elif [ "$var_answer1" -eq "3" ]; then
        printf "====================================================================\n"
        printf "Quitting the app... Thanks for using it!\n"
        printf "====================================================================\n"
        exit
    else
        printf "====================================================================\n"
        printf "'$var_answer' is not a viable answer!\nYou can only enter numbers 1-3!\n";
        printf "====================================================================\n"
    fi
}

while :
do 
    f_menu
done

Upvotes: 2

Related Questions