#!/bin/sh # Execute a command and tag the output of the stdout and stderr streams. self=tlcs # Set the default prefixes and suffixes for stdout/err out_pref='stdout: ' err_pref='stderr: ' out_suff= err_suff= # Parse options out, give help if necessary while getopts 'co:e:' opt ; do case $opt in c) color=1 ;; o) out_pref=$OPTARG ;; e) err_pref=$OPTARG ;; \?) printf >&2 'Unknown option %s\n' "$opt" exit 2 ;; esac done shift "$((OPTIND-1))" # We need at least one more argument if [ "$#" -eq 0 ] ; then printf >&2 '%s: Need a command to run\n' "$self" exit 2 fi # If color was requested for the output, try and get a count of available # colors [ -n "$color" ] && color_count=$( { tput colors || tput Co } 2>/dev/null ) # If the color count is greater than 7, we'll color the output if [ "$((color_count >= 8))" -eq 1 ] ; then # Color code for resetting color_reset=$( { tput me || tput sgr0 } 2>/dev/null ) # If stdout is a terminal, color it if [ -t 1 ] ; then color_stdout=$( { tput AF 2 || tput setaf 2 } 2>/dev/null ) out_pref=${color_stdout}${out_pref} out_suff=${out_suff}${color_reset} fi # If stderr is a terminal, color it if [ -t 2 ] ; then color_stderr=$( { tput AF 1 || tput setaf 1 } 2>/dev/null ) err_pref=${color_stderr}${err_pref} out_suff=${err_suff}${color_reset} fi fi # Create a temporary directory with name in $td, and handle POSIX-ish traps to # remove it when the script exits. td= cleanup() { [ -n "$td" ] && rm -fr -- "$td" if [ "$1" != EXIT ] ; then trap - "$1" kill "-$1" "$$" fi } for sig in EXIT HUP INT TERM ; do # shellcheck disable=SC2064 trap "cleanup $sig" "$sig" done td=$(mktd "$self") || exit # Execute the command, passing stdout and stderr to tl(1) calls as appropriate # via named pipes out=$td/out err=$td/err mkfifo -- "$out" "$err" || exit tl -p "$out_pref" -s "$out_suff" < "$out" & tl -p "$err_pref" -s "$err_suff" < "$err" & "$@" >"$out" 2>"$err" ex=$? ; wait ; exit "$ex"