#!/bin/sh # TODO: better isolate listings.gophermap from accidental clobbering die () { msg="$1" code="$2" # exit code defaults to 1 if printf "%s" "$code" | grep -q '^[0-9]+$'; then code=1 fi # output message to stdout or stderr based on code if [ -n "$msg" ]; then if [ "$code" -eq 0 ]; then printf "%s\\n" "$msg" else printf "%s\\n" "$msg" >&2 fi fi exit "$code" } finish () { rm -f "$tmp" } trap finish EXIT parse_input () { if ! parsed=$(getopt "$arg_options" "$@"); then die "Invalid input" 2 fi eval set -- "$parsed" while true; do case "$1" in -h) flag_help=1 arg_log=0 shift ;; -v) flag_version=1 arg_log=0 shift ;; -d) flag_debug=1 arg_log=0 shift ;; -s) shift arg_ship="$1" shift ;; -z) flag_shortlist=1 shift ;; -n) arg_log=0 shift arg_new="$1" shift ;; --) shift break ;; *) die "Internal error: $1" 3 ;; esac done } show_help () { printf "%s [-hvd] [-s shipname]\\n\\n" "$(basename "$0")" printf " -h Show this help\\n" printf " -v Show current version info\\n" printf " -d Debug mode\\n" printf " -s [shipname] Only log messages for ship named\\n" printf " -n [filename] Create new message with filename\\n" printf " (Users with multiple ships must use -s)\\n" printf "\\n" printf "Passing no options will enter interactive mode.\\n\\n" printf "\\n" } read_key () { _key= if [ -t 0 ]; then if [ -z "$_stty" ]; then _stty=$(stty -g) fi stty -echo -icanon min 1 _key=$(dd bs=1 count=1 2>/dev/null) stty "$_stty" fi } yesno () { read_key case $_key in y ) result=0 ;; * ) result=1 ;; esac return $result } check_log () { ship="$*" printf ">> %s" "${ship}" # look at log entries in gophermap # compare against files in ship directory # store list of unpublished logs logs=$(grep "^0${ship}" "/var/gopher/listing.gophermap" | awk -F'\t' '{print $2}') files=$(find "/var/gopher/$ship" -regex ".*\\.txt$" -not -path '*/\.*' -type f | sed 's|/var/gopher||') uniq=$(printf "%s\\n%s" "$logs" "$files" | sort | uniq -u) if [ -z "$uniq" ]; then printf " .... No messages.\\n" else # check each unpublished message for sending IFS=' ' for u in $uniq do printf "\\n Send message %s? " "$(basename "$u" | sed 's/\.[^.]*$//')" if yesno; then # prompt for title and prepare output printf "\\n Title for message %s? " "$(basename "$u" | sed 's/\.[^.]*$//')" read -r title if [ ! -z "$title" ]; then printf "0%s - %s\\t%s\\n" "$ship" "$title" "$u" | cat - /var/gopher/listing.gophermap > "$tmp" && cat "$tmp" > /var/gopher/listing.gophermap && rm "$tmp" printf "\\n %s - %s .... Sent.\\n" "$(basename "$u" | sed 's/\.[^.]*$//')" "$title" else printf " %s .... No title, abort.\\n" "$(basename "$u" | sed 's/\.[^.]*$//')" fi else printf "\\n %s .... Skipped.\\n" "$(basename "$u" | sed 's/\.[^.]*$//')" fi done unset IFS fi } new_message () { ship="$1" post_file="/var/gopher/${ship}/${2}" template_file="/var/gopher/${ship}/.template" temp_post=$(mktemp -t "$(basename "$0").post.XXXXXXX") || die "Failed to create temporary file" 1 if [ -f "$post_file" ]; then cp "$post_file" "$temp_post" elif [ -f "$template_file" ]; then cp "$template_file" "$temp_post" fi temp_post_time=$(stat -c %Y "$temp_post") ${EDITOR:-nano} "$temp_post" temp_post_time_check=$(stat -c %Y "$temp_post") if [ "$temp_post_time" -ne "$temp_post_time_check" ] ; then printf "Drafted message %s (%s)\\n" "$2" "$1" touch "${post_file}" cat "${temp_post}" > "${post_file}" rm "${temp_post}" else printf "Aborted message.\\n" rm "${temp_post}" fi } main() { parse_input "$@" # debug if [ $flag_debug -gt 0 ]; then set -x fi # shortlist for bash completion if [ $flag_shortlist -gt 0 ]; then out="$ships" die "${out}" 0 fi # version if [ $flag_version -gt 0 ]; then printf "%s\\n" "$version" fi # print help if [ $flag_help -gt 0 ]; then show_help fi # standard log if no params if [ $arg_log -gt 0 ]; then printf "INITIALIZING QEC...\\n" printf "Ready to transmit for [%s]\\n" "${user}" if [ "$numships" -eq 0 ]; then printf "No registered ships found in system.\\n" elif [ "$numships" -eq 1 ]; then if [ -z "$arg_ship" ] || [ "$ships" = "$arg_ship" ]; then check_log "$ships" fi else IFS=' ' for f in $ships do if [ -z "$arg_ship" ] || [ "$f" = "$arg_ship" ]; then check_log "$(basename "$f")" fi done unset IFS fi fi # new message if [ ! -z "$arg_new" ]; then if [ "$numships" -eq 0 ]; then printf "No registered ships found in system.\\n" elif [ "$numships" -eq 1 ]; then if [ -z "$arg_ship" ] || [ "$ships" = "$arg_ship" ]; then new_message "$ships" "$arg_new" fi else IFS=' ' for f in $ships do if [ "$f" = "$arg_ship" ]; then new_message "$arg_ship" "$arg_new" fi done unset IFS fi fi } ############################################################################## ############################################################################## ############################################################################## version="0.1.0" user=$(whoami) ships=$(find /var/gopher -user "$user" -type d -exec basename {} \;) numships=$(echo "${ships}" | wc -l) tmp=$(mktemp -t "$(basename "$0").tmp.XXXXXXX") || die "Failed to create temporary file" 1 flag_help=0 flag_version=0 flag_debug=0 flag_shortlist=0 arg_options="hvds:zn:" arg_log=1 arg_ship="" arg_new="" main "$@"