int pop_exists (int (*)());
#endif
-int pop_init (char *, char *, char *, int, int, int, int, char *);
+int pop_init (char *, char *, char *, char *, int, int, int, int, char *);
int pop_fd (char *, int, char *, int);
int pop_stat (int *, int *);
int pop_retr (int, int (*)());
.RB [ \-pack
.IR file ]
.RB [ \-nopack ]
+.RB [ \-proxy
+.IR command ]
.RB [ \-apop " | " \-noapop ]
.RB [ \-kpop ]
.RB [ \-sasl ]
.RI \*(lq .netrc \*(rq
file should be owned and readable only by you.
.PP
+If passed the
+.B \-proxy
+.I command
+switch,
+.B inc
+will use the specified command to establish the connection to the POP
+server. The string
+.IR %h
+in the command will be substituted by the hostname to connect to.
+.PP
If
.B inc
uses POP, then the
{ "sasl", SASLminc(-4) },
#define SASLMECHSW 25
{ "saslmech", SASLminc(-8) },
+#define PROXYSW 26
+ { "proxy command", POPminc(-5) },
{ NULL, 0 }
};
int kpop = 0, sasl = 0;
char *cp, *maildir, *folder = NULL;
char *format = NULL, *form = NULL;
- char *host = NULL, *user = NULL;
+ char *host = NULL, *user = NULL, *proxy = NULL;
char *audfile = NULL, *from = NULL, *saslmech = NULL;
char buf[BUFSIZ], **argp, *nfs, **arguments;
struct msgs *mp;
if (!(saslmech = *argp++) || *saslmech == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
+ case PROXYSW:
+ if (!(proxy = *argp++) || *proxy == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ continue;
}
}
if (*cp == '+' || *cp == '@') {
/*
* initialize POP connection
*/
- if (pop_init (host, user, pass, snoop, kpop ? 1 : rpop, kpop,
+ if (pop_init (host, user, pass, proxy, snoop, kpop ? 1 : rpop, kpop,
sasl, saslmech) == NOTOK)
adios (NULL, "%s", response);
{ "sasl", SASLminc(-4) },
#define SASLMECHSW 15
{ "saslmech", SASLminc(-5) },
+#define PROXYSW 16
+ { "proxy command", POPminc(-5) },
{ NULL, 0 }
};
static int checkmail (char *, char *, int, int, int);
#ifdef POP
-static int remotemail (char *, char *, int, int, int, int, int, int, char *);
+static int remotemail (char *, char *, char *, int, int, int, int, int, int, char *);
#endif
int kpop = 0, sasl = 0;
int snoop = 0, vecp = 0;
uid_t uid;
- char *cp, *host = NULL, *user, buf[BUFSIZ], *saslmech = NULL;
+ char *cp, *host = NULL, *user, *proxy = NULL;
+ char buf[BUFSIZ], *saslmech = NULL;
char **argp, **arguments, *vec[MAXVEC];
struct passwd *pw;
if (!(saslmech = *argp++) || *saslmech == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
+
+ case PROXYSW:
+ if (!(proxy = *argp++) || *proxy == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ continue;
}
}
if (vecp >= MAXVEC-1)
kpop = 1;
}
if (vecp == 0) {
- status = remotemail (host, user, rpop, kpop, notifysw, 1, snoop,
- sasl, saslmech);
+ status = remotemail (host, user, proxy, rpop, kpop, notifysw, 1,
+ snoop, sasl, saslmech);
} else {
for (vecp = 0; vec[vecp]; vecp++)
- status += remotemail (host, vec[vecp], rpop, kpop, notifysw, 0,
- snoop, sasl, saslmech);
+ status += remotemail (host, vec[vecp], proxy, rpop, kpop,
+ notifysw, 0, snoop, sasl, saslmech);
}
} else {
#endif /* POP */
extern char response[];
static int
-remotemail (char *host, char *user, int rpop, int kpop, int notifysw, int personal, int snoop, int sasl, char *saslmech)
+remotemail (char *host, char *user, char *proxy, int rpop, int kpop, int notifysw, int personal, int snoop, int sasl, char *saslmech)
{
int nmsgs, nbytes, status;
char *pass = NULL;
ruserpass (host, &user, &pass);
/* open the POP connection */
- if (pop_init (host, user, pass, snoop, kpop ? 1 : rpop, kpop,
+ if (pop_init (host, user, pass, proxy, snoop, kpop ? 1 : rpop, kpop,
sasl, saslmech) == NOTOK
|| pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages */
|| pop_quit () == NOTOK) { /* quit POP connection */
}
snprintf (mailname, sizeof(mailname), "PO box for %s@%s", user, host);
- if (pop_init (host, user, pass, snoop, rpop) == NOTOK)
+ if (pop_init (host, user, pass, NULL, snoop, rpop) == NOTOK)
adios (NULL, "%s", response);
if (rpop > 0)
setuid (getuid ());
}
#endif /* CYRUS_SASL */
+
+/*
+ * Split string containing proxy command into an array of arguments
+ * suitable for passing to exec. Returned array must be freed. Shouldn't
+ * be possible to call this with host set to NULL.
+ */
+char **
+parse_proxy(char *proxy, char *host)
+{
+ char **pargv, **p;
+ int pargc = 2;
+ int hlen = strlen(host);
+ int plen = 1;
+ char *cur, *pro;
+ char *c;
+
+ /* skip any initial space */
+ for (pro = proxy; isspace(*pro); pro++)
+ continue;
+
+ /* calculate required size for argument array */
+ for (cur = pro; *cur; cur++) {
+ if (isspace(*cur) && cur[1] && !isspace(cur[1]))
+ plen++, pargc++;
+ else if (*cur == '%' && cur[1] == 'h') {
+ plen += hlen;
+ cur++;
+ } else if (!isspace(*cur))
+ plen++;
+ }
+
+ /* put together list of arguments */
+ p = pargv = malloc(pargc * sizeof(char *));
+ c = *pargv = malloc(plen * sizeof(char));
+ for (cur = pro; *cur; cur++) {
+ if (isspace(*cur) && cur[1] && !isspace(cur[1])) {
+ *c++ = '\0';
+ *++p = c;
+ } else if (*cur == '%' && cur[1] == 'h') {
+ strcpy (c, host);
+ c += hlen;
+ cur++;
+ } else if (!isspace(*cur))
+ *c++ = *cur;
+ }
+ *++p = NULL;
+ return pargv;
+}
+
int
-pop_init (char *host, char *user, char *pass, int snoop, int rpop, int kpop,
- int sasl, char *mech)
+pop_init (char *host, char *user, char *pass, char *proxy, int snoop,
+ int rpop, int kpop, int sasl, char *mech)
{
int fd1, fd2;
char buffer[BUFSIZ];
+ if (proxy && *proxy) {
+ int pid;
+ int inpipe[2]; /* for reading from the server */
+ int outpipe[2]; /* for sending to the server */
+
+ /* first give up any root priviledges we may have for rpop */
+ setuid(getuid());
+
+ pipe(inpipe);
+ pipe(outpipe);
+
+ pid=fork();
+ if (pid==0) {
+ char **argv;
+
+ /* in child */
+ close(0);
+ close(1);
+ dup2(outpipe[0],0); /* connect read end of connection */
+ dup2(inpipe[1], 1); /* connect write end of connection */
+ if(inpipe[0]>1) close(inpipe[0]);
+ if(inpipe[1]>1) close(inpipe[1]);
+ if(outpipe[0]>1) close(outpipe[0]);
+ if(outpipe[1]>1) close(outpipe[1]);
+
+ /* run the proxy command */
+ argv=parse_proxy(proxy, host);
+ execvp(argv[0],argv);
+
+ perror(argv[0]);
+ close(0);
+ close(1);
+ free(*argv);
+ free(argv);
+ exit(10);
+ }
+
+ /* okay in the parent we do some stuff */
+ close(inpipe[1]); /* child uses this */
+ close(outpipe[0]); /* child uses this */
+
+ /* we read on fd1 */
+ fd1=inpipe[0];
+
+ /* and write on fd2 */
+ fd2=outpipe[1];
+
+ } else {
+
#ifdef APOP
- int apop;
+ int apop;
- if ((apop = rpop) < 0)
- rpop = 0;
+ if ((apop = rpop) < 0)
+ rpop = 0;
#endif
#ifndef NNTP
# ifdef KPOP
- if ( kpop ) {
- snprintf (buffer, sizeof(buffer), "%s/%s", KPOP_PRINCIPAL, "kpop");
- if ((fd1 = client (host, "tcp", buffer, 0, response, sizeof(response))) == NOTOK) {
- return NOTOK;
- }
- } else {
+ if ( kpop ) {
+ snprintf (buffer, sizeof(buffer), "%s/%s", KPOP_PRINCIPAL, "kpop");
+ if ((fd1 = client (host, "tcp", buffer, 0, response, sizeof(response))) == NOTOK) {
+ return NOTOK;
+ }
+ } else {
# endif /* KPOP */
- if ((fd1 = client (host, "tcp", POPSERVICE, rpop, response, sizeof(response))) == NOTOK) {
- return NOTOK;
- }
+ if ((fd1 = client (host, "tcp", POPSERVICE, rpop, response, sizeof(response))) == NOTOK) {
+ return NOTOK;
+ }
# ifdef KPOP
- }
+ }
# endif /* KPOP */
#else /* NNTP */
- if ((fd1 = client (host, "tcp", "nntp", rpop, response, sizeof(response))) == NOTOK)
- return NOTOK;
+ if ((fd1 = client (host, "tcp", "nntp", rpop, response, sizeof(response))) == NOTOK)
+ return NOTOK;
#endif
- if ((fd2 = dup (fd1)) == NOTOK) {
- char *s;
+ if ((fd2 = dup (fd1)) == NOTOK) {
+ char *s;
- if ((s = strerror(errno)))
- snprintf (response, sizeof(response),
- "unable to dup connection descriptor: %s", s);
- else
- snprintf (response, sizeof(response),
- "unable to dup connection descriptor: unknown error");
- close (fd1);
- return NOTOK;
+ if ((s = strerror(errno)))
+ snprintf (response, sizeof(response),
+ "unable to dup connection descriptor: %s", s);
+ else
+ snprintf (response, sizeof(response),
+ "unable to dup connection descriptor: unknown error");
+ close (fd1);
+ return NOTOK;
+ }
}
#ifndef NNTP
if (pop_set (fd1, fd2, snoop) == NOTOK)
return NOTOK; /* unknown XTND command */
#endif /* NNTP */
}
-#endif BPOP
+#endif /* BPOP */
int
#endif /* CYRUS_SASL */
fprintf (stderr, "<--- %s\n", response);
}
-#endif DEBUG
+#endif /* DEBUG */
if (strncmp (buffer, TRM, TRMLEN) == 0) {
if (buffer[TRMLEN] == 0)
return DONE;