#!/usr/bin/env ksh # $Id: sapply.ksh,v 1.9 2008/07/31 13:25:29 ksb Exp $ # xapply across -Pn screens, use the present one as a status display, unless # -s is provided. The operational model here is a little unclear, without # some comments. We start a "slave screen" on some empty windows, if you # run out of windows we kinda puke. Sorry. -- ksb # # We are going to make a FIFO for each slave screen we start, so we'll do # that after we process the options. The we are going to start a little # service on each FIFO to launch commands and wait for the results. We'll # use a ptbw to deliver commands to the slave sessions, then poision them # with a "exit" or "kill" command, which will tell us we are done. Wow. # progname=`basename $0` usage="$progname: usage [-fz] [-nsuv] [-count] [-a c] [-i input] [-N else] [-p pad] [-Pjobs] cmd [args]" SAP_TDIR=/tmp/sap$$,$((RANDOM%100)) while ! mkdir -m 0700 $SAP_TDIR ; do SAP_TDIR="$SAP_TDIR-$((RANDOM%1000))" done trap 'rm -rf $SAP_TDIR' EXIT # Read an environment variable as well as the command line options: # protect this script from leading -x's with a bogus underbar, then remove it set _ $SAPPLY ${1+"$@"} shift # get the options from the command line (+ any variables) slide='P=$1; shift; set _ -`expr _"$P" : _'\''-.\(.*\)'\''` ${1+"$@"}; shift' param='if [ $# -lt 2 ]; then echo "$progname: missing value for $1" 1>&2 ; exit 64; fi' SAP_PRE="" SAP_RUN="-fz" SAP_VOICE="" SAP_EXEC='$SAP_SHELL \$CMD' SAP_NOEXEC='cat \$CMD\; echo \"Press Enter for next command\"\; read foo' SAP_SHELL=${SHELL:-$(whence sh)} while [ $# -gt 0 ] do case "$1" in -h*) cat </dev/null" shift ;; -s*) SAP_VOICE=">/dev/null" eval "$slide" ;; -n) SAP_EXEC=$SAP_NOEXEC shift ;; -n*) SAP_EXEC=$SAP_NOEXEC eval "$slide" ;; -P*) PFLAG=`expr _"$1" : _'-.\(.*\)'` shift ;; -S) SAP_SHELL="$2" shift;shift ;; -S*) SAP_SHELL=$(expr "$1" : "-S\(.*\)") shift ;; -V) echo "$progname: version: "'$Id: sapply.ksh,v 1.9 2008/07/31 13:25:29 ksb Exp $' exit 0 ;; -[fuz]) SAP_PRE="$SAP_PRE $1" shift ;; -[fuz]*) SAP_PRE="$SAP_PRE $(expr "$1" : "\(-.\).*")" eval "$slide" ;; -[apN]) SAP_PRE="$SAP_PRE $1 '$2'" shift;shift ;; -[apN]*) SAP_PRE="$SAP_PRE '$1'" shift ;; -[i]) SAP_RUN="$SAP_RUN $1 '$2'" shift;shift ;; -[i]*) SAP_RUN="$SAP_RUN '$1'" shift ;; --) shift break ;; -[AtJR]*) echo "$progname: $1: no implicit ptwb access allowed" exit 78 ;; -e*) echo "$progname: $1: environment set not implemented" exit 78 ;; -*) echo "$progname: $1: unsupported option" 1>&2 echo "$usage" exit 78 ;; *) break ;; esac done if [ 0 -eq ${PFLAG:=3} ] ; then echo "$progname: zero screens doesn't make me happy" exit 64 fi if [ "_" = "_$STY" ] ; then echo "$progname: not in a screen session" 1>&2 exit 69 fi # This shell program manages a single screen, we start one on each slave # pty. This blocks waiting for someone to give us a command, then unblocks # the issuer with a status report from that command. (ksb) cat >$SAP_TDIR/serv <>$SAP_TDIR/plist while read CMD <\$1 ; do [ _exit = _\$CMD -o _kill = _\$CMD ] && break echo "$progname: screen \$WINDOW starts \$(head -1 \$CMD)" >\$2 `eval echo $SAP_EXEC` echo "$progname: screen \$WINDOW exit \$? for \$(head -1 \$CMD)" >\$2 rm \$CMD done # When we are the last let the xapply clients all go, after the others exit [ _kill == _"\$CMD\" ] || exit 0 cd $SAP_TDIR exec /dev/null ; do if [ -n "\$M" ] ; then echo "$M" M="" fi sleep $((RANDOM%2+10)) done done %1' *.code *.code ! # The request side connects to the slave pty via the FIFO to run each # command. We unblock the slave by reading status lines from the ".code" # FIFO, it unblocks us by reading the ".cmd" FIFO. At the end we block # waiting for the .code from the exit (which will come from the last # "kill" command, not the original owner of the FIFO). The "null" output # suppression is just to soak up the status lines I didn't use. (ksb) cat >$SAP_TDIR/fire <$SAP_TDIR/\$SAP_UNIQ echo "$SAP_TDIR/\$SAP_UNIQ" fi >\$SAP_CMD sed -e '/^null\$/d' \$SAP_CODE $SAP_VOICE exec sed -e '/^null\$/d' \$SAP_CODE $SAP_VOICE rm $SAP_TDIR/\$SAP_UNIQ ! # A perl script to output a string with a nul character on the end (ksb) cat >$SAP_TDIR/zed <<\! #!/usr/bin/env perl print $ARGV[1], "\000"; exit 0; ! chmod 755 $SAP_TDIR/serv $SAP_TDIR/fire $SAP_TDIR/zed # This is going to flash the screen a little, I think. SAP_TTY=`tty` for i in `jot $PFLAG 0` do mkfifo -m 0600 $SAP_TDIR/$i.cmd $SAP_TDIR/$i.code screen -t "sapply$i" $SAP_TDIR/serv $SAP_TDIR/$i.cmd $SAP_TDIR/$i.code done