# Defaults: the usage should be as simple as throwing some stuff into
# ~/pub and running $PROGNAME.
DIR=~/pub
PROGNAME="${0##*/}"
# Usage information / help message.
print_usage() {
local text
read -rd '' text << _EOF
${PROGNAME} - manage public directories
usage: ${PROGNAME} [options] [command] [args...]
options:
-h: print this help message
-d: define the public directory path (default ${DIR})
commands:
default: if no command is given, ensure the public directory exists and fix it
fix: fixes permissions of args, recursing on directories (default is the -d option)
add: copies the args into the public directory and fixes them.
link: not implemented right now
show: not implemented right now
bugs and notes:
add command does not understand nested directories right now
_EOF
echo "${text}"
}
# Parse options. Takes $@, returns a number.
# Do shift $number and the $@ becomes just the arguments.
parse_options() {
local opt
local OPTARG
local OPTIND
while getopts 'hd:' opt
do
case "${opt}" in
h)
print_usage
exit
;;
d)
if [[ -d "${OPTARG}" ]]
then
DIR="${OPTARG}"
else
echo "${PROGNAME}: ${OPTARG} is not a directory" >&2
exit 31
fi
;;
*)
echo "internal error" >&2
exit 30
;;
esac
done
return $(( OPTIND - 1 ))
}
# Read the command and arguments, dispatch runtime to another functions
# in sensible manner.
parse_command() {
case "${1}" in
# The default behaviour: make sure $DIR exists and fix that.
''|'default')
ask_user \
0 \
"$PROGNAME default behaviour: Try to setup $DIR?" || exit 0
if [[ -d "${DIR}" ]] || mkdir "${DIR}"
then
# I'm being absurdly clever here to save a few cycles. Since
# the fix thing just below defaults to fixing $DIR, we just
# fall into it using ;& instead of recursing parse_command.
:
else
echo "${PROGNAME}: ${DIR} is not a directory" >&2
exit 41
fi
;&
# fix: fix every arg, default to $DIR.
'fix')
if [[ -e "${2}" ]]
then
fix_permissions "${@: 2}"
else
fix_permissions "${DIR}"
fi
;;
# add: no defaults, raise error if no args
'add')
if [[ -e "${2}" ]]
then
copy_to_DIR "${@: 2}"
else
echo "${PROGNAME}: ${1}: no args" >&2
exit 42
fi
;;
# * fallback: bad commands go to hell. Could try to guess what to do
# if a path is given, but that's a very luxurious feature.
*)
echo "${PROGNAME}: ${1}: bad command" >&2
exit 40
;;
esac
}
# Helper function: print args, prompt for a [y/n] and return 0 or 1
# First arg is the default return value, which can be any integer
ask_user() {
if [[ ! $1 =~ [[:digit:]] ]]
then
echo "internal error" >&2
exit 21
fi
local REPLY
local def
if (( $1 )); then d='[N/y]'; else d='[Y/n]'; fi
echo "${*: 2}"
read -res -n 1 -p " $d>> "
case "${REPLY,,}" in
y) return 0 ;;
n) return 1 ;;
*) return $1 ;;
esac
}
# Fix permissions. Sets:
# files to 644,
# executable files to 755,
# files where path contains 'bin' to 755,
# directories to 755 and recurses on them.
fix_permissions() {
for f
do
if [[ -f "${f}" ]]
then
[[ -x "${f}" ]] && chmod 755 "${f}" && continue
[[ "${f}" =~ bin ]] && chmod 755 "${f}" && continue
chmod 644 "${f}"
elif [[ -d "${f}" ]]
then
chmod 755 "${f}"
fix_permissions "${f}"/*
fi
done
}
# THIS IS TRASH AND CP IS TRASH
copy_to_DIR() {
for f
do
if [[ ! -e "${DIR}"/"${f##*/}" ]]
then
/bin/cp -r "${f}" "${DIR}/" && fix_permissions "${DIR}"/"${f##*/}"
fi
done
}