My dotfiles. Period.

imapdomo-cron 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. #!/bin/bash
  2. #
  3. # shellfu embedded: /home/amahdal/local/mydots/dotfiles/imapdomo/utils/imapdomo
  4. # shellfu version: 0.9.0
  5. #
  6. # neuter any shellfu and shellfu-get calls
  7. shellfu() { :; }
  8. shellfu-get() { echo /dev/null; }
  9. #
  10. # begin module: d85843c5561356764375c3915e2b411b /usr/local/share/shellfu/include-bash/exit.sh
  11. #
  12. #!/bin/bash
  13. EXIT_OK=0
  14. EXIT_NO=1
  15. EXIT_USAGE=2
  16. EXIT_ERROR=3
  17. EXIT_PANIC=4
  18. exit_ok() {
  19. #
  20. # Exit script with success
  21. #
  22. exit $EXIT_OK
  23. }
  24. exit_no() {
  25. #
  26. # Exit script with answer "no"
  27. #
  28. exit $EXIT_NO
  29. }
  30. exit_usage() {
  31. #
  32. # Exit script with usage error
  33. #
  34. exit $EXIT_USAGE
  35. }
  36. exit_error() {
  37. #
  38. # Exit script with generic unexpected error
  39. #
  40. exit $EXIT_ERROR
  41. }
  42. exit_panic() {
  43. #
  44. # Exit script in panic (e.g. assert failure, sure bug)
  45. #
  46. exit $EXIT_PANIC
  47. }
  48. #
  49. # end module: d85843c5561356764375c3915e2b411b /usr/local/share/shellfu/include-bash/exit.sh
  50. #
  51. #
  52. # begin module: 8ee17c6681d102da92d36f71ef523a55 /usr/local/share/shellfu/include-bash/pretty.sh
  53. #
  54. #!/bin/bash
  55. shellfu import exit
  56. #
  57. # Application debug mode
  58. #
  59. PRETTY_DEBUG=${PRETTY_DEBUG:-false}
  60. #
  61. # List of module/function names to exclude from debuging
  62. #
  63. # For the sake of readability of your debug dumps, you can set this
  64. # variable to comma-separated list of module or function names that
  65. # you don't expect to get useful info from.
  66. #
  67. # If the caller has a qualified name (`modname__funcname()`, according
  68. # to Shellfu naming scheme it's possible to use just module name here
  69. # to mute all debug from that module (including internal functions).
  70. # Otherwise, full function name should be listed.
  71. #
  72. PRETTY_DEBUG_EXCLUDE=${PRETTY_DEBUG_EXCLUDE:-}
  73. #
  74. # Application verbosity mode
  75. #
  76. PRETTY_VERBOSE=${PRETTY_VERBOSE:-false}
  77. #
  78. # Name of pretty-printer module
  79. #
  80. # Friendly name of module used for decorating output. For
  81. # example, if the value is NAME, a _pretty_NAME module must
  82. # exist and be importable. Otherwise pretty will fall back
  83. # to plain, which is also the default value.
  84. #
  85. PRETTY=${PRETTY:-plain}
  86. #
  87. # Usage mode -- set to 'subcommand' to remove first dash
  88. #
  89. PRETTY_USAGE=${PRETTY_USAGE:-}
  90. __shellfu_pretty__init() {
  91. #
  92. # Import proper submodule
  93. #
  94. if shellfu try_import "_pretty_${PRETTY}";
  95. then
  96. shellfu import "_pretty_${PRETTY}"
  97. return 0
  98. else
  99. warn "falling back to _pretty_plain"
  100. PRETTY=plain
  101. shellfu import "_pretty_${PRETTY}"
  102. fi
  103. }
  104. ##--------------------##
  105. ## PRINTING FRONT-END ##
  106. ##--------------------##
  107. debug() {
  108. #
  109. # You already know what it does
  110. #
  111. # BTW, following are equivalent:
  112. #
  113. # debug "var1=$var1" "var2=$var2" "result=$result"
  114. # debug -v var1 var2 result
  115. #
  116. $PRETTY_DEBUG || return 0
  117. _pretty__echo "$@"
  118. }
  119. debug_pipe() {
  120. #
  121. # Debug the whole pipe.
  122. #
  123. while IFS= read -r line;
  124. do
  125. debug "|$1: '$line'"
  126. echos "$line"
  127. done
  128. }
  129. die() {
  130. #
  131. # A fatal error
  132. #
  133. _pretty__echo -t
  134. _pretty__echo "$@"
  135. exit_error
  136. }
  137. echos() {
  138. #
  139. # Safer version of echo able to echo "-n"
  140. #
  141. # Traditional echo is broken in that it does not
  142. # distinguish between string to print and its own switches
  143. # (-e, -E or -n), leading to unexpected behavior.
  144. #
  145. # This echo version circumvents this by using printf.
  146. #
  147. printf -- '%s\n' "$@"
  148. }
  149. mkusage() {
  150. #
  151. # Echo out usage patterns and (by default) `exit 2`
  152. #
  153. # mkusage [-e STATUS] [-E] pattern [patern...]
  154. #
  155. # Each pattern is prefixed by "usage: " and a resolved
  156. # script/function name to produce traditional usage hint.
  157. # By default, will exit with status *EXIT_USAGE*, you
  158. # can use `-e STATUS` to specify other number. `-k` can be
  159. # used as shorthand for `-e 0` (e.g. if user asked for
  160. # the patterns)
  161. #
  162. # Use `-E` to prevent exiting; in that case, the status
  163. # that would be fed to `exit` will be used as exit status
  164. # of this function.
  165. #
  166. # Use "--" to delimit end of arguments processed by mkusage.
  167. #
  168. # Setting PRETTY_USAGE to 'subcommand' has effect that
  169. # in each call, first hyphen in the script's "own" name is
  170. # replaced by space; this is used for git-like sub-commands,
  171. # where the actual binary name is e.g. "git-add" for
  172. # "git add".
  173. #
  174. # Recommended usage is to define usage() in your script and
  175. # use this in its body. That way you only need to define
  176. # usage patterns once and skip to them from any place where
  177. # you detect incorrect usage.
  178. #
  179. local es=$EXIT_USAGE
  180. local doexit=true
  181. while true; do case "$1" in
  182. -e) es="$2"; shift 2 || return 2 ;;
  183. -E) doexit=false; shift ;;
  184. -k) es=$EXIT_OK; shift ;;
  185. --) shift; break ;;
  186. *) break ;;
  187. esac done
  188. _pretty__echo -u "$@";
  189. $doexit && exit "$es"
  190. return "$es"
  191. }
  192. mkhelp() {
  193. #
  194. # Echo out help text
  195. #
  196. # mkhelp [-e STATUS] [-E] arg...
  197. #
  198. # By default, will exit with status *EXIT_OK*, you
  199. # can use `-e STATUS` to specify other number.
  200. #
  201. # Use `-E` to prevent exiting; in that case, the status
  202. # that would be fed to `exit` will be used as exit status
  203. # of this function.
  204. #
  205. # Use "--" to delimit end of arguments processed by mkhelp
  206. #
  207. local es=$EXIT_OK
  208. local doexit=true
  209. while true; do case "$1" in
  210. -e) es="$2"; shift 2 || return 2 ;;
  211. -E) doexit=false; shift ;;
  212. --) shift; break ;;
  213. *) break ;;
  214. esac done
  215. _pretty__echo "$@"
  216. $doexit && exit "$es"
  217. return "$es"
  218. }
  219. think() {
  220. #
  221. # If verbose is on, think loud
  222. #
  223. # Use "-l" to split every parameter to separate line, (useful
  224. # or longer warnings)
  225. #
  226. $PRETTY_VERBOSE || return 0
  227. _pretty__echo "$@"
  228. }
  229. warn() {
  230. #
  231. # Warn them
  232. #
  233. # Use "-l" to split every parameter to separate line, (useful
  234. # or longer warnings)
  235. #
  236. _pretty__echo "$@"
  237. }
  238. ##----------##
  239. ## BACK-END ##
  240. ##----------##
  241. _pretty__cat() {
  242. #
  243. # `cat` but without starting a process
  244. #
  245. # Used to avoid spanning new process where stream handler is chosen
  246. # based on some logic
  247. #
  248. while IFS= read -r line;
  249. do echos "$line"; done
  250. }
  251. _pretty__get_caller() {
  252. #
  253. # Get first user function and negative index from stack
  254. #
  255. local fname
  256. local nidx="${#FUNCNAME[@]}"
  257. for fname in "${FUNCNAME[@]}";
  258. do
  259. (( nidx-- ))
  260. _pretty__is_internal && continue
  261. _pretty__is_frontend && continue
  262. test "$fname" = "usage" && continue
  263. echos "$nidx" "$fname"
  264. return
  265. done
  266. }
  267. _pretty__get_frontend() {
  268. #
  269. # Get entry point function name from stack
  270. #
  271. local fname
  272. for fname in "${FUNCNAME[@]}";
  273. do
  274. _pretty__is_internal && continue
  275. _pretty__is_frontend && echos "$fname" && return 0
  276. echo "do not call _pretty_* directly: $fname" >&2
  277. return "$EXIT_USAGE"
  278. done
  279. }
  280. _pretty__is_excluded() {
  281. #
  282. # True if $caller is excluded based on PRETTY_DEBUG_EXCLUDE
  283. #
  284. # Check PRETTY_DEBUG_EXCLUDE to see if $caller (using only module name
  285. # part, if possible) should be muted from debugging.
  286. #
  287. local listed # item listed in PRETTY_DEBUG_EXCLUDE
  288. local name # module part of caller's name
  289. local qualified # is caller "qualified" (ac. to shellfu scheme)?
  290. name="$caller"
  291. case "$name" in
  292. __*__*) qualified=true ;;
  293. __*) qualified=false ;;
  294. *__*) qualified=true ;;
  295. *) qualified=false ;;
  296. esac
  297. if $qualified;
  298. then
  299. # we'll use only the module part of the name
  300. name=${name#_} # drop one "internal" prefix
  301. name=${name#_} # drop yet another one
  302. name=${name%__*} # drop funcname
  303. fi
  304. for listed in ${PRETTY_DEBUG_EXCLUDE//,/ };
  305. do
  306. test "$name" = "$listed" && return 0
  307. done
  308. return 1
  309. }
  310. _pretty__is_frontend() {
  311. #
  312. # True if $fname is one of our "frontends"
  313. #
  314. case "$fname" in
  315. debug) return 0 ;;
  316. debug_pipe) return 0 ;;
  317. die) return 0 ;;
  318. mkhelp) return 0 ;;
  319. think) return 0 ;;
  320. mkusage) return 0 ;;
  321. warn) return 0 ;;
  322. esac
  323. return 1
  324. }
  325. _pretty__is_internal() {
  326. #
  327. # True if $fname is our internal function
  328. #
  329. case "$fname" in
  330. _pretty__*) return 0 ;;
  331. *) return 1 ;;
  332. esac
  333. }
  334. _pretty__echo() {
  335. #
  336. # A smarter echo backend
  337. #
  338. # A smarter backend for debug, warn, think, die and
  339. # mkusage.
  340. #
  341. # -c cmd echo output of a command
  342. # -f file echo output of a file (- for stdin)
  343. # -l line [line...] echo each line separately
  344. # -t add stack trace to output
  345. # -u patt [patt...] convert each patt to usage pattern
  346. # -v var [var...] show contents of each var
  347. #
  348. local frontend # who (of pretty.sh) was called (=> prettyprinter choice)
  349. local caller # which user's function (or script) called it
  350. # ^ ^ eg. if user calls 'debug hello' from function 'foo', then
  351. # : :.. * frontend is 'debug'
  352. # :......... * and caller is 'foo'.
  353. local caller_nidx # negative stack index of caller
  354. local caller_is_main # true if caller was main script or main() in it
  355. local provider # which provider (_pretty__echo_*()) to use
  356. frontend="$(_pretty__get_frontend)" || exit_usage
  357. read caller_nidx caller <<<$(_pretty__get_caller)
  358. test "$frontend" = debug && _pretty__is_excluded "$caller" && return 0
  359. case $caller_nidx:$caller in
  360. 0:*) caller_is_main=true; caller="${0##*/}" ;;
  361. 1:main) caller_is_main=true; caller="${0##*/}" ;;
  362. *:usage) frontend=mkusage ;;
  363. *) caller_is_main=false ;;
  364. esac
  365. while true; do case $1 in
  366. -c|--cmd) provider=cmd; shift; break ;;
  367. -f|--files) provider=files; shift; break ;;
  368. -l|--lines) provider=lines; shift; break ;;
  369. -t|--trace) provider=trace; shift; break ;;
  370. -u|--usage) provider=usage; shift; break ;;
  371. -v|--vars) provider=vars; shift; break ;;
  372. *) provider=args; break ;;
  373. esac done
  374. _pretty__echo_$provider "$@" \
  375. | _pretty__$frontend >&2
  376. }
  377. _pretty__echo_args() {
  378. #
  379. # The simplest (but safe) printing of args
  380. #
  381. echos "$*"
  382. }
  383. _pretty__echo_cmd() {
  384. #
  385. # Print command line, launch it and report exit status
  386. #
  387. local c=\$
  388. test "$(id -u)" -eq 0 && c="#"
  389. echo "$c $*"
  390. "$@"
  391. echo "^ exit status: $?"
  392. }
  393. _pretty__echo_files() {
  394. #
  395. # Print names and contents of existing files
  396. #
  397. local fp
  398. for fp in "$@";
  399. do
  400. if test "$fp" = "-";
  401. then
  402. cat
  403. elif test -s "$fp" || test "$fp" = "/dev/stdin";
  404. then
  405. echo "-- $fp --"
  406. cat "$fp"
  407. fi
  408. done
  409. }
  410. _pretty__echo_lines() {
  411. #
  412. # Echo each argument as a separate line
  413. #
  414. local l;
  415. for l in "$@"; do _pretty__echo_args "$l"; done
  416. }
  417. _pretty__echo_trace() {
  418. #
  419. # Print "decorated" call trace (only in debug mode)
  420. #
  421. $PRETTY_DEBUG || return 0
  422. local depth
  423. echo "== trace =="
  424. for depth in $(seq 0 ${#FUNCNAME});
  425. do
  426. caller "$depth" || break
  427. done \
  428. | tail -n +3 \
  429. | sed -e '
  430. s/^\([^ ]\+\) \([^ ]\+\) \(.*\)/\3:\1:\2()/
  431. # ^line^, ^func^, ^file^
  432. 1 s/^/ -> /g
  433. 2,$ s/^/ /
  434. ' \
  435. | tac
  436. }
  437. _pretty__echo_help() {
  438. local oldverbose="$PRETTY_VERBOSE"
  439. think -l "$@"
  440. PRETTY_VERBOSE=$oldverbose
  441. }
  442. _pretty__echo_usage() {
  443. #
  444. # Compose conventional usage guide
  445. #
  446. # The default mode treats each argument as usage pattern
  447. # (see below for details). Additional formatting can be
  448. # conveniently achieved by switching to other modes, which
  449. # automatically brings necessary headers and indentations
  450. # where needed.
  451. #
  452. # * option mode (`-o`) prints "options:" header and
  453. # indents next arguments,
  454. #
  455. # * command mode (`-c`) prints "commands:" header and
  456. # indents next arguments,
  457. #
  458. # * plain mode (`--`) prints empty line (new paragraph)
  459. # and turns indentations off.
  460. #
  461. # * usage mode (`-u`, active by default), prints
  462. # "usage:" header, indents next arguments and prefixes
  463. # them with name of the script.
  464. #
  465. # A special case of usage mode is when only single
  466. # argument is passed to this function; then instead
  467. # of "usage:" header, this usage pattern is prefixed
  468. # with the same string.
  469. #
  470. # In order to help avoid (rare) conflict between mkusage()
  471. # switches and your usage patterns, the very first argument,
  472. # and each argument that comes right after one of these
  473. # switches are guarranteed not to be interpreted as switch.
  474. #
  475. local self # the script name
  476. local mode=usage # mode
  477. local esc=1 # escape (take next argument as literal)
  478. local arg # argument to iterate
  479. case "$PRETTY_USAGE" in
  480. subcommand) self="${0##*/}"; self="${self/-/ }" ;;
  481. *) self="$caller" ;;
  482. esac
  483. case $# in
  484. 0) return 0 ;;
  485. 1) echo "usage: $self $1"; return 0 ;;
  486. esac
  487. echo usage:
  488. for arg in "$@";
  489. do
  490. case $esc:$arg in
  491. 0:--) shift; mode=plain; esc=1; echo ;;
  492. 0:-c) shift; mode=indent; esc=1; echo; echo commands: ;;
  493. 0:-i) shift; mode=indent; esc=1; echo ;;
  494. 0:-o) shift; mode=indent; esc=1; echo; echo options: ;;
  495. 0:-u) shift; mode=usage; esc=1 ;;
  496. *) esc=0
  497. case $mode in
  498. usage) echo " $self $arg" ;;
  499. indent) echo " $arg" ;;
  500. plain) echos "$arg" ;;
  501. esac
  502. ;;
  503. esac
  504. done
  505. }
  506. _pretty__echo_vars() {
  507. #
  508. # Report value of each named variable
  509. #
  510. local varname
  511. local declare_str
  512. for varname in "$@";
  513. do
  514. if ! _pretty__is_word "$varname";
  515. then
  516. warn "unsafe value skipped: $varname";
  517. continue
  518. fi
  519. if declare_str=$(declare -p "$varname" 2>/dev/null);
  520. then
  521. _pretty__echo "${declare_str#declare ?? }"
  522. else
  523. _pretty__echo "$varname #Unset"
  524. fi
  525. done
  526. }
  527. _pretty__is_word() {
  528. #
  529. # Check if $1 contains only alphanumeric chars or _
  530. #
  531. local tainted="$1"
  532. local clean=$(tr -c -d '_[:alnum:]' <<< "$tainted")
  533. test "$tainted" = "$clean"
  534. }
  535. #
  536. # end module: 8ee17c6681d102da92d36f71ef523a55 /usr/local/share/shellfu/include-bash/pretty.sh
  537. #
  538. #
  539. # begin module: 392f50abe388bd54c01d84ee7b2a0cdd /usr/local/share/shellfu/include-bash/_pretty_plain.sh
  540. #
  541. #!/bin/bash
  542. _pretty__debug() {
  543. local decor="()"
  544. $caller_is_main && decor=
  545. while IFS= read -r line;
  546. do echo "debug:$caller$decor: $line"; done
  547. }
  548. _pretty__die() {
  549. while IFS= read -r line;
  550. do echo "$line"; done
  551. }
  552. _pretty__mkhelp() {
  553. while IFS= read -r line;
  554. do echo "$line"; done
  555. }
  556. _pretty__mkusage() {
  557. while IFS= read -r line;
  558. do echo "$line"; done
  559. }
  560. _pretty__think() {
  561. while IFS= read -r line;
  562. do echo "$line"; done
  563. }
  564. _pretty__warn() {
  565. while IFS= read -r line;
  566. do echo "$line"; done
  567. }
  568. #
  569. # end module: 392f50abe388bd54c01d84ee7b2a0cdd /usr/local/share/shellfu/include-bash/_pretty_plain.sh
  570. #
  571. #!/bin/bash
  572. . "$(shellfu-get path)" || exit 3
  573. shellfu import pretty
  574. usage() {
  575. mkusage "[options] ACTION" \
  576. -o \
  577. "-c DIR change to DIR before doing anything" \
  578. "-d turn on debugging mode" \
  579. -- \
  580. "imapdomo will try to read .imapdomo/host/HOSTNAME/init.lua and" \
  581. ".imapdomo/host/HOSTNAME/handlers/ACTION.lua, where HOSTNAME is your" \
  582. "short hostname (eg. 'foo' in 'foo.example.com')." \
  583. "" \
  584. "four valid actions are understood; since you must write handler for" \
  585. "each action you want to use, the meanings below are purely a guide:" \
  586. "" \
  587. " newmail - check for and file new mail" \
  588. " rewind - re-add messages from FILTER_FAIL back to FILTER_QUEUE" \
  589. " cleanup - delete or archive old messages" \
  590. " migrate - move mail between mailboxes" \
  591. "" \
  592. "See imapfilter_config(5)) for guide and API reference. Few functions"\
  593. "are also available in .imapdomo/common.lua"
  594. }
  595. mkcmd() {
  596. #
  597. # Compose imapfilter command
  598. #
  599. echo -n "IMAPDOMO_ACTION=$Action"
  600. echo -n " IMAPDOMO_HEADERS=$HeaderDir"
  601. echo -n " IMAPFILTER_HOME=$CfgDir"
  602. echo -n " imapfilter"
  603. if $Debug
  604. then
  605. mkdir -p "$LogDir"
  606. echo -n " -d $LogDir/debug.log"
  607. echo -n " -v"
  608. fi
  609. echo -n " -c $CfgDir/main.lua"
  610. }
  611. main() {
  612. local Action # what to do
  613. local Debug # true if debugging
  614. local cmd # imapfilter command
  615. local CfgDir # config directory
  616. local LogDir # directory to store logs
  617. local HeaderDir # directory to store headers by save_header()
  618. local CdTo # change dir to this before running imapfilter
  619. CfgDir="$HOME/.imapdomo"
  620. LogDir="$HOME/.local/share/imapdomo/logs"
  621. HeaderDir="$HOME/.local/share/imapdomo/headers"
  622. Debug=false
  623. #shellcheck disable=SC2034
  624. while true; do case $1 in
  625. -c) CdTo="$2"; shift 2 || usage ;;
  626. -d) Debug=true; PRETTY_DEBUG=true; shift ;;
  627. -*) usage ;;
  628. *) break ;;
  629. esac done
  630. Action="$1"; shift
  631. grep -qw "$Action" <<< "newmail|rewind|cleanup|migrate" || usage
  632. cmd=$(mkcmd)
  633. debug -v cmd
  634. bash -n <<<"$cmd" || die
  635. if test -n "$CdTo";
  636. then
  637. cd "$CdTo" || die
  638. fi
  639. mkdir -p "$HeaderDir" || die
  640. eval "$cmd"
  641. }
  642. main "$@"
  643. #
  644. # end of shellfu-embedded shell script
  645. #