#!/bin/ksh -p PRG=`basename $0` usage () { typeset u="Usage: $PRG (-h hh -m mm -s ss | [+][hh:]mm[:ss] args" cat 1>&2 <<-EnD $u Uses mdisplay to show a window on the screen containing the text of args; if one of the args is - (after a - or --) it also picks up text from stdin. [hh:]mm[:ss]: interpreted as mm, hh:mm or hh:mm:ss; if preceded by a '+', this is relative to the current time. EnD } dieERR () { usage "Internal error" exit 1 } trap ERR dieERR # make sure hh, mm, ss etc treated as decimal integers! typeset -i10 hh=0 mm=0 ss=0 typeset -i10 now_hh=0 now_mm=0 now_ss=0 have_time=n add_time=n ns=0 display=$DISPLAY while getopts :d:h:m:s:0123456789: opt do case $opt in d) display=$OPTARG ;; h) hh=$OPTARG have_time=y add_time=y ;; m) mm=$OPTARG have_time=y add_time=y ;; s) ss=$OPTARG have_time=y add_time=y ;; +[0-9]) shift $((OPTIND - 1)) arg1="${opt}$OPTARG" OPTIND=1 break ;; \?) usage "Invalid option -$opt $OPTARG" exit 1 ;; *) usage "Invalid option -$opt $OPTARG" exit 1 ;; esac done [[ $OPTIND -gt 1 ]] && shift $((OPTIND - 1)) no_shift=n val='tailval=""' tailval='' if [[ $# -gt 0 && "$have_time" != y ]]; then case "$1" in +[0-9][0-9]:[0-9][0-9]:[0-9][0-9]) add_time=y val=`echo "$1" | sed -e 's/+/hh=/' -e 's/:/ mm=/' -e 's/:/ ss=/'` ;; [0-9][0-9]:[0-9][0-9]:[0-9][0-9]*) # absolute time - anything at the end to be checked for am/pm val=`echo "$1" | sed -e 's/^/hh=/' -e 's/:/ mm=/' -e 's/:/ ss=/'` tailval=${val#hh=?? mm=?? ss=??} val="${val%$tailval}" ;; +[0-9][0-9]:[0-9][0-9]) add_time=y [[ $have_time = y ]] && usage "Time specified twice" && exit 1 val=`echo "$1" | sed -e 's/+/hh=/' -e 's/:/ mm=/'` ;; [0-9][0-9]:[0-9][0-9]*) # absolute time - anything at the end to be checked for am/pm val=`echo "$1" | sed -e 's/^/hh=/' -e 's/:/ mm=/'` tailval=${val#hh=?? mm=??} val="${val%$tailval}" ;; +[0-9][0-9]) add_time=y [[ $have_time = y ]] && usage "Time specified twice" && exit 1 val=`echo "$1" | sed -e 's/+/mm=/'` ;; [0-9][0-9]) [[ $have_time = y ]] && usage "Time specified twice" && exit 1 val=`echo "$1" | sed -e 's/^/mm=/'` hh=`date +%H` ;; *) no_shift=y ;; esac [[ "$no_shift" != y ]] && shift elif [[ $have_time != y ]]; then usage No arguments given && exit 1 fi eval "$val" if [[ -n "$tailval" ]]; then case "$tailval" in [aA][mM]) : ;; [pP][mM]) [[ $hh -le 12 ]] && hh=$((hh + 12)) ;; *) set -- "$tailval" "$@" ;; esac fi typeset -i10 rel_secs=$(( ss + 60 * ( mm + ( 60 * hh ) ) )) typeset -i10 abs_secs=0 # get absolute time eval $(date '+now_hh=%H now_mm=%M now_ss=%S start="%a %T"') abs_secs=$(( now_ss + 60 * ( now_mm + ( 60 * now_hh ) ) )) if [[ "$add_time" != y ]]; then while (( abs_secs > rel_secs )); do rel_secs=$((rel_secs + 86400)) done rel_secs=$((rel_secs - abs_secs)) fi # echo relative_time=$add_time hh=$hh mm=$mm ss=$ss # echo rel_secs=$rel_secs if (( rel_secs < 0 )); then usage "specified time in the past" exit fi # assemble other arguments message="" sp="" for arg in "$@"; do if [[ "x$arg" = "x-" ]]; then message="$message$sp`cat`" else message="$message$sp$arg" fi sp=' ' done # do we have a display if [[ -z "$display" || "$display" != *:* ]]; then usage "No known X display (you can add '-d display-name')" exit 1 fi # to fire when? abs_secs=$((abs_secs + rel_secs)) dd=$(( abs_secs / 86400 )) hh=$(( ( abs_secs / 3600 ) % 24 )) mm=$(( ( abs_secs / 60 ) % 60 )) ss=$(( abs_secs % 60 )) target=$(printf '%02d:%02d:%02d' $hh $mm $ss) [[ $dd -gt 0 ]] && dd=" (+$dd days)" || dd="" lines=$(echo "$message" | wc -l) cols=$(echo "$message" | awk '{n=length($0);l=l&2 trap '' TERM HUP # now issue our command - mdisplay only shows its window when it receives data setsidbg ksh -c " exec >/dev/null 2>&1 untrapTERM () { trap - TERM HUP; } trap untrapTERM TERM HUP (sleep $rel_secs; printf '%s' '${message:-Alarm $title}') | \ mdisplay -icontitle '$target $PRG' \ -title '$PRG (from $start for $target)' \ -pb2label '' \ -columns $cols \ -rows $lines \ -bg red \ -display '$display' "