2

I'm playing around with bash read functionality. I like what I have so far as a simple layer on top of my current shell. The read -e does tab-complete and previous commands, and sending EOF with ctrl+d gets me back to my original shell. Here's my reference:

Bash (or other shell): wrap all commands with function/script

I'd like some help handling SIGINT, ctrl+c. In a normal shell, if you start typing and hit ^C halfway, it immediately ends the line. For this simple example, after ^C, I still have to hit return before it's registered.

How do I keep the nice things that readline does, but still handle SIGINT correctly? Ideally, it would send a continue statement to the while read loop, or somehow send a \n to STDIN where my read is waiting.

Example code:

#!/bin/bash
# Emulate bash shell

gtg=1

function handleCtrl-C {
    # What do I do here?
    gtg=0
    return
}

trap handleCtrl-C INT

while read -e -p "> " line
do
    if [[ $gtg == 1 ]] ; then
        eval "$line"
    fi
    gtg=1
done
Community
  • 1
  • 1
CGanote
  • 149
  • 1
  • 6

2 Answers2

0

I think I came up with something finally I liked. See SIGINT to cancel read in bash script? for that answer.

CGanote
  • 149
  • 1
  • 6
-1

Reading man 7 signal tells that some system calls have a restartable flag set as a result will return back to the command

For some system calls, if a signal is caught while the call is executing and the call is prematurely terminated, the call is auto-matically restarted. Any handler installed with signal(3) will have the SA_RESTART flag set, meaning that any restartable system call will not return on receipt of a signal. The affected system calls include read(2), write(2), sendto(2), recvfrom(2),sendmsg(2), and recvmsg(2) on a communications channel or a low speed device and during a ioctl(2) or wait(2). However, calls that have already committed are not restarted, but instead return a partial success (for example, a short read count). These semantics could be changed with siginterrupt(3).

You can try printing the value input to line and verify that the read is resumed after CtrlC return until new line is hit. Type in something like "exit", followed by Ctrl-C and then "exit" the output comes out as "exitexit". Make the following change and run for the above test case

echo ">$line<"
if [ $gtg == 1 ] ; then

You'll the output as

You can verify this with a C program as well.

Aniruddh Dikhit
  • 662
  • 4
  • 10
  • I'm not sure this is what I want - if I type 'exit' and hit Ctrl-C, I want it to throw away exit and give me a new prompt. – CGanote Nov 22 '16 at 19:35