Bug#923762: unblock: mblaze/0.5.1-1
Package: release.debian.org
Severity: normal
User: release.debian.org@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 <nicoo@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 <nicoo@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 qsx@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 <nicoo@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 <nicoo@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 <nicolas@braud-santoni.eu>
+Maintainer: Nicolas Braud-Santoni <nicoo@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 <nicoo@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 <nicoo@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 <nicoo@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
Reply to: