jaromail

a commandline tool to easily and privately handle your e-mail
git clone git://parazyd.org/jaromail.git
Log | Files | Refs | Submodules | README

commit 2b5300d3b156b55a94b1f5ceba6248611fc41cb4
parent 0e1e1e9cb2ff662780c3ab3a9131cf253844812e
Author: Jaromil <jaromil@dyne.org>
Date:   Fri, 16 Jan 2015 12:59:50 +0100

relevant fixes to search, locking and mutt, plus speed improvements using zsh builtins

Diffstat:
Mbuild/install-gnu.sh | 13+++++++++----
Msrc/jaro | 62++++++++++++++++++++++++++++++++++++--------------------------
Msrc/mutt/general | 2+-
Msrc/zlibs/addressbook | 29+++++++++--------------------
Msrc/zlibs/email | 43+++++++++++++++++++++----------------------
Msrc/zlibs/filters | 125+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/zlibs/helpers | 43++++++++++++++++++++++++++++++++-----------
Msrc/zlibs/locking | 76+++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/zlibs/maildirs | 2+-
Msrc/zlibs/search | 9+++------
10 files changed, 226 insertions(+), 178 deletions(-)

diff --git a/build/install-gnu.sh b/build/install-gnu.sh @@ -1,17 +1,17 @@ #!/usr/bin/env zsh -{ test "$PREFIX" = "" } && { PREFIX=/usr/local } +PREFIX=${PREFIX:-/usr/local} # TODO: separate libexec from share JARO_LIBEXEC=$PREFIX/share/jaromail JARO_SHARE=$PREFIX/share/jaromail -mkdir -p $JARO_SHARE +rm -rf "$JARO_SHARE" +mkdir -p "$JARO_SHARE" + { test $? = 0 } || { print "No permissions to install system-wide."; return 1 } -mkdir -p $JARO_LIBEXEC - { test -r doc } && { srcdir=. } { test -r install-gnu.sh } && { srcdir=.. } @@ -28,6 +28,11 @@ mkdir -p $JARO_LIBEXEC/{bin,zlibs} cp $srcdir/src/jaro $JARO_LIBEXEC/bin cp -ra $srcdir/build/gnu/* $JARO_LIBEXEC/bin cp -ra $srcdir/src/zlibs/* $JARO_LIBEXEC/zlibs/ + +for l in `ls $JARO_LIBEXEC/zlibs/ | grep '.zwc$'`; do + rm -f $l +done + for l in `ls $JARO_LIBEXEC/zlibs/ | grep -v '.zwc$'`; do zcompile $JARO_LIBEXEC/zlibs/$l done diff --git a/src/jaro b/src/jaro @@ -35,7 +35,7 @@ DRYRUN=0 CALLMUTT=1 # use gnome-keyring for passwords on GNU systems -GNOMEKEY=0 +GNOMTEKEY=0 # default permission on files umask 066 @@ -45,9 +45,10 @@ typeset -h rm mkdir mutt # load zsh regex module zmodload zsh/regex -# zmodload zsh/mapfile - - +zmodload zsh/mapfile +zmodload zsh/system +zmodload -F zsh/stat b:zstat +zmodload zsh/sched # date stamp datestamp=`date '+%d%b%y'` ########################## @@ -272,23 +273,19 @@ endgame() { done JAROTMPFILES=() - [[ -e "$MAILDIRS"/cache/notmuch.lock ]] && { - func "unlocking notmuch/Xapian search cache" - unlock "$MAILDIRS"/cache/notmuch - } func "endgame() exit code: $exitcode" return $exitcode } -# Trap functions for the _endgame event -TRAPINT() { _endgame INT; return $? } -# TRAPEXIT() { _endgame EXIT; return $? } -TRAPHUP() { _endgame HUP; return $? } -TRAPQUIT() { _endgame QUIT; return $? } -TRAPABRT() { _endgame ABORT; return $? } -TRAPKILL() { _endgame KILL; return $? } -TRAPPIPE() { _endgame PIPE; return $? } -TRAPTERM() { _endgame TERM; return $? } -TRAPSTOP() { _endgame STOP; return $? } +# Trap functions for the endgame event +TRAPINT() { endgame INT; return $? } +# TRAPEXIT() { endgame EXIT; return $? } +TRAPHUP() { endgame HUP; return $? } +TRAPQUIT() { endgame QUIT; return $? } +TRAPABRT() { endgame ABORT; return $? } +TRAPKILL() { endgame KILL; return $? } +TRAPPIPE() { endgame PIPE; return $? } +TRAPTERM() { endgame TERM; return $? } +TRAPSTOP() { endgame STOP; return $? } # TRAPZERR() { func "function returns non-zero." } case $OS in @@ -338,12 +335,20 @@ MUTTDIR="$MAILDIRS/.mutt" cp "$WORKDIR/Mutt.txt" "$MAILDIRS/Mutt.txt" notice "Default Mutt configuration template created" } +_mutt() { + for i; do _fa+=" $i "; done + func "exec: mutt -F $MUTTDIR/rc ${=muttflags} ${_fa}" + [[ "$subcommand" = "peek" ]] || rm -f $MUTTDIR/muttpass + touch $MUTTDIR/muttpass + mutt -F $MUTTDIR/rc ${=muttflags} ${=_fa} + return $? +} # binary programs recognition check_bin() { # required programs - for req in pinentry fetchmail gpg; do + for req in pinentry fetchmail gpg mutt msmtp; do command -v $req >/dev/null { test $? != 0 } && { error "Cannot find $req. Please install it." @@ -377,11 +382,10 @@ check_bin() { # which mutt binary to use if command -v mutt > /dev/null; then - # system-wite - mutt="mutt" + # system-wide # TODO: check if this is also the location on Fedora - pgpewrap="/usr/lib/mutt/pgpewrap" - dotlock="mutt_dotlock" + pgpewrap="${WORKDIR}/bin/gpgewrap" + dotlock="${WORKDIR}/bin/dotlock" elif command -v mutt-jaro > /dev/null; then # in-house compiled mutt=mutt-jaro @@ -392,9 +396,6 @@ check_bin() { exit 1 fi func "Mutt binary: $mutt" - # make sure there is always a muttpass file even if empty - touch $MAILDIR/tmp/muttpass - pidof gnome-keyring-daemon > /dev/null && { act "using gnome-keyring to store secrets" @@ -593,6 +594,8 @@ main() { subcommands_opts[crypt]="" subcommands_opts[cryptsign]="" + subcommands_opts[isml]="" + ### Detect subcommand local -aU every_opts #every_opts behave like a set; that is, an array with unique elements for optspec in $subcommands_opts$main_opts; do @@ -871,6 +874,13 @@ main() { exitcode=$? ;; + isml) + ismailinglist + [[ $? = 0 ]] && \ + notice "Email read from stdin is a mailinglist" + exitcode=$? + ;; + *) # unknown command, pass it to autostart func "unknown command, remote check" autostart ${PARAM} diff --git a/src/mutt/general b/src/mutt/general @@ -36,7 +36,7 @@ set ascii_chars set auto_tag unset beep unset help -set mark_old +set mark_old = no unset markers #set resolve unset sort_re diff --git a/src/zlibs/addressbook b/src/zlibs/addressbook @@ -487,31 +487,18 @@ import() { [[ "$_arg" = "" ]] && { notice "Import address list from stdin into addressbook $list" - _stdin=`cat` + sysread _stdin # reads into var _stdin _new=0 act "imported new entries will be printed on stdout" + e_addr=() for i in ${(f)_stdin}; do # skip comments starting with # [[ "$i[1]" = "#" ]] && continue - _parsed=`print - "From: $i" | ${WORKDIR}/bin/fetchaddr -a -x from` - _e="${_parsed[(ws:,:)1]:l}" - - # check if is really an email - isemail "$_e" - [[ $? = 0 ]] || { - func "not an email: $_e" - continue - } + print - "From: $i" | e_parse From + [[ $? = 0 ]] || continue - # check if the email is not a duplicate - [[ "${result[$_e]}" = "" ]] || { - func "duplicate email: $_e" - continue - } - - _n="${_parsed[(ws:,:)2]}" - result+=("$_e" "$_n") + _e="${e_parsed[(ws:,:)1]:l}" # check if the email is not already known lookup_email "$_e" @@ -520,12 +507,14 @@ import() { continue } + _n="${e_parsed[(ws:,:)2]}" + print - "$_n <$_e>" [[ $DRYRUN = 0 ]] && insert_address "$_e" "$_n" _new=$(( $_new + 1 )) done - notice "Valid unique entries parsed: ${#result}" + notice "Valid unique entries parsed: ${#e_addr}" act "new addresses found: ${_new}" return $? } @@ -664,7 +653,7 @@ export_vcard() { edit_abook() { - abook --config <(cat <<EOF + abook --config <(sysread <<EOF set autosave=true set mutt_command=jaro compose set sort_field=name diff --git a/src/zlibs/email b/src/zlibs/email @@ -23,7 +23,7 @@ # extract all emails found in stdin, one per line compose() { # no args, open in compose mode - ${=mutt} -F $MUTTDIR/rc -H <(print "To: ${PARAM[@]}") + _mutt -H <(print "To: ${PARAM[@]}") return $? } @@ -64,7 +64,7 @@ queue() { error "Group not found: $groupfile" return 1 } - recipients=`cat "$MAILDIRS/Groups/$groupfile" | grep -v '^#'` + grep -v '^#' $MAILDIRS/Groups/$groupfile | sysread recipients groupnum=`print ${recipients} | wc -l` groupmode=`head -n1 "$MAILDIRS/Groups/$groupfile" | awk '/^#mode/ { print $2 } { next }'` [[ "$groupmode" = "" ]] && { groupmode="individual" } @@ -101,7 +101,7 @@ queue() { else # recipients are set in the email envelope - cat "$tmpqueue" | deliver "outbox" + printfile "$tmpqueue" | deliver "outbox" fi unlock "$MAILDIRS/outbox" @@ -282,7 +282,7 @@ smtp_send() { _tmp_create msmtpcfg="$JAROTMP" - cat <<EOF > $msmtpcfg + sysread -o 1 <<EOF > $msmtpcfg account default from ${email} user ${login} @@ -290,10 +290,7 @@ host ${smtp} port ${smtp_port} tls on tls_starttls on -tls_certcheck on -# tls_fingerprint sha1 44:e8:10:ef:35:fc:54:51:fd:84:cf:59:de:af:a9:ab:a1:55:b8:41 -# tls_fingerprint md5 88:65:6e:6d:a5:66:92:a1:9c:47:18:66:d5:b8:56:49 -tls_fingerprint 6A:D4:DF:E4:20:32:F9:66:94:35:0C:33:9D:74:96:5C +tls_certcheck off logfile "${MAILDIRS}/logs/msmtp.log" auth ${auth} password ${password} @@ -337,7 +334,7 @@ send() { _tmp_create anoncfg="$JAROTMP" - cat <<EOF > "$anoncfg" + sysread -o 1 <<EOF > "$anoncfg" REMAIL n POOLSIZE 0 SENDPOOLTIME 0m @@ -390,7 +387,7 @@ BEGIN { body=0 } /^Subject:/ { print " . " $0 } ' - tsize=`stat -c '%s' "$qbody"` + tsize=`zstat +size "$qbody"` act "sending `human_size $tsize` over the network ..." jaro -q smtp -a ${account:-default} < "${qbody}" res=$? @@ -403,7 +400,7 @@ BEGIN { body=0 } notice "Mail sent succesfully" # whitelist those to whom we send mails hdr "$qbody" | learn recipient - cat "$qbody" | deliver sent + printfile "$qbody" | deliver sent [[ $? = 0 ]] && { rm "$qbody" } fi @@ -461,26 +458,28 @@ peek() { } _tmp_create - tmp="$JAROTMP" - cat <<EOF >> "$tmp" + _pass_tmp="$JAROTMP" + sysread -o 1 <<EOF >> "$_pass_tmp" set imap_pass = "${password}" # set imap_peek = yes EOF unset password # when peeking don't mark unread messages as Old # and sort date received with no threading (latest up) - touch "$MAILDIRS/tmp/muttpass" - cat <<EOF >> "$MAILDIRS/tmp/muttpass" -source '$tmp' + rm -f "$MUTTDIR/muttpass" + sysread -o 1 <<EOF > "$MUTTDIR/muttpass" +source '$_pass_tmp' unset mark_old set sort=reverse-date-received EOF - # fork a process to delete the pass files after use - (sleep 1; - cp /dev/null "$MAILDIRS/tmp/muttpass" - cp /dev/null "$tmp" # zero the tmp passfile - ) & - ${=mutt} -F $MUTTDIR/rc -f ${iproto}://${ilogin}@${imap}:${imap_port}/${folder} + + # schedule deletion of pass files after use + sched +1 " +rm -f $MUTTDIR/muttpass +touch $MUTTDIR/muttpass +${=rm} -f $tmp" # zero the tmp passfile after a second + + _mutt -f ${iproto}://${ilogin}@${imap}:${imap_port}/${folder} } # DRYRUN return $? diff --git a/src/zlibs/filters b/src/zlibs/filters @@ -90,7 +90,7 @@ update_filters() { { test -r "$ff" } && { rm -f "$ff" } newlock "$ff" - cat <<EOF >> "$ff" + sysread -o 1 <<EOF >> "$ff" # automatically generated by jaromail typeset -Al filter_from typeset -alU filter_own @@ -100,9 +100,9 @@ filter_own=() filter_to=() EOF - ffilters=`cat "$MAILDIRS/Filters.txt" | awk ' + ffilters=`awk ' /^#/ {next} - /^./ { print $1 ";" $2 ";" $3 ";" $4 }'` + /^./ { print $1 ";" $2 ";" $3 ";" $4 }' "$MAILDIRS/Filters.txt"` # insert filter rules in the cache for f in ${(f)ffilters}; do @@ -112,14 +112,14 @@ EOF destination="${f[(ws:;:)4]}" case $header in to) - cat <<EOF >> "$ff" + sysread -o 1 <<EOF >> "$ff" filter_to+=("${regexp}" "${destination}") EOF func "from: <${regexp}> -> ${destination}" maildirmake $MAILDIRS/$destination ;; from) - cat <<EOF >> "$ff" + sysread -o 1 <<EOF >> "$ff" filter_from+=("${regexp}" "${destination}") EOF func "to: <${regexp}> -> ${destination}" @@ -145,7 +145,7 @@ EOF /^$/ { next } /^email/ { print $2 }' \ "$MAILDIRS"/Accounts/*`; do - cat <<EOF >> "$ff" + sysread -o 1 <<EOF >> "$ff" filter_own+=($i) EOF done @@ -154,7 +154,7 @@ EOF /^#/ { next } /^$/ { next } { print $1 }' "$MAILDIRS/Aliases.txt"`; do - cat <<EOF >> "$ff" + sysread -o 1 <<EOF >> "$ff" filter_own+=($i) EOF done @@ -217,12 +217,12 @@ filter_maildir() { error "User break requested, interrupting operation" break } - + match=0 c=$(($c + 1)) # check if its an empty file - _fsize=`stat -c '%s' "$m"` + _fsize=`zstat +size "$m"` [[ $_fsize = 0 ]] && { act "$c\t/ $numm\t(empty)" rm "$m" @@ -230,9 +230,9 @@ filter_maildir() { } # parse if its a mailinglist - _md=0 + _ml=0 hdr "$m" | ismailinglist - [[ $? = 0 ]] && _md=1 + [[ $? = 0 ]] && _ml=1 list="blacklist" hdr "$m" | sender_isknown @@ -241,10 +241,14 @@ filter_maildir() { act "$c\t/ $numm" continue } - cat "$m" | deliver zz.blacklist - [[ $? = 0 ]] && { rm "$m" } + act "$c\t/ $numm\t-> zz.blacklist" - continue + + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver zz.blacklist + [[ $? = 0 ]] && { rm "$m" } + continue + } } hdr "$m" | awk '/Sender.*mailman-bounce/ { exit 1 }' @@ -253,10 +257,12 @@ filter_maildir() { act "$c\t/ $numm" continue } - cat "$m" | deliver zz.bounces - [[ $? = 0 ]] && { rm "$m" } act "$c\t/ $numm\t-> zz.bounces" - continue + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver zz.bounces + [[ $? = 0 ]] && { rm "$m" } + continue + } } [[ "$ownfilters" = "1" ]] && { @@ -283,16 +289,19 @@ filter_maildir() { match=1 break } + + act "$c\t/ $numm\t-> $_dest\t(from $femail)" # tag mailinglists - if [[ $_md = 1 ]]; then - cat "$m" | deliver "$_dest" "+filtered +mailinglist" - else - cat "$m" | deliver "$_dest" "+filtered" - fi + [[ $DRYRUN = 1 ]] || { + if [[ $_ml = 1 ]]; then + printfile "$m" | deliver "$_dest" "+filtered +mailinglist" + else + printfile "$m" | deliver "$_dest" "+filtered" + fi + } if [[ $? = 0 ]]; then - act "$c\t/ $numm\t-> $_dest\t(from $femail)" match=1 rm "$m" break @@ -332,15 +341,17 @@ filter_maildir() { break } + act "$c\t/ $numm\t-> $_dest\t(to $ft)" # tag mailinglists - if [[ $_md = 1 ]]; then - cat "$m" | deliver "$_dest" "+filtered +mailinglist" - else - cat "$m" | deliver "$_dest" "+filtered" - fi + [[ $DRYRUN = 1 ]] || { + if [[ $_ml = 1 ]]; then + printfile "$m" | deliver "$_dest" "+filtered +mailinglist" + else + printfile "$m" | deliver "$_dest" "+filtered" + fi + } if [[ $? = 0 ]]; then - act "$c\t/ $numm\t-> $_dest\t(to $ft)" match=1 rm "$m" break @@ -369,10 +380,12 @@ filter_maildir() { act "$c\t/ $numm" continue } - cat "$m" | deliver known "+inbox +priv" - [[ $? = 0 ]] && { rm "$m" } act "$c\t/ $numm\t-> known" - continue + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver known "+inbox +priv" + [[ $? = 0 ]] && { rm "$m" } + continue + } } hdr "$m" | awk '/X-Spam-Flag.*YES/ { exit 1 }' @@ -381,10 +394,12 @@ filter_maildir() { act "$c\t/ $numm" continue } - cat "$m" | deliver zz.spam - [[ $? = 0 ]] && { rm "$m" } act "$c\t/ $numm\t-> zz.spam" - continue + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver zz.spam + [[ $? = 0 ]] && { rm "$m" } + continue + } } # parse own email and aliases @@ -397,12 +412,14 @@ filter_maildir() { match=1 break } - cat "$m" | deliver priv "+priv" - [[ $? = 0 ]] && { - rm "$m"; - act "$c\t/ $numm\t-> priv" - match=1 - break + act "$c\t/ $numm\t-> priv" + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver priv "+priv" + [[ $? = 0 ]] && { + rm "$m"; + match=1 + break + } } fi done @@ -414,9 +431,14 @@ filter_maildir() { act "$c\t/ $numm" continue } - cat "$m" | deliver unsorted.ml "+unsorted +mailinglist" - [[ $? = 0 ]] && { rm "$m" } - continue + act "$c\t/ $numm\t-> unsorted.ml" + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver unsorted.ml "+unsorted +mailinglist" + [[ $? = 0 ]] && { + rm "$m" + continue + } + } } # if here then file to unsorted @@ -424,8 +446,10 @@ filter_maildir() { act "$c\t/ $numm" else act "$c\t/ $numm\t-> unsorted" - cat "$m" | deliver unsorted "+unsorted" - [[ $? = 0 ]] && { rm "$m" } + [[ $DRYRUN = 1 ]] || { + printfile "$m" | deliver unsorted "+unsorted" + [[ $? = 0 ]] && { rm "$m" } + } fi done @@ -487,14 +511,14 @@ source '$WORKDIR/.mutt/formats' source '$WORKDIR/.mutt/keybindings' source '$WORKDIR/.mutt/colors' source '$MAILDIRS/Identity.txt' -source '$MAILDIRS/tmp/muttpass' +source '$MUTTDIR/muttpass' EOF [[ "$gpgkey" = "" ]] || { # gpg special settings - cat <<EOF >> "$MUTTDIR"/rc + sysread -o 1 <<EOF >> "$MUTTDIR"/rc ## GnuPG specific settings # create a pgp/mime encrypted attachment set pgp_encrypt_only_command="pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust --encrypt-to $gpgkey -- -r %r -- '%f'" @@ -508,7 +532,7 @@ EOF } # MUTT MAILCAP - cat <<EOF > $MUTTDIR/mailcap + sysread -o 1 <<EOF > $MUTTDIR/mailcap text/plain; iconv -f iso-8859-1 -t utf-8; test=charset=%{charset} \ && test x`echo \"$charset\" | tr a-z A-Z` = xISO-8859-1; copiousoutput text/plain; cat %s @@ -548,7 +572,8 @@ EOF } # Applications.txt # this one is empty and sources files in temp when necessary - touch $MAILDIRS/tmp/muttpass + rm -f "$MUTTDIR/muttpass" + touch "$MUTTDIR/muttpass" # just the header, will be completed later rm -f $MUTTDIR/mboxes diff --git a/src/zlibs/helpers b/src/zlibs/helpers @@ -27,11 +27,17 @@ # which mutt binary to use mutt="mutt" + # remote leading and trailing spaces in a string taken from stdin trim() { sed -e 's/^[[:space:]]*//g ; s/[[:space:]]*\$//g' } +# zmodload zsh/mapfile +printfile() { + print ${mapfile[$1]} +} + # extract all emails found in a text from stdin # outputs them one per line extract_emails() { @@ -40,6 +46,7 @@ awk '{ for (i=1;i<=NF;i++) gsub(/<|>|,/ , "" , $i); print $i } }' } +# zmodload zsh/regex isemail() { [[ "$1" -regex-match "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" ]] && return 0 @@ -108,7 +115,7 @@ autostart() { return 1 } - ${=mutt} -F $MUTTDIR/rc ${=muttflags} -Z + _mutt -Z return $? } @@ -117,7 +124,7 @@ autostart() { [[ $? = 0 ]] && { notice "Composing message to: ${@}" # its an email, TODO see if we have it in our addressbook - ${=mutt} -F $MUTTDIR/rc ${=muttflags} ${=@} + _mutt ${=@} return 0 } @@ -126,12 +133,12 @@ autostart() { # is it a maildir? then open maildircheck ${1} [[ $? = 0 ]] && { - ${=mutt} -F $MUTTDIR/rc ${=muttflags} -f ${1} + _mutt -f ${1} return 0 } # is it a regular file? then attach it [[ -f "$1" ]] && { - ${=mutt} -F $MUTTDIR/rc ${=muttflags} -a ${=@} + _mutt -a ${=@} return 0 } } @@ -140,7 +147,7 @@ autostart() { maildircheck "$MAILDIRS/$1" [[ $? = 0 ]] && { notice "Opening folder ${1}" - ${=mutt} -F $MUTTDIR/rc ${=muttflags} -f "$MAILDIRS/${1}" + _mutt -f "$MAILDIRS/${1}" return 0 } @@ -206,7 +213,7 @@ BEGIN { head=1 } # of course we have a preference for AutOrg, the editor from our suite # however the default is nano if nothing else is choosen. jarovim() { - vim -c 'set fo=tcrq' -c 'set tw=72' -c 'set paste' \ + vim -c 'set fo=tcrq' -c 'set tw=72' \ -c 'map <C-j> {gq}' -c 'imap <C-j> <esc>{gq}i' \ "${@}" return $? @@ -245,11 +252,22 @@ edit_file() { ##################### ## Open a mail folder open_folder() { - notice "Opening folder ${1}" - { maildircheck ${MAILDIRS}/${1} } && { - ${=mutt} -F $MUTTDIR/rc ${=muttflags} -f "$MAILDIRS/${1}" - return $? } - return 1 + notice "Opening folder ${PARAM[1]}" + + if maildircheck "${MAILDIRS}/${PARAM[1]}"; then + _mutt -f "$MAILDIRS/${PARAM[1]}" + exitcode=$? + + elif maildircheck "${PARAM[1]}"; then + _mutt -f "${PARAM[1]}" + exitcode=$? + + else + error "No maildir found: ${PARAM[1]}" + exitcode=1 + + fi + return $exitcode } ############## @@ -381,6 +399,9 @@ human_size() { # TODO: save fingeprints of servers and check connections fingerprint() { +# dyne.org one: +# tls_fingerprint 6A:D4:DF:E4:20:32:F9:66:94:35:0C:33:9D:74:96:5C + read_account ${account} { test $? != 0 } && { error "Invalid account: $account" diff --git a/src/zlibs/locking b/src/zlibs/locking @@ -53,53 +53,55 @@ newlock() { # lock file, create if not existing pidcheck() { # check if lock belongs to us if [ -r "${1}.pid" ]; then - - lockpid="`cat ${1}.pid`" - func "pidcheck: $lockpid" - if [ "$$" = "$lockpid" ]; then - func "${1} lock belongs to us" - else - - error "Unlock attempt by multiple processes on `basename $1`" - { test "$FORCE" = "1" } || { _prun=1 - while [ "$_prun" = "1" ]; do - for p in `ps ax | awk '{ print $1 }'`; do - { test "$p" = "$lockpid" } && { break } - done - if [ "$p" = "$lockpid" ]; then - act "Owner (${lockpid}) still running, waiting release..." - sleep 1; continue - else - act "Owner (${lockpid}) not running, taking over the lock" - rm -f "${1}.pid"; print "$$" > "${1}.pid" - _prun=0 - fi - done - } - act "left behind by $lockpid - we ($$) will take over" - - fi - + + lockpid="`cat ${1}.pid`" + func "pidcheck: $lockpid" + if [[ "$$" = "$lockpid" ]]; then + func "${1} lock belongs to us" + else + + error "Unlock attempt by multiple processes on `basename $1`" + [[ "$FORCE" = "1" ]] || { _prun=1 + while [ "$_prun" = "1" ]; do + [[ $global_quit = 1 ]] && { break } + for p in `ps ax | awk '{ print $1 }'`; do + { test "$p" = "$lockpid" } && { break } + done + if [ "$p" = "$lockpid" ]; then + act "Owner (${lockpid}) still running, waiting release..." + sleep 1; + continue + else + act "Owner (${lockpid}) not running, taking over the lock" + rm -f "${1}.pid"; print "$$" > "${1}.pid" + _prun=0 + fi + done + } + act "left behind by $lockpid - we ($$) will take over" + + fi + else # pid file doesn't exists - func "no pid file found for: $1" - func "we will take it over" - print "$$" > "${1}.pid" + func "no pid file found for: $1" + func "we will take it over" + print "$$" > "${1}.pid" fi return 0 } unlock() { func "unlock: $1" - + pidcheck "$1" - { test $? = 0 } || { return 1 } - + [[ $? = 0 ]] || { return 1 } + ${WORKDIR}/bin/dotlock -u "$1" - { test $? = 0 } || { - rm -f "$1.lock" - { test $? = 0 } || { error "Unable to unlock: $1"; return 1 } + [[ $? = 0 ]] || { + rm -f "$1.lock" + [[ $? = 0 ]] || { error "Unable to unlock: $1"; return 1 } } - { test -r "${1}.pid" } && { rm -f "${1}.pid" } + [[ -r "${1}.pid" ]] && { rm -f "${1}.pid" } return 0 } unlink() { # delete a file that we are locking diff --git a/src/zlibs/maildirs b/src/zlibs/maildirs @@ -237,7 +237,7 @@ deliver() { tags="$2" func "indexing tags: $tags" - cat | nm insert --folder="$dest" ${=tags} + nm insert --folder="$dest" ${=tags} res=$? [[ $res = 0 ]] || \ error "Could not deliver email file into maildir $dest with tags $tags" diff --git a/src/zlibs/search b/src/zlibs/search @@ -29,8 +29,10 @@ nm() { func "notmuch $@" [[ -r "$MAILDIRS"/cache/notmuch/rc ]] || nm_setup + lock "$MAILDIRS"/cache/notmuch notmuch --config="$MAILDIRS"/cache/notmuch/rc ${@} _res=$? + unlock "$MAILDIRS"/cache/notmuch [[ $_res = 0 ]] || { error "Notmuch error on command: ${@}" func "Returning status to caller: $_res" @@ -101,12 +103,9 @@ nm_index() { nm_search() { - func "notmuch --config=${nm_dir}/rc search --output=files ${=PARAM}" - + # launch the search with notmuch - lock "$MAILDIRS"/cache/notmuch search_results=`nm search --output=files ${=PARAM}` - unlock "$MAILDIRS"/cache/notmuch [[ $? = 0 ]] || { error "notmuch search failed with an error" return 1 @@ -198,10 +197,8 @@ user_agent = Jaro Mail <http://jaromail.dyne.org> translated = ☰ EOF - lock "$MAILDIRS"/cache/notmuch alot -c "$MAILDIRS"/cache/alot/rc -n "$MAILDIRS"/cache/notmuch/rc \ search ${=PARAM} - unlock "$MAILDIRS"/cache/notmuch return $? }