## nmh _does_ have a test suite!
##
TESTS_ENVIRONMENT = MH_OBJ_DIR="@abs_builddir@" \
+ MH_VERSION="$(VERSION)" \
+ OAUTH_SUPPORT='@OAUTH_SUPPORT@' \
+ CURL_USER_AGENT='@CURL_USER_AGENT@' \
MH_TEST_DIR="@abs_builddir@/test/testdir" \
nmhlibexecdir="$(nmhlibexecdir)" bindir="$(bindir)" \
mandir="$(mandir)" nmhetcdir="$(nmhetcdir)" \
test/mhshow/test-subpart test/mhshow/test-msg-buffer-boundaries \
test/mhstore/test-mhstore test/mkstemp/test-mkstemp \
test/new/test-basic test/pick/test-pick test/pick/test-stderr \
+ test/oauth/test-mhlogin test/oauth/test-mhparam test/oauth/test-send \
+ test/oauth/test-inc test/oauth/test-share \
test/post/test-post-aliases test/post/test-post-basic \
test/post/test-post-multiple test/post/test-post-bcc \
test/post/test-post-dcc test/post/test-post-fcc \
check_SCRIPTS = test/common.sh
check_PROGRAMS = test/getfullname test/getcanon test/fakepop test/fakesmtp \
- test/getcwidth
+ test/getcwidth test/fakehttp
## The location of installed nmhetcdir is, for all purposes except
## distcheck, $nmhetcdir. For distcheck, prepend $MH_INST_DIR (from
uip/mhparam uip/mhpath uip/mhshow uip/mhstore uip/msgchk \
uip/new uip/packf uip/pick uip/prompter uip/refile \
uip/repl uip/rmf uip/rmm uip/scan uip/send uip/show uip/sortm \
- uip/whatnow uip/whom
+ uip/whatnow uip/whom uip/mhlogin
bin_SCRIPTS = uip/mhmail etc/sendfiles
h/mh.h h/mhcachesbr.h h/mhparse.h h/mime.h \
h/mts.h h/nmh.h h/picksbr.h h/popsbr.h h/prototypes.h \
h/rcvmail.h h/scansbr.h h/signals.h h/tws.h h/utils.h \
- mts/smtp/smtp.h sbr/ctype-checked.h
+ mts/smtp/smtp.h sbr/ctype-checked.h h/oauth.h \
+ thirdparty/jsmn/jsmn.h
##
## Extra files we need to install in various places
man/prompter.1 man/rcvdist.1 man/rcvpack.1 man/rcvstore.1 \
man/rcvtty.1 man/refile.1 man/repl.1 man/rmf.1 man/rmm.1 \
man/scan.1 man/send.1 man/sendfiles.1 man/show.1 man/slocal.1 \
- man/sortm.1 man/unseen.1 man/whatnow.1 man/whom.1
+ man/sortm.1 man/unseen.1 man/whatnow.1 man/whom.1 man/mhlogin.1
##
## Sources for our man pages
man/rcvstore.man man/rcvtty.man man/refile.man man/repl.man \
man/rmf.man man/rmm.man man/scan.man man/send.man \
man/sendfiles.man man/show.man man/slocal.man man/sortm.man \
- man/unseen.man man/whatnow.man man/whom.man
+ man/unseen.man man/whatnow.man man/whom.man man/mhlogin.man
##
## Files we need to include in the distribution which aren't found by
test/mhbuild/somebinary \
test/mhbuild/nulls \
test/mhbuild/textplain \
- test/post/test-post-common.sh test/valgrind.supp uip/mhmail \
+ test/post/test-post-common.sh test/valgrind.supp \
+ test/oauth/common.sh \
+ uip/mhmail \
SPECS/nmh.spec SPECS/build-nmh-cygwin $(man_SRCS)
##
uip_comp_SOURCES = uip/comp.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c
-uip_comp_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
+uip_comp_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(CURLLIB) $(POSTLINK)
uip_dist_SOURCES = uip/dist.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c uip/forwsbr.c
-uip_dist_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
+uip_dist_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(CURLLIB) $(POSTLINK)
uip_flist_SOURCES = uip/flist.c
uip_flist_LDADD = $(LDADD) $(POSTLINK)
uip_forw_SOURCES = uip/forw.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c uip/forwsbr.c
-uip_forw_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
+uip_forw_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(CURLLIB) $(POSTLINK)
uip_inc_SOURCES = uip/inc.c uip/scansbr.c uip/dropsbr.c uip/popsbr.c
-uip_inc_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(SASLLIB) $(POSTLINK)
+uip_inc_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(SASLLIB) $(CURLLIB) $(POSTLINK)
uip_install_mh_SOURCES = uip/install-mh.c
uip_install_mh_LDADD = $(LDADD) $(POSTLINK)
uip_mhstore_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
uip_msgchk_SOURCES = uip/msgchk.c uip/popsbr.c
-uip_msgchk_LDADD = $(LDADD) $(SASLLIB) $(POSTLINK)
+uip_msgchk_LDADD = $(LDADD) $(SASLLIB) $(CURLLIB) $(POSTLINK)
uip_new_SOURCES = uip/new.c
uip_new_LDADD = $(LDADD) $(POSTLINK)
uip_repl_SOURCES = uip/repl.c uip/replsbr.c uip/whatnowproc.c uip/whatnowsbr.c \
uip/sendsbr.c uip/annosbr.c uip/distsbr.c
-uip_repl_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
+uip_repl_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(CURLLIB) $(POSTLINK)
uip_rmf_SOURCES = uip/rmf.c
uip_rmf_LDADD = $(LDADD) $(POSTLINK)
uip_send_SOURCES = uip/send.c uip/sendsbr.c uip/annosbr.c \
uip/distsbr.c
-uip_send_LDADD = $(LDADD) $(POSTLINK)
+uip_send_LDADD = $(LDADD) $(CURLLIB) $(POSTLINK)
uip_show_SOURCES = uip/show.c uip/mhlsbr.c
uip_show_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
uip_whatnow_SOURCES = uip/whatnow.c uip/whatnowsbr.c uip/sendsbr.c \
uip/annosbr.c uip/distsbr.c
-uip_whatnow_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(POSTLINK)
+uip_whatnow_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(CURLLIB) $(POSTLINK)
uip_whom_SOURCES = uip/whom.c uip/distsbr.c
uip_whom_LDADD = $(LDADD) $(POSTLINK)
uip_mhl_SOURCES = uip/mhl.c uip/mhlsbr.c
uip_mhl_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK)
+uip_mhlogin_SOURCES = uip/mhlogin.c
+uip_mhlogin_LDADD = mts/libmts.a $(LDADD) $(CURLLIB) $(POSTLINK)
+
uip_mkstemp_SOURCES = uip/mkstemp.c
uip_mkstemp_LDADD = $(LDADD) $(POSTLINK)
uip/annosbr.c uip/distsbr.c
uip_viamail_LDADD = $(LDADD) $(POSTLINK)
+##
+## Other program definitions
+##
+
test_getfullname_SOURCES = test/getfullname.c
test_getfullname_LDADD = $(LDADD) $(POSTLINK)
+ ##
+ ## Other program definitions
+ ##
+
test_getcanon_SOURCES = test/getcanon.c
test_getcanon_LDADD = $(POSTLINK)
-test_fakepop_SOURCES = test/fakepop.c
+test_fakepop_SOURCES = test/fakepop.c test/server.c
test_fakepop_LDADD = $(POSTLINK)
-test_fakesmtp_SOURCES = test/fakesmtp.c
+test_fakesmtp_SOURCES = test/fakesmtp.c test/server.c
test_fakesmtp_LDADD = $(POSTLINK)
+test_fakehttp_SOURCES = test/fakehttp.c test/server.c
+test_fakehttp_LDADD = $(POSTLINK)
+
test_getcwidth_SOURCES = test/getcwidth.c
test_getcwidth_LDADD = $(POSTLINK)
etc_gen_ctype_checked_SOURCES = etc/gen-ctype-checked.c
etc_gen_ctype_checked_LDADD = $(POSTLINK)
+docs_contrib_sendfrom_SOURCES = docs/contrib/sendfrom.c
+docs_contrib_sendfrom_LDADD = $(LDADD) $(TERMLIB) $(CURLLIB) $(POSTLINK)
+
##
## Our rebuild rules for files that aren't built via the normal mechanisms
##
## Hard-code the config/version.c target, instead of using $@, so this
## rule works for the distcheck target with Solaris (System V) make.
-docs_contrib_sendfrom_SOURCES = docs/contrib/sendfrom.c
-docs_contrib_sendfrom_LDADD = $(LDADD) $(TERMLIB) $(CURLLIB) $(POSTLINK)
+
## distcheck uses VPATH, causes that make to prepend the VPATH to $@.
config/version.c: Makefile $(srcdir)/config/version.sh
env srcdir="$(srcdir)" sh $(srcdir)/config/version.sh $(VERSION) > ./config/version.c
sbr/error.c sbr/ext_hook.c sbr/fdcompare.c \
sbr/folder_addmsg.c sbr/folder_delmsgs.c \
sbr/folder_free.c sbr/folder_pack.c \
- sbr/folder_read.c sbr/folder_realloc.c sbr/gans.c \
- sbr/getans.c sbr/getanswer.c sbr/getarguments.c \
+ sbr/folder_read.c sbr/folder_realloc.c sbr/read_switch.c \
- sbr/read_switch_multiword.c sbr/read_yes_or_no_if_tty.c sbr/getarguments.c \
++ sbr/read_switch_multiword.c sbr/read_switch_multiword_via_readline.c \
++ sbr/read_yes_or_no_if_tty.c sbr/getarguments.c \
sbr/getcpy.c sbr/geteditor.c sbr/getfolder.c \
- sbr/getpass.c \
+ sbr/getpass.c sbr/read_line.c \
sbr/fmt_addr.c sbr/fmt_compile.c sbr/fmt_new.c \
sbr/fmt_rfc2047.c sbr/fmt_scan.c \
sbr/icalparse.y sbr/icalendar.l sbr/datetime.c \
sbr/trimcpy.c sbr/unquote.c \
sbr/uprf.c sbr/vfgets.c \
sbr/mf.c sbr/utils.c sbr/ctype-checked.c \
- sbr/m_mktemp.c sbr/getansreadline.c sbr/vector.c \
- config/config.c config/version.c sbr/oauth.c \
- sbr/m_mktemp.c sbr/read_switch_multiword_via_readline.c sbr/vector.c \
- config/config.c config/version.c
++ sbr/m_mktemp.c sbr/vector.c sbr/oauth.c \
++ config/config.c config/version.c \
+ thirdparty/jsmn/jsmn.c
##
## Because these files use the definitions in the libmh rule below,
void argsplit_msgarg (struct msgs_array *, char *, char **);
void argsplit_insert (struct msgs_array *, char *, char **);
void arglist_free (char *, char **);
- void ambigsw (char *, struct swit *);
+ void ambigsw (const char *, const struct swit *);
int atooi(char *);
char **brkstring (char *, char *, char *);
struct msgs *folder_read (char *name, int lockflag);
struct msgs *folder_realloc (struct msgs *, int, int);
- int gans (char *, struct swit *);
- char **getans (char *, struct swit *);
+
+ /*
+ * Flush standard output, read a line from standard input into a static buffer,
+ * zero out the newline, and return a pointer to the buffer.
+ * On error, return NULL.
+ */
+ const char *read_line(void);
+
+ /*
+ * Print null-terminated PROMPT to and flush standard output. Read answers from
+ * standard input until one matches an entry in SWITCHES. When one matches,
+ * return its swret field. Return 0 on EOF.
+ */
+ int read_switch(const char *PROMPT, const struct swit *SWITCHES);
+
+ /*
+ * If standard input is not a tty, return 1 without printing anything. Else,
+ * print null-terminated PROMPT to and flush standard output. Read answers from
+ * standard input until one is "yes" or "no", returning 1 for "yes" and 0 for
+ * "no". Also return 0 on EOF.
+ */
+ int read_yes_or_no_if_tty(const char *PROMPT);
+
+ /*
+ * Print null-terminated PROMPT to and flush standard output. Read multi-word
+ * answers from standard input until a first word matches an entry in SWITCHES.
+ * When one matches, return a pointer to an array of pointers to the words.
+ * Return NULL on EOF, interrupt, or other error.
+ */
+ char **read_switch_multiword(const char *PROMPT, const struct swit *SWITCHES);
+
+ /*
+ * Same as read_switch_multiword but using readline(3) for input.
+ */
#ifdef READLINE_SUPPORT
- char **getans_via_readline (char *, struct swit *);
+ char **read_switch_multiword_via_readline (char *, struct swit *);
#endif /* READLINE_SUPPORT */
- int getanswer (char *);
+
char **getarguments (char *, int, char **, int);
/*
void m_pclose(void);
void m_unknown(m_getfld_state_t *, FILE *);
- int makedir (char *);
+ int makedir (const char *);
char *message_id (time_t, int);
/*
int pidstatus (int, FILE *, char *);
char *pluspath(char *);
void print_help (char *, struct swit *, int);
- void print_sw (char *, struct swit *, char *, FILE *);
+ void print_sw (const char *, const struct swit *, char *, FILE *);
void print_version (char *);
void push (void);
char *pwd (void);
char *r1bindex(char *, int);
-void readconfig (struct node **, FILE *, char *, int);
+void readconfig (struct node **, FILE *, const char *, int);
int refile (char **, char *);
void ruserpass (char *, char **, char **);
int remdir (char *);
void seq_setprev (struct msgs *);
void seq_setunseen (struct msgs *, int);
int showfile (char **, char *);
- int smatch(char *, struct swit *);
+ int smatch(const char *, const struct swit *);
/*
* Convert a set of bit flags to printable format.
* from least significant bit to most significant.
*/
char *snprintb (char *buffer, size_t size, unsigned flags, char *bitfield);
- int ssequal (char *, char *);
+ int ssequal (const char *, const char *);
int stringdex (char *, char *);
char *trimcpy (char *);
int unputenv (char *);
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("sasl", SASLminc(5), SASLSW) \
+ X("nosasl", SASLminc(3), NOSASLSW) \
+ X("saslmech", SASLminc(5), SASLMECHSW) \
+ X("authservice", SASLminc(0), AUTHSERVICESW) \
X("proxy command", 0, PROXYSW) \
#define X(sw, minchars, id) id,
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;
int nmsgs, nbytes;
char *MAILHOST_env_variable;
-
done=inc_done;
/* absolutely the first thing we do is save our privileges,
if (!(saslmech = *argp++) || *saslmech == '-')
adios (NULL, "missing argument to %s", argp[-2]);
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]);
if (inc_type == INC_POP) {
struct nmh_creds creds = { 0, 0, 0 };
+ if (auth_svc == NULL) {
+ if (saslmech && ! strcasecmp(saslmech, "xoauth2")) {
+ adios (NULL, "must specify -authservice with -saslmech xoauth2");
+ }
+ nmh_get_credentials (host, user, sasl, &creds);
+ } else {
+ if (user == NULL) {
+ adios (NULL, "must specify -user with -saslmech xoauth2");
+ }
+ creds.user = user;
+ }
+
/*
* initialize POP connection
*/
- nmh_get_credentials (host, user, sasl, &creds);
if (pop_init (host, port, creds.user, creds.password, proxy, snoop,
- sasl, saslmech) == NOTOK)
+ sasl, saslmech, auth_svc) == NOTOK)
adios (NULL, "%s", response);
/* Check if there are any messages */
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);
}
#include <h/mh.h>
#include <fcntl.h>
+#include <h/utils.h>
+#ifdef OAUTH_SUPPORT
+# include <h/oauth.h>
+#endif
#ifndef CYRUS_SASL
# define SASLminc(a) (a)
X("server host", 6, SERVSW) \
X("snoop", 5, SNOOPSW) \
X("sasl", SASLminc(4), SASLSW) \
- X("nosasl", SASLminc(-6), NOSASLSW) \
- X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
- X("saslmech mechanism", SASLminc(-5), SASLMECHSW) \
+ X("nosasl", SASLminc(6), NOSASLSW) \
+ X("saslmaxssf", SASLminc(6), SASLMXSSFSW) \
+ X("saslmech mechanism", SASLminc(6), SASLMECHSW) \
+ X("authservice", SASLminc(0), AUTHSERVICESW) \
X("user username", SASLminc(-4), USERSW) \
X("attach", -6, ATTACHSW) \
X("noattach", -8, NOATTACHSW) \
char *cp, *dfolder = NULL, *maildir = NULL;
char buf[BUFSIZ], **ap, **argp, **arguments, *program;
char *msgs[MAXARGS], **vec;
+ const char *user = NULL, *saslmech = NULL;
struct msgs *mp;
struct stat st;
+ int snoop = 0;
+ char *auth_svc = NULL;
if (nmh_init(argv[0], 1)) { return 1; }
vec[vecp++] = --cp;
continue;
+ case SNOOPSW:
+ snoop++;
+ vec[vecp++] = --cp;
+ continue;
+
case DEBUGSW:
debugsw++; /* fall */
case NFILTSW:
case NMSGDSW:
case WATCSW:
case NWATCSW:
- case SNOOPSW:
case SASLSW:
case NOSASLSW:
case TLSSW:
vec[vecp++] = --cp;
continue;
+ case USERSW:
+ vec[vecp++] = --cp;
+ if (!(cp = *argp++) || *cp == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ vec[vecp++] = cp;
+ user = cp;
+ continue;
+
+ case SASLMECHSW:
+ if (!(saslmech = *argp++) || *saslmech == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ 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 ALIASW:
case FILTSW:
case WIDTHSW:
case CLIESW:
case SERVSW:
- case SASLMECHSW:
case SASLMXSSFSW:
- case USERSW:
case PORTSW:
case MTSSM:
case MTSSW:
adios (msgs[0], "unable to stat draft file");
cp = concat ("Use \"", msgs[0], "\"? ", NULL);
for (status = LISTDSW; status != YESW;) {
- if (!(argp = getans (cp, anyl)))
+ if (!(argp = read_switch_multiword (cp, anyl)))
done (1);
switch (status = smatch (*argp, anyl)) {
case NOSW:
distfile = NULL;
}
+#ifdef OAUTH_SUPPORT
+ 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");
+ }
+
+ vec[vecp++] = "-authservice";
+ if (saslmech && ! strcasecmp(saslmech, "xoauth2")) {
+ vec[vecp++] = mh_oauth_do_xoauth (user, auth_svc, snoop ? stderr : NULL);
+ } else {
+ vec[vecp++] = auth_svc;
+ }
+ }
+#else
+ NMH_UNUSED(auth_svc);
+ NMH_UNUSED(user);
+ NMH_UNUSED(saslmech);
+#endif /* OAUTH_SUPPORT */
+
if (altmsg == NULL || stat (altmsg, &st) == NOTOK) {
st.st_mtime = 0;
st.st_dev = 0;
#include <h/mime.h>
#include <h/utils.h>
+#ifdef OAUTH_SUPPORT
+# include <h/oauth.h>
+#endif
+
#define WHATNOW_SWITCHES \
X("draftfolder +folder", 0, DFOLDSW) \
X("draftmessage msg", 0, DMSGSW) \
snprintf (prompt, sizeof(prompt), myprompt, invo_name);
for (;;) {
#ifdef READLINE_SUPPORT
- if (!(argp = getans_via_readline (prompt, aleqs))) {
+ if (!(argp = read_switch_multiword_via_readline (prompt, aleqs))) {
#else /* ! READLINE_SUPPORT */
- if (!(argp = getans (prompt, aleqs))) {
+ if (!(argp = read_switch_multiword (prompt, aleqs))) {
#endif /* READLINE_SUPPORT */
(void) m_unlink (LINK);
done (1);
X("draftfolder +folder", -6, SDRFSW) \
X("draftmessage msg", -6, SDRMSW) \
X("nodraftfolder", -3, SNDRFSW) \
- X("sasl", SASLminc(-4), SASLSW) \
- X("nosasl", SASLminc(-6), NOSASLSW) \
- X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
- X("saslmech", SASLminc(-5), SASLMECHSW) \
- X("user", SASLminc(-4), USERSW) \
+ X("sasl", SASLminc(4), SASLSW) \
+ X("nosasl", SASLminc(6), NOSASLSW) \
+ X("saslmaxssf", SASLminc(10), SASLMXSSFSW) \
+ X("saslmech", SASLminc(5), SASLMECHSW) \
+ X("authservice", SASLminc(0), AUTHSERVICESW) \
+ X("user username", SASLminc(4), USERSW) \
X("attach fieldname", 6, SNDATTACHSW) \
X("noattach", 0, SNDNOATTACHSW) \
X("attachformat", 7, SNDATTACHFORMAT) \
int vecp, n = 1;
char *cp, buf[BUFSIZ], **argp, *program;
char **arguments, *savearg[MAXARGS], **vec;
+ const char *user = NULL, *saslmech = NULL;
+ char *auth_svc = NULL;
+ int snoop = 0;
struct stat st;
#ifndef lint
case NMSGDSW:
case WATCSW:
case NWATCSW:
- case SNOOPSW:
case SASLSW:
case NOSASLSW:
case TLSSW:
vec[vecp++] = --cp;
continue;
+ case SNOOPSW:
+ snoop++;
+ vec[vecp++] = --cp;
+ continue;
+
+ case AUTHSERVICESW:
+#ifdef OAUTH_SUPPORT
+ if (!(auth_svc = *argp++) || *auth_svc == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+#else
+ NMH_UNUSED (user);
+ NMH_UNUSED (auth_svc);
+ adios (NULL, "not built with OAuth support");
+#endif
+ continue;
+
+ case SASLMECHSW:
+ saslmech = *argp;
+ /* fall thru */
case ALIASW:
case FILTSW:
case WIDTHSW:
case CLIESW:
case SERVSW:
case SASLMXSSFSW:
- case SASLMECHSW:
case USERSW:
case PORTSW:
case MTSSM:
return;
}
vec[vecp++] = cp;
+ user = cp;
continue;
case SDRFSW:
distfile = NULL;
}
+#ifdef OAUTH_SUPPORT
+ 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");
+ }
+
+ vec[vecp++] = "-authservice";
+ if (saslmech && ! strcasecmp(saslmech, "xoauth2")) {
+ vec[vecp++] = mh_oauth_do_xoauth (user, auth_svc, snoop ? stderr : NULL);
+ } else {
+ vec[vecp++] = auth_svc;
+ }
+ }
+#else
+ NMH_UNUSED(saslmech);
+#endif /* OAUTH_SUPPORT */
+
if (altmsg == NULL || stat (altmsg, &st) == NOTOK) {
st.st_mtime = 0;
st.st_dev = 0;