]> diplodocus.org Git - nmh/blobdiff - uip/inc.c
Added warning about when post(1) can't refile(1) a draft.
[nmh] / uip / inc.c
index b76f1cd96d8d04bf33b646ba479b9559a6a9f287..5ce18b624d0d772fcf0ac0e129ce035729d29344 100644 (file)
--- a/uip/inc.c
+++ b/uip/inc.c
@@ -1,6 +1,4 @@
-
-/*
- * inc.c -- incorporate messages from a maildrop into a folder
+/* inc.c -- incorporate messages from a maildrop into a folder
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -8,7 +6,13 @@
  */
 
 #ifdef MAILGROUP
-/* Revised: Sat Apr 14 17:08:17 PDT 1990 (marvit@hplabs)
+/*
+ * Thu Feb 12 21:00 CST 2015            Marcin Cieslak <saper@saper.info>
+ *    Replaced setgid() calls with setegid() so that it works with dot
+ *    locking on FreeBSD.  setegid() should be supported on modern POSIX
+ *    systems.
+ *
+ * Revised: Sat Apr 14 17:08:17 PDT 1990 (marvit@hplabs)
  *    Added hpux hacks to set and reset gid to be "mail" as needed. The reset
  *    is necessary so inc'ed mail is the group of the inc'er, rather than
  *    "mail". We setgid to egid only when [un]locking the mail file. This
 #include <h/tws.h>
 #include <h/mts.h>
 
-#ifndef CYRUS_SASL
-# define SASLminc(a) (a)
+#ifndef TLS_SUPPORT
+# define TLSminc(a) (a)
 #else
-# define SASLminc(a)  0
+# define TLSminc(a)  0
 #endif
 
 #define INC_SWITCHES \
     X("width columns", 0, WIDTHSW) \
     X("version", 0, VERSIONSW) \
     X("help", 0, HELPSW) \
-    X("snoop", -5, SNOOPSW) \
-    X("sasl", SASLminc(-4), SASLSW) \
-    X("nosasl", SASLminc(-6), NOSASLSW) \
-    X("saslmech", SASLminc(-8), SASLMECHSW) \
+    X("snoop", 0, SNOOPSW) \
+    X("sasl", 0, SASLSW) \
+    X("nosasl", 0, NOSASLSW) \
+    X("saslmech", 0, SASLMECHSW) \
+    X("initialtls", TLSminc(-10), INITTLSSW) \
+    X("notls", TLSminc(-5), NOTLSSW) \
+    X("certverify", TLSminc(-10), CERTVERSW) \
+    X("nocertverify", TLSminc(-12), NOCERTVERSW) \
+    X("authservice", 0, AUTHSERVICESW) \
     X("proxy command", 0, PROXYSW) \
 
 #define X(sw, minchars, id) id,
@@ -127,10 +136,16 @@ static FILE *pf = NULL;
  * For setting and returning to "mail" gid
  */
 #ifdef MAILGROUP
-static int return_gid;
+static gid_t return_gid;
 #define TRYDROPGROUPPRIVS() DROPGROUPPRIVS()
-#define DROPGROUPPRIVS() setgid(getgid())
-#define GETGROUPPRIVS() setgid(return_gid)
+#define DROPGROUPPRIVS() \
+    if (setegid(getgid()) != 0) { \
+        adios ("setegid", "unable to restore group to %ld", (long) getgid()); \
+    }
+#define GETGROUPPRIVS() \
+    if (setegid(return_gid) != 0) { \
+        adios ("setegid", "unable to set group to %ld", (long) return_gid); \
+    }
 #define SAVEGROUPPRIVS() return_gid = getegid()
 #else
 /* define *GROUPPRIVS() as null; this avoids having lots of "#ifdef MAILGROUP"s */
@@ -161,24 +176,25 @@ maildir_srt(const void *va, const void *vb)
     const struct Maildir_entry *a = va, *b = vb;
     if (a->mtime > b->mtime)
       return 1;
-    else if (a->mtime < b->mtime)
+    if (a->mtime < b->mtime)
       return -1;
-    else
-      return 0;
+    return 0;
 }
 
 int
 main (int argc, char **argv)
 {
-    int chgflag = 1, trnflag = 1;
-    int noisy = 1, width = 0;
+    bool chgflag;
+    int trnflag = 1;
+    bool noisy;
+    int width = -1;
     int hghnum = 0, msgnum = 0;
-    int sasl = 0;
+    bool sasl, tls, noverify;
     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;
     char *host = NULL, *port = NULL, *user = NULL, *proxy = NULL;
-    char *audfile = NULL, *from = NULL, *saslmech = NULL;
+    char *audfile = NULL, *from = NULL, *saslmech = NULL, *auth_svc = NULL;
     char buf[BUFSIZ], **argp, *nfs, **arguments;
     struct msgs *mp = NULL;
     struct stat st, s1;
@@ -188,7 +204,6 @@ main (int argc, char **argv)
 
     int nmsgs, nbytes;
     char *MAILHOST_env_variable;
-
     done=inc_done;
 
 /* absolutely the first thing we do is save our privileges,
@@ -199,7 +214,7 @@ main (int argc, char **argv)
 
     if (nmh_init(argv[0], 1)) { return 1; }
 
-    mts_init (invo_name);
+    mts_init ();
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
 
@@ -219,16 +234,18 @@ main (int argc, char **argv)
     if (pophost && *pophost)
        host = pophost;
 
+    sasl = tls = false;
+    chgflag = noisy = noverify = true;
     while ((cp = *argp++)) {
        if (*cp == '-') {
            switch (smatch (++cp, switches)) {
-           case AMBIGSW: 
+           case AMBIGSW:
                ambigsw (cp, switches);
                done (1);
-           case UNKWNSW: 
+           case UNKWNSW:
                adios (NULL, "-%s unknown", cp);
 
-           case HELPSW: 
+           case HELPSW:
                snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name);
                print_help (buf, switches, 1);
                done (0);
@@ -236,20 +253,20 @@ main (int argc, char **argv)
                print_version(invo_name);
                done (0);
 
-           case AUDSW: 
+           case AUDSW:
                if (!(cp = *argp++) || *cp == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                audfile = getcpy (m_maildir (cp));
                continue;
-           case NAUDSW: 
+           case NAUDSW:
                audfile = NULL;
                continue;
 
-           case CHGSW: 
-               chgflag++;
+           case CHGSW:
+                chgflag = true;
                continue;
-           case NCHGSW: 
-               chgflag = 0;
+           case NCHGSW:
+                chgflag = false;
                continue;
 
            /*
@@ -259,14 +276,14 @@ main (int argc, char **argv)
             * 1 by default (truncating is default)
             * 0 if -notruncate is given
             */
-           case TRNCSW: 
+           case TRNCSW:
                trnflag = 2;
                continue;
-           case NTRNCSW: 
+           case NTRNCSW:
                trnflag = 0;
                continue;
 
-           case FILESW: 
+           case FILESW:
                if (!(cp = *argp++) || *cp == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                from = path (cp, TFILE);
@@ -279,25 +296,25 @@ main (int argc, char **argv)
                    trnflag = 0;
                continue;
 
-           case SILSW: 
-               noisy = 0;
+           case SILSW:
+                noisy = false;
                continue;
-           case NSILSW: 
-               noisy++;
+           case NSILSW:
+                noisy = true;
                continue;
 
-           case FORMSW: 
+           case FORMSW:
                if (!(form = *argp++) || *form == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                format = NULL;
                continue;
-           case FMTSW: 
+           case FMTSW:
                if (!(format = *argp++) || *format == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                form = NULL;
                continue;
 
-           case WIDTHSW: 
+           case WIDTHSW:
                if (!(cp = *argp++) || *cp == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                width = atoi (cp);
@@ -331,16 +348,42 @@ main (int argc, char **argv)
                continue;
        
            case SASLSW:
-               sasl++;
+                sasl = true;
                continue;
            case NOSASLSW:
-               sasl = 0;
+                sasl = false;
                continue;
        
            case SASLMECHSW:
                if (!(saslmech = *argp++) || *saslmech == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
                continue;
+
+           case INITTLSSW:
+                tls = true;
+               continue;
+
+           case NOTLSSW:
+                tls = false;
+               continue;
+
+           case CERTVERSW:
+                noverify = false;
+               continue;
+
+           case NOCERTVERSW:
+                noverify = true;
+               continue;
+
+           case AUTHSERVICESW:
+#ifdef OAUTH_SUPPORT
+                if (!(auth_svc = *argp++) || *auth_svc == '-')
+                    adios (NULL, "missing argument to %s", argp[-2]);
+#else
+                adios (NULL, "not built with OAuth support");
+#endif
+                continue;
+
            case PROXYSW:
                if (!(proxy = *argp++) || *proxy == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
@@ -363,7 +406,7 @@ main (int argc, char **argv)
     if (host && !*host)
        host = NULL;
 
-    /* guarantee dropping group priveleges; we might not have done so earlier */
+    /* guarantee dropping group privileges; we might not have done so earlier */
     DROPGROUPPRIVS();
 
     /*
@@ -381,14 +424,29 @@ main (int argc, char **argv)
      * a POP server?
      */
     if (inc_type == INC_POP) {
-       struct nmh_creds creds = { 0, 0, 0 };
+       int tlsflag = 0;
+
+       if (auth_svc == NULL) {
+           if (saslmech  &&  ! strcasecmp(saslmech, "xoauth2")) {
+               adios (NULL, "must specify -authservice with -saslmech xoauth2");
+           }
+       } else {
+           if (user == NULL) {
+               adios (NULL, "must specify -user with -saslmech xoauth2");
+           }
+       }
+
+       if (tls)
+           tlsflag |= P_INITTLS;
+
+       if (noverify)
+           tlsflag |= P_NOVERIFY;
 
        /*
         * initialize POP connection
         */
-       nmh_get_credentials (host, user, sasl, &creds);
-       if (pop_init (host, port, creds.user, creds.password, proxy, snoop,
-                     sasl, saslmech) == NOTOK)
+       if (pop_init (host, port, user, proxy, snoop, sasl, saslmech,
+                     tlsflag, auth_svc) == NOTOK)
            adios (NULL, "%s", response);
 
        /* Check if there are any messages */
@@ -468,9 +526,7 @@ main (int argc, char **argv)
            qsort (Maildir, num_maildir_entries, sizeof(*Maildir), maildir_srt);
        }
 
-       if ((cp = strdup(newmail)) == (char *)0)
-           adios (NULL, "error allocating memory to copy newmail");
-
+       cp = mh_xstrdup(newmail);
        newmail = cp;
     }
 
@@ -483,9 +539,7 @@ main (int argc, char **argv)
     if (!folder)
        folder = getfolder (0);
     maildir = m_maildir (folder);
-
-    if ((maildir_copy = strdup(maildir)) == (char *)0)
-        adios (maildir, "error allocating memory to copy maildir");
+    maildir_copy = mh_xstrdup(maildir);
 
     if (!folder_exists(maildir)) {
         /* If the folder doesn't exist, and we're given the -silent flag,
@@ -535,7 +589,7 @@ go_to_it:
     if (audfile) {
        int i;
        if ((i = stat (audfile, &st)) == NOTOK)
-           advise (NULL, "Creating Receive-Audit: %s", audfile);
+           inform("Creating Receive-Audit: %s", audfile);
        if ((aud = fopen (audfile, "a")) == NULL)
            adios (audfile, "unable to append to");
        else if (i == NOTOK)
@@ -572,7 +626,7 @@ go_to_it:
                if (errno != ENOENT)
                    adios (packfile, "error on file");
                cp = concat ("Create file \"", packfile, "\"? ", NULL);
-               if (noisy && !getanswer (cp))
+               if (noisy && !read_yes_or_no_if_tty (cp))
                    done (1);
                free (cp);
            }
@@ -587,12 +641,18 @@ go_to_it:
        }
 
        for (i = 1; i <= nmsgs; i++) {
+           charstring_t scanl = NULL;
+
            msgnum++;
            if (packfile) {
+                size_t len;
+
                fseek (pf, 0L, SEEK_CUR);
                pos = ftell (pf);
                size = 0;
-               fwrite (mmdlm1, 1, strlen (mmdlm1), pf);
+                len = strlen(mmdlm1);
+               if (fwrite(mmdlm1, 1, len, pf) < len)
+                   advise (mmdlm1, "fwrite");
                start = ftell (pf);
 
                if (pop_retr (i, pop_pack) == NOTOK)
@@ -604,7 +664,7 @@ go_to_it:
                    adios (packfile, "write error on");
                fseek (pf, start, SEEK_SET);
            } else {
-               cp = getcpy (m_name (msgnum));
+               cp = mh_xstrdup(m_name (msgnum));
                if ((pf = fopen (cp, "w+")) == NULL)
                    adios (cp, "unable to write");
                chmod (cp, m_gmprot ());
@@ -619,8 +679,8 @@ go_to_it:
            }
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              packfile ? 0 : msgnum == mp->hghmsg + 1 && chgflag,
-                             1, NULL, stop - start, noisy)) {
-           case SCNEOF: 
+                             1, NULL, stop - start, noisy, &scanl)) {
+           case SCNEOF:
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
 
@@ -628,24 +688,30 @@ go_to_it:
                trnflag = 0;
                noisy++;
                /* advise (cp, "unable to read"); already advised */
-               /* fall thru */
+               /* FALLTHRU */
 
            case SCNERR:
-           case SCNNUM: 
+           case SCNNUM:
                break;
 
-           case SCNMSG: 
+           case SCNMSG:
            case SCNENC:
-           default: 
+           default:
                if (aud)
-                   fputs (scanl, aud);
+                   fputs (charstring_buffer (scanl), aud);
                if (noisy)
                    fflush (stdout);
                break;
            }
+           charstring_free (scanl);
+
            if (packfile) {
+                size_t len;
+
                fseek (pf, stop, SEEK_SET);
-               fwrite (mmdlm2, 1, strlen (mmdlm2), pf);
+                len = strlen(mmdlm2);
+               if (fwrite(mmdlm2, 1, len, pf) < len)
+                   advise (mmdlm2, "fwrite");
                if (fflush (pf) || ferror (pf)) {
                    int e = errno;
                    pop_quit ();
@@ -666,6 +732,8 @@ go_to_it:
 
            if (trnflag && pop_dele (i) == NOTOK)
                adios (NULL, "%s", response);
+
+           scan_finished();
        }
 
        if (pop_quit () == NOTOK)
@@ -683,25 +751,28 @@ go_to_it:
        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)) {
+                             msgnum == hghnum && chgflag, 1, NULL, 0L, noisy,
+                             &scanl)) {
            case SCNFAT:
-           case SCNEOF: 
+           case SCNEOF:
                break;
 
            case SCNERR:
                if (aud)
                    fputs ("inc aborted!\n", aud);
-               advise (NULL, "aborted!");      /* doesn't clean up locks! */
+               inform("aborted!");     /* doesn't clean up locks! */
                break;
 
-           case SCNNUM: 
-               advise (NULL, "BUG in %s, number out of range", invo_name);
+           case SCNNUM:
+               inform("BUG in %s, number out of range", invo_name);
                break;
 
-           default: 
-               advise (NULL, "BUG in %s, scan() botch (%d)", invo_name, incerr);
+           default:
+               inform("BUG in %s, scan() botch (%d)", invo_name, incerr);
                break;
 
            case SCNMSG:
@@ -711,16 +782,18 @@ go_to_it:
                 */
 
                (void)snprintf(b, sizeof (b), "%s/%d", maildir_copy, msgnum + 1);
-               (void)ext_hook("add-hook", b, (char *)0);
+               (void)ext_hook("add-hook", b, NULL);
 
                if (aud)
-                   fputs (scanl, aud);
+                   fputs (charstring_buffer (scanl), aud);
                if (noisy)
                    fflush (stdout);
 
                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.
             */
@@ -733,10 +806,12 @@ go_to_it:
 
        hghnum = msgnum = mp->hghmsg;
        for (i = 0; i < num_maildir_entries; i++) {
+           charstring_t scanl = NULL;
+
            msgnum++;
 
            sp = Maildir[i].filename;
-           cp = getcpy (m_name (msgnum));
+           cp = mh_xstrdup(m_name (msgnum));
            pf = NULL;
            if (!trnflag || link(sp, cp) == -1) {
                static char buf[65536];
@@ -757,7 +832,7 @@ go_to_it:
                }
                fclose (sf);
                sf = NULL;
-           } 
+           }
            if (pf == NULL && (pf = fopen (cp, "r")) == NULL)
                adios (cp, "not available");
            chmod (cp, m_gmprot ());
@@ -765,8 +840,8 @@ go_to_it:
            fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
-                             1, NULL, stop - start, noisy)) {
-           case SCNEOF: 
+                             1, NULL, stop - start, noisy, &scanl)) {
+           case SCNEOF:
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
 
@@ -774,28 +849,30 @@ go_to_it:
                trnflag = 0;
                noisy++;
                /* advise (cp, "unable to read"); already advised */
-               /* fall thru */
+               /* FALLTHRU */
 
            case SCNERR:
-           case SCNNUM: 
+           case SCNNUM:
                break;
 
-           case SCNMSG: 
+           case SCNMSG:
            case SCNENC:
-           default: 
+           default:
                /*
                 *  Run the external program hook on the message.
                 */
 
                (void)snprintf(b, sizeof (b), "%s/%d", maildir_copy, msgnum + 1);
-               (void)ext_hook("add-hook", b, (char *)0);
+               (void)ext_hook("add-hook", b, NULL);
 
                if (aud)
-                   fputs (scanl, aud);
+                   fputs (charstring_buffer (scanl), aud);
                if (noisy)
                    fflush (stdout);
                break;
            }
+           charstring_free (scanl);
+
            if (ferror(pf) || fclose (pf)) {
                int e = errno;
                (void) m_unlink (cp);
@@ -808,6 +885,8 @@ go_to_it:
            if (trnflag && m_unlink (sp) == NOTOK)
                adios (sp, "couldn't unlink");
            free (sp); /* Free Maildir[i]->filename */
+
+           scan_finished();
        }
        free (Maildir); /* From now on Maildir is just a flag - don't dref! */
     }
@@ -840,7 +919,7 @@ go_to_it:
     if (inc_type == INC_FILE && Maildir == NULL) {
        if (trnflag) {
            if (stat (newmail, &st) != NOTOK && s1.st_mtime != st.st_mtime)
-               advise (NULL, "new messages have arrived!\007");
+               inform("new messages have arrived!\007");
            else {
                int newfd;
                if ((newfd = creat (newmail, 0600)) != NOTOK)
@@ -856,7 +935,7 @@ go_to_it:
     }
 
     if (msgnum == hghnum) {
-       admonish (NULL, "no messages incorporated");
+       inform("no messages incorporated, continuing...");
     } else {
        /*
         * Lock the sequence file now, and loop to set the right flags
@@ -869,7 +948,7 @@ go_to_it:
        context_replace (pfolder, folder);      /* update current folder */
 
        if ((mp2 = folder_read(folder, 1)) == NULL) {
-           admonish(NULL, "Unable to reread folder %s", folder);
+           inform("Unable to reread folder %s, continuing...", folder);
            goto skip;
        }
 
@@ -879,7 +958,7 @@ go_to_it:
 
        if (msgnum >= mp2->hghoff
                && !(mp2 = folder_realloc (mp2, mp2->lowoff, msgnum + 1))) {
-           advise (NULL, "unable to reallocate folder storage");
+           inform("unable to reallocate folder storage");
            goto skip;
        }
 
@@ -926,6 +1005,7 @@ skip:
 static void
 inc_done (int status)
 {
+    done = exit;
     if (packfile && pd != NOTOK)
        mbx_close (packfile, pd);
     if (locked)
@@ -952,9 +1032,9 @@ pop_pack (char *s)
     char buffer[BUFSIZ];
 
     snprintf (buffer, sizeof(buffer), "%s\n", s);
-    for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++)
+    for ( ; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++)
        continue;
-    for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++)
+    for ( ; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++)
        continue;
     fputs (buffer, pf);
     size += strlen (buffer) + 1;