Skip to content

Instantly share code, notes, and snippets.

@uniphil
Last active December 4, 2016 06:24
Show Gist options
  • Save uniphil/af999f835bc7d0cf08f0791eb5093f2b to your computer and use it in GitHub Desktop.
Save uniphil/af999f835bc7d0cf08f0791eb5093f2b to your computer and use it in GitHub Desktop.
Signals helper for CISC-220
$ ./sig.sh ./shortLines poem.txt out.txt 24 USR1 USR2 USR1 USR2 INT
✎ For Whom the Bell Tolls
⚡ USR1
Input file: sig_pipe.fifo
Output file: out.txt
✎ John Donne
⚡ USR2
Lines read: 2
⚡ USR1
✎ No man is an island,
⚡ USR2
✎ Entire of itself.
⚡ INT
Exiting early!
#!/usr/bin/env bash
set -eo pipefail
red=$(printf '\033[1;31m')
yellow=$(printf '\033[1;33m')
purple=$(printf '\033[0;35m')
nocolour=$(printf '\033[0m')
usage() {
echo -e "${red}Error: $1${nocolour}\n" >&2
echo -e "Usage:\n\t$0 PROG INFILE OUTFILE LIMIT [SIGNAL,]" >&2
echo -e "Where:" >&2
echo -e "\tPROG: The executable compiled from your shortLines.c program" >&2
echo -e "\tINFILE: A sample text file to use for your program" >&2
echo -e "\tOUTFILE: The file to write out the truncated lines to" >&2
echo -e "\tLIMIT: The maximum line length before truncating" >&2
echo -e "\tSIGNAL: One or more signals to send to PROG" >&2
echo -e "\nEXAMPLE:\n\t$0 ./myProgram poem.txt out.txt 9 USR1 USR2 INT" >&2
exit 1
}
test $# -ge 4 ||\
usage "Wrong number of arguments"
PROG=$1
INFILE=$2
OUTFILE=$3
LIMIT=$4
FIFO=sig_pipe.fifo
test -e "$PROG" ||\
usage "PROG '$PROG' not found. Please provide your program's name as PROG"
test -x "$PROG" ||\
usage "PROG '$PROG' is not executable"
test -f "$INFILE" ||\
usage "INFILE not found: '$INFILE'. Please provide the path to a plain text file to use as input"
if [ -e "$OUTFILE" ] &&\
[ ! -w $OUTFILE ] ; then
usage "OUTFILE is not writable: '$OUTFILE'" ;
fi
if [ -e "$FIFO" ] &&\
[ ! -p "$FIFO" ] ; then
usage "Refusing to clobber non-fifo file '$FIFO'. Remove or rename it and try again."
fi
# if the fifo doesn't exist, create it
test -e "$FIFO" || mkfifo "$FIFO"
# Run the program with the fifo as the input file. The program just thinks it's
# a file (woo unix!).
# Reading the fifo blocks the program until we write data to it. This lets us
# send signals in between program line reads in a reliable-ish way.
"$PROG" "$FIFO" "$OUTFILE" "$LIMIT" &
PROG_PID=$!
# Alternate streaming lines and sending signals into the program
# If there are fewer lines than signals, the extra signals are ignored
SIG_INDEX=5
while read -r line ; do
# if the program exited already, don't try to keep sending it lines
if ! ps -p $PROG_PID > /dev/null ; then
break
fi
# Write out a line
# It gets redirected to the fifo by piping the loop output through tee
echo $line
# If there are more signals to send, send the next one
if [ ! -z ${!SIG_INDEX} ] ; then
sleep 0.1 # hack around race between writing a line and sending signal
echo -e "${yellow} ⚡ ${!SIG_INDEX}${nocolour}" >&2
kill -s ${!SIG_INDEX} $PROG_PID
SIG_INDEX=$((SIG_INDEX+1))
fi
done < $INFILE\
| tee "$FIFO"\
| sed "s/.*/${purple} ✎ &${nocolour}/"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment