#!/bin/sh

# command_client: barebones notebook interface under Unix
# Written by Serge Winitzki.
#
# Requirements: sh or bash, mkfifo, cat, tee, /dev/null
#	Usage:
#		command_client "application" [options] < inputfile
#	Note: quotes are needed around the application command if it contains spaces. Customize the variables "quit" and "extracommand" for your application.
#	On first call, a fifo pipe is created in /tmp and the target application is started in the background and set up to continuously get input from the fifo ("server mode"). On subsequent calls, input from STDIN is passed to the application. Any input given on the first call is also passed to the application. 
#	The fifo pipe is named according to the username and application name. Existence of the pipe is taken as a sign that the "server" is up and running. By definition, only one session can be run by one user on one machine.
#	The pipe should be removed when the target application quits. This can be done by "trap" function which is a bash built-in but it may not be available under other shells.
#	Option "-stop" explicitly removes the pipe and stops the server:
#		command_client "application -flags" -stop
#	Option "-pass" copies input to the ooutput
#		command_client "application -flags" -pass

############################################################
#
# Determine the command to launch interactive application
#

if [ `basename $0` = yacas_client ] ; then
	command="yacas"
	quit="quit"	# Command to quit application
	# Special setup for Yacas
	extracommand="cat -v | sed -e 's/^.*^\[\[K^M//g; s/\^M^\[\[[0-9]*C.*$//'"
else
	command="$1"	# Run application
	extracommand="cat"	# Command to prettify application output
	quit="quit"	# Command to quit application
	if [ "X$1" = X ] ; then
		echo "command_client : barebones notebook interface for Unix"
		echo "Usage: `basename $0` command [-stop] [-pass] < input"
		exit
	else
		shift
	fi
fi


#
# Make up a name of the fifo pipes based on username and command
# Note that "$fifo" may contain spaces!
#

fifo="/tmp/fifo.$USER.$command"

#
# Auxiliary files
#

curout="$fifo.tmp"
infifo="$fifo.in"

cleanup() {
	rm -f "$infifo" "$curout"
#	echo "command_client: exiting... ($1)" # Debugging
}

#
# Check if -restart option is given
#

if [ "X$1" = "X-stop" ] ; then
	[ -f "$curout" ] && cat "$curout" | eval "$extracommand"
#	echo "$quit" >> $infifo
#	sleep 2
	cleanup "stopping"
	echo "Server stopped."
	exit
fi

#
# Check if -pass option is given
#

if [ "X$1" = "X-pass" ] ; then
	pass=yes
	shift
else
	pass=no
fi

#
# Check whether we are being run the first time, i.e. whether the fifo pipe exists.
#

if [ ! -p "$infifo" ] ; then	# This is our first run
	echo "Starting server."
	# Fifo does not exist, so we have to create it
	cleanup "first run"
	mkfifo "$infifo" #"$outfifo"
	cat /dev/null > "$curout"
	# Start the "server"
#	trap cleanup 0	# traps aren't working well for us
#	(
		(
#		("$command" < "$infifo">> "$curout") &	# This doesn't work b/c of repeated opening of pipe
		while test -p "$infifo"; do
			sleep 1	# Reduce system load
			cat
		done
		echo "$quit"
		sleep 1
		) < "$infifo" | ( $command; cleanup "quit" ) >> "$curout" &
#	) &
	sleep 1
fi


#
# Pass our input to the "server" and optionally pass through to output
#

if [ "$pass" = "yes" ] ; then
	tee -a "$infifo"
else
	cat >> "$infifo"
fi

#
# Print parts of the output that aren't yet printed
#

sleep 2	# Allow some time for processing
if test -f "$curout"; then
	cat "$curout" | eval "$extracommand"
	cat /dev/null > "$curout"
fi

#
# End
#
