s-nail-14_5_2-maildir.patch, 2014-02-10: Apply: $ cd s-nail-14.5.2 $ patch -bu < s-nail-14_5_2-maildir.patch Description: To overcome a general design problem of the Berkeley Mail codebase i once added realpath(3) calls to be able to resolve the path of a mailbox file: like that changing a directory wouldn't cause the program to "hang" because the (relatively) opened mailbox became inaccessible. (Again: the real solution will take many years.) My first KISS solution to one aspect of the general problem was [3adf33ee] (schdir(): realpath() local files before leaving CWD.., 2013-01-08), and it should possibly have worked with maildir boxes, because we'd only did anything once the user actively used the `chdir' command (and who does), but Christos Zoulas from NetBSD actually forced me to do more (after i've reported the general Berkeley bug), and that led to the current code, which always calls realpath(3). Anyway, i wasn't in the position to reflect the impact of doing so at that time. And the entire codebase needs to be reworked anyway. (:( Anyway -- this patch is an adjusted combination of the [1c2563b] (lex.c:_update_mailname(): continue if realname() fails.., 2014-02-10) and [13f325f] (Avoid "cannot canonicalize" maildir warning.., 2014-02-10) changesets that have been pushed to [master], and make maildir mailboxes usable again. Notes: The patch is so large because it was cherry-picked from [crawl] onto [master] and (thus) includes the very large [nyd] topic branch style-and- much-more changes. Sorry for that. lex.c | 11 +++-- maildir.c | 152 +++++++++++++++++++++++++++++++++----------------------------- 2 files changed, 87 insertions(+), 76 deletions(-) diff --git a/lex.c b/lex.c index 922faf8..3b3b3cc 100644 --- a/lex.c +++ b/lex.c @@ -164,7 +164,7 @@ _update_mailname(char const *name) { char tbuf[MAXPATHLEN], *mailp, *dispp; size_t i, j; - bool_t rv; + bool_t rv = TRU1; /* Don't realpath(3) if it's only an update request */ if (name != NULL) { @@ -174,9 +174,10 @@ _update_mailname(char const *name) if (realpath(name, mailname) == NULL) { fprintf(stderr, tr(151, "Can't canonicalize `%s'\n"), name); rv = FAL0; - goto jleave; + goto jdocopy; } } else +jdocopy: #endif n_strlcpy(mailname, name, sizeof(mailname)); } @@ -197,9 +198,10 @@ _update_mailname(char const *name) /* We want to see the name of the folder .. on the screen */ i = strlen(mailp); - if ((rv = (i < sizeof(displayname) - 1))) + if (i < sizeof(displayname) - 1) memcpy(dispp, mailp, i + 1); else { + rv = FAL0; /* Avoid disrupting multibyte sequences (if possible) */ #ifndef HAVE_C90AMEND1 j = sizeof(displayname) / 3 - 1; @@ -212,9 +214,6 @@ _update_mailname(char const *name) snprintf(dispp, sizeof(displayname), "%.*s...%s", (int)j, mailp, mailp + i); } -#ifdef HAVE_REALPATH -jleave: -#endif return rv; } diff --git a/maildir.c b/maildir.c index 32180bd..3d45f77 100644 --- a/maildir.c +++ b/maildir.c @@ -1,5 +1,5 @@ /*@ S-nail - a mail user agent derived from Berkeley Mail. - *@ Maildir folder support. + *@ Maildir folder support. FIXME rewrite - why do we chdir(2)?? * * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany. * Copyright (c) 2012 - 2014 Steffen "Daode" Nurpmeso . @@ -101,75 +101,87 @@ jleave: ; FL int maildir_setfile(char const * volatile name, int nmail, int isedit) { - sighandler_type volatile saveint; - struct cw cw; - int i = -1, omsgCount; - - (void)&saveint; - (void)&i; - omsgCount = msgCount; - if (cwget(&cw) == STOP) { - fprintf(stderr, "Fatal: Cannot open current directory\n"); - return -1; - } - if (!nmail) - quit(); - saveint = safe_signal(SIGINT, SIG_IGN); - if (chdir(name) < 0) { - fprintf(stderr, "Cannot change directory to \"%s\".\n", name); - cwrelse(&cw); - return -1; - } - if (!nmail) { - edit = (isedit != 0); - if (mb.mb_itf) { - fclose(mb.mb_itf); - mb.mb_itf = NULL; - } - if (mb.mb_otf) { - fclose(mb.mb_otf); - mb.mb_otf = NULL; - } - initbox(name); - mb.mb_type = MB_MAILDIR; - } - _maildir_table = NULL; - if (sigsetjmp(_maildir_jmp, 1) == 0) { - if (nmail) - mktable(); - if (saveint != SIG_IGN) - safe_signal(SIGINT, maildircatch); - i = maildir_setfile1(name, nmail, omsgCount); - } - if (nmail && _maildir_table != NULL) - free(_maildir_table); - safe_signal(SIGINT, saveint); - if (i < 0) { - mb.mb_type = MB_VOID; - *mailname = '\0'; - msgCount = 0; - } - if (cwret(&cw) == STOP) { - fputs("Fatal: Cannot change back to current directory.\n", - stderr); - abort(); - } - cwrelse(&cw); - setmsize(msgCount); - if (nmail && mb.mb_sorted && msgCount > omsgCount) { - mb.mb_threaded = 0; - sort((void *)-1); - } - if (!nmail) - sawcom = FAL0; - if (!nmail && !edit && msgCount == 0) { - if (mb.mb_type == MB_MAILDIR && !ok_blook(emptystart)) - fprintf(stderr, "No mail at %s\n", name); - return 1; - } - if (nmail && msgCount > omsgCount) - newmailinfo(omsgCount); - return 0; + sighandler_type volatile saveint; + struct cw cw; + int i = -1, omsgCount; + + /* TODO ince we have a VOID box... */ + omsgCount = msgCount; + if (cwget(&cw) == STOP) { + fprintf(stderr, "Cannot open current directory"); + goto jleave; + } + + if (!nmail) + quit(); + + saveint = safe_signal(SIGINT, SIG_IGN); + + if (!nmail) { + edit = (isedit != 0); + if (mb.mb_itf) { + fclose(mb.mb_itf); + mb.mb_itf = NULL; + } + if (mb.mb_otf) { + fclose(mb.mb_otf); + mb.mb_otf = NULL; + } + initbox(name); + mb.mb_type = MB_MAILDIR; + } + + if (chdir(name) < 0) { + fprintf(stderr, "Cannot change directory to \"%s\".\n", name);/*TODO tr*/ + mb.mb_type = MB_VOID; + *mailname = '\0'; + msgCount = 0; + cwrelse(&cw); + safe_signal(SIGINT, saveint); + goto jleave; + } + + _maildir_table = NULL; + if (sigsetjmp(_maildir_jmp, 1) == 0) { + if (nmail) + mktable(); + if (saveint != SIG_IGN) + safe_signal(SIGINT, &maildircatch); + i = maildir_setfile1(name, nmail, omsgCount); + } + if (nmail && _maildir_table != NULL) + free(_maildir_table); + + safe_signal(SIGINT, saveint); + + if (i < 0) { + mb.mb_type = MB_VOID; + *mailname = '\0'; + msgCount = 0; + } + + if (cwret(&cw) == STOP) + panic("Cannot change back to current directory.");/* TODO tr */ + cwrelse(&cw); + + setmsize(msgCount); + if (nmail && mb.mb_sorted && msgCount > omsgCount) { + mb.mb_threaded = 0; + sort((void*)-1); + } + if (!nmail) + sawcom = FAL0; + if (!nmail && !edit && msgCount == 0) { + if (mb.mb_type == MB_MAILDIR /* XXX ?? */ && !ok_blook(emptystart)) + fprintf(stderr, tr(258, "No mail at %s\n"), name); + i = 1; + goto jleave; + } + if (nmail && msgCount > omsgCount) + newmailinfo(omsgCount); + i = 0; +jleave: + return i; } static int