<commit_before>/* popsbr.c -- POP client subroutines
 *
 * This code is Copyright (c) 2002, by the authors of nmh.  See the
 * COPYRIGHT file in the root directory of the nmh distribution for
 * complete copyright information.
 */

#include <h/mh.h>
#include <h/utils.h>
#include <h/oauth.h>
#include <h/netsec.h>

#include <h/popsbr.h>
#include <h/signals.h>
#include "sbr/base64.h"

#define	TRM	"."

static int poprint = 0;

char response[BUFSIZ];
static netsec_context *nsc = NULL;

/*
 * static prototypes
 */

static int command(const char *, ...) CHECK_PRINTF(1, 2);
static int multiline(void);

static int traverse(int (*)(void *, char *), void *closure,
    const char *, ...) CHECK_PRINTF(3, 4);
static int vcommand(const char *, va_list) CHECK_PRINTF(1, 0);
static int pop_getline (char *, int, netsec_context *);
static int pop_sasl_callback(enum sasl_message_type, unsigned const char *,
			     unsigned int, unsigned char **, unsigned int *,
			     char **);

static int
check_mech(char *server_mechs, size_t server_mechs_size)
{
  int status, sasl_capability = 0;

    /*
     * First off, we're going to send the CAPA command to see if we can
     * even support the AUTH command, and if we do, then we'll get a
     * list of mechanisms the server supports.  If we don't support
     * the CAPA command, then it's unlikely that we will support
     * SASL
     */

    if (command("CAPA") == NOTOK) {
	snprintf(response, sizeof(response),
		 "The POP CAPA command failed; POP server does not "
		 "support SASL");
	return NOTOK;
    }

    while ((status = multiline()) != DONE) {
        if (status == NOTOK)
	    return NOTOK;

        if (strncasecmp(response, "SASL ", 5) == 0) {
            /* We've seen the SASL capability.  Grab the mech list. */
            sasl_capability++;
            strncpy(server_mechs, response + 5, server_mechs_size);
        }
    }

    if (!sasl_capability) {
	snprintf(response, sizeof(response), "POP server does not support "
		 "SASL");
	return NOTOK;
    }

    return OK;
}

/*
 * 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 = (unsigned char *) 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;
    }
    *c = '\0';
    *++p = NULL;
    return pargv;
}

int
pop_init (char *host, char *port, char *user, char *proxy, int snoop,
	  int sasl, char *mech, int tls, const char *oauth_svc)
{
    int fd1, fd2;
    char buffer[BUFSIZ];
    char *errstr;

    nsc = netsec_init();  

    if (user)
	netsec_set_userid(nsc, user);

    netsec_set_hostname(nsc, host);

    if (oauth_svc != NULL) {
	if (netsec_set_oauth_service(nsc, oauth_svc) != OK) {
	    snprintf(response, sizeof(response), "OAuth2 not supported");
	    return NOTOK;
	}
    }

    if (proxy && *proxy) {
       int pid;
       int inpipe[2];	  /* for reading from the server */
       int outpipe[2];    /* for sending to the server */

       if (pipe(inpipe) < 0) {
	   adios ("inpipe", "pipe");
       }
       if (pipe(outpipe) < 0) {
	   adios ("outpipe", "pipe");
       }

       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 {
	if ((fd1 = client (host, port ? port : "pop3", response,
			   sizeof(response), snoop)) == NOTOK) {
	    return NOTOK;
	}
	fd2 = fd1;
    }

    SIGNAL (SIGPIPE, SIG_IGN);

    netsec_set_fd(nsc, fd1, fd2);
    netsec_set_snoop(nsc, snoop);<commit_msg>pop_init(): After proxy's execve(2) failure, exit(1), not exit(10).<commit_after>/* popsbr.c -- POP client subroutines
 *
 * This code is Copyright (c) 2002, by the authors of nmh.  See the
 * COPYRIGHT file in the root directory of the nmh distribution for
 * complete copyright information.
 */

#include <h/mh.h>
#include <h/utils.h>
#include <h/oauth.h>
#include <h/netsec.h>

#include <h/popsbr.h>
#include <h/signals.h>
#include "sbr/base64.h"

#define	TRM	"."

static int poprint = 0;

char response[BUFSIZ];
static netsec_context *nsc = NULL;

/*
 * static prototypes
 */

static int command(const char *, ...) CHECK_PRINTF(1, 2);
static int multiline(void);

static int traverse(int (*)(void *, char *), void *closure,
    const char *, ...) CHECK_PRINTF(3, 4);
static int vcommand(const char *, va_list) CHECK_PRINTF(1, 0);
static int pop_getline (char *, int, netsec_context *);
static int pop_sasl_callback(enum sasl_message_type, unsigned const char *,
			     unsigned int, unsigned char **, unsigned int *,
			     char **);

static int
check_mech(char *server_mechs, size_t server_mechs_size)
{
  int status, sasl_capability = 0;

    /*
     * First off, we're going to send the CAPA command to see if we can
     * even support the AUTH command, and if we do, then we'll get a
     * list of mechanisms the server supports.  If we don't support
     * the CAPA command, then it's unlikely that we will support
     * SASL
     */

    if (command("CAPA") == NOTOK) {
	snprintf(response, sizeof(response),
		 "The POP CAPA command failed; POP server does not "
		 "support SASL");
	return NOTOK;
    }

    while ((status = multiline()) != DONE) {
        if (status == NOTOK)
	    return NOTOK;

        if (strncasecmp(response, "SASL ", 5) == 0) {
            /* We've seen the SASL capability.  Grab the mech list. */
            sasl_capability++;
            strncpy(server_mechs, response + 5, server_mechs_size);
        }
    }

    if (!sasl_capability) {
	snprintf(response, sizeof(response), "POP server does not support "
		 "SASL");
	return NOTOK;
    }

    return OK;
}

/*
 * 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 = (unsigned char *) 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;
    }
    *c = '\0';
    *++p = NULL;
    return pargv;
}

int
pop_init (char *host, char *port, char *user, char *proxy, int snoop,
	  int sasl, char *mech, int tls, const char *oauth_svc)
{
    int fd1, fd2;
    char buffer[BUFSIZ];
    char *errstr;

    nsc = netsec_init();  

    if (user)
	netsec_set_userid(nsc, user);

    netsec_set_hostname(nsc, host);

    if (oauth_svc != NULL) {
	if (netsec_set_oauth_service(nsc, oauth_svc) != OK) {
	    snprintf(response, sizeof(response), "OAuth2 not supported");
	    return NOTOK;
	}
    }

    if (proxy && *proxy) {
       int pid;
       int inpipe[2];	  /* for reading from the server */
       int outpipe[2];    /* for sending to the server */

       if (pipe(inpipe) < 0) {
	   adios ("inpipe", "pipe");
       }
       if (pipe(outpipe) < 0) {
	   adios ("outpipe", "pipe");
       }

       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(1);
       }

       /* 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 {
	if ((fd1 = client (host, port ? port : "pop3", response,
			   sizeof(response), snoop)) == NOTOK) {
	    return NOTOK;
	}
	fd2 = fd1;
    }

    SIGNAL (SIGPIPE, SIG_IGN);

    netsec_set_fd(nsc, fd1, fd2);
    netsec_set_snoop(nsc, snoop);
{'fraction_non_alphanumeric': 0.15444200057377833, 'fraction_numerical': 0.014631347422779, 'mean_word_length': 2.5753846153846154, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2915323', 'n_tokens_mistral': 3954, 'n_tokens_neox': 3702, 'n_words': 1090}