cosmic/bin/log

294 lines
7.7 KiB
Bash
Executable File

#!/bin/sh
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 () {
while getopts "$arg_options" opt; do
case "$opt" in
h)
flag_help=1
arg_log=0
;;
v)
flag_version=1
arg_log=0
;;
d)
flag_debug=1
arg_log=0
;;
c)
flag_nocolor=1
;;
s)
arg_ship="$OPTARG"
;;
z)
flag_shortlist=1
;;
f)
arg_log=0
flag_file=1
flag_nocolor=1
arg_file="$OPTARG"
;;
t)
flag_title=1
arg_title="$OPTARG"
;;
*)
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 " -c No-Color 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"
}
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
if [ -z "${u##*\#*}" ] ;then
printf " ${RED}Warning!${RESET} Message title [%s] contains illegal character \"#\". Skipping.\\n" "$(basename "$u" | sed 's/\.[^.]*$//')"
else
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
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
}
contains() {
string="$1"
substring="$2"
if test "${string#*$substring}" != "$string"
then
return 0 # $substring is in $string
else
return 1 # $substring is not in $string
fi
}
main() {
run_user=$(id -un)
if [ "$run_user" = "root" ] || [ "$run_user" = "publish" ]; then
# if running as publish, check who sudoed and create ship for that user
user="$SUDO_USER"
else
user="$run_user"
fi
version="0.1.1"
user="$SUDO_USER"
ships=$(find /var/gopher -maxdepth 1 -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
flag_file=0
flag_title=0
flag_nocolor=0
arg_options="hvdct:f:s:z"
arg_log=1
arg_ship=""
arg_file=""
arg_title=""
parse_input "$@"
if [ $flag_nocolor -gt 0 ]; then
YELLOW=""
GREEN=""
RED=""
RESET=""
else
YELLOW="$(tput setaf 12)"
GREEN="$(tput setaf 10)"
RED="$(tput setaf 9)"
RESET="$(tput sgr0)"
fi
# 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
# handle -f switch
if [ $flag_file -gt 0 ]; then
if [ -r "$arg_file" ]; then
owner=$(stat -c %U "$arg_file")
if [ "$user" = "$owner" ]; then
# if file exists and user owns it
realfile=$(readlink -f "$arg_file")
for ship in $ships
do
if contains "$realfile" "/var/gopher/${ship}"; then
if [ "$(wc -L < "$realfile")" -lt 81 ]; then
# looking for -t titles only for now
if [ $flag_title -gt 0 ]; then
if printf "%s" "$arg_title" | grep -Pq "^[\\x20-\\x7E]*$"; then
gopherfile="$(printf "%s" "$realfile" | sed 's|/var/gopher||')"
printf "0%s - %s\\t%s\\n" "$ship" "$arg_title" "$gopherfile" | cat - /var/gopher/listing.gophermap > "$tmp" && cat "$tmp" > /var/gopher/listing.gophermap && rm "$tmp"
fi
fi
fi
fi
done
fi
fi
fi
}
##############################################################################
##############################################################################
##############################################################################
run_user=$(id -un)
if [ "$run_user" = "root" ] || [ "$run_user" = "publish" ]; then
main "$@"
else
exec sudo -u publish "$0" "$@"
fi