#!/bin/bash # IPC Demo using bash and terminal windows # 2019-2022 F-Hauri.ch # All this stuff is licensed under GPLV3+ # # some command to populate both stdOut and stdErr # > do ls -ld /t{mp,nt} # > do date >&2 # > do date | tee /dev/stderr # # for showing XTRACE in main console, run: # > do export BASH_XTRACEFD=$saveI;set -x # XTrm=${1:-x-terminal-emulator} declare -A X_TERMBASE='([gnome]="gnome-terminal --geometry" [konsole]="konsole --geometry" [lxterm]="lxterm -geom" [mate]="mate-terminal --geometry" [xterm]="xterm -geom" [x-terminal-emulator]="x-terminal-emulator -geometry")' declare -A X_TERMEXEC='([gnome]="--" [mate]="--" [xterm]="-e" [lxterm]="-e" [konsole]="-e" [x-terminal-emulator]="-e")' exec {logw}<> <(:) . <(echo "exec $logw> >(" # To run `xterm` instead of `gnome-terminal`, you have to swap lines, # not only comment and uncomment! Run this sed command: # sed '/^#/{N;/xterm.*geom/{ s/#\(.*\)\n\(.*\)/#\2\n\1/ }}' -i filename # xterm -T 'Log window...' -geom +1000 -e sh -c " cat <<-EOpenLog >/dev/null ${X_TERMBASE[$XTrm]} +1000 ${X_TERMEXEC[$XTrm]} bash -c " printf '\\e];Log window...\\a\\nThis is normal OUTPUT window.\\n\\n'; exec stdbuf -i0 -o0 -e0 cat /proc/$$/fd/$logw" ) EOpenLog ) sleep .2 # to ensure order of window pops exec {errw}<> <(:) . <(echo "exec $errw> >(" # xterm -T 'Error window...' -geom +1000+400 -e sh -c " cat <<-EOpenErr >/dev/null ${X_TERMBASE[$XTrm]} +1000+600 ${X_TERMEXEC[$XTrm]} bash -c " printf '\\e];Error window...\\a\\nThis is ERROR window.\\n\\n'; exec stdbuf -i0 -o0 -e0 cat /proc/$$/fd/$errw" ) EOpenErr ) sleep .2 # to ensure order of window pops exec {inw}<> >(:) . <(echo "exec $inw< <(" # xterm -T 'Input window...' -geom +1 -e bash -c " cat <<-EOpenIn >/dev/null ${X_TERMBASE[$XTrm]} +1 ${X_TERMEXEC[$XTrm]} bash -c " printf '\\e];Input window...\\a'; grep '[a-z] *) *# \|^# [^ ]' '$0'; printf '\\nThis is INPUT window, hit your commands there!\\n\\n'; HISTFILE=/tmp/ipc_dem.hist; export HISTFILE; touch \\\$HISTFILE; loop=:; while \\\$loop && history -c && history -r \\\$HISTFILE && read -e -p '> ' foo ;do tee -a <<<\"\\\$foo\" \\\$HISTFILE; [[ \\\$foo == exit ]] && loop=false; done >/proc/$$/fd/$inw" ) EOpenIn ) case $XTrm in mate | gnome ) sleep .5 # To prevent end of script before gnome-terminal hold fd. esac exec {saveI}>&1 # Save real STDOUT exec {saveE}>&2 # Save real STDERR exec 2>&$errw # Redirect STDERR to Error window exec 1>&$logw # Redirect STDOUT to Log window while [ -e /dev/fd/$inw ] && read -u $inw cmd args; do case $cmd in free | date | df | pwd | ls | uptime ) # Simple UN*X commands lastcmd=$cmd; $cmd $args;; top ) # 15 first lines of "top -n1" lastcmd=$cmd; top -n1 | head -n 15 ;; help ) # Print this lastcmd=$cmd; grep '[a-z] *) *# \|^# [^ ]' "$0" ;; do ) # Execute args via `eval` lastcmd="DO $args"; eval "$args" ;; exit ) # Exit. exec {inw}<&- # Close Input window ;; ''|'#'* ) ;; *) echo >&2 "Error: '$cmd' not defined!" ;; esac done exec 1>&$saveI # Restore STDOUT exec 2>&$saveE # Restore STDERR exec {inw}<&- # Close Input window exec {logw}>&- # Close Log window exec {errw}>&- # Close Err window exec {saveI}>&- # Release STDOUT backup exec {saveE}>&- # Release STDERR backup echo "End (last command (before exit) was: '$lastcmd'". notAcommand # This must output some error on *regular* STDERR ls -l /dev/fd/ # Everything could be back now