X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/d3d8f636ed951b4c02bdeeb146b528fe00dfbb48..ddf3a8574f657dcb8c53fc5908e7bebbde1994b5:/uip/inc.c diff --git a/uip/inc.c b/uip/inc.c index 26cdbe53..c34d28ae 100644 --- a/uip/inc.c +++ b/uip/inc.c @@ -30,19 +30,43 @@ */ #endif -#include -#include +#include "h/mh.h" +#include "sbr/fmt_new.h" +#include "sbr/dtime.h" +#include "scansbr.h" +#include "sbr/m_name.h" +#include "sbr/m_gmprot.h" +#include "sbr/getarguments.h" +#include "sbr/concat.h" +#include "sbr/seq_setunseen.h" +#include "sbr/seq_setcur.h" +#include "sbr/seq_save.h" +#include "sbr/smatch.h" +#include "sbr/getfolder.h" +#include "sbr/ext_hook.h" +#include "sbr/folder_read.h" +#include "sbr/folder_realloc.h" +#include "sbr/folder_free.h" +#include "sbr/context_save.h" +#include "sbr/context_replace.h" +#include "sbr/context_find.h" +#include "sbr/ambigsw.h" +#include "sbr/path.h" +#include "sbr/print_version.h" +#include "sbr/print_help.h" +#include "sbr/error.h" +#include "h/utils.h" #include -#include -#include -#include -#include -#include -#include -#include -#include "../sbr/lock_file.h" -#include "../sbr/m_maildir.h" -#include "../sbr/m_mktemp.h" +#include "h/dropsbr.h" +#include "popsbr.h" +#include "h/fmt_scan.h" +#include "h/signals.h" +#include "h/tws.h" +#include "h/mts.h" +#include "h/done.h" +#include "sbr/lock_file.h" +#include "sbr/m_maildir.h" +#include "sbr/m_mktemp.h" #ifndef TLS_SUPPORT # define TLSminc(a) (a) @@ -72,6 +96,7 @@ X("sasl", 0, SASLSW) \ X("nosasl", 0, NOSASLSW) \ X("saslmech", 0, SASLMECHSW) \ + X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NOTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ @@ -98,14 +123,14 @@ static struct Maildir_entry { time_t mtime; } *Maildir = NULL; static int num_maildir_entries = 0; -static int snoop = 0; +static bool snoop; -extern char response[]; - -static long start; -static long stop; +typedef struct { + FILE *mailout; + long written; +} pop_closure; -static FILE *pf = NULL; +extern char response[]; /* This is an attempt to simplify things by putting all the * privilege ops into macros. @@ -149,17 +174,18 @@ static gid_t return_gid; #endif /* not MAILGROUP */ /* these variables have to be globals so that done() can correctly clean up the lockfile */ -static int locked = 0; +static bool locked; static char *newmail; static FILE *in; /* * prototypes */ +static int maildir_srt(const void *va, const void *vb) PURE; static void inc_done(int) NORETURN; static int pop_action(void *closure, char *); -int +static int maildir_srt(const void *va, const void *vb) { const struct Maildir_entry *a = va, *b = vb; @@ -179,7 +205,9 @@ main (int argc, char **argv) bool noisy; int width = -1; int hghnum = 0, msgnum = 0; - bool sasl, tls, noverify; + FILE *pf = NULL; + bool sasl, noverify; + int tls = 0; int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */ char *cp, *maildir = NULL, *folder = NULL; char *format = NULL, *form = NULL; @@ -191,10 +219,11 @@ main (int argc, char **argv) FILE *aud = NULL; char b[PATH_MAX + 1]; char *maildir_copy = NULL; /* copy of mail directory because the static gets overwritten */ + charstring_t scanl = NULL; int nmsgs, nbytes; char *MAILHOST_env_variable; - done=inc_done; + set_done(inc_done); /* absolutely the first thing we do is save our privileges, * and drop them if we can. @@ -202,7 +231,7 @@ main (int argc, char **argv) SAVEGROUPPRIVS(); TRYDROPGROUPPRIVS(); - if (nmh_init(argv[0], 1)) { return 1; } + if (nmh_init(argv[0], true, true)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); @@ -224,7 +253,7 @@ main (int argc, char **argv) if (pophost && *pophost) host = pophost; - sasl = tls = false; + sasl = false; chgflag = noisy = noverify = true; while ((cp = *argp++)) { if (*cp == '-') { @@ -233,7 +262,7 @@ main (int argc, char **argv) ambigsw (cp, switches); done (1); case UNKWNSW: - adios (NULL, "-%s unknown", cp); + die("-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name); @@ -245,8 +274,8 @@ main (int argc, char **argv) case AUDSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - audfile = getcpy (m_maildir (cp)); + die("missing argument to %s", argp[-2]); + audfile = mh_xstrdup(m_maildir(cp)); continue; case NAUDSW: audfile = NULL; @@ -275,7 +304,7 @@ main (int argc, char **argv) case FILESW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); from = path (cp, TFILE); /* @@ -295,38 +324,38 @@ main (int argc, char **argv) case FORMSW: if (!(form = *argp++) || *form == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); form = NULL; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); width = atoi (cp); continue; case HOSTSW: if (!(host = *argp++) || *host == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case PORTSW: if (!(port = *argp++) || *port == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case USERSW: if (!(user = *argp++) || *user == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; case SNOOPSW: - snoop++; + snoop = true; continue; case SASLSW: @@ -338,15 +367,19 @@ main (int argc, char **argv) case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); + continue; + + case TLSSW: + tls = 1; continue; case INITTLSSW: - tls = true; + tls = 2; continue; case NOTLSSW: - tls = false; + tls = 0; continue; case CERTVERSW: @@ -360,25 +393,24 @@ main (int argc, char **argv) case AUTHSERVICESW: #ifdef OAUTH_SUPPORT if (!(auth_svc = *argp++) || *auth_svc == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); #else - adios (NULL, "not built with OAuth support"); + die("not built with OAuth support"); #endif continue; case PROXYSW: if (!(proxy = *argp++) || *proxy == '-') - adios (NULL, "missing argument to %s", argp[-2]); + die("missing argument to %s", argp[-2]); continue; } } if (*cp == '+' || *cp == '@') { if (folder) - adios (NULL, "only one folder at a time!"); - else - folder = pluspath (cp); + die("only one folder at a time!"); + folder = pluspath (cp); } else { - adios (NULL, "usage: %s [+folder] [switches]", invo_name); + die("usage: %s [+folder] [switches]", invo_name); } } @@ -400,16 +432,18 @@ main (int argc, char **argv) if (auth_svc == NULL) { if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { - adios (NULL, "must specify -authservice with -saslmech xoauth2"); + die("must specify -authservice with -saslmech xoauth2"); } } else { if (user == NULL) { - adios (NULL, "must specify -user with -saslmech xoauth2"); + die("must specify -user with -saslmech xoauth2"); } } - if (tls) - tlsflag |= P_INITTLS; + if (tls == 1) + tlsflag = P_STARTTLS; + else if (tls == 2) + tlsflag = P_INITTLS; if (noverify) tlsflag |= P_NOVERIFY; @@ -419,15 +453,15 @@ main (int argc, char **argv) */ if (pop_init (host, port, user, proxy, snoop, sasl, saslmech, tlsflag, auth_svc) == NOTOK) - adios (NULL, "%s", response); + die("%s", response); /* Check if there are any messages */ if (pop_stat (&nmsgs, &nbytes) == NOTOK) - adios (NULL, "%s", response); + die("%s", response); if (nmsgs == 0) { pop_quit(); - adios (NULL, "no mail to incorporate"); + die("no mail to incorporate"); } } else if (inc_type == INC_FILE) { @@ -442,56 +476,56 @@ main (int argc, char **argv) newmail = concat (MAILDIR, "/", MAILFIL, NULL); } if (stat (newmail, &s1) == NOTOK || s1.st_size == 0) - adios (NULL, "no mail to incorporate"); - if (s1.st_mode & S_IFDIR) { - DIR *md; - struct dirent *de; - struct stat ms; - int i; - i = 0; - cp = concat (newmail, "/new", NULL); - if ((md = opendir(cp)) == NULL) - adios (NULL, "unable to open %s", cp); - while ((de = readdir (md)) != NULL) { - if (de->d_name[0] == '.') - continue; - if (i >= num_maildir_entries) { - if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL) - adios(NULL, "not enough memory for %d messages", 2*i+16); - num_maildir_entries = 2*i+16; - } - Maildir[i].filename = concat (cp, "/", de->d_name, NULL); - if (stat(Maildir[i].filename, &ms) != 0) - adios (Maildir[i].filename, "couldn't get delivery time"); - Maildir[i].mtime = ms.st_mtime; - i++; - } - free (cp); - closedir (md); - cp = concat (newmail, "/cur", NULL); - if ((md = opendir(cp)) == NULL) - adios (NULL, "unable to open %s", cp); - while ((de = readdir (md)) != NULL) { - if (de->d_name[0] == '.') - continue; - if (i >= num_maildir_entries) { - if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL) - adios(NULL, "not enough memory for %d messages", 2*i+16); - num_maildir_entries = 2*i+16; - } - Maildir[i].filename = concat (cp, "/", de->d_name, NULL); - if (stat(Maildir[i].filename, &ms) != 0) - adios (Maildir[i].filename, "couldn't get delivery time"); - Maildir[i].mtime = ms.st_mtime; - i++; - } - free (cp); - closedir (md); - if (i == 0) - adios (NULL, "no mail to incorporate"); - num_maildir_entries = i; - qsort (Maildir, num_maildir_entries, sizeof(*Maildir), maildir_srt); - } + die("no mail to incorporate"); + if (s1.st_mode & S_IFDIR) { + DIR *md; + struct dirent *de; + struct stat ms; + int i; + i = 0; + cp = concat (newmail, "/new", NULL); + if ((md = opendir(cp)) == NULL) + die("unable to open %s", cp); + while ((de = readdir (md)) != NULL) { + if (de->d_name[0] == '.') + continue; + if (i >= num_maildir_entries) { + if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL) + die("not enough memory for %d messages", 2*i+16); + num_maildir_entries = 2*i+16; + } + Maildir[i].filename = concat (cp, "/", de->d_name, NULL); + if (stat(Maildir[i].filename, &ms) != 0) + adios (Maildir[i].filename, "couldn't get delivery time"); + Maildir[i].mtime = ms.st_mtime; + i++; + } + free (cp); + closedir (md); + cp = concat (newmail, "/cur", NULL); + if ((md = opendir(cp)) == NULL) + die("unable to open %s", cp); + while ((de = readdir (md)) != NULL) { + if (de->d_name[0] == '.') + continue; + if (i >= num_maildir_entries) { + if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL) + die("not enough memory for %d messages", 2*i+16); + num_maildir_entries = 2*i+16; + } + Maildir[i].filename = concat (cp, "/", de->d_name, NULL); + if (stat(Maildir[i].filename, &ms) != 0) + adios (Maildir[i].filename, "couldn't get delivery time"); + Maildir[i].mtime = ms.st_mtime; + i++; + } + free (cp); + closedir (md); + if (i == 0) + die("no mail to incorporate"); + num_maildir_entries = i; + qsort (Maildir, num_maildir_entries, sizeof(*Maildir), maildir_srt); + } cp = mh_xstrdup(newmail); newmail = cp; @@ -519,13 +553,13 @@ main (int argc, char **argv) /* read folder and create message structure */ if (!(mp = folder_read (folder, 0))) - adios (NULL, "unable to read folder %s", folder); + die("unable to read folder %s", folder); if (inc_type == INC_FILE && Maildir == NULL) { /* Mail from a spool file. */ if (access (newmail, W_OK) != NOTOK) { - locked++; + locked = true; if (trnflag) { SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGINT, SIG_IGN); @@ -537,7 +571,7 @@ main (int argc, char **argv) in = lkfopenspool (newmail, "r"); DROPGROUPPRIVS(); if (in == NULL) - adios (NULL, "unable to lock and fopen %s", newmail); + die("unable to lock and fopen %s", newmail); fstat (fileno(in), &s1); } else { trnflag = 0; @@ -555,14 +589,14 @@ main (int argc, char **argv) inform("Creating Receive-Audit: %s", audfile); if ((aud = fopen (audfile, "a")) == NULL) adios (audfile, "unable to append to"); - else if (i == NOTOK) + if (i == NOTOK) chmod (audfile, m_gmprot ()); if (from) fprintf (aud, "<> %s -ms %s\n", dtimenow(0), from); else { if (host) - fprintf (aud, "<> %s -host %s -user %s\n", dtimenow(0), + fprintf (aud, "<> %s -host %s -user %s\n", dtimenow(0), host, user); else fprintf (aud, "<> %s\n", dtimenow (0)); @@ -584,27 +618,28 @@ main (int argc, char **argv) if (inc_type == INC_POP) { /* Mail from a POP server. */ int i; + pop_closure pc; hghnum = msgnum = mp->hghmsg; for (i = 1; i <= nmsgs; i++) { - charstring_t scanl = NULL; msgnum++; cp = mh_xstrdup(m_name (msgnum)); if ((pf = fopen (cp, "w+")) == NULL) adios (cp, "unable to write"); chmod (cp, m_gmprot ()); - start = stop = 0L; - if (pop_retr(i, pop_action, NULL) == NOTOK) - adios (NULL, "%s", response); + pc.written = 0; + pc.mailout = pf; + if (pop_retr(i, pop_action, &pc) == NOTOK) + die("%s", response); if (fflush (pf)) adios (cp, "write error on"); fseek (pf, 0L, SEEK_SET); switch (incerr = scan (pf, msgnum, 0, nfs, width, msgnum == mp->hghmsg + 1 && chgflag, - 1, NULL, stop - start, noisy, &scanl)) { + 1, NULL, pc.written, noisy, &scanl)) { case SCNEOF: printf ("%*d empty\n", DMAXFOLDER, msgnum); break; @@ -620,7 +655,6 @@ main (int argc, char **argv) break; case SCNMSG: - case SCNENC: default: if (aud) fputs (charstring_buffer (scanl), aud); @@ -628,7 +662,9 @@ main (int argc, char **argv) fflush (stdout); break; } - charstring_free (scanl); + + if (scanl) + charstring_clear (scanl); if (ferror(pf) || fclose (pf)) { int e = errno; @@ -640,13 +676,16 @@ main (int argc, char **argv) free (cp); if (trnflag && pop_dele (i) == NOTOK) - adios (NULL, "%s", response); + die("%s", response); scan_finished(); } + charstring_free (scanl); + scanl = NULL; + if (pop_quit () == NOTOK) - adios (NULL, "%s", response); + die("%s", response); } else if (inc_type == INC_FILE && Maildir == NULL) { /* Mail from a spool file. */ @@ -654,8 +693,6 @@ main (int argc, char **argv) scan_detect_mbox_style (in); /* the MAGIC invocation... */ hghnum = msgnum = mp->hghmsg; for (;;) { - charstring_t scanl = NULL; - /* create scanline for new message */ switch (incerr = scan (in, msgnum + 1, msgnum + 1, nfs, width, msgnum == hghnum && chgflag, 1, NULL, 0L, noisy, @@ -679,7 +716,6 @@ main (int argc, char **argv) break; case SCNMSG: - case SCNENC: /* * Run the external program hook on the message. */ @@ -692,16 +728,18 @@ main (int argc, char **argv) if (noisy) fflush (stdout); + charstring_clear (scanl); msgnum++; continue; } - charstring_free (scanl); /* If we get here there was some sort of error from scan(), * so stop processing anything more from the spool. */ break; } + charstring_free (scanl); + scanl = NULL; } else { /* Mail from Maildir. */ @@ -711,8 +749,6 @@ main (int argc, char **argv) hghnum = msgnum = mp->hghmsg; for (i = 0; i < num_maildir_entries; i++) { - charstring_t scanl = NULL; - msgnum++; sp = Maildir[i].filename; @@ -723,7 +759,7 @@ main (int argc, char **argv) size_t nrd; if ((sf = fopen (sp, "r")) == NULL) - adios (sp, "unable to read for copy"); + adios (sp, "unable to read for copy"); if ((pf = fopen (cp, "w+")) == NULL) adios (cp, "unable to write for copy"); while ((nrd = fread(buf, 1, sizeof(buf), sf)) > 0) @@ -745,7 +781,7 @@ main (int argc, char **argv) fseek (pf, 0L, SEEK_SET); switch (incerr = scan (pf, msgnum, 0, nfs, width, msgnum == mp->hghmsg + 1 && chgflag, - 1, NULL, stop - start, noisy, &scanl)) { + 1, NULL, 0, noisy, &scanl)) { case SCNEOF: printf ("%*d empty\n", DMAXFOLDER, msgnum); break; @@ -761,7 +797,6 @@ main (int argc, char **argv) break; case SCNMSG: - case SCNENC: default: /* * Run the external program hook on the message. @@ -776,7 +811,7 @@ main (int argc, char **argv) fflush (stdout); break; } - charstring_free (scanl); + charstring_clear (scanl); if (ferror(pf) || fclose (pf)) { int e = errno; @@ -794,6 +829,8 @@ main (int argc, char **argv) scan_finished(); } free (Maildir); /* From now on Maildir is just a flag - don't dref! */ + charstring_free (scanl); + scanl = NULL; } scan_finished (); @@ -806,7 +843,7 @@ main (int argc, char **argv) } else { fclose (in); in = NULL; } - adios (NULL, "failed"); + die("failed"); } if (aud) @@ -837,7 +874,7 @@ main (int argc, char **argv) if (msgnum == hghnum) { inform("no messages incorporated, continuing..."); } else { - /* + /* * Lock the sequence file now, and loop to set the right flags * in the folder structure */ @@ -904,7 +941,7 @@ skip: static void NORETURN inc_done (int status) { - done = exit; + set_done(exit); if (locked) { GETGROUPPRIVS(); @@ -917,8 +954,14 @@ inc_done (int status) static int pop_action(void *closure, char *s) { - NMH_UNUSED(closure); - fprintf (pf, "%s\n", s); - stop += strlen (s) + 1; - return 0; /* Is return value used? This was missing before 1999-07-15. */ + pop_closure *pc; + int n; + + pc = closure; + n = fprintf(pc->mailout, "%s\n", s); + if (n < 0) + return NOTOK; + pc->written += n; /* Count linefeed too. */ + + return OK; }