/* $Cambridge: hermes/src/mailchk/mailchk.c,v 1.6 2003/08/12 13:12:34 dpc22 Exp $ */

#include "mailchk.h"

/* For getpwuid() */
#include <pwd.h>
#include <sys/types.h>

/* ====================================================================== */

#define DEFAULT_OUTPUT_FILENAME ".biff.current"     /* In home directory */
static char *output_filename = NULL;
static int old_exists = 0;

/* Write message count to nominated file */

static BOOL
my_update(int exists)
{
    FILE *file;

    if (exists == old_exists)
        return(T);

    if ((file=fopen(output_filename, "w")) == NULL)
        return(NIL);

    fprintf(file, "%d\n", exists); 

    fclose(file);

    old_exists = exists;
    return(T);
}

/* ====================================================================== */

int
main(int argc, char *argv[])
{
    int opt;
    struct iostream *stream;
    char *s, *t;
    char *hostname = xstrdup("imap.hermes.cam.ac.uk/ssl");
    char *mailbox  = "INBOX";
    BOOL  use_ssl  = NIL;
    char *username = NULL;
    char *password = NULL;
    struct passwd *passwd = NULL;
    pid_t pid;
    BOOL foreground = NIL;
    BOOL debug = NIL;
    char *dir;

    /* Very little proceeded on stdout: stop any buffering effects */
    setbuf(stdout, NULL);

    /* Make sure logging apparatus set to sensible default case */
    log_set_background(NIL);
    log_set_debug(NIL);

    /* Set up imap callback for EXISTS events */
    imap_set_callback(my_update);

    /* Switch to home directory for this user */
    if ((dir = (char *) getenv ("HOME")) == NULL) {
        if ((passwd = getpwuid(getuid())) == NULL)
            log_fatal("Unable to lookup local username");
            
        dir = passwd->pw_dir;
    }
    if (chdir(dir) < 0)
        log_fatal("chdir(%s) failed: %s", dir, strerror(errno));

    /* Parse command line */
    while ((opt = getopt(argc, argv, "dfo:u:p:h:sm:")) != EOF) {
        switch (opt) {
        case 'd':
            debug = T;
            break;
        case 'f':
            foreground = T;
            break;
        case 'o':
            output_filename = xstrdup(optarg);
            break;
        case 'h':
            hostname = xstrdup(optarg);
            break;
        case 'u':
            username = xstrdup(optarg);
            break;
        case 'p':
            password = xstrdup(optarg);
            break;
        case 's':
            use_ssl = T;
            break;
        case 'm':
            mailbox = xstrdup(optarg);
            break;
        }
    }

    /* Chop up hostname argument for c-client style /tag options */
    if ((s = strchr(hostname, '/'))) {
        *s++ = '\0';
    
        while (s) {
            if ((t = strchr(s, '/')))
                *t++ = '\0';

            if (!strcmp(s, "tls") || !strcmp(s, "ssl") || !strcmp(s, "secure"))
                use_ssl = T;
            else if (!strcmp(s, "notls") || !strcmp(s, "nossl"))
                use_ssl = NIL;
            else if (!strcmp(s, "debug"))
                debug = T;
            else if (!strncmp(s, "user=", 5))
                username = s+5;
            else
                log_fatal("Unknown flag: %s", s);
            
            s = t;
        }
    }

    if (debug)
        log_set_debug(T);

    if (output_filename == NULL)
        output_filename = xstrdup(DEFAULT_OUTPUT_FILENAME);

    if (username == NULL) {
        if ((passwd=getpwuid(getuid())) == NULL)
            log_fatal("Unable to lookup local username");

        username = xstrdup(passwd->pw_name);
    }

    /* Initialise SSL subsystem if required */
    if (use_ssl)
        ssl_context_init();

    /* Connect to the IMAP server or proxy */
    printf("Connecting to %s (%s) as user %s\n",
           hostname, (use_ssl) ? "using SSL" : "not using SSL", username);

    if (!(stream=imap_connect(hostname, use_ssl)))
        log_fatal("Unable to create iostream");

    /* Authenticate to the IMAP server or proxy */
    if (password == NULL) {
        int i;

        for (i = 0 ; i < 3 ; i++) {
            password = getpass("Password: ");   /* Slightly evil */

            if (imap_authenticate(stream, username, password))
                break;

            printf("Login failed, please try again\n");
        }
        if (i == 3)
            log_fatal("Unable to authenticate");
    } else if (!imap_authenticate(stream, username, password))
        log_fatal("Unable to authenticate");

    /* Pick a mailbox of interest */
    if (!imap_examine(stream, mailbox))
        log_fatal("Unable to EXAMINE %s", mailbox);

    /* Run in foreground */
    if (foreground) {
        printf("Login successful: running session in foreground\n");

        do {
            imap_idle(stream);
        } while (!iostream_is_eof(stream));
        iostream_close(stream);
        if (use_ssl) ssl_context_free();
        return(0);
    }

    /* Run in background */
    printf("Login successful: disconnecting from terminal\n");
    log_set_background(T);

    if ((pid = fork()) < 0)
        log_fatal("fork() failed: %s", strerror(errno));
        
    if (pid == 0) {
        /* Child process */

        /* Disconnect from controlling terminal */
        close(0);
        close(1);
        close(2);
        open("/dev/null", O_RDONLY);
        open("/dev/null", O_WRONLY);
        open("/dev/null", O_WRONLY);

        do {
            imap_idle(stream);
        } while (!iostream_is_eof(stream));

        iostream_close(stream);
        if (use_ssl) ssl_context_free();
        _exit(0);
    }

#if 0
    /* Child gets upset if parent closes file? */
    iostream_close(stream);
    if (use_ssl) ssl_context_free();
#endif

    return(0);
}
