/*
 * qmtp.c - Forward a message to a QMTP server.  This program is meant to
 * be run from tcpclient as follows:
 *
 *	tcpclient <host> 209 ./qmtp <sender> <recipient>
 *
 * I use this program to forward my mail to my home machine.  If that
 * fails the mail is spooled on the server.  My .qmail file looks like
 * this:
 *
 * 	|if tcpclient home.machine.org 209 $HOME/qmtp "$SENDER" neil; \
 * 		then exit 99; else exit 0; fi
 *	./Maildir/
 *
 * If you find any security problems with this program please let me know.
 *
 * September 1999
 * Neil Schemenauer <nascheme@enme.ucalgary.ca>
 */

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>

#define BUF_SIZE 4096

void die(char *message)
{
    fprintf(stderr, "Error: %s\n", message);
    exit(2);
}

void die_errno(void)
{
    perror("Error");
    exit(2);
}

void copy_file(FILE *input, FILE *output)
{
    char buf[BUF_SIZE];
    int nread;

    while (1) {
        nread = fread(buf, 1, BUF_SIZE, input);
        if (nread == 0) {
            if (ferror(input)) {
                die_errno();
            } else {
                break;
            }
        }
        if (fwrite(buf, 1, nread, output) != nread) {
            die("short write");
        }
    }
}

int main(int argc, char **argv)
{
    char *sender, *recipient;
    struct stat st;
    int size;
    char buf[BUF_SIZE];
    char *response;
    int status;
    FILE *message, *output, *input;

    if (argc != 3) {
        fprintf(stderr, "Usage: %s <sender> <recipient>\n", argv[0]);
        exit(1);
    }
    sender = argv[1];
    recipient = argv[2];
    message = stdin;
    input = fdopen(6, "rb");
    output = fdopen(7, "wb");
    /*
    message = fdopen(3, "rb");
    input = stdin;
    output = stdout;
    */
    if (!message) {
        die("can't open message");
    }
    /* find message size */
    if (fstat(fileno(message), &st) == -1) {
        die_errno();
    }
    size = st.st_size + 1;

    /* write message */
    fprintf(output, "%d:\n", size);
    copy_file(message, output);
    fprintf(output, ",");
    /* write sender */
    fprintf(output, "%d:%s,", strlen(sender), sender);
    /* write recepient list */
    snprintf(buf, BUF_SIZE, "%d:%s,", strlen(recipient), recipient);
    fprintf(output, "%d:%s,", strlen(buf), buf);
    fflush(output);
    /* read response */
    if (fscanf(input, "%9d", &size) < 1) {
        die("bad netstring format");
    }
    if (fgetc(input) != ':') {
        die("bad netstring format");
    }
    response = malloc(size+1);
    if (!response) {
        die("out of memory");
    }
    if (fread(response, 1, size, input) < size) {
        die_errno();
    }
    if (fgetc(input) != ',') {
        die("bad netstring format");
    }
    switch (response[0]) {
        case 'K':
            status = 0;
            break;
        case 'Z':
            status = 111;
            break;
        case 'D':
            status = 100;
            break;
        default:
            die("bad response format");
    }
    /* print status message */
    fwrite(response+1, 1, size-1, stderr);
    fprintf(stderr, "\n");
    return status;
}
