#!/bin/sh #exec 2>> /tmp/bgrun.stderr #set -x SELF="${0##*/}" TEMPDIR= TEMPDIR_SENTINEL=.tempdir cleanup() { if [ -e $TEMPDIR_SENTINEL ]; then local TEMPDIR; TEMPDIR="$PWD" echo Cleaning up tempdir $TEMPDIR… >> output.stderr notify_output cd / rm -rf "$TEMPDIR" else notify_output fi trap - 1 2 3 4 5 6 7 8 10 11 12 13 14 15 } trap cleanup 1 2 3 4 5 6 7 8 10 11 12 13 14 15 enter_tempdir() { if [ -e $TEMPDIR_SENTINEL ]; then return else if [ -z "${TMPDIR:-}" ]; then TMPDIR=/tmp fi for i in $LOGNAME volatile; do if [ -d "${TMPDIR}/$i" ]; then TMPDIR="${TMPDIR}/$i" break fi done cd $(mktemp -dp "$TMPDIR" mutt.XXXXXXXXXX) touch $TEMPDIR_SENTINEL fi } notify() { if [ -x "$(command -v awesome-client)" ]; then local stdout stderr escaped output stdout="${2:-}" stderr="${3:-}" for i in stdout stderr; do if eval test -s output.$i; then anything=1 escaped=$(eval sed -e 's,\",\\\",g' output.$i) output="${output:+$output }${i}: $escaped" fi done [ -n "${escaped:-}" ] || return awesome-client <<-_eof local naughty = require("naughty") naughty.notify({ preset = naughty.config.presets.low, title = "${1:-Output from mutt/$SELF}", text = [[$output]] }) _eof fi } notify_output() { [ -e $TEMPDIR_SENTINEL ] || return local stdout stderr anything for i in stdout stderr; do if [ -s "output.$i" ]; then eval $i="'output.$i'" else eval $i=/dev/null fi done notify "Output from mutt/$SELF" $stdout $stderr } guess_extension() { python -c "import mimetypes; print(mimetypes.guess_extension('$1'))" } get_file() { local t if [ -z "$1" ]; then t=$(TMPDIR="$PWD" tempfile -s $(guess_extension "$MIMETYPE")) cat > "$t" echo "$t" else t="$(echo ${1##*/} | sed -re 's![^[:alnum:],.@%^+=_-]!_!gi')" ln "$1" "$t" 2>/dev/null || cp "$1" "$t" echo "$t" fi } MIMETYPE= FILENAME= VIEWER= DELAY=1 state= for arg in "$@"; do case "$state/$arg" in (/-t) state=t;; (t/*) MIMETYPE="$arg"; state=;; (/-f) state=f;; (f/*) FILENAME="$arg"; state=;; (/-d) state=d;; (d/*) DELAY="$arg"; state=;; (/-v) state=v;; (v/*) VIEWER="$arg"; state=;; (*) echo >&2 "E: Invalid argument: $i" exit 1 ;; esac done launch_viewer() { local filename; filename="$1" if [ -z "$VIEWER" ]; then [ -n "${2:-}" ] && filename="${2}:${1}" run-mailcap "$filename" > output.stdout 2> output.stderr else $VIEWER "$filename" > output.stdout 2> output.stderr fi } case "$SELF" in (bgview) # make a copy of the file, then launch a shell process in the background # to divert to run-mailcap, after which the temporary directory gets # cleaned up. enter_tempdir FILE="$(get_file "$FILENAME")" ( ts=$(($(date +%s) + $DELAY)) launch_viewer "$FILE" "$MIMETYPE" while [ $(date +%s) -lt $ts ]; do sleep $DELAY; done cleanup ) & trap - 1 2 3 4 5 6 7 8 10 11 12 13 14 15 ;; (bgview-fifo) # hack to stay around until the viewer has read the file: make a fifo and # wait for the cat process to finish writing to it, which means that it # must have been consumed on the other end. enter_tempdir FILE="$(get_file "$FILENAME")" FIFO="fifo-${FILE##*/}" mkfifo "$FIFO" cat "$FILE" > "$FIFO" & # For some reason, we do have to write a tempfile and cannot seem to # redirect stdin directly to the fifo, i.e. this does not work instead of # the previous three lines: ## cat > "$FIFO" & launch_viewer "$FIFO" "$MIMETYPE" wait cleanup ;; (bgview-delay) # hack to stay around until the file hasn't been accessed for a few # seconds, so that we can clean up. This is for cases when the FIFO method # doesn't work, because e.g. Firefox randomly chooses it needs to read # HTML files twice. enter_tempdir FILE="$(get_file "$FILENAME")" touch "$FILE" (launch_viewer "$FILE" "$MIMETYPE") & ( while [ $(($(stat -c%X "$FILE") + $DELAY)) -gt $(date +%s) ]; do sleep $DELAY done echo Cleaning up $TMPDIR… > $TMPDIR/output.stderr cleanup ) & trap - 1 2 3 4 5 6 7 8 10 11 12 13 14 15 ;; esac