*/
#include <h/mh.h>
+#include <h/utils.h>
extern int client(char *args, char *protocol, char *service, int rproto,
char *response, int len_response);
#endif
#ifdef CYRUS_SASL
-# include <sasl.h>
-# include <saslutil.h>
+# include <sasl/sasl.h>
+# include <sasl/saslutil.h>
#endif /* CYRUS_SASL */
#include <h/popsbr.h>
static int sasl_fgetc(FILE *);
#endif /* CYRUS_SASL */
-static int traverse (int (*)(), const char *, ...);
+static int traverse (int (*)(char *), const char *, ...);
static int vcommand(const char *, va_list);
-static int getline (char *, int, FILE *);
+static int sasl_getline (char *, int, FILE *);
static int putline (char *, FILE *);
len = strlen(pass);
- *psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len);
-
- if (! *psecret)
- return SASL_NOMEM;
+ *psecret = (sasl_secret_t *) mh_xmalloc(sizeof(sasl_secret_t) + len);
(*psecret)->len = len;
strcpy((char *) (*psecret)->data, pass);
}
#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;
+ unsigned 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 = mh_xmalloc(pargc * sizeof(char *));
+ c = *pargv = mh_xmalloc(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];
rpop = 0;
#endif
+ 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 {
+
#ifndef NNTP
+ if ( kpop ) {
# 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 {
-# endif /* KPOP */
- if ((fd1 = client (host, "tcp", POPSERVICE, rpop, response, sizeof(response))) == NOTOK) {
+ snprintf (buffer, sizeof(buffer), "%s/%s", KPOP_PRINCIPAL, "kpop");
+ if ((fd1 = client (host, "tcp", buffer, 0, response, sizeof(response))) == NOTOK) {
+ return NOTOK;
+ }
+# else /* KPOP */
+ snprintf (response, sizeof(response), "this version of nmh compiled without KPOP support");
return NOTOK;
- }
-# ifdef KPOP
- }
# endif /* KPOP */
+ } else {
+ if ((fd1 = client (host, "tcp", POPSERVICE, rpop, response, sizeof(response))) == NOTOK) {
+ return NOTOK;
+ }
+ }
#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)
SIGNAL (SIGPIPE, SIG_IGN);
- switch (getline (response, sizeof response, input)) {
+ switch (sasl_getline (response, sizeof response, input)) {
case OK:
if (poprint)
fprintf (stderr, "<--- %s\n", response);
int
-pop_retr (int msgno, int (*action)())
+pop_retr (int msgno, int (*action)(char *))
{
#ifndef NNTP
return traverse (action, "RETR %d", (targ_t) msgno);
static int
-traverse (int (*action)(), const char *fmt, ...)
+traverse (int (*action)(char *), const char *fmt, ...)
{
int result;
va_list ap;
int
-pop_top (int msgno, int lines, int (*action)())
+pop_top (int msgno, int lines, int (*action)(char *))
{
#ifndef NNTP
return traverse (action, "TOP %d %d", (targ_t) msgno, (targ_t) lines);
snprintf (buffer, sizeof(buffer), fmt, a, b, c, d);
ap = brkstring (buffer, " ", "\n"); /* a hack, i know... */
- if (!strcasecmp(ap[0], "x-bboards")) { /* XTND "X-BBOARDS group */
+ if (!mh_strcasecmp(ap[0], "x-bboards")) { /* XTND "X-BBOARDS group */
/* most of these parameters are meaningless under NNTP.
* bbc.c was modified to set AKA and LEADERS as appropriate,
* the rest are left blank.
*/
return OK;
}
- if (!strcasecmp (ap[0], "archive") && ap[1]) {
+ if (!mh_strcasecmp (ap[0], "archive") && ap[1]) {
snprintf (xtnd_name, sizeof(xtnd_name), "%s", ap[1]); /* save the name */
xtnd_last = 0;
xtnd_first = 1; /* setup to fail in pop_stat */
return OK;
}
- if (!strcasecmp (ap[0], "bboards")) {
+ if (!mh_strcasecmp (ap[0], "bboards")) {
if (ap[1]) { /* XTND "BBOARDS group" */
snprintf (xtnd_name, sizeof(xtnd_name), "%s", ap[1]); /* save the name */
return NOTOK; /* unknown XTND command */
#endif /* NNTP */
}
-#endif BPOP
+#endif /* BPOP */
int
fprintf(stderr, "(decrypted) ");
#endif /* CYRUS_SASL */
- switch (getline (response, sizeof response, input)) {
+ switch (sasl_getline (response, sizeof response, input)) {
case OK:
if (poprint)
fprintf (stderr, "<--- %s\n", response);
{
char buffer[BUFSIZ + TRMLEN];
- if (getline (buffer, sizeof buffer, input) != OK)
+ if (sasl_getline (buffer, sizeof buffer, input) != OK)
return NOTOK;
#ifdef DEBUG
if (poprint) {
#endif /* CYRUS_SASL */
fprintf (stderr, "<--- %s\n", response);
}
-#endif DEBUG
+#endif /* DEBUG */
if (strncmp (buffer, TRM, TRMLEN) == 0) {
if (buffer[TRMLEN] == 0)
return DONE;
*/
static int
-getline (char *s, int n, FILE *iop)
+sasl_getline (char *s, int n, FILE *iop)
{
int c;
char *p;
}
if (retbufsize > size) {
- buffer = realloc(buffer, retbufsize);
- if (!buffer) {
- snprintf(response, sizeof(response), "Error during realloc in "
- "read routine: %s", strerror(errno));
- return -2;
- }
+ buffer = mh_xrealloc(buffer, retbufsize);
size = retbufsize;
}