| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 | #!/bin/bash
#shellcheck disable=SC1090
. "$(sfpath)" || exit 3
shellfu import pretty
IMAPDOMO_CFGDIR="__IMAPDOMO_CONFIG_USER__"
IMAPDOMO_USER_CACHE="__IMAPDOMO_USER_CACHE__"
IMAPDOMO_HOME="__IMAPDOMO_SHARE__"
usage() {
    mkusage "$@" "[options] ACTION" \
        -o                                                                    \
            "-c DIR      change to DIR before doing anything"                 \
            "-l          list handlers and exit"                              \
            "-d          turn on debugging mode"                              \
            "-N          turn off locking; make sure that handlers cannot"    \
            "            interfere with each other or that another locking"   \
            "            mechanism is in place.  Also see NOTE below."        \
       --                                                                     \
       "imapdomo will try to read init.lua and handlers/ACTION.lua from its"  \
       "configuration directory."                                             \
       ""                                                                     \
       "See imapfilter_config(5)) for guide and API reference.  Few functions"\
       "are also available in .imapdomo/imapdomo.lua"                         \
       ""                                                                     \
       "NOTE: Be aware that it's your responsibility to ensure that filters"  \
       "don't cause performance problems. (Trust me, it's not so hard to"     \
       "\"earn\" yourself a nice server ban--I learned that the hard way)."
}
bug() {
    #
    # Die because of bug
    #
    local msg=$1
    local self
    self=$(basename "$0")
    warn "bug in $self (__MKIT_PROJ_VERSION__): $msg"
}
mkcmd() {
    #
    # Compose imapfilter command
    #
    echo -n "IMAPDOMO_ACTION=$Action"
    echo -n "  LUA_PATH='$IMAPDOMO_HOME/?.lua;;'"
    echo -n "  IMAPDOMO_CFGDIR=$CfgDir"
    echo -n "  IMAPDOMO_HEADERS=$HeaderDir"
    echo -n "  IMAPFILTER_HOME=$CfgDir"
    echo -n "  imapfilter"
    if $Debug
    then
        mkdir -p "$LogDir"
        echo -n "  -d $LogDir/debug.log"
        echo -n "  -v"
    fi
    echo -n "  -c $IMAPDOMO_HOME/main.lua"
    if test -n "$Certs"
    then
        echo -n " -t $Certs"
    fi
}
show_version() {
    echo '__MKIT_PROJ_NAME__ (__MKIT_PROJ_TAGLINE__) __MKIT_PROJ_VERSION__'
    exit 0
}
show_semversion() {
    echo '__MKIT_PROJ_VERSION__'
    exit 0
}
lshandlers() {
    #
    # List recognized handlers
    #
    find "$CfgDir/handlers" -name "*.lua" -printf '%f\n' \
      | sed 's/.lua$//'
}
lock() {
    #
    # Put the lockfile
    #
    debug -v NoLock
    $NoLock && return 0
    date +"$$@%s" > "$IMAPDOMO_USER_CACHE/lock"
    debug -f "$IMAPDOMO_USER_CACHE/lock"
}
is_locked() {
    #
    # Does lockfile exist?
    #
    # True if lockfile exists. False if lockfile does not exist or locking
    # is turned off.
    #
    debug -v NoLock
    $NoLock && return 1
    debug -f "$IMAPDOMO_USER_CACHE/lock"
    test -e "$IMAPDOMO_USER_CACHE/lock"
}
unlock() {
    #
    # Remove the lockfile
    #
    debug -v NoLock
    $NoLock && return 0
    debug -f "$IMAPDOMO_USER_CACHE/lock"
    rm "$IMAPDOMO_USER_CACHE/lock"
}
handle() {
    #
    # Handle action $Action
    #
    local cmd       # imapfilter command
    lshandlers | grep -qwe "$Action" || {
        warn "no handler for action: $Action.lua in $CfgDir/handlers"
        return 2
    }
    cmd=$(mkcmd)
    debug -v cmd
    bash -n <<<"$cmd" || {
        bug "bad syntax of cmd: '$cmd'"
        return 3
    }
    if test -n "$CdTo";
    then
        cd "$CdTo" || {
            warn "cannot chdir to: $CdTo"
            return 3
        }
    fi
    mkdir -p "$HeaderDir" || {
        warn "cannot create header directory: $HeaderDir"
        return 3
    }
    eval "$cmd"
}
main() {
    local Action    # what to do
    local Debug     # true if debugging
    local CfgDir    # config directory
    local LogDir    # directory to store logs
    local HeaderDir # directory to store headers by save_header()
    local CdTo      # change dir to this before running imapfilter
    local Certs     # certificate storage
    local es=0      # exit status of this function
    local NoLock    # disable locks
    CfgDir="$IMAPDOMO_CFGDIR"
    LogDir="$IMAPDOMO_USER_CACHE/logs"
    HeaderDir="$IMAPDOMO_USER_CACHE/headers"
    Certs="$IMAPDOMO_CFGDIR/certificates"
    NoLock=false
    Debug=false
    #shellcheck disable=SC2034
    while true; do case $1 in
        -c) CdTo="$2";  shift 2 || usage -w "missing value to: $1" ;;
        -d) Debug=true; PRETTY_DEBUG=true; shift ;;
        -t) Certs="$2"; shift 2 || usage -w "missing value to: $1" ;;
        -l) lshandlers; exit ;;
        -N) NoLock=true; shift ;;
        -V|--version-semver) show_semversion ;;
        --version) show_version ;;
        -*) usage -w "unknown argument: '$1'" ;;
        *)  break ;;
    esac done
    Action="$1"; shift
    test -n "$Action" || usage -w "no action specified"
    test -f "$CfgDir/mailboxes.lua" || die "no mailboxes defined"
    debug -v Action CfgDir LogDir HeaderDir Debug CdTo NoLock
    is_locked && return 1
    lock
    handle; es=$?
    unlock
    return $es
}
main "$@"
 |