diff --git a/GNUmakefile b/GNUmakefile index 07a0b1a..d3c081e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,5 +1,6 @@ CFLAGS?=-g -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 override CFLAGS:=-Wall -Wno-switch -Wextra $(CFLAGS) +LDFLAGS?=-fstack-protector-strong LDLIBS=-lrt OS := $(shell uname) @@ -25,10 +26,10 @@ SCRIPT = mcolor mcom mless mmkdir mquote museragent all: $(ALL) museragent $(ALL) : % : %.o -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 mystrverscmp.o +maddr magrep mdeliver mdirs mexport mflag mflow mgenmid mhdr mpick mscan msed \ + mshow msort mthread : blaze822.o mymemmem.o mytimegm.o +maddr magrep mdeliver mdirs mexport mflag mgenmid mhdr minc mlist mpick mscan \ + msed mseq 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 diff --git a/blaze822.c b/blaze822.c index 9262f6f..47f03a2 100644 --- a/blaze822.c +++ b/blaze822.c @@ -443,7 +443,10 @@ blaze822(char *file) if (!mesg) return 0; - fd = open(file, O_RDONLY); + if (strcmp(file, "/dev/stdin") == 0) + fd = dup(0); + else + fd = open(file, O_RDONLY); if (fd < 0) { free(mesg); return 0; diff --git a/blaze822_priv.h b/blaze822_priv.h index a84c963..e5f4a09 100644 --- a/blaze822_priv.h +++ b/blaze822_priv.h @@ -12,9 +12,9 @@ struct message { #define isfws(c) (((unsigned char)(c) == ' ' || (unsigned char)(c) == '\t' || (unsigned char)(c) == '\n' || (unsigned char)(c) == '\r')) -// ASCII lowercase/uppercase without alpha check (wrong for "@[\]^_") -#define lc(c) ((c) | 0x20) -#define uc(c) ((c) & 0xdf) +// 7bit-ASCII only lowercase/uppercase +#define lc(c) (((unsigned)(c)-'A') < 26 ? ((c) | 0x20) : (c)) +#define uc(c) (((unsigned)(c)-'a') < 26 ? ((c) & 0xdf) : (c)) // dirent type that can be a mail/dir (following symlinks) #if defined(DT_REG) && defined(DT_LNK) && defined(DT_UNKNOWN) diff --git a/contrib/mgpg b/contrib/mgpg index 4a46701..4190501 100755 --- a/contrib/mgpg +++ b/contrib/mgpg @@ -20,7 +20,7 @@ n=$(mshow -t "$tmp" | awk -F: ' /: application\/octet-stream/ {if (supported) print $1}') if [ "$n" ]; then - mshow -O "$tmp" "$n" | $GPG -d 2>&1 || exit 0 + mshow -O "$tmp" "$n" | $GPG --quiet -d 2>&1 || exit 0 exit 64 fi exit 63 diff --git a/man/mblaze-profile.5 b/man/mblaze-profile.5 index 65d1b3d..d9aaad5 100644 --- a/man/mblaze-profile.5 +++ b/man/mblaze-profile.5 @@ -49,11 +49,18 @@ The fully qualified domain name used for .Li Message\&-Id\&: generation in .Xr mgenmid 1 . +.It Li Maildir\&: +If set, +.Xr mdirs 1 +will use this maildir when no directories are supplied. .It Li Outbox\&: If set, .Xr mcom 1 -will create draft messages in this maildir, -and save messages there after sending. +will save messages in this maildir after sending. +.It Li Drafts\&: +If set, +.Xr mcom 1 +will create draft messages in this maildir (defaults to Outbox). .It Li Reply-From\&: A comma-separated list of display name and mail address pairs, formatted like this: .Dl Li Primary Name , Name v.2 , \[dq]Name, My Third\[dq] , ... diff --git a/man/mblaze.7 b/man/mblaze.7 index 328bcef..da2aebf 100644 --- a/man/mblaze.7 +++ b/man/mblaze.7 @@ -163,6 +163,9 @@ thread it and look at it interactively: Or you could list the attachments of the 20 largest messages in your INBOX: .Dl mlist ~/Maildir/INBOX | msort -S | tail -20 | mshow -t .Pp +Or delete messages beyond a certain age: +.Dl mlist ~/Maildir/INBOX | mpick -t 'mtime < \&"-365d\&"' | xargs rm +.Pp Or apply the patches from the current message: .Dl mshow -O . '*.diff' | patch .Pp diff --git a/man/mcom.1 b/man/mcom.1 index 36fd6f3..957c322 100644 --- a/man/mcom.1 +++ b/man/mcom.1 @@ -6,7 +6,7 @@ .Nm mfwd , .Nm mbnc , .Nm mrep -.Nd compose, reply, forward, bounce, send messages +.Nd compose, forward, bounce, reply, send messages .Sh SYNOPSIS .Nm mcom .Op Fl Ar header Ar values\ ... diff --git a/man/mdirs.1 b/man/mdirs.1 index 44ffae4..f564803 100644 --- a/man/mdirs.1 +++ b/man/mdirs.1 @@ -1,4 +1,4 @@ -.Dd January 22, 2020 +.Dd July 25, 2023 .Dt MDIRS 1 .Os .Sh NAME @@ -17,6 +17,14 @@ for maildir folders and prints them, separated by newlines. .Pp +If +.Ar dirs +is not present then use +.Sq Li Maildir\&: +from +.Pa "${MBLAZE:-$HOME/.mblaze}/profile" +.Pq if set . +.Pp To .Nm , a maildir folder is a directory containing @@ -36,10 +44,20 @@ Print folders separated by a NUL character. .It Fl a Traverse into all subfolders, without considering the maildir++ name conventions. .El +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev MBLAZE +Directory containing mblaze configuration. +.Po +Default: +.Pa $HOME/.mblaze +.Pc +.El .Sh EXIT STATUS .Ex -std .Sh SEE ALSO -.Xr find 1 +.Xr find 1 , +.Xr mblaze-profile 5 .Sh AUTHORS .An Leah Neukirchen Aq Mt leah@vuxu.org .Sh LICENSE diff --git a/man/minc.1 b/man/minc.1 index cb71c85..6b7f96c 100644 --- a/man/minc.1 +++ b/man/minc.1 @@ -17,6 +17,9 @@ by moving them from to .Pa cur , and adjusting the filenames. +If used non-interactively with no specified folders, +.Nm +reads directory names from the standard input. .Pp By default, the new filenames are printed, separated by newlines. diff --git a/mcolor b/mcolor index d3a402a..6e3417f 100755 --- a/mcolor +++ b/mcolor @@ -7,15 +7,19 @@ function so(s) { return sprintf("\033[1m%s\033[0m", s) } BEGIN { hdr = 1; if ("NO_COLOR" in ENVIRON || match(ENVIRON["TERM"], "^(dumb|network|9term)")) no_color = 1 } no_color { print; next } /\r$/ { sub(/\r$/, "") } -/^\014$/ { nextmail = 1; next } -/^$/ { hdr = 0 } +/^\014$/ { nextmail = 1; print(fg(co("FF",232), $0)); next } +/^$/ { hdr = 0; diff = 0 } /^-- $/ { ftr = 1 } +/^diff -/ { diff = 1 } /^--- .* ---/ { print fg(co("SEP",242), $0); ftr = 0; sig = 0; next } /^-----BEGIN .* SIGNATURE-----/ { sig = 1 } nextmail && /^From:/ { hdr = 1 } hdr && /^From:/ { print so(fg(co("FROM",119), $0)); next } hdr { print fg(co("HEADER",120), $0); next } ftr { print fg(co("FOOTER",244), $0); next } +diff && /^-/ { print fg(co("DIFF_D",160), $0); next } +diff && /^\+/ { print fg(co("DIFF_I",40), $0); next } +diff && /^@/ { print fg(co("DIFF_R",226), $0); next } /^-----BEGIN .* MESSAGE-----/ || /^-----END .* SIGNATURE-----/ { print fg(co("SIG",244), $0); sig = 0; next } sig { print fg(co("SIG",244), $0); next } diff --git a/mcom b/mcom index 5bcfdc7..6d882ed 100755 --- a/mcom +++ b/mcom @@ -237,7 +237,9 @@ esac hdrs="$(printf '%s\n' "${hdrs#$NL}" | mhdr -)" outbox=$(mhdr -h outbox "$MBLAZE/profile" | sed "s:^~/:$HOME/:") -if [ -z "$outbox" ]; then +draftbox=$(mhdr -h drafts "$MBLAZE/profile" | sed "s:^~/:$HOME/:") +draftbox="${draftbox:-$outbox}" +if [ -z "$draftbox" ]; then if [ -z "$resume" ]; then i=0 while [ -f "snd.$i" ]; do @@ -250,13 +252,13 @@ if [ -z "$outbox" ]; then draftmime="$draft.mime" else if [ -z "$resume" ]; then - draft="$(true | mdeliver -v -c -XD "$outbox")" + draft="$(true | mdeliver -v -c -XD "$draftbox")" if [ -z "$draft" ]; then - printf '%s\n' "$0: failed to create draft in outbox $outbox." 1>&2 + printf '%s\n' "$0: failed to create draft in outbox $draftbox." 1>&2 exit 1 fi elif [ -z "$draft" ]; then - draft=$(mlist -D "$outbox" | msort -r -M | sed 1q) + draft=$(mlist -D "$draftbox" | msort -r -M | sed 1q) fi draftmime="$(printf '%s\n' "$draft" | sed 's,\(.*\)/cur/,\1/tmp/mime-,')" fi @@ -322,7 +324,10 @@ fi ) fi ;; *mbnc*) - set -- $(mseq -- "$@") + old_ifs="$IFS" + IFS=$NL + set -- $(mseq -r -- "$@") + IFS="$old_ifs" if [ "$#" -ne 1 ]; then printf 'mbnc: needs exactly one mail to bounce\n' 1>&2 exit 1 @@ -341,11 +346,14 @@ fi printf 'Resent-Date: %s\n' "$(mdate)" ( IFS=$NL - cat $(mseq -- "$@") + cat $(mseq -r -- "$@") ) ;; *mrep*) - set -- $(mseq -- "$@") + old_ifs="$IFS" + IFS=$NL + set -- $(mseq -r -- "$@") + IFS="$old_ifs" if [ "$#" -ne 1 ]; then printf 'mrep: needs exactly one mail to reply to\n' 1>&2 exit 1 @@ -441,7 +449,11 @@ while :; do if $sendmail <"$draftmime"; then if [ "$outbox" ]; then mv "$draftmime" "$draft" - ${sendhook:-mflag -d -S} "$draft" + if test -z "${sendhook}"; then + mrefile "$(mflag -d -S "$draft")" "$outbox" + else + ${sendhook} "$draft" + fi else rm "$draft" "$draftmime" fi @@ -459,7 +471,11 @@ while :; do stampdate "$draft" if $sendmail <"$draft"; then if [ "$outbox" ]; then - ${sendhook:-mflag -d -S} "$draft" + if test -z "${sendhook}"; then + mrefile "$(mflag -d -S "$draft")" "$outbox" + else + ${sendhook} "$draft" + fi else rm "$draft" fi diff --git a/mdeliver.c b/mdeliver.c index c9e00c5..5269929 100644 --- a/mdeliver.c +++ b/mdeliver.c @@ -355,7 +355,11 @@ usage2: if (argc != optind+1) goto usage2; - xpledge("stdio rpath wpath cpath", ""); + xpledge("stdio rpath wpath cpath fattr", ""); + if (!preserve_mtime && !Mflag) { + /* drop fattr */ + xpledge("stdio rpath wpath cpath", ""); + } targetdir = argv[optind]; diff --git a/mdirs.c b/mdirs.c index 5f49906..89ebab5 100644 --- a/mdirs.c +++ b/mdirs.c @@ -3,8 +3,10 @@ #include #include +#include #include #include +#include #include #include "blaze822.h" @@ -72,6 +74,33 @@ mdirs(char *fpath) closedir(dir); } +char * +profile_maildir() +{ + char *f = blaze822_home_file("profile"); + struct message *config = blaze822(f); + char *maildir; + static char path[PATH_MAX]; + + if (!config) + return 0; + + if (!(maildir = blaze822_hdr(config, "maildir"))) + return 0; + + if (strncmp(maildir, "~/", 2) == 0) { + const char *home = getenv("HOME"); + if (!home) { + struct passwd *pw = getpwuid(getuid()); + home = pw ? pw->pw_dir : "/dev/null/homeless"; + } + snprintf(path, sizeof path, "%s/%s", home, maildir+2); + maildir = path; + } + + return maildir; +} + int main(int argc, char *argv[]) { @@ -86,11 +115,17 @@ usage: exit(1); } - if (argc == optind) - goto usage; - xpledge("stdio rpath", ""); + if (argc == optind) { + char *maildir = profile_maildir(); + if (maildir) { + mdirs(maildir); + return 0; + } + goto usage; + } + char toplevel[PATH_MAX]; if (!getcwd(toplevel, sizeof toplevel)) { perror("mdirs: getcwd"); diff --git a/mflow.c b/mflow.c index 9bed19d..5ba925e 100644 --- a/mflow.c +++ b/mflow.c @@ -1,3 +1,7 @@ +#ifdef __sun +#define __EXTENSIONS__ /* to get TIOCGWINSZ */ +#endif + #include #include @@ -9,6 +13,7 @@ #include #include #include +#include #include "blaze822.h" #include "xpledge.h" diff --git a/minc.c b/minc.c index c1d28fd..2811646 100644 --- a/minc.c +++ b/minc.c @@ -74,14 +74,17 @@ usage: exit(1); } - if (optind == argc) - goto usage; - xpledge("stdio rpath cpath", ""); status = 0; - for (i = optind; i < argc; i++) - inc(argv[i]); + if (optind == argc) { + if (isatty(0)) + goto usage; + blaze822_loop(0, 0, inc); + } else { + for (i = optind; i < argc; i++) + inc(argv[i]); + } return status; } diff --git a/mlist.c b/mlist.c index 5debf99..20061d9 100644 --- a/mlist.c +++ b/mlist.c @@ -111,8 +111,8 @@ list(char *prefix, char *file) #include struct linux_dirent64 { - ino64_t d_ino; /* 64-bit inode number */ - off64_t d_off; /* 64-bit offset to next structure */ + uint64_t d_ino; /* 64-bit inode number */ + int64_t d_off; /* 64-bit offset to next structure */ unsigned short d_reclen; /* Size of this dirent */ unsigned char d_type; /* File type */ char d_name[]; /* Filename (null-terminated) */ diff --git a/mmime.c b/mmime.c index ab5bcf4..6334569 100644 --- a/mmime.c +++ b/mmime.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/mscan.c b/mscan.c index 52ba9a4..4052f1f 100644 --- a/mscan.c +++ b/mscan.c @@ -1,6 +1,9 @@ #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 700 #endif +#ifdef __sun +#define __EXTENSIONS__ /* to get TIOCGWINSZ */ +#endif #include "xpledge.h" @@ -19,6 +22,7 @@ #include #include #include +#include #include "blaze822.h" #include "u8decode.h" @@ -571,9 +575,13 @@ main(int argc, char *argv[]) struct winsize w; int ttyfd = open("/dev/tty", O_RDONLY | O_NOCTTY); - if (ttyfd >= 0 && ioctl(ttyfd, TIOCGWINSZ, &w) == 0) { - cols = w.ws_col; + if (ttyfd >= 0) { + if (ioctl(ttyfd, TIOCGWINSZ, &w) == 0) + cols = w.ws_col; + close(ttyfd); + } + if (isatty(1)) { char *pg; pg = getenv("MBLAZE_PAGER"); if (!pg) @@ -586,8 +594,6 @@ main(int argc, char *argv[]) pg, strerror(errno)); } } - if (ttyfd >= 0) - close(ttyfd); xpledge("stdio rpath", ""); diff --git a/rfc2047.c b/rfc2047.c index 3074b4d..5aec546 100644 --- a/rfc2047.c +++ b/rfc2047.c @@ -201,7 +201,8 @@ blaze822_decode_rfc2047(char *dst, char *src, size_t dlen, char *tgtenc) if (ic == (iconv_t)-1) goto nocode; - char enc = lc(*e++); + char enc = lc(*e); + e++; if (*e++ != '?') goto nocode; char *start = e; diff --git a/t/1100-mhdr.t b/t/1100-mhdr.t new file mode 100755 index 0000000..9937041 --- /dev/null +++ b/t/1100-mhdr.t @@ -0,0 +1,26 @@ +#!/bin/sh -e +cd ${0%/*} +. ./lib.sh + +plan 9 + +cat <tmp +Header: foo +Header2: bar +Header-Three: quux +Header_Four: ding + +Body +EOF + +check_same 'Header' 'mhdr -h Header ./tmp' 'echo foo' +check_same 'Header2' 'mhdr -h Header2 ./tmp' 'echo bar' +check_same 'Header-Three' 'mhdr -h Header-Three ./tmp' 'echo quux' +check_same 'Header_Four' 'mhdr -h Header_Four ./tmp' 'echo ding' + +check_same 'header' 'mhdr -h header ./tmp' 'echo foo' +check_same 'header2' 'mhdr -h header2 ./tmp' 'echo bar' +check_same 'header-Three' 'mhdr -h header-Three ./tmp' 'echo quux' +check_same 'header_Four' 'mhdr -h header_Four ./tmp' 'echo ding' + +check 'issue 235' 'mhdr ./tmp |grep -i header_four' diff --git a/t/9000-minc.t b/t/9000-minc.t index 3d5b789..9b29194 100644 --- a/t/9000-minc.t +++ b/t/9000-minc.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 1 +plan 2 rm -rf test.dir mkdir test.dir @@ -16,4 +16,10 @@ inbox/new/2 check_test 'minc' -eq 2 'minc inbox | wc -l' +while read f; do touch "$f"; done <