From 531152d1f7295768922140aa4ad620dbd664ccb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Sun, 13 Oct 2024 17:30:10 +0200 Subject: [PATCH 1/3] mpick/mscan: count seen mails in the callback function --- mpick.c | 10 ++++++---- mscan.c | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/mpick.c b/mpick.c index 661e472..8864094 100644 --- a/mpick.c +++ b/mpick.c @@ -190,6 +190,7 @@ static int need_thr; static long kept; static long num; +static long seen; static struct expr *expr; static long cur_idx; @@ -1363,6 +1364,7 @@ collect(char *file) struct mlist *ml; char *f; + seen++; f = xstrdup(file); m = xcalloc(1, sizeof *m); m = mailfile(m, f); @@ -1409,6 +1411,7 @@ void oneline(char *file) { struct mailinfo m = { 0 }; + seen++; m.index = num++; (void) mailfile(&m, file); if (expr && !eval(expr, &m)) @@ -1429,7 +1432,6 @@ oneline(char *file) int main(int argc, char *argv[]) { - long i; int c; int vflag; @@ -1466,9 +1468,9 @@ main(int argc, char *argv[]) void (*cb)(char *) = need_thr ? collect : oneline; if (argc == optind && isatty(0)) - i = blaze822_loop1(":", cb); + blaze822_loop1(":", cb); else - i = blaze822_loop(argc-optind, argv+optind, cb); + blaze822_loop(argc-optind, argv+optind, cb); /* print and free last thread */ if (Tflag && thr) @@ -1477,7 +1479,7 @@ main(int argc, char *argv[]) freeexpr(expr); if (vflag) - fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept); + fprintf(stderr, "%ld mails tested, %ld picked.\n", seen, kept); for (; files; files = fileq) { fileq = files->next; diff --git a/mscan.c b/mscan.c index bb6cd9e..3f5bc71 100644 --- a/mscan.c +++ b/mscan.c @@ -30,6 +30,7 @@ static int cols; static wchar_t replacement = L'?'; static char *cur; +static long seen; static char *aliases[32]; static int alias_idx; @@ -306,6 +307,7 @@ print_human(intmax_t i, int w) void oneline(char *file) { + seen++; if (!init) { // delay loading of the seq until we need to scan the first // file, in case someone in the pipe updated the map before @@ -622,17 +624,16 @@ main(int argc, char *argv[]) fflag = v; } - long i; if (argc == optind && isatty(0)) - i = blaze822_loop1(":", oneline); + blaze822_loop1(":", oneline); else - i = blaze822_loop(argc-optind, argv+optind, oneline); + blaze822_loop(argc-optind, argv+optind, oneline); if (pager_pid > 0) pipeclose(pager_pid); if (vflag) - fprintf(stderr, "%ld mails scanned\n", i); + fprintf(stderr, "%ld mails scanned\n", seen); return 0; } From dc5636c7ff4a78f5d5c9359b623227ed8352b7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Sun, 13 Oct 2024 14:31:31 +0200 Subject: [PATCH 2/3] blaze822: Use return value of loop functions for error handling Callers which need the number of messages processed need to count in the callback function now, see the previous commit. --- blaze822.h | 4 ++-- seq.c | 32 ++++++++++++++++++-------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/blaze822.h b/blaze822.h index 1346345..aba23e2 100644 --- a/blaze822.h +++ b/blaze822.h @@ -85,8 +85,8 @@ struct blaze822_seq_iter { }; char *blaze822_seq_next(char *map, char *range, struct blaze822_seq_iter *iter); -long blaze822_loop(int, char **, void (*)(char *)); -long blaze822_loop1(char *arg, void (*cb)(char *)); +int blaze822_loop(int, char **, void (*)(char *)); +int blaze822_loop1(char *arg, void (*cb)(char *)); char *blaze822_home_file(char *basename); // filter.c diff --git a/seq.c b/seq.c index 5d98284..073a58c 100644 --- a/seq.c +++ b/seq.c @@ -493,11 +493,13 @@ iterdir(char *dir, void (*cb)(char *)) m = ""; n = scandir(dir, &namelist, 0, mailsort); } - - if (n == -1) { - if (errno == ENOTDIR) + + if (n == -1) { + if (errno == ENOTDIR) { cb(dir); - return 1; + return 1; + } + return 0; } long i = 0; @@ -515,31 +517,34 @@ iterdir(char *dir, void (*cb)(char *)) return i; } -long +int blaze822_loop(int argc, char *argv[], void (*cb)(char *)) { char *line = 0; size_t linelen = 0; ssize_t rd; - long i = 0; if (argc == 0) { while ((rd = getdelim(&line, &linelen, '\n', stdin)) != -1) { if (line[rd-1] == '\n') line[rd-1] = 0; cb(line); - i++; } free(line); - return i; + + return 0; } char *map = 0; + int status = 0; int map_opened = 0; - int j = 0; + long i; for (i = 0; i < argc; i++) { if (strchr(argv[i], '/')) { // a file name - j += iterdir(argv[i], cb); + if (!iterdir(argv[i], cb)) { + fprintf(stderr, "mblaze: warning: file '%s' does not exist\n", argv[i]); + status = 1; + } } else if (strcmp(argv[i], "-") == 0) { if (isatty(0)) { fprintf(stderr, "mblaze: warning: - now means " @@ -547,7 +552,6 @@ blaze822_loop(int argc, char *argv[], void (*cb)(char *)) "use .- to refer to previous mail\n"); } cb("/dev/stdin"); - j++; } else { if (!map_opened) { map = blaze822_seq_open(0); @@ -557,15 +561,15 @@ blaze822_loop(int argc, char *argv[], void (*cb)(char *)) while ((line = blaze822_seq_next(map, argv[i], &iter))) { cb(line); free(line); - j++; } } } free(map); - return j; + + return status; } -long +int blaze822_loop1(char *arg, void (*cb)(char *)) { char *args[] = { arg }; From 89e7d05e1467b8a4b2597dd7304a69495bad092a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Sun, 13 Oct 2024 19:21:33 +0200 Subject: [PATCH 3/3] Add error handling for blaze822_loop to all callers --- maddr.c | 6 ++---- magrep.c | 7 +++++-- mdeliver.c | 4 +--- mexport.c | 4 ++-- mflag.c | 20 +++++++++----------- mhdr.c | 7 +++++-- minc.c | 3 ++- mlist.c | 5 +++-- mpick.c | 7 ++++--- mscan.c | 12 ++++++------ msed.c | 6 ++---- mseq.c | 10 ++++------ mshow.c | 21 +++++++++++---------- msort.c | 7 ++++--- mthread.c | 12 ++++++++---- t/1100-mhdr.t | 4 +++- t/1500-maddr.t | 4 +++- t/1700-mshow.t | 3 ++- t/1800-mexport.t | 3 ++- t/3000-magrep.t | 5 ++++- t/6000-msort.t | 4 +++- t/8000-mflag.t | 4 +++- 22 files changed, 88 insertions(+), 70 deletions(-) diff --git a/maddr.c b/maddr.c index 4982a8c..fe9751e 100644 --- a/maddr.c +++ b/maddr.c @@ -114,9 +114,7 @@ main(int argc, char *argv[]) xpledge("stdio rpath", ""); if (argc == optind && isatty(0)) - blaze822_loop1(":", addr); + return blaze822_loop1(":", addr); else - blaze822_loop(argc-optind, argv+optind, addr); - - return 0; + return blaze822_loop(argc-optind, argv+optind, addr); } diff --git a/magrep.c b/magrep.c index 608048a..2f0b845 100644 --- a/magrep.c +++ b/magrep.c @@ -231,10 +231,13 @@ main(int argc, char *argv[]) exit(2); } + int ret; if (argc == optind && isatty(0)) - blaze822_loop1(":", magrep); + ret = blaze822_loop1(":", magrep); else - blaze822_loop(argc-optind, argv+optind, magrep); + ret = blaze822_loop(argc-optind, argv+optind, magrep); + if (ret) + return 2; if (cflag && !qflag && !mflag) printf("%ld\n", matches); diff --git a/mdeliver.c b/mdeliver.c index 73fac4a..d2cc222 100644 --- a/mdeliver.c +++ b/mdeliver.c @@ -331,9 +331,7 @@ main(int argc, char *argv[]) if (argc == optind + 1 && isatty(0)) goto usage; else - blaze822_loop(argc - 1 - optind, argv + optind, refile); - - return 0; + return blaze822_loop(argc - 1 - optind, argv + optind, refile); } int c; diff --git a/mexport.c b/mexport.c index 0ac490d..4ad06a3 100644 --- a/mexport.c +++ b/mexport.c @@ -148,9 +148,9 @@ main(int argc, char *argv[]) xpledge("stdio rpath", ""); if (argc == optind && isatty(0)) - blaze822_loop1(":", export); + status |= blaze822_loop1(":", export); else - blaze822_loop(argc-optind, argv+optind, export); + status |= blaze822_loop(argc-optind, argv+optind, export); return status; } diff --git a/mflag.c b/mflag.c index ae9a9f2..a05e27f 100644 --- a/mflag.c +++ b/mflag.c @@ -141,31 +141,29 @@ main(int argc, char *argv[]) if (vflag) { if (argc == optind && !isatty(0)) { - blaze822_loop(0, 0, flag); // read from stdin - return 0; + return blaze822_loop(0, 0, flag); // read from stdin } args = calloc(argsalloc, sizeof (char *)); if (!args) exit(-1); + int status; if (argc == optind) - blaze822_loop1(".", add); + status = blaze822_loop1(".", add); else - blaze822_loop(argc-optind, argv+optind, add); + status = blaze822_loop(argc-optind, argv+optind, add); if (isatty(0)) - blaze822_loop1(":", flag); + status |= blaze822_loop1(":", flag); else - blaze822_loop(0, 0, flag); + status |= blaze822_loop(0, 0, flag); - return 0; + return status; } if (argc == optind && isatty(0)) - blaze822_loop1(".", flag); + return blaze822_loop1(".", flag); else - blaze822_loop(argc-optind, argv+optind, flag); - - return 0; + return blaze822_loop(argc-optind, argv+optind, flag); } diff --git a/mhdr.c b/mhdr.c index b6e9fa0..2677aa1 100644 --- a/mhdr.c +++ b/mhdr.c @@ -249,10 +249,13 @@ main(int argc, char *argv[]) xpledge("stdio rpath", ""); + int ret; if (argc == optind && isatty(0)) - blaze822_loop1(".", header); + ret = blaze822_loop1(".", header); else - blaze822_loop(argc-optind, argv+optind, header); + ret = blaze822_loop(argc-optind, argv+optind, header); + if (ret) + return 2; return status; } diff --git a/minc.c b/minc.c index 757c65b..3ae444e 100644 --- a/minc.c +++ b/minc.c @@ -81,7 +81,8 @@ main(int argc, char *argv[]) if (optind == argc) { if (isatty(0)) goto usage; - blaze822_loop(0, 0, inc); + if (blaze822_loop(0, 0, inc)) + return 1; } else { for (i = optind; i < argc; i++) inc(argv[i]); diff --git a/mlist.c b/mlist.c index e0ec42c..00a14ec 100644 --- a/mlist.c +++ b/mlist.c @@ -282,10 +282,11 @@ main(int argc, char *argv[]) flagsum++; } + int status = 0; if (optind == argc) { if (isatty(0)) goto usage; - blaze822_loop(0, 0, listarg); + status = blaze822_loop(0, 0, listarg); } else { for (i = optind; i < argc; i++) listarg(argv[i]); @@ -300,5 +301,5 @@ main(int argc, char *argv[]) tunseen, tflagged, tcount); } - return 0; + return status; } diff --git a/mpick.c b/mpick.c index 8864094..fe21b5a 100644 --- a/mpick.c +++ b/mpick.c @@ -1466,11 +1466,12 @@ main(int argc, char *argv[]) xpledge("stdio rpath wpath cpath proc exec", 0); + int status; void (*cb)(char *) = need_thr ? collect : oneline; if (argc == optind && isatty(0)) - blaze822_loop1(":", cb); + status = blaze822_loop1(":", cb); else - blaze822_loop(argc-optind, argv+optind, cb); + status = blaze822_loop(argc-optind, argv+optind, cb); /* print and free last thread */ if (Tflag && thr) @@ -1490,5 +1491,5 @@ main(int argc, char *argv[]) free(files); } - return 0; + return status; } diff --git a/mscan.c b/mscan.c index 3f5bc71..5bf8238 100644 --- a/mscan.c +++ b/mscan.c @@ -561,10 +561,9 @@ main(int argc, char *argv[]) if (nflag) { if (argc == optind && isatty(0)) - blaze822_loop1(":", numline); + return blaze822_loop1(":", numline); else - blaze822_loop(argc-optind, argv+optind, numline); - return 0; + return blaze822_loop(argc-optind, argv+optind, numline); } now = time(0); @@ -624,10 +623,11 @@ main(int argc, char *argv[]) fflag = v; } + int status; if (argc == optind && isatty(0)) - blaze822_loop1(":", oneline); + status = blaze822_loop1(":", oneline); else - blaze822_loop(argc-optind, argv+optind, oneline); + status = blaze822_loop(argc-optind, argv+optind, oneline); if (pager_pid > 0) pipeclose(pager_pid); @@ -635,5 +635,5 @@ main(int argc, char *argv[]) if (vflag) fprintf(stderr, "%ld mails scanned\n", seen); - return 0; + return status; } diff --git a/msed.c b/msed.c index c545278..30a1f60 100644 --- a/msed.c +++ b/msed.c @@ -330,9 +330,7 @@ main(int argc, char *argv[]) optind++; if (argc == optind && isatty(0)) - blaze822_loop1(".", sed); + return blaze822_loop1(".", sed); else - blaze822_loop(argc-optind, argv+optind, sed); - - return 0; + return blaze822_loop(argc-optind, argv+optind, sed); } diff --git a/mseq.c b/mseq.c index ac3aa19..8a21c2c 100644 --- a/mseq.c +++ b/mseq.c @@ -301,13 +301,11 @@ main(int argc, char *argv[]) xpledge("stdio rpath wpath cpath", ""); - if (cflag) - blaze822_loop1(cflag, overridecur); + if (cflag && blaze822_loop1(cflag, overridecur)) + return 1; - if (Cflag) { - blaze822_loop1(Cflag, setcur); - return 0; - } + if (Cflag) + return blaze822_loop1(Cflag, setcur); if (Sflag && optind != argc) { fprintf(stderr, "error: -S/-A doesn't take arguments.\n"); diff --git a/mshow.c b/mshow.c index d0871f2..aeb7b40 100644 --- a/mshow.c +++ b/mshow.c @@ -587,13 +587,13 @@ extract_cb(char *file) blaze822_walk_mime(msg, 0, extract_mime); } -void +int extract(char *file, int argc, char **argv, int use_stdout) { extract_argc = argc; extract_argv = argv; extract_stdout = use_stdout; - blaze822_loop1(file, extract_cb); + return blaze822_loop1(file, extract_cb); } static char *newcur; @@ -832,21 +832,22 @@ main(int argc, char *argv[]) } } + int status = 0; if (xflag) { // extract xpledge("stdio rpath wpath cpath", NULL); - extract(xflag, argc-optind, argv+optind, 0); + status = extract(xflag, argc-optind, argv+optind, 0); } else if (Oflag) { // extract to stdout xpledge("stdio rpath", NULL); - extract(Oflag, argc-optind, argv+optind, 1); + status = extract(Oflag, argc-optind, argv+optind, 1); } else if (tflag) { // list xpledge("stdio rpath", NULL); if (argc == optind && isatty(0)) - blaze822_loop1(".", list); + status = blaze822_loop1(".", list); else - blaze822_loop(argc-optind, argv+optind, list); + status = blaze822_loop(argc-optind, argv+optind, list); } else if (Rflag) { // render for reply xpledge("stdio rpath", NULL); - blaze822_loop(argc-optind, argv+optind, reply); + status = blaze822_loop(argc-optind, argv+optind, reply); } else { // show /* XXX pledge: still r/w on the whole file-system + fork/exec */ if (!(qflag || rflag || Fflag)) { @@ -857,9 +858,9 @@ main(int argc, char *argv[]) filters = blaze822(f); } if (argc == optind && isatty(0)) - blaze822_loop1(".", show); + status = blaze822_loop1(".", show); else - blaze822_loop(argc-optind, argv+optind, show); + status = blaze822_loop(argc-optind, argv+optind, show); if (!nflag) // don't set cur if (newcur) blaze822_seq_setcur(newcur); @@ -875,5 +876,5 @@ main(int argc, char *argv[]) return 1; } - return 0; + return status; } diff --git a/msort.c b/msort.c index 55ec6aa..240f250 100644 --- a/msort.c +++ b/msort.c @@ -323,10 +323,11 @@ main(int argc, char *argv[]) if (!mails) exit(-1); + int status; if (argc == optind && isatty(0)) - blaze822_loop1(":", add); + status = blaze822_loop1(":", add); else - blaze822_loop(argc-optind, argv+optind, add); + status = blaze822_loop(argc-optind, argv+optind, add); qsort(mails, idx, sizeof (struct mail), order); @@ -337,5 +338,5 @@ main(int argc, char *argv[]) for (i = 0; i < idx; i++) printf("%s\n", mails[i].file); - return 0; + return status; } diff --git a/mthread.c b/mthread.c index 77fb21e..87bf269 100644 --- a/mthread.c +++ b/mthread.c @@ -421,7 +421,10 @@ main(int argc, char *argv[]) while ((c = getopt(argc, argv, "S:prv")) != -1) switch (c) { - case 'S': blaze822_loop1(optarg, thread); break; + case 'S': + if (blaze822_loop1(optarg, thread)) + return 1; + break; case 'v': vflag = 1; break; case 'p': pflag = 1; break; case 'r': rflag = 1; break; @@ -432,10 +435,11 @@ main(int argc, char *argv[]) optional = 0; + int status; if (argc == optind && isatty(0)) - blaze822_loop1(":", thread); + status = blaze822_loop1(":", thread); else - blaze822_loop(argc-optind, argv+optind, thread); + status = blaze822_loop(argc-optind, argv+optind, thread); // the tree of all toplevel threads has depth -1, // so toplevel threads have depth 0. @@ -446,5 +450,5 @@ main(int argc, char *argv[]) sort_tree(top, -1); print_tree(top, -1); - return 0; + return status; } diff --git a/t/1100-mhdr.t b/t/1100-mhdr.t index 9937041..f924419 100755 --- a/t/1100-mhdr.t +++ b/t/1100-mhdr.t @@ -2,7 +2,7 @@ cd ${0%/*} . ./lib.sh -plan 9 +plan 10 cat <tmp Header: foo @@ -24,3 +24,5 @@ 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' +check 'non-existent mail' 'mhdr ./does-not-exist ; [ $? -eq 2 ]' + diff --git a/t/1500-maddr.t b/t/1500-maddr.t index cfca3e7..bd886a3 100755 --- a/t/1500-maddr.t +++ b/t/1500-maddr.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 11 +plan 13 rm -rf test.dir mkdir test.dir @@ -82,5 +82,7 @@ check_same 'long addr' 'maddr -h long 4' 'echo "heeeeeeeeeeeeeeeeeeeeeeeeeeeeeee check_same 'decode iso8859' 'maddr -h DecodeISO8859 5' 'echo "Keld Jørn Simonsen "' check_same 'decode long iso8859' 'maddr -h DecodeLongISO8859 5' 'echo "\"If you can read this you understand the example. z a b\" "' check_same 'decode utf8' 'maddr -h DecodeUTF8 5' 'echo "z’z "' +check 'non-existent mail' 'maddr -S /does/not/exist ; [ $? -eq 1 ]' +check_same 'keep going on non-existent mail' 'maddr /does/not/exist 3 /does/not/exist || true' 'echo "rajwinder@example.com"' ) diff --git a/t/1700-mshow.t b/t/1700-mshow.t index f974026..31791fa 100755 --- a/t/1700-mshow.t +++ b/t/1700-mshow.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 2 +plan 3 # Nested MIME where the outer boundary is a prefix of the inner boundary cat <tmp @@ -39,3 +39,4 @@ EOF check 'nested mail has 5 attachments' 'mshow -t ./tmp | wc -l | grep 6' check 'nested mail has text/html attachment' 'mshow -t ./tmp | grep text/html' +check 'non-existent mail' 'mshow ./does-not-exist ; [ $? -eq 1 ]' diff --git a/t/1800-mexport.t b/t/1800-mexport.t index c0eadbd..9ee945c 100755 --- a/t/1800-mexport.t +++ b/t/1800-mexport.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 2 +plan 3 cat <tmp.1 Subject: message 1 @@ -24,3 +24,4 @@ mexport ./tmp.1 ./tmp.2 ./tmp.3 >./tmp.mbox check 'generated mbox has 16 lines' 'cat ./tmp.mbox | wc -l | grep 16' check 'generated mbox has 7 empty lines' 'grep -c "^$" ./tmp.mbox | grep 7' +check 'non-existent mail' 'mexport ./foo-bar ; [ $? -eq 1 ]' diff --git a/t/3000-magrep.t b/t/3000-magrep.t index f20cbb6..4cf4fbd 100644 --- a/t/3000-magrep.t +++ b/t/3000-magrep.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 10 +plan 12 rm -rf test.dir mkdir test.dir @@ -191,4 +191,7 @@ check_same 'print match only' 'magrep -o subject:nice :' 'cat expect' echo 'inbox/cur/3:2,' >expect check_same 'multiple subjects' 'magrep subject:multi :' 'cat expect' +check 'non-existent mail' 'magrep subject:nice /does/not/exist ; [ $? -eq 2 ]' +check 'error take precedence over match' 'magrep subject:nomatch : /does/not/exist ; [ $? -eq 2 ]' + ) diff --git a/t/6000-msort.t b/t/6000-msort.t index e4fc609..cb9e15d 100644 --- a/t/6000-msort.t +++ b/t/6000-msort.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 5 +plan 6 rm -rf test.dir mkdir test.dir @@ -85,4 +85,6 @@ inbox/cur/1:2, ! check_same 'subject' 'msort -s :' 'cat expect' +check 'non-existent mail' 'msort -s /does/not/exist ; [ $? -eq 1 ]' + ) diff --git a/t/8000-mflag.t b/t/8000-mflag.t index 65562f6..7918906 100644 --- a/t/8000-mflag.t +++ b/t/8000-mflag.t @@ -1,7 +1,7 @@ #!/bin/sh -e cd ${0%/*} . ./lib.sh -plan 16 +plan 18 rm -rf test.dir mkdir test.dir @@ -35,5 +35,7 @@ check 'mark trashed' 'mflag -T 1 && [ -e "inbox/cur/1:2,T" ]' check_test 'fix seq' -eq 2 'mseq -f : | mseq -S | wc -l' check 'unmark trashed' 'mflag -t 1 && [ -e "inbox/cur/1:2," ]' check_test 'fix seq' -eq 2 'mseq -f : | mseq -S | wc -l' +check 'non-existent mail' 'mflag -S /does/not/exist ; [ $? -eq 1 ]' +check 'keep going on non-existent mail' 'mflag -t /does/not/exist 1 ; [ -e "inbox/cur/1:2," ]' )