]> diplodocus.org Git - nmh/blobdiff - uip/inc.c
Implement OAuth 2.0 [1] for XOAUTH2 in SMTP [2] and POP3 [3].
[nmh] / uip / inc.c
index 3aa5e50fde06fbf4e579d2bdac13a1e5b741c89e..a4aea3e7d38412ae029fb2e37497b893d6a40bbb 100644 (file)
--- a/uip/inc.c
+++ b/uip/inc.c
@@ -52,6 +52,7 @@
     X("form formatfile", 0, FORMSW) \
     X("format string", 5, FMTSW) \
     X("host hostname", 0, HOSTSW) \
     X("form formatfile", 0, FORMSW) \
     X("format string", 5, FMTSW) \
     X("host hostname", 0, HOSTSW) \
+    X("oauth service", 0, OAUTHSW) \
     X("user username", 0, USERSW) \
     X("pack file", 0, PACKSW) \
     X("nopack", 0, NPACKSW) \
     X("user username", 0, USERSW) \
     X("pack file", 0, PACKSW) \
     X("nopack", 0, NPACKSW) \
@@ -171,7 +172,7 @@ int
 main (int argc, char **argv)
 {
     int chgflag = 1, trnflag = 1;
 main (int argc, char **argv)
 {
     int chgflag = 1, trnflag = 1;
-    int noisy = 1, width = 0;
+    int noisy = 1, width = -1;
     int hghnum = 0, msgnum = 0;
     int sasl = 0;
     int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */
     int hghnum = 0, msgnum = 0;
     int sasl = 0;
     int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */
@@ -185,10 +186,10 @@ 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 */
     FILE *aud = NULL;
     char b[PATH_MAX + 1];
     char *maildir_copy = NULL; /* copy of mail directory because the static gets overwritten */
+    const char *oauth_svc = NULL;
 
     int nmsgs, nbytes;
     char *MAILHOST_env_variable;
 
     int nmsgs, nbytes;
     char *MAILHOST_env_variable;
-
     done=inc_done;
 
 /* absolutely the first thing we do is save our privileges,
     done=inc_done;
 
 /* absolutely the first thing we do is save our privileges,
@@ -197,11 +198,7 @@ main (int argc, char **argv)
     SAVEGROUPPRIVS();
     TRYDROPGROUPPRIVS();
 
     SAVEGROUPPRIVS();
     TRYDROPGROUPPRIVS();
 
-    setlocale(LC_ALL, "");
-    invo_name = r1bindex (argv[0], '/');
-
-    /* read user profile/context */
-    context_read();
+    if (nmh_init(argv[0], 1)) { return 1; }
 
     mts_init (invo_name);
     arguments = getarguments (invo_name, argc, argv, 1);
 
     mts_init (invo_name);
     arguments = getarguments (invo_name, argc, argv, 1);
@@ -317,6 +314,16 @@ main (int argc, char **argv)
                    adios (NULL, "missing argument to %s", argp[-2]);
                continue;
 
                    adios (NULL, "missing argument to %s", argp[-2]);
                continue;
 
+            case OAUTHSW:
+#ifdef OAUTH_SUPPORT
+                if (!(cp = *argp++) || *cp == '-')
+                    adios (NULL, "missing argument to %s", argp[-2]);
+                oauth_svc = cp;
+#else
+                adios (NULL, "not built with OAuth support");
+#endif
+                continue;
+
            case USERSW:
                if (!(user = *argp++) || *user == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
            case USERSW:
                if (!(user = *argp++) || *user == '-')
                    adios (NULL, "missing argument to %s", argp[-2]);
@@ -387,12 +394,20 @@ main (int argc, char **argv)
     if (inc_type == INC_POP) {
        struct nmh_creds creds = { 0, 0, 0 };
 
     if (inc_type == INC_POP) {
        struct nmh_creds creds = { 0, 0, 0 };
 
+       if (oauth_svc == NULL) {
+           nmh_get_credentials (host, user, sasl, &creds);
+       } else {
+           if (user == NULL) {
+               adios (NULL, "must specify -user with -oauth");
+           }
+           creds.user = user;
+       }
+
        /*
         * initialize POP connection
         */
        /*
         * initialize POP connection
         */
-       nmh_get_credentials (host, user, sasl, &creds);
        if (pop_init (host, port, creds.user, creds.password, proxy, snoop,
        if (pop_init (host, port, creds.user, creds.password, proxy, snoop,
-                     sasl, saslmech) == NOTOK)
+                     sasl, saslmech, oauth_svc) == NOTOK)
            adios (NULL, "%s", response);
 
        /* Check if there are any messages */
            adios (NULL, "%s", response);
 
        /* Check if there are any messages */
@@ -591,12 +606,16 @@ go_to_it:
        }
 
        for (i = 1; i <= nmsgs; i++) {
        }
 
        for (i = 1; i <= nmsgs; i++) {
+           charstring_t scanl = NULL;
+
            msgnum++;
            if (packfile) {
                fseek (pf, 0L, SEEK_CUR);
                pos = ftell (pf);
                size = 0;
            msgnum++;
            if (packfile) {
                fseek (pf, 0L, SEEK_CUR);
                pos = ftell (pf);
                size = 0;
-               fwrite (mmdlm1, 1, strlen (mmdlm1), pf);
+               if (fwrite (mmdlm1, 1, strlen (mmdlm1), pf) < strlen (mmdlm1)) {
+                   advise (mmdlm1, "fwrite");
+               }
                start = ftell (pf);
 
                if (pop_retr (i, pop_pack) == NOTOK)
                start = ftell (pf);
 
                if (pop_retr (i, pop_pack) == NOTOK)
@@ -623,7 +642,7 @@ go_to_it:
            }
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              packfile ? 0 : msgnum == mp->hghmsg + 1 && chgflag,
            }
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              packfile ? 0 : msgnum == mp->hghmsg + 1 && chgflag,
-                             1, NULL, stop - start, noisy)) {
+                             1, NULL, stop - start, noisy, &scanl)) {
            case SCNEOF: 
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
            case SCNEOF: 
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
@@ -642,14 +661,18 @@ go_to_it:
            case SCNENC:
            default: 
                if (aud)
            case SCNENC:
            default: 
                if (aud)
-                   fputs (scanl, aud);
+                   fputs (charstring_buffer (scanl), aud);
                if (noisy)
                    fflush (stdout);
                break;
            }
                if (noisy)
                    fflush (stdout);
                break;
            }
+           charstring_free (scanl);
+
            if (packfile) {
                fseek (pf, stop, SEEK_SET);
            if (packfile) {
                fseek (pf, stop, SEEK_SET);
-               fwrite (mmdlm2, 1, strlen (mmdlm2), pf);
+               if (fwrite (mmdlm2, 1, strlen (mmdlm2), pf) < strlen (mmdlm1)) {
+                   advise (mmdlm2, "fwrite");
+               }
                if (fflush (pf) || ferror (pf)) {
                    int e = errno;
                    pop_quit ();
                if (fflush (pf) || ferror (pf)) {
                    int e = errno;
                    pop_quit ();
@@ -660,7 +683,7 @@ go_to_it:
            } else {
                if (ferror(pf) || fclose (pf)) {
                    int e = errno;
            } else {
                if (ferror(pf) || fclose (pf)) {
                    int e = errno;
-                   unlink (cp);
+                   (void) m_unlink (cp);
                    pop_quit ();
                    errno = e;
                    adios (cp, "write error on");
                    pop_quit ();
                    errno = e;
                    adios (cp, "write error on");
@@ -670,6 +693,8 @@ go_to_it:
 
            if (trnflag && pop_dele (i) == NOTOK)
                adios (NULL, "%s", response);
 
            if (trnflag && pop_dele (i) == NOTOK)
                adios (NULL, "%s", response);
+
+           scan_finished();
        }
 
        if (pop_quit () == NOTOK)
        }
 
        if (pop_quit () == NOTOK)
@@ -687,9 +712,12 @@ go_to_it:
        scan_detect_mbox_style (in);            /* the MAGIC invocation... */
        hghnum = msgnum = mp->hghmsg;
        for (;;) {
        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,
            /* 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: 
                break;
            case SCNFAT:
            case SCNEOF: 
                break;
@@ -718,13 +746,15 @@ go_to_it:
                (void)ext_hook("add-hook", b, (char *)0);
 
                if (aud)
                (void)ext_hook("add-hook", b, (char *)0);
 
                if (aud)
-                   fputs (scanl, aud);
+                   fputs (charstring_buffer (scanl), aud);
                if (noisy)
                    fflush (stdout);
 
                msgnum++;
                continue;
            }
                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.
             */
            /* If we get here there was some sort of error from scan(),
             * so stop processing anything more from the spool.
             */
@@ -737,6 +767,8 @@ go_to_it:
 
        hghnum = msgnum = mp->hghmsg;
        for (i = 0; i < num_maildir_entries; i++) {
 
        hghnum = msgnum = mp->hghmsg;
        for (i = 0; i < num_maildir_entries; i++) {
+           charstring_t scanl = NULL;
+
            msgnum++;
 
            sp = Maildir[i].filename;
            msgnum++;
 
            sp = Maildir[i].filename;
@@ -755,7 +787,7 @@ go_to_it:
                        break;
                if (ferror(sf) || fflush(pf) || ferror(pf)) {
                        int e = errno;
                        break;
                if (ferror(sf) || fflush(pf) || ferror(pf)) {
                        int e = errno;
-                       fclose(pf); fclose(sf); unlink(cp);
+                       fclose(pf); fclose(sf); (void) m_unlink(cp);
                        errno = e;
                        adios(cp, "copy error %s -> %s", sp, cp);
                }
                        errno = e;
                        adios(cp, "copy error %s -> %s", sp, cp);
                }
@@ -769,7 +801,7 @@ go_to_it:
            fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
            fseek (pf, 0L, SEEK_SET);
            switch (incerr = scan (pf, msgnum, 0, nfs, width,
                              msgnum == mp->hghmsg + 1 && chgflag,
-                             1, NULL, stop - start, noisy)) {
+                             1, NULL, stop - start, noisy, &scanl)) {
            case SCNEOF: 
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
            case SCNEOF: 
                printf ("%*d  empty\n", DMAXFOLDER, msgnum);
                break;
@@ -795,23 +827,27 @@ go_to_it:
                (void)ext_hook("add-hook", b, (char *)0);
 
                if (aud)
                (void)ext_hook("add-hook", b, (char *)0);
 
                if (aud)
-                   fputs (scanl, aud);
+                   fputs (charstring_buffer (scanl), aud);
                if (noisy)
                    fflush (stdout);
                break;
            }
                if (noisy)
                    fflush (stdout);
                break;
            }
+           charstring_free (scanl);
+
            if (ferror(pf) || fclose (pf)) {
                int e = errno;
            if (ferror(pf) || fclose (pf)) {
                int e = errno;
-               unlink (cp);
+               (void) m_unlink (cp);
                errno = e;
                adios (cp, "write error on");
            }
            pf = NULL;
            free (cp);
 
                errno = e;
                adios (cp, "write error on");
            }
            pf = NULL;
            free (cp);
 
-           if (trnflag && unlink (sp) == NOTOK)
+           if (trnflag && m_unlink (sp) == NOTOK)
                adios (sp, "couldn't unlink");
            free (sp); /* Free Maildir[i]->filename */
                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! */
     }
        }
        free (Maildir); /* From now on Maildir is just a flag - don't dref! */
     }
@@ -851,7 +887,7 @@ go_to_it:
                    close (newfd);
                else
                    admonish (newmail, "error zero'ing");
                    close (newfd);
                else
                    admonish (newmail, "error zero'ing");
-               unlink(map_name(newmail));
+               (void) m_unlink(map_name(newmail));
            }
        } else {
            if (noisy)
            }
        } else {
            if (noisy)
@@ -956,9 +992,9 @@ pop_pack (char *s)
     char buffer[BUFSIZ];
 
     snprintf (buffer, sizeof(buffer), "%s\n", 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;
        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;
        continue;
     fputs (buffer, pf);
     size += strlen (buffer) + 1;