/* Quick, but mostly compliant maildir delivery program
   Reads one mbox style message from stdin and attempts to deliver
   it to the maildir specified by the first argument on the command
   line.  if $MAILDIR exists, delivery is to $MAILDIR/argv[0]
 */

/* Copyright 1997, Brian J. Swetland <swetland@uiuc.edu>
   Share and Enjoy. */

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

#define HOSTNAME "hagbard" /* put your hostname here */

char *_name;

void die(char *why, char *arg)
{
    fprintf(stderr,"%s: ",_name);
    fprintf(stderr,why,arg);
    fprintf(stderr,"\n");
    exit(1);
}

int main(int argc, char *argv[])
{
    char *maildir;
    struct stat sinfo;
    int fd,len,now,skipfrom,retry;
    char tmp[4096],buf[4096],*p;

    _name = argv[0];

    maildir = getenv("MAILDIR");

    if(argc != 2) die("No destination",NULL);

    if(maildir){
        sprintf(tmp,"%s/%s",maildir,argv[1]);
    } else {
        strcpy(tmp,argv[1]);
    }

	/* 1. chdir() to maildir directory */
    if(chdir(tmp))
        die("Cannot chdir to %s",tmp);

    for(retry=5;retry;sleep(2),retry--){
            /* 2. stat(tmp/time.pid.host) */
        now = time(NULL);
        sprintf(tmp,"tmp/%d.%d.hagbard",now,getpid());

            /* 3. if errno != ENOENT, retry */
        if(stat(tmp,&sinfo) != -1) continue;
        if(errno != ENOENT) continue;

            /* 4. create tmp/time.pid.host */
        if((fd = open(tmp,O_WRONLY|O_EXCL|O_CREAT,0600)) == -1)
            continue;

            /* 5. nfs-write the contents */
        skipfrom = 1;
        while((len = read(0,buf,4096)) != -1){
            if(len == 0) break;
            if(skipfrom){
                skipfrom=0;
				/* this won't work right if the entire
				   From line is not read in the first read */
                if(!strncmp("From ",buf,5)){
                    for(p=buf;len && (*p!='\r') && (*p!='\n');p++,len--);
                    if(len && *p=='\r') len--, p++;
                    if(len && *p=='\n') len--, p++;

                    if(len) {
                        if(write(fd,p,len) == -1){
                            close(fd);
                            unlink(tmp);
                            die("Write Failed",NULL);
                        }
                    }
                    continue;	
                }
            }
            if(write(fd,buf,len) == -1){
                close(fd);
                unlink(tmp);
                die("Write Failed",NULL);
            }
        }
        if(close(fd) == -1) {
            unlink(tmp);
            die("Close Failed",NULL);
        }

            /* 6. link final dest */
        sprintf(buf,"new/%d.%d.%s",now,getpid(),HOSTNAME);
        if(link(tmp,buf) == -1){
            unlink(tmp);
            die("Link Failed",NULL);
        }

        unlink(tmp);
        exit(0);
    }

    die("Could not deliver in 5 tries",NULL);
    return 0;
}

