cosmic/bin/log

290 lines
7.3 KiB
Bash
Executable File

#!/bin/sh
YELLOW="$(tput setaf 11)"
GREEN="$(tput setaf 10)"
RED="$(tput setaf 9)"
RESET="$(tput sgr0)"
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"
}
yesno () {
old_stty_cfg=$(stty -g)
stty raw -echo
yn=$(while ! head -c 1 | grep -i '[ny]'; do true; done)
stty "$old_stty_cfg"
case $yn in
y ) result=0 ;;
* ) result=1 ;;
esac
return $result
}
check_log () {
ship="$*"
printf ">> %s" "${YELLOW}${ship}${RESET}"
# 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 new messages.\\n"
else
printf "\\n" # break to new line for each message query
# check each unpublished message for sending
IFS='
'
for u in $uniq
do
printf " Send [%s%s%s]? " "${YELLOW}" "$(basename "$u" | sed 's/\.[^.]*$//')" "${RESET}"
if yesno; then
# prompt for title and prepare output
printf ".. %sYES%s.\\n" "${GREEN}" "${RESET}"
# check for UTF compatability or fail
if iconv -f UTF-8 "/var/gopher${u}" > /dev/null 2> /dev/null; then
if [ "$(wc -L < "/var/gopher${u}")" -gt 80 ]; then
printf " ${RED}Warning!${RESET} Message [%s] exceeds 80 columns.\\n" "$(basename "$u" | sed 's/\.[^.]*$//')"
fi
get_title
else
printf " Message [%s] is not encoded in UTF-8. %sABORT%s\\n" "$(basename "$u" | sed 's/\.[^.]*$//')" "${RED}" "${RESET}"
fi
else
printf ".. %sNO%s.\\n" "${RED}" "${RESET}"
fi
done
unset IFS
fi
}
get_title () {
printf " Title for [%s%s%s] (null exits): " "${YELLOW}" "$(basename "$u" | sed 's/\.[^.]*$//')" "${RESET}"
read -r title
if [ -z "$title" ]; then
printf " .. No title. %sABORT%s.\\n" "${RED}" "${RESET}"
return
else
title=$(printf "%s" "$title" | cut -c -60)
printf " .. Confirm title [%s%s%s]? " "${YELLOW}" "$title" "${RESET}"
if yesno; then
printf ".. %sYES%s.\\n" "${GREEN}" "${RESET}"
if printf "%s" "$title" | grep -Pq "^[\\x20-\\x7E]*$"; 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 " .. [%s] .. %sSENT%s.\\n" "$title" "${GREEN}" "${RESET}"
else
printf " .. Titles must be ASCII characters. %sTry Again%s.\\n" "${RED}" "${RESET}"
get_title
fi
else
printf ".. %sNO%s.\\n" "${RED}" "${RESET}"
get_title
fi
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() {
version="0.1.1"
user="$SUDO_USER"
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=""
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 "%sINITIALIZING QEC%s .. %sGOOD%s\\n" "${YELLOW}" "${RESET}" "${GREEN}" "${RESET}"
printf "Ready to transmit for [%s]\\n" "${GREEN}${user}${RESET}"
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 [ -n "$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
}
##############################################################################
##############################################################################
##############################################################################
run_user=$(id -un)
if [ "$run_user" = "root" ] || [ "$run_user" = "publish" ]; then
main "$@"
else
exec sudo -u publish "$0" "$@"
fi