Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Dear release team, I uploaded a new version of mblaze, which reset the package's transition countdown, which will cause it to miss the hard freeze window: https://qa.debian.org/excuses.php?package=mblaze I did so as the newest upstream release includes security-relevant changes: mblaze (0.5.1-1) unstable; urgency=high (security fixes) * New upstream release (2019-03-03) + Fixes for buffer-overflows, found by fuzzing. + Fixes for memleaks. * Remove unused lintian override * debian/rules: Remove useless dh_missing invocation. A single binary package is being produced. -- Nicolas Braud-Santoni <ni...@debian.org> Mon, 04 Mar 2019 18:40:01 +0100 Moreover, version 0.5-1 closes several Debian bugs (including a RC one): mblaze (0.5-1) unstable; urgency=medium * New upstream release (2019-02-09) + Closes: 921891 + GNUmakefile: correct reference to SOURCE_DATE_EPOCH, patch by Chris Lamb Closes: #907537 * Rename mless and msort to mblaze-less and mblaze-sort Closes: #887988 correctly, avoids conflicts on mpdtoys & msort * Switch to debhelper 12. The compatibility level is now controlled by a Build-Depends. * Declare compliance with policy v4.2.1. No change required. * debian/rules + Make dh_missing fail the build + Symlink docs from mblaze-* to mblaze -- Nicolas Braud-Santoni <ni...@debian.org> Tue, 12 Feb 2019 11:44:33 +0100 The debdiff is attached. Best, nicoo unblock mblaze/0.5.1-1 - -- System Information: Debian Release: buster/sid APT prefers testing APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 4.19.0-2-amd64 (SMP w/4 CPU cores) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled -----BEGIN PGP SIGNATURE----- iQJFBAEBCgAvFiEEU7EqA8ZVHYoLJhPE5vmO4pLV7MsFAlx9wacRHG5pY29vQGRl Ymlhbi5vcmcACgkQ5vmO4pLV7MsdVw//X2febyz+EoW+0lN1iSGZYSeqJhIzC11m zOippy/KMeCjbjPuqgI1xBTuLBzNYbV+Y6gwf94+4O8KdqRcxHhjP1zE5ttWqVQD bzMmIB4hr1xIua11OG9Oy1FdG+Fs49nqmaYvo4q7k0qg0VfohwBJEuHnPZEea14y iT/7o/nnhqNnhZIlNv1dhCJWA00hlMt18/7QjG9bSdYRo8iJUdNmkVY750Adv1+S MicSLHtnGy+/2AGYxU/0oW6sPFPBLiXli9gpqN6KhwdF4L6aroRnMswfbThxtc/s GmFETyK/UIJ/6N5pt3ff9fSeU3CHvJclNm4TljKFPfGg4r49Oj+rZeXepddg5Acv 7AaXhB3gMZEwgKtmM02kqwMDdWPRZ3Fwlo6La/3ZJuflNnaBgytlr90Bh8lCAyPI rMjrtP0jcWq1EIRWUgqCaIPFMfvwPMAyTRtORfzOdGtC9ZOBnEBzuqNgHqv5qpEt dLQGHFRQJwDrpFc0veWqXZ01UcIO39fNFIMxUf1nAYw80NRcMRvvCT8IUucCLybq PKn6lLwUfyu+MbfIdyuw7F9hSgMVINmTX1lH8u+Mk1L9p2sn+96JXh1YWAVtrVhn +k8sSA2P5lOBWQLrRtq34VIjv9zlNRKz+5JO4vbdQ9AuZI+0C77PKK08nnixPCrc EL4q69REWC0= =AOMb -----END PGP SIGNATURE-----
diff -Nru mblaze-0.4/blaze822.c mblaze-0.5.1/blaze822.c --- mblaze-0.4/blaze822.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/blaze822.c 2019-03-03 17:12:56.000000000 +0100 @@ -152,14 +152,20 @@ // never writes more than dstmax to dst // returns how many bytes were appended static size_t -safe_append(char *dst, size_t dstmax, char *strbeg, char *strend) +safe_append(char *dst, size_t dstmax, char *srcbeg, char *srcend) { - size_t dstlen = strlen(dst); - if (dstmax - dstlen - 1 < strend - strbeg) - strend = strbeg + (dstmax - dstlen - 1); - memcpy(dst + dstlen, strbeg, strend - strbeg); - dst[dstlen + (strend - strbeg)] = 0; - return strend - strbeg; + size_t srclen = srcend - srcbeg; + size_t dstlen = strnlen(dst, dstmax); + + if (dstlen == dstmax) + return 0; + + if (dstmax - dstlen < srclen + 1) + srclen = dstmax - dstlen - 1; + memcpy(dst + dstlen, srcbeg, srclen); + dst[dstlen + srclen] = 0; + + return srclen; } static size_t @@ -213,8 +219,9 @@ s++; if (*addr || *disp) break; + } else { + s++; } - s++; } else if (*s == '<') { char tok[1024] = { 0 }; char *c = tok; @@ -222,7 +229,9 @@ s++; while (*s && c < e && *s != '>') { s = skip_comment(s); - if (*s == '"') { + if (!*s) { + break; + } else if (*s == '"') { // local part may be quoted, allow all s++; while (*s && c < e && *s != '"') { @@ -258,7 +267,7 @@ char *e = tok + sizeof tok; s++; while (*s && c < e && *s != '"') { - if (*s == '\\') + if (*s == '\\' && *(s+1)) s++; *c++ = *s++; } @@ -274,7 +283,8 @@ } else if (*s == '(') { char *z = skip_comment(s); if (!*disp && *addr) // user@host (name) - safe_append(disp, sizeof disp, s + 1, z - 1); + safe_append(disp, sizeof disp, s + 1, + *z ? z-1 : (*(z-1) == ')' ? z-1 : z)); else if (*disp) { // copy comment safe_append_space(disp, sizeof disp); safe_append(disp, sizeof disp, s, z); @@ -285,6 +295,8 @@ // in ipv6 address if (tc < te) *tc++ = *s++; + else + s++; } else { // ignore group name and start over s++; tc = ttok; @@ -298,6 +310,8 @@ s++; if (tc < te) *tc++ = *s++; + else + s++; } } @@ -504,8 +518,10 @@ size_t hlen = end - src; buf = malloc(hlen+1); - if (!buf) + if (!buf) { + free(mesg); return 0; + } memcpy(buf, src, hlen); end = buf+hlen; @@ -664,6 +680,7 @@ char *buf = mmap(0, len+1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (buf == MAP_FAILED) { + free(mesg); perror("mmap"); goto error; } diff -Nru mblaze-0.4/contrib/_mblaze mblaze-0.5.1/contrib/_mblaze --- mblaze-0.4/contrib/_mblaze 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/contrib/_mblaze 2019-03-03 17:12:56.000000000 +0100 @@ -0,0 +1,402 @@ +#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd mgenmid mhdr minc mless mlist mmime mmkdir mpick mrep mscan msed mseq mshow msort mthread + +_mblaze_colon_separated_headers() { + _message 'headers (colon separated)' +} + +_mblaze_message() { + local ret=1 expl tmp curmsg + local -a mseq mseqnums mshortcuts mshortcutdescrs + setopt localoptions extendedglob + + if [[ -prefix './' ]]; then + _description files expl 'message file' + _files "$expl[@]" && ret=0 + fi + + curmsg=$(mseq .) + if [[ -z $curmsg || ! -f $curmsg ]]; then + _message 'no current sequence' + return $ret + fi + + mseq=( ${(f)"$(mscan -f '%3n %c%u%r %10d %17f %t %2i%s' : 2>/dev/null)"} ) + mseq=( ${(M)mseq:# #<->*} ) + mseqnums=( ${(M)${mseq## #}##<->} ) + mseq=( ${mseq//:/\\:} ) + _describe -V -t mseq 'seq messages' mseq mseqnums && ret=0 + + mshortcuts=( '.' '+' '$' '^' '=' '_' ) + mshortcutdescrs=( + ' . current message' + ' + next message' + # ' - previous message' + ' $ last message' + ' ^ parent message' + ' = current thread' + ' _ current subthread' + ) + + _describe -t mshortcuts 'shortcuts' mshortcutdescrs mshortcuts -S '' && ret=0 + + return $ret +} + +_mblaze_message_part() { + setopt localoptions noksharrays extendedglob + local ret=1 expl tmp msgarg parts partnums + tmp=$words[(i)(-O|-x)] + if (( tmp >= $#words )); then + _message -e mparts 'message parts (parse error)' + return 1 + fi + + msgarg=$words[$tmp+1] + parts=( ${(f)"$(mshow -t $msgarg)"} ) + parts=( ${(M)parts:# ##<->:*} ) + if [[ -n $parts ]]; then + partnums=( ${${parts## #}%%:*} ) + parts=( ${parts//:/\\:} ) + _describe -V -t mparts 'message parts' parts partnums -l && ret=0 + else + _message -e mparts 'message parts (none found)' + fi + + return $ret +} + +_mblaze_dirs() { + local ret=1 expl countnew countcur + local -a mailboxes mailbox_descriptions + setopt localoptions extendedglob + + mailboxes=( */cur(:h) ) + mailbox_descriptions=( ${(f)"$(mlist -i $mailboxes)"} ) + _describe -t mailboxes "mailboxes" mailbox_descriptions mailboxes && ret=0 + + _description files expl 'directories' + _path_files "$expl[@]" -g "^(${(j:|:)mailboxes})(/)" && ret=0 +} + +_mblaze_header_regex() { + _message header\ regex +} + +_mblaze_flags() { + _message flags +} + + +_maddr() { + local context state line expl + local -A opt_args + + _arguments \ + '-a[print addr-spec address without display name]' \ + '-h[search only given headers]:header list:_mblaze_colon_separated_headers' \ + '*:message:_mblaze_message' +} + +_magrep() { + local context state line expl + local -A opt_args + + _arguments \ + '-a[search for regex in RFC 2822 address header parts only]' \ + '-c[only print a count of matching messages]' \ + '-d[decode the header according to RFC 2047 prior to searching]' \ + '-i[match regex case insensitively]' \ + '-m[do not show more than max matches]:max: ' \ + '(-c -q -v)-o[print matches only]' \ + '(-c -q -v)-p[print filename, header and matching]' \ + '-q[quiet mode: do not print anything]' \ + '-v[invert match]' \ + '*:message:_mblaze_header_regex' +} + +_mbnc() { + local context state line expl + local -A opt_args + + _arguments \ + ':message:_mblaze_message' +} + +_mcom() { + local context state line expl + local -A opt_args + + _arguments \ + - resume \ + '-r[resume editing]:draft: ' \ + - recip \ + '*:recipients: ' +} + +_mdeliver() { + local context state line expl + local -A opt_args + + _arguments \ + '-c[deliver into cur/ instead of new/]' \ + '-v[print message filename after delivery]' \ + '-X[override flags]:flags:_mblaze_flags' \ + '-M[deliver messages from mbox]' \ + ':dir:_mblaze_dirs' +} + +_mdirs() { + _mblaze_dirs +} + +_mexport() { + local context state line expl + local -A opt_args + + _arguments \ + '-S[add Status and X-Status headers according to flags]' \ + '*:messages:_mblaze_message' +} + +_mflag() { + local context state line expl + local -A opt_args + + _arguments \ + '(-d)-D[mark as draft]' \ + '(-f)-F[mark as flagged]' \ + '(-p)-P[mark as passed (resent/forwarded/bounced)]' \ + '(-r)-R[mark as replied-to]' \ + '(-s)-S[mark as seen]' \ + '(-t)-T[mark as trashed]' \ + '-X[mark with characters]:marking characters: ' \ + '(-D)-d[unmark as draft]' \ + '(-F)-f[unmark as flagged]' \ + '(-P)-p[unmark as passed (resent/forwarded/bounced)]' \ + '(-R)-r[unmark as replied-to]' \ + '(-S)-s[unmark as seen]' \ + '(-T)-t[unmark as trashed]' \ + '-x[unmark with characters]:marked chacaters: ' \ + '-v[read messages from standard input or current sequence]' \ + '*:messages:_mblaze_message' +} + +_mflow() { + local context state line expl + local -A opt_args + + _arguments \ + '-f[force wrapping of long lines]' \ + '*-q[prefix lines with >]' \ + '-w[set maximum line length]:width: ' \ + '*:dirs:_mblaze_dirs' +} + +_mfwd() { + local context state line expl + local -A opt_args + + _arguments \ + '-r[forward as plain text]' \ + ':*:message:_mblaze_message' +} + +_mgenmid() { + _message 'no arguments' +} + +_mhdr() { + local context state line expl + local -A opt_args + + _arguments \ + '-h[print specific headers only]:headers: ' \ + '-p[print specific parameter from header only]:parameter: ' \ + '-d[print headers decoded]' \ + '-H[prefix output with filename]' \ + '-M[print all occurrences, not only the first]' \ + '(-D)-A[print addresses from headers]' \ + '(-A)-D[print date as unix timestamp]' \ + '*:message:_mblaze_message' +} + +_minc() { + local context state line expl + local -A opt_args + + _arguments \ + '-q[quiet mode: don'\''t print filenames]' \ + '*:dirs:_mblaze_dirs' +} + +_mless() { + local context state line expl + local -A opt_args + + _arguments \ + ':message:_mblaze_message' +} + +_mlist() { + local context state line expl + local -A opt_args + + _arguments \ + '(-d)-D[only list messages marked as draft]' \ + '(-f)-F[only list messages marked as flagged]' \ + '(-p)-P[only list messages marked as passed (resent/forwarded/bounced)]' \ + '(-r)-R[only list messages marked as replied-to]' \ + '(-s)-S[only list messages marked as seen]' \ + '(-t)-T[only list messages marked as trashed]' \ + '-X[only list messages marked with characters]:marked characters: ' \ + '(-D)-d[don'\''t list messages marked as draft]' \ + '(-F)-f[don'\''t list messages marked as flagged]' \ + '(-P)-p[don'\''t list messages marked as passed (resent/forwarded/bounced)]' \ + '(-R)-r[don'\''t list messages marked as replied-to]' \ + '(-S)-s[don'\''t list messages marked as seen]' \ + '(-T)-t[don'\''t list messages marked as trashed]' \ + '-x[don'\''t list messages marked with characters]:marked chacaters: ' \ + '(-c -N)-C[only list messages in cur]' \ + '(-n -C)-N[only list messages in new]' \ + '(-C -N)-c[don'\''t list messages in cur]' \ + '(-N -C)-n[don'\''t list messages in new]' \ + '-i[print summaries instead of folder names]' \ + '*:dirs:_mblaze_dirs' +} + +_mmkdir() { + local context state line expl + local -A opt_args + + _arguments \ + '*:directory name: ' +} + +_mmime() { + local context state line expl + local -A opt_args + + _arguments \ + '(-r)-c[check mode (don'\''t output anything)]' \ + '(-c)-r[raw mode (generate text/plain)]' \ + '-t[override Content-Type of toplevel part]:Content-Type: ' +} + +_mpick() { + local context state line expl + local -A opt_args + + _arguments \ + '-T[include whole thread]' \ + '-t[limit messages to test]:test: ' \ + '*:message:_mblaze_message' +} + +_mrep() { + local context state line expl + local -A opt_args + + _arguments \ + ':message:_mblaze_message' +} + +_mscan() { + local context state line expl + local -A opt_args + + _arguments \ + '-n[only print message numbers]' \ + '-I[force ISO date output]' \ + '-f[specify output format]:format: ' \ + '*:messages:_mblaze_message' +} + +_msed() { + local context state line expl + local -A opt_args + + _arguments \ + ':sed script: ' \ + '*:messages:_mblaze_message' +} + +_mseq() { + local context state line expl + local -A opt_args + + _arguments \ + '(Cmode)-f[fix non-existing filenames]' \ + '(Cmode)-r[remove leading indentation from filenames]' \ + - argmode \ + '-c[use current message]:message:_mblaze_message' \ + '*:messages:_mblaze_message' \ + - Smode \ + '-S[set message sequence from stdin]' \ + - Amode \ + '-A[append message sequence from stdin]' \ + - Cmode \ + '-C[set current message]:message:_mblaze_message' +} + +_mshow() { + local context state line expl + local -A opt_args + + _arguments \ + - regular \ + '-n[only print message numbers]' \ + '-h[display only given headers]:header list:_mblaze_colon_separated_headers' \ + '-A[mixed/alternative preference]:mime type: ' \ + '-n[don'\''t update current message link]' \ + '(-r)-q[print only header]' \ + '(-q)-r[print body raw]' \ + '(-q)-F[don'\''t apply MIME filters]' \ + '-H[print headers raw]' \ + '-L[don'\''t filter headers]' \ + '(-q)-N[don'\''t show MIME structure markers]' \ + '*:messages:_mblaze_message' \ + - xmode \ + '-x[extraction mode]:message:_mblaze_message:*:part:_mblaze_message_part' \ + - Omode \ + '-O[extraction mode to standard output]:message:_mblaze_message:*:part:_mblaze_message_part' \ + - tmode \ + '-t[list mode]:*:message:_mblaze_message' \ + - Rmode \ + '-R[render text parts]:message:_mblaze_message' +} + +_msort() { + local context state line expl + local -A opt_args + + _arguments \ + '-r[reverse order]' \ + '*:message:_mblaze_message' \ + + '(order)' \ + '-f[sort by From]' \ + '-d[sort by Date]' \ + '-s[sort by Subject]' \ + '-F[sort by filename]' \ + '-M[sort by file modification time]' \ + '-S[sort by file size]' \ + '-U[sort unread messages after read messages]' \ + '-I[sort flagged messages before unflagged messages]' +} + +_mthread() { + local context state line expl + local -A opt_args + + _arguments \ + '-a[don'\''t prune unresolved Message-IDs]' \ + '-S[treat as optional messages]:optional message:_mblaze_message' \ + '*:message:_mblaze_message' +} + +_mblaze() { + local ret=1 + _call_function ret _$service + return ret +} + +_mblaze "$@" diff -Nru mblaze-0.4/contrib/mencrypt mblaze-0.5.1/contrib/mencrypt --- mblaze-0.4/contrib/mencrypt 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/contrib/mencrypt 2019-03-03 17:12:56.000000000 +0100 @@ -5,17 +5,20 @@ IFS=' ' -FLAGS=$(mhdr -d -A -h from:to:cc:bcc: "$1" |sort -u |sed 's/^/--recipient=/') +FLAGS=$(maddr -a -h from:to:cc:bcc: "$1" |sort -u |sed 's/^/--recipient=/') + +FROM=$(maddr -a -h from "$1" | sed 1q) +[ "$FROM" ] && key="--default-key=$FROM" TMPD=$(mktemp -d -t mencrypt.XXXXXX) trap "rm -rf '$TMPD'" INT TERM EXIT awk '/^$/,0' "$1" | mmime | - gpg --armor --encrypt --sign $FLAGS -o $TMPD/msg.asc || + gpg2 "$key" --armor --encrypt --sign $FLAGS -o "$TMPD/msg.asc" || exit $? -printf 'Version: 1\n' >$TMPD/version +printf 'Version: 1\n' >"$TMPD/version" { sed '/^$/q' "$1" diff -Nru mblaze-0.4/contrib/menter mblaze-0.5.1/contrib/menter --- mblaze-0.4/contrib/menter 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/contrib/menter 2019-03-03 17:12:56.000000000 +0100 @@ -1,14 +1,17 @@ #!/bin/sh -e # menter [MSG] - run subshell in temporary directory with MSG extracted -[ "$#" -eq 0 ] && set -- : +[ "$#" -eq 0 ] && set -- . + +f="$(mseq "$1" | sed 1q)" +[ -z "$f" ] && printf 'No message %s.\n' "$1" 1>&2 && exit 1 dir=$(mktemp -d -t menter.XXXXXX) cd "$dir" mshow -t "$1" mshow -x "$1" 2>/dev/null ls -l -ln -s "$(mseq "$1")" msg +ln -s "$f" msg "${SHELL:-/bin/sh}" || true echo rm -r "$dir" rm -r "$dir" diff -Nru mblaze-0.4/contrib/mgpg mblaze-0.5.1/contrib/mgpg --- mblaze-0.4/contrib/mgpg 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/contrib/mgpg 2019-03-03 17:12:56.000000000 +0100 @@ -14,7 +14,7 @@ /: application\/octet-stream/ {if (supported) print $1}') if [ "$n" ]; then - mshow -O "$tmp" "$n" | gpg -d 2>&1 + mshow -O "$tmp" "$n" | gpg2 -d 2>&1 || exit 0 exit 64 fi exit 63 diff -Nru mblaze-0.4/contrib/mmairix mblaze-0.5.1/contrib/mmairix --- mblaze-0.4/contrib/mmairix 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/contrib/mmairix 2019-03-03 17:12:56.000000000 +0100 @@ -1,4 +1,4 @@ #!/bin/sh # mmairix QUERY - mblaze wrapper around mairix -mairix -r "$@" | sed 's,//*,/,g' | mless +mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mless diff -Nru mblaze-0.4/contrib/msearch mblaze-0.5.1/contrib/msearch --- mblaze-0.4/contrib/msearch 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/contrib/msearch 2019-03-03 17:12:56.000000000 +0100 @@ -0,0 +1,45 @@ +#!/bin/sh + +MBLAZE=${MBLAZE:-$HOME/.mblaze} +engine=$(mhdr -h search-engine "$MBLAZE/profile") + +while getopts nmx opt; do + case $opt in + n) + engine=notmuch + ;; + m) + engine=mu + ;; + x) + engine=mairix + ;; + '?') + printf "Usage: %s: [-n | -m | -x] query\n" "$0" 1>&2 + exit 1 + ;; + esac +done +shift $(($OPTIND - 1)) + +[ -z "$engine" ] && engine=notmuch + +case $engine in + notmuch) + exec notmuch search --output=files "$@" + ;; + mu) + exec mu find --fields l "$@" + ;; + mairix) + if [ "$#" -eq 0 ]; then + printf "Usage: %s -x query\n" "$0" 1>&2 + exit 1 + fi + exec mairix -r "$@" + ;; + *) + echo "Unsupported search engine: $engine" + exit 1 + ;; +esac diff -Nru mblaze-0.4/contrib/msearch.1 mblaze-0.5.1/contrib/msearch.1 --- mblaze-0.4/contrib/msearch.1 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/contrib/msearch.1 2019-03-03 17:12:56.000000000 +0100 @@ -0,0 +1,75 @@ +.Dd September 27, 2018 +.Dt MSEARCH 1 +.Os +.Sh NAME +.Nm msearch +.Nd search messages +.Sh SYNOPSIS +.Nm +.Op Fl n | Fl m | Fl x +.Op Fl - +.Op Ar query +.Sh DESCRIPTION +.Nm +searches for messages matching +.Ar query , +using an external search engine, and prints file names separated by newlines. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl n +Search using +.Xr notmuch-search 1 . +.It Fl m +Search using +.Xr mu-find 1 . +.It Fl x +Search using +.Xr mairix 1 . +.It Fl - +Stop scanning for arguments. +.It Ar query +The search query, whose interpretation is up to the search engine. +This can also contain additional arguments for them +.El +.Pp +If no search engine is specified as an argument, +.Sq Li Search-Engine\&: +from +.Pa "${MBLAZE:-$HOME/.mblaze}/profile" +is used. +Valid values for this setting are +.Sq notmuch , +.Sq mairix , +and +.Sq mu . +If that is unset, +.Xr notmuch-search 1 +is used. +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev MBLAZE +Directory containing mblaze configuration files. +(Default: +.Pa $HOME/.mblaze ) +.El +.Sh EXIT STATUS +.Ex -std +Note that the called programs may have their own exit values. +.Sh SEE ALSO +.Xr mairix 1 , +.Xr mu-find 1 , +.Xr notmuch-search 1 , +.Xr mblaze-profile 5 +.Sh AUTHORS +.An Thomas Schneider Aq Mt q...@chaotikum.eu +.Sh LICENSE +.Nm +is in the public domain. +.Pp +To the extent possible under law, +the creator of this work +has waived all copyright and related or +neighboring rights to this work. +.Pp +.Lk http://creativecommons.org/publicdomain/zero/1.0/ diff -Nru mblaze-0.4/contrib/msign mblaze-0.5.1/contrib/msign --- mblaze-0.4/contrib/msign 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/contrib/msign 2019-03-03 17:12:56.000000000 +0100 @@ -9,8 +9,11 @@ TMPD=$(mktemp -d -t msign.XXXXXX) trap "rm -rf '$TMPD'" INT TERM EXIT +FROM=$(maddr -a -h from "$1" | sed 1q) +[ "$FROM" ] && key="--default-key=$FROM" + awk '/^$/,0' "$1" | mmime | sed 's/$/ /' >"$TMPD"/content -gpg --armor --detach-sign -o "$TMPD"/signature.asc "$TMPD"/content || +gpg2 $key --armor --detach-sign -o "$TMPD"/signature.asc "$TMPD"/content || exit $? { diff -Nru mblaze-0.4/contrib/mverify mblaze-0.5.1/contrib/mverify --- mblaze-0.4/contrib/mverify 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/contrib/mverify 2019-03-03 17:12:56.000000000 +0100 @@ -1,7 +1,7 @@ #!/bin/sh # mverify MSG - verify a OpenPGP or SMIME message -# Needs gpg (for OpenPGP) and openssl (for SMIME). +# Needs gpg2 (for OpenPGP) and openssl (for SMIME). [ "$#" -eq 0 ] && set -- . @@ -14,7 +14,7 @@ function q(a) { gsub("\\47", "\47\\\47\47", a); return "\47"a"\47" } END { if (type == "" && plain) { // guess plain text armored signature - exit(system("mshow -r " q(msg) " | gpg --verify")); + exit(system("mshow -r " q(msg) " | gpg2 --verify")); } else if (type == "") { print("No signature found.") exit(100) @@ -22,7 +22,7 @@ exit(system("mshow -r -O " q(msg) " " q(content) \ " | sed $DOS2UNIX | " \ " { mshow -O " q(msg) " " q(signature) \ - " | gpg --verify - /dev/fd/3; } 3<&0")) + " | gpg2 --verify - /dev/fd/3; } 3<&0")) } else if (type == "application/pkcs7-signature") { exit(system("mshow -r -O " q(msg) " " q(signed) \ " | openssl smime -verify")) diff -Nru mblaze-0.4/debian/changelog mblaze-0.5.1/debian/changelog --- mblaze-0.4/debian/changelog 2018-08-19 12:22:49.000000000 +0200 +++ mblaze-0.5.1/debian/changelog 2019-03-04 18:40:01.000000000 +0100 @@ -1,3 +1,37 @@ +mblaze (0.5.1-1) unstable; urgency=high (security fixes) + + * New upstream release (2019-03-03) + + Fixes for buffer-overflows, found by fuzzing. + + Fixes for memleaks. + + * Remove unused lintian override + * debian/rules: Remove useless dh_missing invocation. + A single binary package is being produced. + + -- Nicolas Braud-Santoni <ni...@debian.org> Mon, 04 Mar 2019 18:40:01 +0100 + +mblaze (0.5-1) unstable; urgency=medium + + * New upstream release (2019-02-09) + + Closes: 921891 + + GNUmakefile: correct reference to SOURCE_DATE_EPOCH, patch by Chris Lamb + Closes: #907537 + + * Rename mless and msort to mblaze-less and mblaze-sort + Closes: #887988 correctly, avoids conflicts on mpdtoys & msort + + * Switch to debhelper 12. + The compatibility level is now controlled by a Build-Depends. + + * Declare compliance with policy v4.2.1. + No change required. + + * debian/rules + + Make dh_missing fail the build + + Symlink docs from mblaze-* to mblaze + + -- Nicolas Braud-Santoni <ni...@debian.org> Tue, 12 Feb 2019 11:44:33 +0100 + mblaze (0.4-1) unstable; urgency=medium * New upstream version (2018-08-15) diff -Nru mblaze-0.4/debian/compat mblaze-0.5.1/debian/compat --- mblaze-0.4/debian/compat 2018-02-13 12:47:54.000000000 +0100 +++ mblaze-0.5.1/debian/compat 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -11 diff -Nru mblaze-0.4/debian/control mblaze-0.5.1/debian/control --- mblaze-0.4/debian/control 2018-08-19 12:22:49.000000000 +0200 +++ mblaze-0.5.1/debian/control 2019-03-04 18:40:01.000000000 +0100 @@ -1,17 +1,17 @@ Source: mblaze -Maintainer: Nicolas Braud-Santoni <nico...@braud-santoni.eu> +Maintainer: Nicolas Braud-Santoni <ni...@debian.org> Section: utils Priority: optional -Build-Depends: debhelper (>= 11) -Standards-Version: 4.2.0 +Build-Depends: debhelper-compat (= 12) +Standards-Version: 4.3.0 Homepage: https://github.com/chneukirchen/mblaze Vcs-Browser: https://salsa.debian.org/debian/mblaze Vcs-Git: https://salsa.debian.org/debian/mblaze.git + Package: mblaze Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} -Conflicts: msort, mpdtoys Description: UNIX utilities to deal with Maildir The mblaze message system is a set of Unix utilities to deal with mail kept in Maildir folders. It is a classic command line MUA and has no features for diff -Nru mblaze-0.4/debian/mblaze.lintian-overrides mblaze-0.5.1/debian/mblaze.lintian-overrides --- mblaze-0.4/debian/mblaze.lintian-overrides 2018-02-13 12:47:54.000000000 +0100 +++ mblaze-0.5.1/debian/mblaze.lintian-overrides 1970-01-01 01:00:00.000000000 +0100 @@ -1,2 +0,0 @@ -# Ignore false-negative in hardening-check -mblaze: hardening-no-fortify-functions usr/bin/mdirs diff -Nru mblaze-0.4/debian/patches/Rename-mless-to-mblaze-less.patch mblaze-0.5.1/debian/patches/Rename-mless-to-mblaze-less.patch --- mblaze-0.4/debian/patches/Rename-mless-to-mblaze-less.patch 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/debian/patches/Rename-mless-to-mblaze-less.patch 2019-03-04 18:40:01.000000000 +0100 @@ -0,0 +1,42 @@ +Subject: Rename mless to mblaze-less + +--- + contrib/_mblaze | 4 ++-- + contrib/mmairix | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/contrib/_mblaze b/contrib/_mblaze +index f58cb65..41207e3 100644 +Origin: vendor +Bug-Debian: https://bugs.debian.org/887988 +Forwarded: not-needed +From: Nicolas Braud-Santoni <ni...@debian.org> +Last-Update: 2019-02-23 + +--- a/contrib/_mblaze ++++ b/contrib/_mblaze +@@ -1,4 +1,4 @@ +-#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd mgenmid mhdr minc mless mlist mmime mmkdir mpick mrep mscan msed mseq mshow msort mthread ++#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd mgenmid mhdr minc mblaze-less mlist mmime mmkdir mpick mrep mscan msed mseq mshow msort mthread + + _mblaze_colon_separated_headers() { + _message 'headers (colon separated)' +@@ -229,7 +229,7 @@ _minc() { + '*:dirs:_mblaze_dirs' + } + +-_mless() { ++_mblaze-less() { + local context state line expl + local -A opt_args + +diff --git a/contrib/mmairix b/contrib/mmairix +index e4c9844..810bb59 100755 +--- a/contrib/mmairix ++++ b/contrib/mmairix +@@ -1,4 +1,4 @@ + #!/bin/sh + # mmairix QUERY - mblaze wrapper around mairix + +-mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mless ++mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mblaze-less diff -Nru mblaze-0.4/debian/patches/Rename-msort-to-mblaze-sort.patch mblaze-0.5.1/debian/patches/Rename-msort-to-mblaze-sort.patch --- mblaze-0.4/debian/patches/Rename-msort-to-mblaze-sort.patch 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/debian/patches/Rename-msort-to-mblaze-sort.patch 2019-03-04 18:40:01.000000000 +0100 @@ -0,0 +1,56 @@ +Subject: Rename msort to mblaze-sort + +--- + contrib/_mblaze | 4 ++-- + contrib/mmairix | 2 +- + mcom | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/contrib/_mblaze b/contrib/_mblaze +index 41207e3..3d11390 100644 +Origin: vendor +Bug-Debian: https://bugs.debian.org/887988 +Forwarded: not-needed +From: Nicolas Braud-Santoni <ni...@debian.org> +Last-Update: 2019-02-23 + +--- a/contrib/_mblaze ++++ b/contrib/_mblaze +@@ -1,4 +1,4 @@ +-#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd mgenmid mhdr minc mblaze-less mlist mmime mmkdir mpick mrep mscan msed mseq mshow msort mthread ++#compdef maddr magrep mbnc mcom mdeliver mdirs mexport mflag mflow mfwd mgenmid mhdr minc mblaze-less mlist mmime mmkdir mpick mrep mscan msed mseq mshow mblaze-sort mthread + + _mblaze_colon_separated_headers() { + _message 'headers (colon separated)' +@@ -365,7 +365,7 @@ _mshow() { + '-R[render text parts]:message:_mblaze_message' + } + +-_msort() { ++_mblaze-sort() { + local context state line expl + local -A opt_args + +diff --git a/contrib/mmairix b/contrib/mmairix +index 810bb59..6caff93 100755 +--- a/contrib/mmairix ++++ b/contrib/mmairix +@@ -1,4 +1,4 @@ + #!/bin/sh + # mmairix QUERY - mblaze wrapper around mairix + +-mairix -r "$@" | sed 's,//*,/,g' | msort -rd | mblaze-less ++mairix -r "$@" | sed 's,//*,/,g' | mblaze-sort -rd | mblaze-less +diff --git a/mcom b/mcom +index 91498c9..73c5fbb 100755 +--- a/mcom ++++ b/mcom +@@ -245,7 +245,7 @@ else + exit 1 + fi + elif [ -z "$draft" ]; then +- draft=$(mlist -D "$outbox" | msort -r -M | sed 1q) ++ draft=$(mlist -D "$outbox" | mblaze-sort -r -M | sed 1q) + fi + draftmime="$(printf '%s\n' "$draft" | sed 's,\(.*\)/cur/,\1/tmp/mime-,')" + fi diff -Nru mblaze-0.4/debian/patches/series mblaze-0.5.1/debian/patches/series --- mblaze-0.4/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/debian/patches/series 2019-03-04 18:40:01.000000000 +0100 @@ -0,0 +1,2 @@ +Rename-mless-to-mblaze-less.patch +Rename-msort-to-mblaze-sort.patch diff -Nru mblaze-0.4/debian/README.Debian mblaze-0.5.1/debian/README.Debian --- mblaze-0.4/debian/README.Debian 1970-01-01 01:00:00.000000000 +0100 +++ mblaze-0.5.1/debian/README.Debian 2019-03-04 18:40:01.000000000 +0100 @@ -0,0 +1,4 @@ +Executables mless and msort got renamed to mblaze-less and mblaze-sort, due to +conflicts with packages mpdtoys and msort. + + -- Nicolas Braud-Santoni <ni...@debian.org>, Sat, 23 Feb 2019 20:09:22 +0100 diff -Nru mblaze-0.4/debian/rules mblaze-0.5.1/debian/rules --- mblaze-0.4/debian/rules 2018-08-19 12:22:49.000000000 +0200 +++ mblaze-0.5.1/debian/rules 2019-03-04 18:40:01.000000000 +0100 @@ -11,5 +11,15 @@ override_dh_auto_test: : # Testsuite is currently broken under sbuild +override_dh_install: + mv debian/mblaze/usr/bin/mless debian/mblaze/usr/bin/mblaze-less + mv debian/mblaze/usr/share/man/man1/mless.1 debian/mblaze/usr/share/man/man1/mblaze-less.1 + mv debian/mblaze/usr/bin/msort debian/mblaze/usr/bin/mblaze-sort + mv debian/mblaze/usr/share/man/man1/msort.1 debian/mblaze/usr/share/man/man1/mblaze-sort.1 + dh_install + override_dh_installchangelogs: dh_installchangelogs NEWS.md + +override_dh_installdocs: + dh_installdocs --link-doc=mblaze diff -Nru mblaze-0.4/GNUmakefile mblaze-0.5.1/GNUmakefile --- mblaze-0.4/GNUmakefile 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/GNUmakefile 2019-03-03 17:12:56.000000000 +0100 @@ -28,17 +28,16 @@ maddr magrep mdeliver mexport mflag mflow mgenmid mhdr mpick mscan msed mshow \ msort mthread : blaze822.o mymemmem.o mytimegm.o maddr magrep mdeliver mexport mflag mgenmid mhdr mlist mpick mscan msed mseq \ - mshow msort mthread : seq.o slurp.o + mshow msort mthread : seq.o slurp.o mystrverscmp.o maddr magrep mflow mhdr mpick mscan mshow : rfc2047.o magrep mflow mhdr mshow : rfc2045.o mshow : filter.o safe_u8putstr.o rfc2231.o pipeto.o mscan : pipeto.o -msort : mystrverscmp.o mmime : slurp.o minc mlist : squeeze_slash.o museragent: FRC - @test -n "$$SOURCE_TIME_EPOCH" || BUILDDATE=$$(date '+ (%Y-%m-%d)'); \ + @test -n "$$SOURCE_DATE_EPOCH" || BUILDDATE=$$(date '+ (%Y-%m-%d)'); \ printf '#!/bin/sh\nprintf "User-Agent: mblaze/%s%s\\n"\n' \ "$$({ git describe --always --dirty 2>/dev/null || cat VERSION; } | sed 's/^v//')" \ "$$BUILDDATE" >$@ @@ -59,8 +58,6 @@ $(DESTDIR)$(MANDIR)/man5 \ $(DESTDIR)$(MANDIR)/man7 install -m0755 $(ALL) $(SCRIPT) $(DESTDIR)$(BINDIR) - ln -sf mless $(DESTDIR)$(BINDIR)/mnext - ln -sf mless $(DESTDIR)$(BINDIR)/mprev ln -sf mcom $(DESTDIR)$(BINDIR)/mbnc ln -sf mcom $(DESTDIR)$(BINDIR)/mfwd ln -sf mcom $(DESTDIR)$(BINDIR)/mrep diff -Nru mblaze-0.4/magrep.c mblaze-0.5.1/magrep.c --- mblaze-0.4/magrep.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/magrep.c 2019-03-03 17:12:56.000000000 +0100 @@ -14,6 +14,7 @@ static int aflag; static int cflag; static int dflag; +static int hflag; static int iflag; static int lflag; static int oflag; @@ -31,7 +32,7 @@ match(char *file, char *hdr, char *s) { if (oflag && !cflag && !qflag && !vflag && !lflag) { - regmatch_t pmatch; + regmatch_t pmatch = {0}; int len, matched; matched = 0; while (*s && regexec(&pattern, s, 1, &pmatch, 0) == 0) { @@ -42,6 +43,8 @@ } if (pflag) printf("%s: %s: ", file, hdr); + else if (hflag) + printf("%s: ", hdr); printf("%.*s\n", len, s); s += len; matched++; @@ -52,9 +55,12 @@ exit(0); matches++; if (!cflag) { - printf("%s", file); + if (vflag || !hflag) + printf("%s", file); if (pflag && !vflag) printf(": %s: %s", hdr, s); + else if (hflag && !vflag) + printf("%s: %s", hdr, s); putchar('\n'); } if (mflag && matches >= mflag) @@ -82,7 +88,7 @@ strcasecmp(charset, "utf-8") == 0 || strcasecmp(charset, "utf8") == 0 || strcasecmp(charset, "us-ascii") == 0) { - if (pflag && !cflag && !oflag && !vflag) { + if ((hflag || pflag) && !cflag && !oflag && !vflag) { char *s, *p; for (p = s = body; p < body+bodylen+1; p++) { if (*p == '\r' || *p == '\n') { @@ -117,6 +123,7 @@ return; blaze822_walk_mime(msg, 0, match_part); + blaze822_free(msg); } int @@ -183,11 +190,12 @@ main(int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "acdilm:opqv")) != -1) + while ((c = getopt(argc, argv, "acdhilm:opqv")) != -1) switch (c) { case 'a': aflag = 1; break; case 'c': cflag = 1; break; case 'd': dflag = 1; break; + case 'h': hflag = 1; break; case 'i': iflag = REG_ICASE; break; case 'l': lflag = 1; break; case 'm': mflag = atol(optarg); break; @@ -198,7 +206,7 @@ default: usage: fprintf(stderr, -"Usage: magrep [-c|-o|-p|-q|-m max] [-v] [-i] [-l] [-a|-d] header:regex [msgs...]\n"); +"Usage: magrep [-c|-h|-o|-p|-q|-m max] [-v] [-i] [-l] [-a|-d] header:regex [msgs...]\n"); exit(2); } diff -Nru mblaze-0.4/man/magrep.1 mblaze-0.5.1/man/magrep.1 --- mblaze-0.4/man/magrep.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/magrep.1 2019-03-03 17:12:56.000000000 +0100 @@ -1,4 +1,4 @@ -.Dd July 7, 2018 +.Dd September 10, 2018 .Dt MAGREP 1 .Os .Sh NAME @@ -6,7 +6,7 @@ .Nd search messages matching a pattern .Sh SYNOPSIS .Nm -.Op Fl c | Fl q | Fl m Ar max +.Op Fl c | Fl h | Fl o | Fl p | Fl q | Fl m Ar max .Op Fl v .Op Fl i .Op Fl l @@ -75,6 +75,10 @@ Decode the .Ar header according to RFC 2047 prior to searching. +.It Fl h +Like +.Fl p +but do not print the file name. .It Fl i Match .Ar regex diff -Nru mblaze-0.4/man/mblaze.7 mblaze-0.5.1/man/mblaze.7 --- mblaze-0.4/man/mblaze.7 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mblaze.7 2019-03-03 17:12:56.000000000 +0100 @@ -32,7 +32,7 @@ .It Xr mexport 1 export messages as mbox file .It Xr mflag 1 -manipulate maildir flags +manipulate maildir message flags .It Xr mflow 1 reflow format=flowed plain text messages .It Xr mfwd 1 diff -Nru mblaze-0.4/man/mcom.1 mblaze-0.5.1/man/mcom.1 --- mblaze-0.4/man/mcom.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mcom.1 2019-03-03 17:12:56.000000000 +0100 @@ -1,4 +1,4 @@ -.Dd January 6, 2017 +.Dd January 29, 2019 .Dt MCOM 1 .Os .Sh NAME @@ -14,6 +14,7 @@ .Nm mcom .Fl r Op draft .Nm mrep +.Op Fl noquote .Op Fl Ar header Ar values\ ... Fl - .Ar msg .Nm mfwd @@ -36,6 +37,9 @@ .Nm mrep creates the draft such that the message will be a reply to .Ar msg . +Unless +.Fl noquote +is passed, it will contain the original mail quoted. .Pp .Nm mfwd creates the draft with a subject and body appropriate @@ -93,6 +97,12 @@ .Nm mfwd , or .Nm mbnc . +.Pp +If the flag +.Fl send +is passed, +the message will be sent directly using the data on +the command line, and no editor or edit loop will be run. .Sh MENU COMMANDS .Bl -tag -width 2n .It Ic s diff -Nru mblaze-0.4/man/mdirs.1 mblaze-0.5.1/man/mdirs.1 --- mblaze-0.4/man/mdirs.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mdirs.1 2019-03-03 17:12:56.000000000 +0100 @@ -6,6 +6,7 @@ .Nd list maildir folders, recursively .Sh SYNOPSIS .Nm +.Op Fl 0 .Ar dirs\ ... .Sh DESCRIPTION .Nm @@ -27,7 +28,11 @@ names must begin with .Sq Li \&. . .Pp -There are currently no options. +The options are as follows: +.Bl -tag -width Ds +.It Fl 0 +Print folders separated by a NUL character. +.El .Sh EXIT STATUS .Ex -std .Sh SEE ALSO diff -Nru mblaze-0.4/man/mflag.1 mblaze-0.5.1/man/mflag.1 --- mblaze-0.4/man/mflag.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mflag.1 2019-03-03 17:12:56.000000000 +0100 @@ -3,7 +3,7 @@ .Os .Sh NAME .Nm mflag -.Nd manipulate maildir flags +.Nd manipulate maildir message flags .Sh SYNOPSIS .Nm .Op Fl DFPRST diff -Nru mblaze-0.4/man/mgenmid.1 mblaze-0.5.1/man/mgenmid.1 --- mblaze-0.4/man/mgenmid.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mgenmid.1 2019-03-03 17:12:56.000000000 +0100 @@ -1,4 +1,4 @@ -.Dd August 1, 2016 +.Dd December 25, 2018 .Dt MGENMID 1 .Os .Sh NAME @@ -9,7 +9,7 @@ .Sh DESCRIPTION .Nm generates and prints a unique Message-ID. -The Message-ID consists of an encoded timestamp, +The Message-ID consists of an encrypted timestamp, a random value, and a fully qualified domain name. .Pp diff -Nru mblaze-0.4/man/mpick.1 mblaze-0.5.1/man/mpick.1 --- mblaze-0.4/man/mpick.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mpick.1 2019-03-03 17:12:56.000000000 +0100 @@ -7,6 +7,7 @@ .Sh SYNOPSIS .Nm .Op Fl T +.Op Fl v .Op Fl t Ar test .Op Ar msglist\ ... .Sh DESCRIPTION @@ -29,6 +30,8 @@ .Ar test , see .Sx TESTS . +.It Fl v +Print how many messages were tested and picked to standard error. .El .Sh MSGLISTS .Nm diff -Nru mblaze-0.4/man/mscan.1 mblaze-0.5.1/man/mscan.1 --- mblaze-0.4/man/mscan.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mscan.1 2019-03-03 17:12:56.000000000 +0100 @@ -1,4 +1,4 @@ -.Dd June 28, 2017 +.Dd September 25, 2018 .Dt MSCAN 1 .Os .Sh NAME @@ -6,9 +6,10 @@ .Nd generate one-line message summaries .Sh SYNOPSIS .Nm +.Op Fl I .Op Fl n +.Op Fl v .Op Fl f Ar format -.Op Fl I .Ar msgs\ ... .Sh DESCRIPTION .Nm @@ -55,13 +56,15 @@ .Pp The options are as follows: .Bl -tag -width Ds -.It Fl n -Only print message numbers -.Pq or filenames, if the message is not in the current sequence . .It Fl I Force ISO date output, even for .Sq Cm "%d" . +.It Fl n +Only print message numbers +.Pq or filenames, if the message is not in the current sequence . +.It Fl v +Print how many messages were scanned to standard error. .It Fl f Ar format Format according to the string .Ar format , @@ -186,7 +189,7 @@ .Sq Li To\&: .It Li \&+ You are in -.Sq Li Cc\:& +.Sq Li Cc\&: .It Li \&: You are in .Sq Li Resent\&-To\&: diff -Nru mblaze-0.4/man/msed.1 mblaze-0.5.1/man/msed.1 --- mblaze-0.4/man/msed.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/msed.1 2019-03-03 17:12:56.000000000 +0100 @@ -123,6 +123,7 @@ .Ex -std .Sh SEE ALSO .Xr sed 1 , +.Xr mhdr 1 , .Xr mmsg 7 , .Xr regex 7 / .Xr re_format 7 diff -Nru mblaze-0.4/man/mshow.1 mblaze-0.5.1/man/mshow.1 --- mblaze-0.4/man/mshow.1 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/man/mshow.1 2019-03-03 17:12:56.000000000 +0100 @@ -1,4 +1,4 @@ -.Dd April 17, 2018 +.Dd August 24, 2018 .Dt MSHOW 1 .Os .Sh NAME @@ -91,6 +91,9 @@ can be specified by number, filename or .Xr fnmatch 3 pattern. +If no +.Ar parts +are specified, extracts all attachments with a filename. .It Fl O Ar msg Like .Fl x @@ -121,7 +124,11 @@ and re-encodes them into UTF-8 if necessary. .Pp Other filters can be specified in the file -.Pa ${MBLAZE:-$HOME/.mblaze}/filter , +.Pa ${MBLAZE:-$HOME/.mblaze}/filter +.Po +or via +.Ev MAILFILTER +.Pc , in the format: .Pp .D1 Ar type/subtype Ns Li \&: Ar command @@ -132,6 +139,7 @@ will then spawn a pipe to .Ar command , write the MIME part +to standard input and display the output. The environment variable .Ev PIPE_CHARSET @@ -158,6 +166,14 @@ All other exit statuses are regarded as errors. .Sh ENVIRONMENT .Bl -tag -width MBLAZE_NOCOLOR +.It Ev MAILFILTER +Path to an alternative +.Pa filter +file. +.It Ev MBLAZE_NOCOLOR +If non-empty, +.Nm +will not spawn a colorization filter. .It Ev MBLAZE_PAGER Any non-empty value of the environment variable .Ev MBLAZE_PAGER @@ -166,10 +182,6 @@ When empty or set to .Sq Ic cat , no pager is spawned. -.It Ev MBLAZE_NOCOLOR -If non-empty, -.Nm -will not spawn a colorization filter. .El .Sh EXIT STATUS .Ex -std diff -Nru mblaze-0.4/mbnc mblaze-0.5.1/mbnc --- mblaze-0.4/mbnc 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mbnc 2019-03-03 17:12:56.000000000 +0100 @@ -11,7 +11,7 @@ } notmine() { - mine="$(maddr -a -h local-mailbox:alternate-mailboxes: $MBLAZE/profile)" + mine="$(maddr -a -h local-mailbox:alternate-mailboxes: "$MBLAZE/profile")" grep -Fv -e "$mine" } @@ -40,6 +40,27 @@ fi } +checksensible() { + awk ' + /^$/ { + seenheader=1 + exit + } + !(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) { + bad=1 + print "invalid header line: "$0 >"/dev/stderr" + } + END { + if (!seenheader) { + print "warning: message does not contain an empty line between headers and body." >"/dev/stderr" + exit 1 + } + if (bad) + exit 1 + } +' "$1" +} + stripempty() { tmp=$(mktemp -t mcom.XXXXXX) msed 's/^[ \t]*$//d' "$1" >"$tmp" @@ -55,13 +76,13 @@ if needs_multipart "$draft"; then ( IFS=$NL - msed '/attach/d' $draft - for f in $(mhdr -M -h attach $draft); do + msed '/attach/d' "$draft" + for f in $(mhdr -M -h attach "$draft"); do printf '#%s %s\n' \ - "$(file -Lbi $f | sed 's/ //g')" \ + "$(file -Lbi "$f" | sed 's/ //g')" \ "$f" done - ) | mmime >$draftmime + ) | mmime >"$draftmime" else mmime -r <"$draft" >"$draftmime" fi @@ -74,8 +95,11 @@ sendmail="${sendmail:-sendmail} ${sendmail_args:--t}" default_from=$(mhdr -h local-mailbox "$MBLAZE/profile") +defaultc=e + hdrs= resume= +noquote= case "$0" in *mcom*) hdr=to @@ -90,11 +114,22 @@ shift resume=1 if [ "$#" -gt 0 ]; then - echo "used draft $1" - draft="$1" + case "$1" in + /*|./*) draft="$1";; + *) draft="./$1";; + esac + if ! [ -f "$draft" ]; then + printf 'mcom: no such draft %s\n' \ + "$draft" 1>&2 + exit 1 + fi + echo "using draft $draft" shift fi ;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -118,6 +153,9 @@ -r) shift raw=1;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -139,6 +177,9 @@ --) shift break;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -160,6 +201,12 @@ --) shift break;; + -send) + defaultc=justsend + shift;; + -noquote) + noquote=1 + shift;; -??*) hdr=${1#-} shift;; @@ -280,8 +327,8 @@ if [ "$ng" ]; then printf 'Newsgroups: %s\n' "$ng" else - to=$(mhdr -h reply-to "$1") - [ -z "$to" ] && to=$(mhdr -h from "$1") + to=$(mhdr -d -h reply-to "$1") + [ -z "$to" ] && to=$(mhdr -d -h from "$1") printf 'To: %s\n' "$to" printf 'Cc: %s\n' \ "$(mhdr -d -A -h to:cc: "$1" | @@ -308,8 +355,10 @@ cat "$MBLAZE/headers" 2>/dev/null printf '\n' - mquote "$1" - printf '\n' + if [ -z "$noquote" ]; then + mquote "$1" + printf '\n' + fi ( IFS=$NL cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h body /dev/stdin) @@ -332,10 +381,10 @@ cat "$SIGNATURE" fi esac -} >$draft +} >"$draft" automime= -c=e +c=$defaultc while :; do case "$c" in s|send) @@ -352,15 +401,15 @@ ;; esac - if [ -e $draftmime ]; then - if [ $draft -ot $draftmime ] || [ "$automime" -eq 1 ]; then - stampdate $draftmime - if $sendmail <$draftmime; then + if [ -e "$draftmime" ]; then + if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 ]; then + stampdate "$draftmime" + if $sendmail <"$draftmime"; then if [ "$outbox" ]; then - mv $draftmime $draft - mflag -d -S $draft + mv "$draftmime" "$draft" + mflag -d -S "$draft" else - rm $draft $draftmime + rm "$draft" "$draftmime" fi else printf '%s\n' "mcom: $sendmail failed, kept draft $draft" @@ -369,15 +418,16 @@ else printf 'mcom: re-run mmime first.\n' c= + continue fi else - if mmime -c <$draft; then - stampdate $draft - if $sendmail <$draft; then + if mmime -c <"$draft"; then + stampdate "$draft" + if $sendmail <"$draft"; then if [ "$outbox" ]; then - mflag -d -S $draft + mflag -d -S "$draft" else - rm $draft + rm "$draft" fi else printf '%s\n' "mcom: $sendmail failed, kept draft $draft" @@ -386,6 +436,7 @@ else printf '%s\n' "mcom: message needs to be MIME-encoded first." c= + continue fi fi @@ -398,49 +449,64 @@ exit 0 ;; c|cancel) - stampdate $draft + stampdate "$draft" printf '%s\n' "mcom: cancelled draft $draft" exit 1 ;; m|mime) do_mime - mshow -t $draftmime + mshow -t "$draftmime" c= ;; e|edit) c= - if ! ${EDITOR:-vi} $draft; then - c=c + if ! ${EDITOR:-vi} "$draft"; then + c=d + else + if checksensible "$draft"; then + stripempty "$draft" + if mmime -c <"$draft" && ! needs_multipart "$draft"; then + automime= + else + automime=1 + do_mime + fi + else + printf '\n' + fi fi - stripempty $draft - if mmime -c <$draft && ! needs_multipart $draft; then + ;; + justsend) + stripempty "$draft" + if mmime -c <"$draft" && ! needs_multipart "$draft"; then automime= else automime=1 do_mime fi + c=send ;; d|delete) - rm -i $draft - if ! [ -f $draft ]; then - rm -f $draftmime + rm -i "$draft" + if ! [ -f "$draft" ]; then + rm -f "$draftmime" printf '%s\n' "mcom: deleted draft $draft" exit 0 fi c= ;; sign) - msign $draft >$draftmime - mshow -t $draftmime + msign "$draft" >"$draftmime" + mshow -t "$draftmime" c= ;; encrypt) - mencrypt $draft >$draftmime - mshow -t $draftmime + mencrypt "$draft" >"$draftmime" + mshow -t "$draftmime" c= ;; show) - if [ -e $draftmime ]; then + if [ -e "$draftmime" ]; then mshow "$draftmime" else mshow "$draft" diff -Nru mblaze-0.4/mcom mblaze-0.5.1/mcom --- mblaze-0.4/mcom 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mcom 2019-03-03 17:12:56.000000000 +0100 @@ -11,7 +11,7 @@ } notmine() { - mine="$(maddr -a -h local-mailbox:alternate-mailboxes: $MBLAZE/profile)" + mine="$(maddr -a -h local-mailbox:alternate-mailboxes: "$MBLAZE/profile")" grep -Fv -e "$mine" } @@ -40,6 +40,27 @@ fi } +checksensible() { + awk ' + /^$/ { + seenheader=1 + exit + } + !(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) { + bad=1 + print "invalid header line: "$0 >"/dev/stderr" + } + END { + if (!seenheader) { + print "warning: message does not contain an empty line between headers and body." >"/dev/stderr" + exit 1 + } + if (bad) + exit 1 + } +' "$1" +} + stripempty() { tmp=$(mktemp -t mcom.XXXXXX) msed 's/^[ \t]*$//d' "$1" >"$tmp" @@ -55,13 +76,13 @@ if needs_multipart "$draft"; then ( IFS=$NL - msed '/attach/d' $draft - for f in $(mhdr -M -h attach $draft); do + msed '/attach/d' "$draft" + for f in $(mhdr -M -h attach "$draft"); do printf '#%s %s\n' \ - "$(file -Lbi $f | sed 's/ //g')" \ + "$(file -Lbi "$f" | sed 's/ //g')" \ "$f" done - ) | mmime >$draftmime + ) | mmime >"$draftmime" else mmime -r <"$draft" >"$draftmime" fi @@ -74,8 +95,11 @@ sendmail="${sendmail:-sendmail} ${sendmail_args:--t}" default_from=$(mhdr -h local-mailbox "$MBLAZE/profile") +defaultc=e + hdrs= resume= +noquote= case "$0" in *mcom*) hdr=to @@ -90,11 +114,22 @@ shift resume=1 if [ "$#" -gt 0 ]; then - echo "used draft $1" - draft="$1" + case "$1" in + /*|./*) draft="$1";; + *) draft="./$1";; + esac + if ! [ -f "$draft" ]; then + printf 'mcom: no such draft %s\n' \ + "$draft" 1>&2 + exit 1 + fi + echo "using draft $draft" shift fi ;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -118,6 +153,9 @@ -r) shift raw=1;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -139,6 +177,9 @@ --) shift break;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -160,6 +201,12 @@ --) shift break;; + -send) + defaultc=justsend + shift;; + -noquote) + noquote=1 + shift;; -??*) hdr=${1#-} shift;; @@ -280,8 +327,8 @@ if [ "$ng" ]; then printf 'Newsgroups: %s\n' "$ng" else - to=$(mhdr -h reply-to "$1") - [ -z "$to" ] && to=$(mhdr -h from "$1") + to=$(mhdr -d -h reply-to "$1") + [ -z "$to" ] && to=$(mhdr -d -h from "$1") printf 'To: %s\n' "$to" printf 'Cc: %s\n' \ "$(mhdr -d -A -h to:cc: "$1" | @@ -308,8 +355,10 @@ cat "$MBLAZE/headers" 2>/dev/null printf '\n' - mquote "$1" - printf '\n' + if [ -z "$noquote" ]; then + mquote "$1" + printf '\n' + fi ( IFS=$NL cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h body /dev/stdin) @@ -332,10 +381,10 @@ cat "$SIGNATURE" fi esac -} >$draft +} >"$draft" automime= -c=e +c=$defaultc while :; do case "$c" in s|send) @@ -352,15 +401,15 @@ ;; esac - if [ -e $draftmime ]; then - if [ $draft -ot $draftmime ] || [ "$automime" -eq 1 ]; then - stampdate $draftmime - if $sendmail <$draftmime; then + if [ -e "$draftmime" ]; then + if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 ]; then + stampdate "$draftmime" + if $sendmail <"$draftmime"; then if [ "$outbox" ]; then - mv $draftmime $draft - mflag -d -S $draft + mv "$draftmime" "$draft" + mflag -d -S "$draft" else - rm $draft $draftmime + rm "$draft" "$draftmime" fi else printf '%s\n' "mcom: $sendmail failed, kept draft $draft" @@ -369,15 +418,16 @@ else printf 'mcom: re-run mmime first.\n' c= + continue fi else - if mmime -c <$draft; then - stampdate $draft - if $sendmail <$draft; then + if mmime -c <"$draft"; then + stampdate "$draft" + if $sendmail <"$draft"; then if [ "$outbox" ]; then - mflag -d -S $draft + mflag -d -S "$draft" else - rm $draft + rm "$draft" fi else printf '%s\n' "mcom: $sendmail failed, kept draft $draft" @@ -386,6 +436,7 @@ else printf '%s\n' "mcom: message needs to be MIME-encoded first." c= + continue fi fi @@ -398,49 +449,64 @@ exit 0 ;; c|cancel) - stampdate $draft + stampdate "$draft" printf '%s\n' "mcom: cancelled draft $draft" exit 1 ;; m|mime) do_mime - mshow -t $draftmime + mshow -t "$draftmime" c= ;; e|edit) c= - if ! ${EDITOR:-vi} $draft; then - c=c + if ! ${EDITOR:-vi} "$draft"; then + c=d + else + if checksensible "$draft"; then + stripempty "$draft" + if mmime -c <"$draft" && ! needs_multipart "$draft"; then + automime= + else + automime=1 + do_mime + fi + else + printf '\n' + fi fi - stripempty $draft - if mmime -c <$draft && ! needs_multipart $draft; then + ;; + justsend) + stripempty "$draft" + if mmime -c <"$draft" && ! needs_multipart "$draft"; then automime= else automime=1 do_mime fi + c=send ;; d|delete) - rm -i $draft - if ! [ -f $draft ]; then - rm -f $draftmime + rm -i "$draft" + if ! [ -f "$draft" ]; then + rm -f "$draftmime" printf '%s\n' "mcom: deleted draft $draft" exit 0 fi c= ;; sign) - msign $draft >$draftmime - mshow -t $draftmime + msign "$draft" >"$draftmime" + mshow -t "$draftmime" c= ;; encrypt) - mencrypt $draft >$draftmime - mshow -t $draftmime + mencrypt "$draft" >"$draftmime" + mshow -t "$draftmime" c= ;; show) - if [ -e $draftmime ]; then + if [ -e "$draftmime" ]; then mshow "$draftmime" else mshow "$draft" diff -Nru mblaze-0.4/mdeliver.c mblaze-0.5.1/mdeliver.c --- mblaze-0.4/mdeliver.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mdeliver.c 2019-03-03 17:12:56.000000000 +0100 @@ -1,3 +1,4 @@ +#include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> @@ -30,6 +31,8 @@ char *targetdir; long delivery; +int preserve_mtime; +int try_rename; char host[64]; void @@ -45,9 +48,10 @@ } int -deliver(FILE *infile) +deliver(char *infilename) { int outfd; + FILE *infile; FILE *outfile; char dst[PATH_MAX]; char tmp[PATH_MAX]; @@ -57,6 +61,22 @@ char *line = 0; size_t linelen = 0; + if (infilename) { + if (try_rename) { + infile = 0; + } else { + infile = fopen(infilename, "r"); + if (!infile) { + fprintf(stderr, "mrefile: %s: %s\n", + infilename, strerror(errno)); + return -1; + } + } + } else { + // mdeliver + infile = stdin; + } + if (Mflag) { // skip to first "From " line while (1) { @@ -65,7 +85,7 @@ if (rd == -1) { if (errno == 0) errno = EINVAL; // invalid mbox file - return -1; + goto fail; } if (strncmp("From ", line, 5) == 0) @@ -73,9 +93,9 @@ } } - while (!feof(infile)) { + do { delivery++; -tryagain: +try_again: gettimeofday(&tv, 0); snprintf(id, sizeof id, "%ld.M%06ldP%ldQ%ld.%s", @@ -84,13 +104,39 @@ snprintf(tmp, sizeof tmp, "%s/tmp/%s", targetdir, id); - outfd = open(tmp, O_CREAT | O_WRONLY | O_EXCL, 0666); + if (try_rename) { + snprintf(dst, sizeof dst, "%s/%s/%s:2,%s", + targetdir, cflag ? "cur" : "new", id, Xflag); + if (rename(infilename, dst) == 0) + goto success; + + /* rename failed, open file and try copying */ + + infile = fopen(infilename, "r"); + if (!infile) { + fprintf(stderr, "mrefile: %s: %s\n", + infilename, strerror(errno)); + return -1; + } + } + + struct stat st; + if (fstat(fileno(infile), &st) < 0) + st.st_mode = 0600; + if (S_ISFIFO(st.st_mode)) + st.st_mode = 0600; + outfd = open(tmp, O_CREAT | O_WRONLY | O_EXCL, + st.st_mode & 07777); if (outfd < 0) { if (errno == EEXIST) - goto tryagain; - fprintf(stderr, "mrefile: %s: %s\n", - tmp, strerror(errno)); - return -1; + goto try_again; + if (errno == ENOENT) + fprintf(stderr, "mrefile: %s/tmp: %s\n", + targetdir, strerror(errno)); + else + fprintf(stderr, "mrefile: %s: %s\n", + tmp, strerror(errno)); + goto fail; } outfile = fdopen(outfd, "w"); @@ -104,7 +150,7 @@ ssize_t rd = getdelim(&line, &linelen, '\n', infile); if (rd == -1) { if (errno != 0) - return -1; + goto fail; break; } char *line_start = line; @@ -142,14 +188,14 @@ } if (fwrite(line_start, 1, rd, outfile) != (size_t)rd) - return -1; + goto fail; } if (fflush(outfile) == EOF) - return -1; + goto fail; if (fsync(outfd) < 0) - return -1; + goto fail; if (fclose(outfile) == EOF) - return -1; + goto fail; // compress flags int i, j; @@ -173,18 +219,40 @@ utimes(tmp, times); } } + blaze822_free(msg); + } + + if (preserve_mtime) { + const struct timespec times[2] = { + { tv.tv_sec, tv.tv_usec * 1000L }, +#if (defined(__APPLE__) && defined(__MACH__)) + st.st_mtimespec +#else /* POSIX.1-2008 */ + st.st_mtim +#endif + }; + utimensat(AT_FDCWD, tmp, times, 0); } snprintf(dst, sizeof dst, "%s/%s/%s:2,%s", targetdir, (cflag || is_old) ? "cur" : "new", id, Xflag ? Xflag : statusflags); if (rename(tmp, dst) != 0) - return -1; + goto fail; +success: if (vflag) printf("%s\n", dst); - } + } while (Mflag && !feof(infile)); + + if (infile) + fclose(infile); return 0; + +fail: + if (infile) + fclose(infile); + return -1; } void @@ -193,12 +261,6 @@ while (*file == ' ' || *file == '\t') file++; - FILE *f = fopen(file, "r"); - if (!f) { - fprintf(stderr, "mrefile: %s: %s\n", file, strerror(errno)); - return; - } - // keep flags char *flags = strstr(file, ":2,"); if (flags) @@ -206,13 +268,12 @@ else Xflag = ""; - if (deliver(f) < 0) { + if (deliver(file) < 0) { perror("mrefile"); return; } - fclose(f); - if (!kflag) + if (!kflag && !try_rename) unlink(file); } @@ -223,11 +284,13 @@ // mrefile(1) cflag = 1; // use cur/ + preserve_mtime = 1; + try_rename = 1; int c; while ((c = getopt(argc, argv, "kv")) != -1) switch (c) { - case 'k': kflag = 1; break; + case 'k': kflag = 1; try_rename = 0; break; case 'v': vflag = 1; break; default: usage: @@ -274,7 +337,7 @@ gethost(); - if (deliver(stdin) < 0) { + if (deliver(0) < 0) { perror("mdeliver"); return 2; } diff -Nru mblaze-0.4/mdirs.c mblaze-0.5.1/mdirs.c --- mblaze-0.4/mdirs.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mdirs.c 2019-03-03 17:12:56.000000000 +0100 @@ -9,12 +9,14 @@ #include "blaze822.h" +static char sep = '\n'; + void pwd() { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof cwd)) - puts(cwd); + printf("%s%c", cwd, sep); } void @@ -72,19 +74,31 @@ main(int argc, char *argv[]) { int c, i; - while ((c = getopt(argc, argv, "")) != -1) + while ((c = getopt(argc, argv, "0")) != -1) switch (c) { + case '0': sep = '\0'; break; default: usage: - fprintf(stderr, "Usage: mdirs dirs...\n"); + fprintf(stderr, "Usage: mdirs [-0] dirs...\n"); exit(1); } if (argc == optind) goto usage; - for (i = 0; i < argc; i++) + char toplevel[PATH_MAX]; + if (!getcwd(toplevel, sizeof toplevel)) { + perror("mdirs: getcwd"); + exit(-1); + } + + for (i = 0; i < argc; i++) { mdirs(argv[i]); + if (chdir(toplevel) < 0) { + perror("mdirs: chdir"); + exit(-1); + } + } return 0; } diff -Nru mblaze-0.4/mflow.c mblaze-0.5.1/mflow.c --- mblaze-0.4/mflow.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mflow.c 2019-03-03 17:12:56.000000000 +0100 @@ -40,7 +40,7 @@ if (column == 0) { for (; column < quotes; column++) putchar('>'); - if (quotes) + if (quotes && *line != ' ') putchar(' '); } @@ -60,7 +60,7 @@ for (; column < quotes; column++) putchar('>'); column++; - if (quotes) + if (quotes && *line != ' ') putchar(' '); } diff -Nru mblaze-0.4/mgenmid.c mblaze-0.5.1/mgenmid.c --- mblaze-0.4/mgenmid.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mgenmid.c 2019-03-03 17:12:56.000000000 +0100 @@ -85,30 +85,35 @@ struct timeval tp; gettimeofday(&tp, (struct timezone *)0); - uint64_t rnd; + uint64_t rnd1, rnd2; int rndfd = open("/dev/urandom", O_RDONLY); if (rndfd >= 0) { - unsigned char rndb[8]; + unsigned char rndb[16]; if (read(rndfd, rndb, sizeof rndb) != sizeof rndb) goto fallback; close(rndfd); int i; - for (i = 0, rnd = 0; i < 8; i++) - rnd = rnd*256 + rndb[i]; + for (i = 0, rnd1 = 0; i < 8; i++) + rnd1 = rnd1*256 + rndb[i]; + for (i = 0, rnd2 = 0; i < 8; i++) + rnd2 = rnd2*256 + rndb[i+8]; } else { fallback: srand48(tp.tv_sec ^ tp.tv_usec ^ getpid()); - rnd = ((uint64_t)lrand48() << 32) + lrand48(); + rnd1 = ((uint64_t)lrand48() << 32) + lrand48(); + rnd2 = ((uint64_t)lrand48() << 32) + lrand48(); } - rnd |= (1ULL << 63); // set highest bit to force full width + rnd1 ^= ((uint64_t)tp.tv_sec * 1000000LL + tp.tv_usec); + rnd1 |= (1ULL << 63); // set highest bit to force full width + rnd2 |= (1ULL << 63); // set highest bit to force full width putchar('<'); - printb36(((uint64_t)tp.tv_sec * 1000000LL + tp.tv_usec)); + printb36(rnd1); putchar('.'); - printb36(rnd); + printb36(rnd2); putchar('@'); fputs(host, stdout); putchar('>'); diff -Nru mblaze-0.4/mless mblaze-0.5.1/mless --- mblaze-0.4/mless 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mless 2019-03-03 17:12:56.000000000 +0100 @@ -37,9 +37,9 @@ mshow "$2" fi | mcolor else - mseq -r $2 + mseq -r "$2" echo - cat "$(mseq -r $2)" + cat "$(mseq -r "$2")" fi exit $? fi @@ -53,11 +53,7 @@ exec mseq : fi -case "$0" in - *mnext) set -- +;; - *mprev) set -- -;; - *) [ "$#" -eq 1 ] && set -- ${1:-.};; -esac +[ "$#" -eq 1 ] && set -- ${1:-.} if [ "$#" -ge 1 ]; then mseq -C "$1" @@ -68,12 +64,12 @@ export MLESS_RAW=0 export MLESS_HTML=0 while :; do - if [ -f $MBLAZE/mless ]; then - export LESSKEY=$MBLAZE/mless - elif [ -f $HOME/.mblaze/mless ]; then - export LESSKEY=$HOME/.mblaze/mless - elif [ -f $HOME/.mless ]; then - export LESSKEY=$HOME/.mless + if [ -f "$MBLAZE/mless" ]; then + export LESSKEY="$MBLAZE/mless" + elif [ -f "$HOME/.mblaze/mless" ]; then + export LESSKEY="$HOME/.mblaze/mless" + elif [ -f "$HOME/.mless" ]; then + export LESSKEY="$HOME/.mless" fi LESSOPEN="|$0 --filter %s" \ less -Ps"mless %f?m (message %i of %m).." -R \ diff -Nru mblaze-0.4/mmime.c mblaze-0.5.1/mmime.c --- mblaze-0.4/mmime.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mmime.c 2019-03-03 17:12:56.000000000 +0100 @@ -282,6 +282,9 @@ char *s, *e; size_t l = strlen(line); + if (l == 0) + return; + if (line[l-1] == '\n') line[l-1] = 0; @@ -299,7 +302,7 @@ int prevq = 0; // was the previous word encoded as qp? - size_t linelen = s - line; + ssize_t linelen = s - line; while (*s) { size_t highbit = 0; diff -Nru mblaze-0.4/mmkdir mblaze-0.5.1/mmkdir --- mblaze-0.4/mmkdir 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mmkdir 2019-03-03 17:12:56.000000000 +0100 @@ -1,9 +1,11 @@ #!/bin/sh # mmkdir DIRS... - create new maildirs +umask 077 + r=0 for dir; do - mkdir -p -m 0700 $dir/cur $dir/new $dir/tmp || r=1 + mkdir -p "$dir"/cur "$dir"/new "$dir"/tmp || r=1 done exit $r diff -Nru mblaze-0.4/mnext mblaze-0.5.1/mnext --- mblaze-0.4/mnext 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mnext 1970-01-01 01:00:00.000000000 +0100 @@ -1,107 +0,0 @@ -#!/bin/sh -# mless [MSG] - less(1)-wrapper around mshow - -colorscan() { -awk ' -function co(n, c) { e = ENVIRON["MCOLOR_" n]; return e ? e : c } -function fg(c, s) { return sprintf("\033[38;5;%03dm%s\033[0m", c, s) } -function so(s) { return sprintf("\033[1m%s\033[0m", s) } -/^>/ { print so(fg(co("CUR",119), $0)); next } -/^ *\\_/ { print fg(co("MISS",242), $0); next } -{ print }' -} - -if [ -n "${NO_COLOR+set}" ]; then - colorscan() { cat -; } -fi - -if [ "$1" = --filter ]; then - if [ "$2" = //scan ]; then - mscan : 2>/dev/null | colorscan - exit $? - fi - - mseq -C "$2" - mscan .-2:.+3 2>/dev/null | colorscan - echo - - if ! [ -f "$(mseq -r "$2")" ]; then - mseq "$2" - exit - fi - - if [ $MLESS_RAW -eq 0 ]; then - if [ $MLESS_HTML -eq 1 ]; then - mshow -A text/html "$2" - else - mshow "$2" - fi | mcolor - else - mseq -r $2 - echo - cat "$(mseq -r $2)" - fi - exit $? -fi - -if [ "$#" -eq 0 ] && ! [ -t 0 ]; then - mseq -S >/dev/null - set -- : -fi - -if ! [ -t 1 ]; then - exec mseq : -fi - -case "$0" in - *mnext) set -- +;; - *mprev) set -- -;; - *) [ "$#" -eq 1 ] && set -- ${1:-.};; -esac - -if [ "$#" -ge 1 ]; then - mseq -C "$1" -fi - -nl=" -" -export MLESS_RAW=0 -export MLESS_HTML=0 -while :; do - if [ -f $MBLAZE/mless ]; then - export LESSKEY=$MBLAZE/mless - elif [ -f $HOME/.mblaze/mless ]; then - export LESSKEY=$HOME/.mblaze/mless - elif [ -f $HOME/.mless ]; then - export LESSKEY=$HOME/.mless - fi - LESSOPEN="|$0 --filter %s" \ - less -Ps"mless %f?m (message %i of %m).." -R \ - "+:e $(mscan -n .)$nl" //scan $(mscan -n :) - case "$?" in - 0|1) exit $?;; - 36) # $ goto end - mseq -C '$' 2>/dev/null - ;; - 78) # N go to next unseen message - nu=$(magrep -v -m1 :S .:) && mseq -C "$nu" - ;; - 107) # k next thread - mseq -C "$(mseq .+1: | sed -n '/^[^ <]/{p;q;}')" - ;; - 100) # d mark read - mflag -S . - mseq -f : | mseq -S - mseq -C + - ;; - 82) # R toggle raw mode - MLESS_RAW=$((1-$MLESS_RAW)) - ;; - 72) # H toggle HTML mode - MLESS_HTML=$((1-$MLESS_HTML)) - ;; - 94) # ^ goto parent - mseq -C '.^' 2>/dev/null - ;; - esac -done diff -Nru mblaze-0.4/mpick.c mblaze-0.5.1/mpick.c --- mblaze-0.4/mpick.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mpick.c 2019-03-03 17:12:56.000000000 +0100 @@ -284,7 +284,7 @@ pos++; while (*pos && (*pos != '"' || (*pos == '"' && *(pos+1) == '"'))) { - if (len >= bufsiz) { + if (len+1 >= bufsiz) { bufsiz = 2*bufsiz + 16; buf = realloc(buf, bufsiz); if (!buf) @@ -809,7 +809,7 @@ if (!m->msg || !(b = blaze822_chdr(m->msg, h))) goto err; - char buf[100]; + char buf[4096]; blaze822_decode_rfc2047(buf, b, sizeof buf - 1, "UTF-8"); if (!*buf) goto err; @@ -1142,17 +1142,20 @@ { long i; int c; + int vflag; argv0 = argv[0]; now = time(0); num = 1; + vflag = 0; - while ((c = getopt(argc, argv, "Tt:")) != -1) + while ((c = getopt(argc, argv, "Tt:v")) != -1) switch (c) { case 'T': Tflag = need_thr = 1; break; case 't': expr = chain(expr, EXPR_AND, parse_expr(optarg)); break; + case 'v': vflag = 1; break; default: - fprintf(stderr, "Usage: %s [-T] [-t test] [msglist ...]\n", argv0); + fprintf(stderr, "Usage: %s [-Tv] [-t test] [msglist ...]\n", argv0); exit(1); } @@ -1169,6 +1172,7 @@ if (Tflag && thr) do_thr(); - fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept); + if (vflag) + fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept); return 0; } diff -Nru mblaze-0.4/mprev mblaze-0.5.1/mprev --- mblaze-0.4/mprev 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mprev 1970-01-01 01:00:00.000000000 +0100 @@ -1,107 +0,0 @@ -#!/bin/sh -# mless [MSG] - less(1)-wrapper around mshow - -colorscan() { -awk ' -function co(n, c) { e = ENVIRON["MCOLOR_" n]; return e ? e : c } -function fg(c, s) { return sprintf("\033[38;5;%03dm%s\033[0m", c, s) } -function so(s) { return sprintf("\033[1m%s\033[0m", s) } -/^>/ { print so(fg(co("CUR",119), $0)); next } -/^ *\\_/ { print fg(co("MISS",242), $0); next } -{ print }' -} - -if [ -n "${NO_COLOR+set}" ]; then - colorscan() { cat -; } -fi - -if [ "$1" = --filter ]; then - if [ "$2" = //scan ]; then - mscan : 2>/dev/null | colorscan - exit $? - fi - - mseq -C "$2" - mscan .-2:.+3 2>/dev/null | colorscan - echo - - if ! [ -f "$(mseq -r "$2")" ]; then - mseq "$2" - exit - fi - - if [ $MLESS_RAW -eq 0 ]; then - if [ $MLESS_HTML -eq 1 ]; then - mshow -A text/html "$2" - else - mshow "$2" - fi | mcolor - else - mseq -r $2 - echo - cat "$(mseq -r $2)" - fi - exit $? -fi - -if [ "$#" -eq 0 ] && ! [ -t 0 ]; then - mseq -S >/dev/null - set -- : -fi - -if ! [ -t 1 ]; then - exec mseq : -fi - -case "$0" in - *mnext) set -- +;; - *mprev) set -- -;; - *) [ "$#" -eq 1 ] && set -- ${1:-.};; -esac - -if [ "$#" -ge 1 ]; then - mseq -C "$1" -fi - -nl=" -" -export MLESS_RAW=0 -export MLESS_HTML=0 -while :; do - if [ -f $MBLAZE/mless ]; then - export LESSKEY=$MBLAZE/mless - elif [ -f $HOME/.mblaze/mless ]; then - export LESSKEY=$HOME/.mblaze/mless - elif [ -f $HOME/.mless ]; then - export LESSKEY=$HOME/.mless - fi - LESSOPEN="|$0 --filter %s" \ - less -Ps"mless %f?m (message %i of %m).." -R \ - "+:e $(mscan -n .)$nl" //scan $(mscan -n :) - case "$?" in - 0|1) exit $?;; - 36) # $ goto end - mseq -C '$' 2>/dev/null - ;; - 78) # N go to next unseen message - nu=$(magrep -v -m1 :S .:) && mseq -C "$nu" - ;; - 107) # k next thread - mseq -C "$(mseq .+1: | sed -n '/^[^ <]/{p;q;}')" - ;; - 100) # d mark read - mflag -S . - mseq -f : | mseq -S - mseq -C + - ;; - 82) # R toggle raw mode - MLESS_RAW=$((1-$MLESS_RAW)) - ;; - 72) # H toggle HTML mode - MLESS_HTML=$((1-$MLESS_HTML)) - ;; - 94) # ^ goto parent - mseq -C '.^' 2>/dev/null - ;; - esac -done diff -Nru mblaze-0.4/mrep mblaze-0.5.1/mrep --- mblaze-0.4/mrep 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mrep 2019-03-03 17:12:56.000000000 +0100 @@ -11,7 +11,7 @@ } notmine() { - mine="$(maddr -a -h local-mailbox:alternate-mailboxes: $MBLAZE/profile)" + mine="$(maddr -a -h local-mailbox:alternate-mailboxes: "$MBLAZE/profile")" grep -Fv -e "$mine" } @@ -40,6 +40,27 @@ fi } +checksensible() { + awk ' + /^$/ { + seenheader=1 + exit + } + !(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) { + bad=1 + print "invalid header line: "$0 >"/dev/stderr" + } + END { + if (!seenheader) { + print "warning: message does not contain an empty line between headers and body." >"/dev/stderr" + exit 1 + } + if (bad) + exit 1 + } +' "$1" +} + stripempty() { tmp=$(mktemp -t mcom.XXXXXX) msed 's/^[ \t]*$//d' "$1" >"$tmp" @@ -55,13 +76,13 @@ if needs_multipart "$draft"; then ( IFS=$NL - msed '/attach/d' $draft - for f in $(mhdr -M -h attach $draft); do + msed '/attach/d' "$draft" + for f in $(mhdr -M -h attach "$draft"); do printf '#%s %s\n' \ - "$(file -Lbi $f | sed 's/ //g')" \ + "$(file -Lbi "$f" | sed 's/ //g')" \ "$f" done - ) | mmime >$draftmime + ) | mmime >"$draftmime" else mmime -r <"$draft" >"$draftmime" fi @@ -74,8 +95,11 @@ sendmail="${sendmail:-sendmail} ${sendmail_args:--t}" default_from=$(mhdr -h local-mailbox "$MBLAZE/profile") +defaultc=e + hdrs= resume= +noquote= case "$0" in *mcom*) hdr=to @@ -90,11 +114,22 @@ shift resume=1 if [ "$#" -gt 0 ]; then - echo "used draft $1" - draft="$1" + case "$1" in + /*|./*) draft="$1";; + *) draft="./$1";; + esac + if ! [ -f "$draft" ]; then + printf 'mcom: no such draft %s\n' \ + "$draft" 1>&2 + exit 1 + fi + echo "using draft $draft" shift fi ;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -118,6 +153,9 @@ -r) shift raw=1;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -139,6 +177,9 @@ --) shift break;; + -send) + defaultc=justsend + shift;; -??*) hdr=${1#-} shift;; @@ -160,6 +201,12 @@ --) shift break;; + -send) + defaultc=justsend + shift;; + -noquote) + noquote=1 + shift;; -??*) hdr=${1#-} shift;; @@ -280,8 +327,8 @@ if [ "$ng" ]; then printf 'Newsgroups: %s\n' "$ng" else - to=$(mhdr -h reply-to "$1") - [ -z "$to" ] && to=$(mhdr -h from "$1") + to=$(mhdr -d -h reply-to "$1") + [ -z "$to" ] && to=$(mhdr -d -h from "$1") printf 'To: %s\n' "$to" printf 'Cc: %s\n' \ "$(mhdr -d -A -h to:cc: "$1" | @@ -308,8 +355,10 @@ cat "$MBLAZE/headers" 2>/dev/null printf '\n' - mquote "$1" - printf '\n' + if [ -z "$noquote" ]; then + mquote "$1" + printf '\n' + fi ( IFS=$NL cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h body /dev/stdin) @@ -332,10 +381,10 @@ cat "$SIGNATURE" fi esac -} >$draft +} >"$draft" automime= -c=e +c=$defaultc while :; do case "$c" in s|send) @@ -352,15 +401,15 @@ ;; esac - if [ -e $draftmime ]; then - if [ $draft -ot $draftmime ] || [ "$automime" -eq 1 ]; then - stampdate $draftmime - if $sendmail <$draftmime; then + if [ -e "$draftmime" ]; then + if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 ]; then + stampdate "$draftmime" + if $sendmail <"$draftmime"; then if [ "$outbox" ]; then - mv $draftmime $draft - mflag -d -S $draft + mv "$draftmime" "$draft" + mflag -d -S "$draft" else - rm $draft $draftmime + rm "$draft" "$draftmime" fi else printf '%s\n' "mcom: $sendmail failed, kept draft $draft" @@ -369,15 +418,16 @@ else printf 'mcom: re-run mmime first.\n' c= + continue fi else - if mmime -c <$draft; then - stampdate $draft - if $sendmail <$draft; then + if mmime -c <"$draft"; then + stampdate "$draft" + if $sendmail <"$draft"; then if [ "$outbox" ]; then - mflag -d -S $draft + mflag -d -S "$draft" else - rm $draft + rm "$draft" fi else printf '%s\n' "mcom: $sendmail failed, kept draft $draft" @@ -386,6 +436,7 @@ else printf '%s\n' "mcom: message needs to be MIME-encoded first." c= + continue fi fi @@ -398,49 +449,64 @@ exit 0 ;; c|cancel) - stampdate $draft + stampdate "$draft" printf '%s\n' "mcom: cancelled draft $draft" exit 1 ;; m|mime) do_mime - mshow -t $draftmime + mshow -t "$draftmime" c= ;; e|edit) c= - if ! ${EDITOR:-vi} $draft; then - c=c + if ! ${EDITOR:-vi} "$draft"; then + c=d + else + if checksensible "$draft"; then + stripempty "$draft" + if mmime -c <"$draft" && ! needs_multipart "$draft"; then + automime= + else + automime=1 + do_mime + fi + else + printf '\n' + fi fi - stripempty $draft - if mmime -c <$draft && ! needs_multipart $draft; then + ;; + justsend) + stripempty "$draft" + if mmime -c <"$draft" && ! needs_multipart "$draft"; then automime= else automime=1 do_mime fi + c=send ;; d|delete) - rm -i $draft - if ! [ -f $draft ]; then - rm -f $draftmime + rm -i "$draft" + if ! [ -f "$draft" ]; then + rm -f "$draftmime" printf '%s\n' "mcom: deleted draft $draft" exit 0 fi c= ;; sign) - msign $draft >$draftmime - mshow -t $draftmime + msign "$draft" >"$draftmime" + mshow -t "$draftmime" c= ;; encrypt) - mencrypt $draft >$draftmime - mshow -t $draftmime + mencrypt "$draft" >"$draftmime" + mshow -t "$draftmime" c= ;; show) - if [ -e $draftmime ]; then + if [ -e "$draftmime" ]; then mshow "$draftmime" else mshow "$draft" diff -Nru mblaze-0.4/mscan.c mblaze-0.5.1/mscan.c --- mblaze-0.4/mscan.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mscan.c 2019-03-03 17:12:56.000000000 +0100 @@ -29,6 +29,7 @@ static int Iflag; static int nflag; +static int vflag; static int curyear; static time_t now; static char default_fflag[] = "%c%u%r %-3n %10d %17f %t %2i%s"; @@ -52,6 +53,7 @@ int r = u8decode(s, &c); if (r < 0) { r = 1; + l--; fprintf(out, "%lc", (wint_t)replacement); } else { l -= wcwidth((wchar_t)c); @@ -338,12 +340,12 @@ wleft--; break; case 'u': // unseen - if (strchr(flags, 'F')) + if (strchr(flags, 'T')) + putchar('x'); + else if (strchr(flags, 'F')) putchar('*'); else if (msg && !strchr(flags, 'S')) putchar('.'); - else if (strchr(flags, 'T')) - putchar('x'); else putchar(' '); wleft--; @@ -489,16 +491,17 @@ int main(int argc, char *argv[]) { - pid_t pid1 = -1; + pid_t pager_pid = -1; int c; - while ((c = getopt(argc, argv, "If:n")) != -1) + while ((c = getopt(argc, argv, "If:nv")) != -1) switch (c) { case 'I': Iflag++; break; case 'f': fflag = optarg; break; case 'n': nflag = 1; break; + case 'v': vflag = 1; break; default: - fprintf(stderr, "Usage: mscan [-n] [-f format] [-I] [msgs...]\n"); + fprintf(stderr, "Usage: mscan [-Inv] [-f format] [msgs...]\n"); exit(1); } @@ -528,8 +531,8 @@ if (!pg) pg = getenv("PAGER"); if (pg && *pg && strcmp(pg, "cat") != 0) { - pid1 = pipeto(pg); - if (pid1 < 0) + pager_pid = pipeto(pg); + if (pager_pid < 0) fprintf(stderr, "mscan: spawning pager '%s': %s\n", pg, strerror(errno)); @@ -567,10 +570,12 @@ i = blaze822_loop1(":", oneline); else i = blaze822_loop(argc-optind, argv+optind, oneline); - fprintf(stderr, "%ld mails scanned\n", i); - if (pid1 > 0) - pipeclose(pid1); + if (pager_pid > 0) + pipeclose(pager_pid); + + if (vflag) + fprintf(stderr, "%ld mails scanned\n", i); return 0; } diff -Nru mblaze-0.4/msed.c mblaze-0.5.1/msed.c --- mblaze-0.4/msed.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/msed.c 2019-03-03 17:12:56.000000000 +0100 @@ -28,7 +28,7 @@ #define APPC(c) do { if (b >= bufe) return str; *b++ = c; } while (0) regex_t srchrx; - regmatch_t pmatch[10]; + regmatch_t pmatch[10] = {{0}}; if (regcomp(&srchrx, srch, iflag ? REG_ICASE : 0) != 0) return str; @@ -218,6 +218,8 @@ free(flags); break; + case '\0': + break; default: fprintf(stderr, "msed: unknown command: '%c'\n", *e); exit(1); diff -Nru mblaze-0.4/mshow.c mblaze-0.5.1/mshow.c --- mblaze-0.4/mshow.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mshow.c 2019-03-03 17:12:56.000000000 +0100 @@ -35,6 +35,7 @@ struct message *filters; static int mimecount; +static int extractcount; static int safe_output; static int reply_found; @@ -224,6 +225,11 @@ } setenv("PIPE_CONTENTTYPE", ct, 1); + char *messageid = blaze822_hdr(msg, "message-id"); + if (messageid) { + setenv("MESSAGE_ID", messageid, 1); + } + char *output; size_t outlen; int e = filter(body, bodylen, cmd, &output, &outlen); @@ -326,6 +332,10 @@ struct message *imsg = 0; while (blaze822_multipart(msg, &imsg)) { m++; + + if (blaze822_bodylen(imsg) == 0) + continue; + char *ict = blaze822_hdr(imsg, "content-type"); if (!ict) ict = fallback_ct; @@ -521,6 +531,7 @@ printf("%s\n", bufptr); writefile(bufptr, body, bodylen); } + extractcount++; } else if (filename && fnmatch(a, filename, FNM_PATHNAME) == 0) { // extract by name @@ -541,6 +552,7 @@ printf("\n"); writefile(filename, body, bodylen); } + extractcount++; } } } @@ -551,6 +563,8 @@ void extract_cb(char *file) { + while (*file == ' ' || *file == '\t') + file++; struct message *msg = blaze822_file(file); if (!msg) return; @@ -833,5 +847,10 @@ if (pid1 > 0) pipeclose(pid1); + if ((xflag || Oflag) && extractcount < argc-optind) { + fprintf(stderr, "mshow: could not extract all attachments\n"); + return 1; + } + return 0; } diff -Nru mblaze-0.4/mthread.c mblaze-0.5.1/mthread.c --- mblaze-0.4/mthread.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/mthread.c 2019-03-03 17:12:56.000000000 +0100 @@ -64,7 +64,7 @@ } else { // invent new message-id for internal tracking static long i; - char buf[32]; + char buf[40]; snprintf(buf, sizeof buf, "thread%08ld@localhost", ++i); return strdup(buf); } @@ -307,7 +307,8 @@ c->mid = c->child->mid; c->file = c->child->file; c->msg = c->child->msg; - c->date = c->child->date; + if (c->child->date > c->date) + c->date = c->child->date; c->optional = c->child->optional; c->child = c->child->child; } diff -Nru mblaze-0.4/NEWS.md mblaze-0.5.1/NEWS.md --- mblaze-0.4/NEWS.md 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/NEWS.md 2019-03-03 17:12:56.000000000 +0100 @@ -1,3 +1,29 @@ +## 0.5.1 (2019-03-03) + +* mdeliver: preserve mtime in mrefile +* mdirs: add -0 to separate folders by NUL characters +* Fixes for buffer-overflows, found by fuzzing. +* Fixes for memleaks. + +## 0.5 (2019-02-09) + +* New tool msearch to wrap several mail indexers. +* New zsh completion _mblaze. +* mnext/mprev were removed (you can call `mless +`/`mless -`). +* The GnuPG tools in contrib/ now use gpg2. +* mshow exits with error if it could not extract all attachments +* mrep: add -noquote to disable quoting the message replied to +* mdeliver: keep permissions of messages +* mcom: aborting the editor is now more like delete than cancel +* mcom: add -send to send directly without editing +* mcom: check if mail is formatted sensibly +* mpick: new flag -v for statistics +* mscan: new flag -v for statistics +* magrep: add -h, which is like -p but doesn't print the file name +* mscan: prioritize displaying trashed mail over other markers +* mpick: fix off-by-one in expression parsing +* Many bug fixes + ## 0.4 (2018-08-15) * New tool mrefile to move or copy messages. diff -Nru mblaze-0.4/README mblaze-0.5.1/README --- mblaze-0.4/README 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/README 2019-03-03 17:12:56.000000000 +0100 @@ -19,7 +19,7 @@ mdeliver(1) deliver messages or import mbox file mdirs(1) list maildir folders, recursively mexport(1) export messages as mbox file - mflag(1) manipulate maildir flags + mflag(1) manipulate maildir message flags mflow(1) reflow format=flowed plain text messages mfwd(1) forward messages mgenmid(1) generate a Message-ID @@ -128,6 +128,6 @@ To the extent possible under law, the creator of this work has waived all copyright and related or neighboring rights to this work. - http://creativecommons.org/publicdomain/zero/1.0/ + http://creativecommons.org/publicdomain/zero/1.0/ Void Linux January 6, 2018 Void Linux diff -Nru mblaze-0.4/rfc2047.c mblaze-0.5.1/rfc2047.c --- mblaze-0.4/rfc2047.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/rfc2047.c 2019-03-03 17:12:56.000000000 +0100 @@ -130,6 +130,10 @@ iconv_t ic = (iconv_t)-1; char *srcenc = 0; + // need space for trailing nul + if (dlen-- == 0) + return 0; + char *startdst = dst; size_t startdlen = dlen; diff -Nru mblaze-0.4/rfc2231.c mblaze-0.5.1/rfc2231.c --- mblaze-0.4/rfc2231.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/rfc2231.c 2019-03-03 17:12:56.000000000 +0100 @@ -54,8 +54,10 @@ if (!srcenc) return 0; sbuf = strchr(sbuf+1, '\''); - if (!sbuf) + if (!sbuf) { + free(srcenc); return 0; + } sbuf++; } while (sbuf < ebuf && dst < dstend) { diff -Nru mblaze-0.4/safe_u8putstr.c mblaze-0.5.1/safe_u8putstr.c --- mblaze-0.4/safe_u8putstr.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/safe_u8putstr.c 2019-03-03 17:12:56.000000000 +0100 @@ -34,8 +34,11 @@ fputc(0xc0 | (*s >> 6), stream); fputc(0x80 | (*s & 0x3f), stream); } - } else if (c < 32 && + } else if (c < 32 && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r') { + // NUL + if (l == 0) + l = 1; // C0 fputc(0xe2, stream); fputc(0x90, stream); diff -Nru mblaze-0.4/seq.c mblaze-0.5.1/seq.c --- mblaze-0.4/seq.c 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/seq.c 2019-03-03 17:12:56.000000000 +0100 @@ -467,44 +467,53 @@ return r; } +int mystrverscmp(const char *, const char *); + +static int +mailsort(const struct dirent **a, const struct dirent **b) +{ + return mystrverscmp((*a)->d_name, (*b)->d_name); +} + static long iterdir(char *dir, void (*cb)(char *)) { - DIR *fd, *fd2; - struct dirent *d; + struct dirent **namelist; - long i = 0; + int n; + + char sub[PATH_MAX]; + snprintf(sub, sizeof sub, "%s/cur", dir); - fd = opendir(dir); - if (!fd) { + char *m = "/cur"; + + n = scandir(sub, &namelist, 0, mailsort); + if (n == -1 && (errno == ENOENT || errno == ENOTDIR)) { + m = ""; + n = scandir(dir, &namelist, 0, mailsort); + } + + if (n == -1) { if (errno == ENOTDIR) cb(dir); return 1; } - char sub[PATH_MAX]; - snprintf(sub, sizeof sub, "%s/cur", dir); - fd2 = opendir(sub); - if (fd2) { - closedir(fd); - fd = fd2; - } - - while ((d = readdir(fd))) { + long i = 0; + for (i = 0; i < n; i++) { + if (namelist[i]->d_name[0] != '.') #if defined(DT_REG) && defined(DT_UNKNOWN) - if (d->d_type != DT_REG && d->d_type != DT_UNKNOWN) - continue; + if (namelist[i]->d_type == DT_REG || + namelist[i]->d_type == DT_UNKNOWN) #endif - if (d->d_name[0] == '.') - continue; - if (fd2) - snprintf(sub, sizeof sub, "%s/cur/%s", dir, d->d_name); - else - snprintf(sub, sizeof sub, "%s/%s", dir, d->d_name); - cb(sub); - i++; + { + snprintf(sub, sizeof sub, "%s%s/%s", + dir, m, namelist[i]->d_name); + cb(sub); + } + free(namelist[i]); } - closedir(fd); + free(namelist); return i; } diff -Nru mblaze-0.4/t/1000-mmime.t mblaze-0.5.1/t/1000-mmime.t --- mblaze-0.4/t/1000-mmime.t 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/t/1000-mmime.t 2019-03-03 17:12:56.000000000 +0100 @@ -9,7 +9,7 @@ Body EOF -# https://github.com/chneukirchen/mblaze/issues/20 +# https://github.com/leahneukirchen/mblaze/issues/20 check 'mime -r runs' 'mmime -r <tmp >tmp2' check 'no overlong lines' 'awk "{if(length(\$0)>=80)exit 1}" <tmp2' diff -Nru mblaze-0.4/VERSION mblaze-0.5.1/VERSION --- mblaze-0.4/VERSION 2018-08-15 17:16:45.000000000 +0200 +++ mblaze-0.5.1/VERSION 2019-03-03 17:12:56.000000000 +0100 @@ -1 +1 @@ -0.4 +0.5.1