diff options
Diffstat (limited to 'src/main.sh')
-rw-r--r-- | src/main.sh | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/main.sh b/src/main.sh new file mode 100644 index 0000000..e17b751 --- /dev/null +++ b/src/main.sh @@ -0,0 +1,223 @@ +#!@@SH@@ +# +# pro-archman +# src/pro-archman.sh +# Main program file +# +# Copyright (C) 2013 Patrick "P. J." McDermott +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set -u + +# Constant global variables +PKGLIBDIR='@@PKGLIBDIR@@' +PKGLIBCMDDIR='@@PKGLIBCMDDIR@@' +PKGLIBCMD='@@PKGLIBCMD@@' +LF=' +' +OPTSTRING='hVvb:' + +# Global variables +loading_cmd= +base_dir= +conf_incoming_channel= +conf_incoming_dir= +conf_pool_gc_delay= +conf_verbose= +conf_gzip= +lock= +exit_status= + +# use() must be defined inline so it can be used to load other modules. +use() +{ + local module="${1}" + local default_dir= + local lib_subdir= + local dir= + + if [ "x${module%/*}" = "x${module}" ]; then + default_dir="${PKGLIBDIR}" + lib_subdir='' + else + case "${module%/*}" in + 'cmd') + loading_cmd="$(printf '%s' "${module##*/}" | \ + tr '[A-Z]' '[a-z]' | \ + tr -C '[a-z0-9_]' '_')" + default_dir="${PKGLIBCMDDIR}" + lib_subdir='cmd' + ;; + esac + fi + + if [ "${ARCHMAN_LIBDIR+set}" = 'set' ]; then + dir="${ARCHMAN_LIBDIR:-.}/${lib_subdir}" + else + dir="${default_dir}" + fi + + if [ -f "${dir}/${module##*/}.sho" ]; then + . "${dir}/${module##*/}.sho" + else + printf '%s: Error: Failed to load module "%s": %s\n' \ + "${0##*/}" "${module}" 'no such file or directory' >&2 + exit 2 + fi +} + +use locale +use cmd +use index +use garbage + +main() +{ + local cmd= + local status= + + init_sigs + load_locale + load_cmds + + get_options "${@}" + shift $(($OPTIND - 1)) + + base_dir="${opt_b:-.}" + + if ${opt_h:-false}; then + cmd='help' + elif ${opt_V:-false}; then + cmd='version' + elif [ ${#} -lt 1 ]; then + cmd_help_main >&2 + exit 1 + else + cmd="${1}" + shift + fi + + run_cmd "${cmd}" "${@}" + status=${?} + + return ${status} +} + +init_sigs() +{ + local i= + local sig= + + # We need the signal *number* in the signal handler. The only portable + # and easy way to get the number of a named signal is to search for it + # as in the following loop hack. + i=0 + while [ ${i} -lt 127 ]; do + i=$(($i + 1)) + sig="$(kill -l ${i} 2>/dev/null)" || continue + case "${sig}" in + 'HUP' | 'INT' | 'QUIT' | 'ABRT' | 'ALRM' | 'TERM') + trap "handle_sig ${i}" ${i} + ;; + esac + done +} + +get_options() +{ + local opt= + + unset OPTARG + while getopts "${OPTSTRING}" opt; do + if [ "x${opt}" != 'x?' ]; then + eval "opt_${opt}=\"\${OPTARG:-true}\"" + fi + unset OPTARG + done + + return 0 +} + +init() +{ + lock + get_conf +} + +lock() +{ + mkdir -p "${base_dir}/.db" + lock="${base_dir}/.db/lock" + if ! (set -C; printf '%d\n' "${$}" >"${lock}") 2>/dev/null; then + error 2 "$(get_msg 'lock_fail')" + fi +} + +get_conf() +{ + local old_dir= + + # Set defaults. + conf_incoming_channel='dev' + conf_incoming_dir='../incoming' + conf_pool_gc_delay=86400 + conf_verbose=false + conf_gzip=true + + if [ -f "${base_dir}/conf" ]; then + . "${base_dir}/conf" + fi + + old_dir="$(pwd)" + cd "${base_dir}" + if [ -d "${conf_incoming_dir}" ]; then + conf_incoming_dir="$(cd "${conf_incoming_dir}" && pwd)" + fi + cd "${old_dir}" + + case "${conf_verbose}" in + 'false' | '0' | 'off' | 'no') conf_verbose=false;; + *) conf_verbose=true;; + esac + + return 0 +} + +fini() +{ + update_feeds + collect_garbage + unlock +} + +unlock() +{ + rm -f "${lock}" +} + +handle_sig() +{ + local sig="${1}" + + unlock + + if [ "x${exit_status:+set}" = 'xset' ]; then + exit ${exit_status} + else + exit $((128 + $sig)) + fi +} + +main "${@}" |