/*  General Mail Utilities
 *  culled from other files to reduce unnecessary cross references.
 *  This material is believed to be in the public domain.
 */
#ifdef MSDOS
#include <io.h>
#endif
#include <fcntl.h>
#include <ctype.h>
#include "global.h"
#include "socket.h"
#include "mailutil.h"
#include "mailbox.h"
#include "smtp.h"
#include "files.h"
#include "bm.h"
#include "index.h"
  
#ifdef linux
extern int close __ARGS((int)); /* this should be in fcntl.h... */
extern int unlink __ARGS((char *)); /* can't include unistd.h, collisions */
#endif
  
/*  Jan 92  Bill Simpson
 *      The following routines were combined from smtpserv.c,
 *      pop3cli.c and nntpcli.c
 */
  
/* June 93 - Johan. K. Reinalda, WG7J
 * Mail file indexing added.
 */
  
#ifdef POP3CLIENT
  
/* Receive message from socket, copying to file.
 * Returns number of lines received, -1 indicates error
 */
int
recvmail(s,buf,len,fp,trace)
int s;      /* Socket index */
char *buf;  /* Line buffer */
unsigned len;   /* Length of buffer */
FILE *fp;   /* File to copy into */
int trace;  /* to trace or not to trace */
{
    int lines = 0;
  
    while (recvline(s,buf,len) != -1) {
        register char *p = buf;
  
        if (trace >= 4)
            log(s,"<==%s", buf);
  
        /* check for end of message . or escaped .. */
        if (*p == '.') {
            if (*++p == '\n') {
                if (trace >= 3)
                    log(s,"received %d lines", lines);
                return lines;
            } else if ( *p != '.' ) {
                p--;
            }
        } else if (strncmp(p,"From ",5) == 0) {
            /* for UNIX mail compatiblity */
            (void) putc('>',fp);
        }
        /* Append to data file */
        fputs(p,fp);
        ++lines;
    }
    if ( trace >= 1 )
        log(s,"receive error after %d lines", lines);
    return -1;
}
#endif
  
#if (defined(POP2CLIENT) || defined(POP3CLIENT))
  
/* Copy from the work file into the mailbox.
 * -1 indicates error
 */
int
copymail(filename,buf,len,wfp,trace)
char *filename; /* Target Filename */
char *buf;  /* Line buffer */
unsigned len;   /* Length of buffer */
FILE *wfp;  /* File to copy from */
int trace;      /* to trace or not to trace */
{
    FILE *mfp = NULLFILE;
  
    while (mlock(Mailspool,filename)) {
        pause(10000L);  /* 10 seconds */
    }
  
    sprintf(buf,"%s/%s.txt",Mailspool,filename);
    if ((mfp = fopen(buf,"a+")) == NULL) {
        if ( trace >= 1 )
            log(-1,"*** Unable to open %s!!!\n", buf);
        tprintf("\n*** Unable to open %s!!!\n", buf);
        rmlock(Mailspool,filename);
        return -1;
    }
  
    rewind(wfp);            /* start of new mail, just to be safe ! */
    fseek(mfp,0,SEEK_END);  /* End of mailbox file */
  
    /* loop for all lines in file */
    while(fgets(buf,len,wfp) != NULL) {
        pwait(NULL);    /* give other processes time in long copy */
        fputs(buf,mfp); /* Write to the mailbox */
    }
    fclose(mfp);
  
    /* Update the index */
    IndexFile(filename,0);
  
    rmlock(Mailspool,filename);
    return 0;
}
#endif
  
  
/*  Jan 92  Bill Simpson
 *      The following routines were extracted from smtpserv.c
 *      and smtpcli.c, since they are used from several places.
 */
  
static void mklockname(char *lockname,char *dir,char *id) {
  
    if (id == NULLCHAR || !*id) strcpy(lockname, dir);
    else sprintf(lockname,"%s/%s",dir,id);
    dirformat(lockname);
    strcat(lockname,".lck");
}
  
/* create mail lockfile */
int
mlock(dir,id)
char *dir,*id;
{
    int fd;
    char lockname[FILE_PATH_SIZE];
  
    /* Try to create the lock file in an atomic operation */
    mklockname(lockname,dir,id);
  
#ifdef        AMIGA
    /* don't ask, really, just don't ask... I'd do file locking on
     * an Amiga much more differently than this.
     */
    if(access(lockname, 0) == 0)
        return -1;
#endif
    if((fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT,0600)) == -1)
        return -1;
    close(fd);
    return 0;
}
  
  
/* remove mail lockfile */
int
rmlock(dir,id)
char *dir,*id;
{
    char lockname[FILE_PATH_SIZE];
  
    mklockname(lockname,dir,id);
    return(unlink(lockname));
}
  
  
/*      Jan 92  Bill Simpson
 *      The following routines were extracted from mailbox.c,
 *      since they are used from several places.
 */
  
  
/* Read the rewrite file for lines where the first word is a regular
 * expression and the second word are rewriting rules. The special
 * character '$' followed by a digit denotes the string that matched
 * a '*' character. The '*' characters are numbered from 1 to 9.
 * Example: the line "*@*.* $2@$1.ampr.org" would rewrite the address
 * "foo@bar.xxx" to "bar@foo.ampr.org".
 * $H is replaced by our hostname, and $$ is an escaped $ character.
 * If the third word on the line has an 'r' character in it, the function
 * will recurse with the new address.
 */
char *
rewrite_address(addr)
char *addr;
{
    char *argv[10], buf[PLINELEN], *cp, *cp2, *retstr;
    int cnt;
    FILE *fp;
  
    if ((fp = fopen(Rewritefile,READ_TEXT)) == NULLFILE)
        return NULLCHAR;
  
    memset((char *)argv,0,10*sizeof(char *));
    while(fgets(buf,sizeof(buf),fp) != NULLCHAR) {
        if(*buf == '#')     /* skip commented lines */
            continue;
  
        if((cp = strchr(buf,' ')) == NULLCHAR) /* get the first word */
            if((cp = strchr(buf,'\t')) == NULLCHAR)
                continue;
        *cp = '\0';
        if((cp2 = strchr(buf,'\t')) != NULLCHAR){
            *cp = ' ';
            cp = cp2;
            *cp = '\0';
        }
        if(!wildmat(addr,buf,argv))
            continue;       /* no match */
        rip(++cp);
        /* scan past additional whitespaces */
        while (*cp == ' ' || *cp == '\t') ++cp;
        cp2 = retstr = (char *) callocw(1,PLINELEN);
        while(*cp != '\0' && *cp != ' ' && *cp != '\t')
            if(*cp == '$') {
                if(isdigit(*(++cp)))
                    if(argv[*cp - '0'-1] != '\0')
                        strcat(cp2,argv[*cp - '0'-1]);
                if(*cp == 'h' || *cp == 'H') /* Our hostname */
                    strcat(cp2,Hostname);
                if(*cp == '$')  /* Escaped $ character */
                    strcat(cp2,"$");
                cp2 = retstr + strlen(retstr);
                cp++;
            }
            else
                *cp2++ = *cp++;
        for(cnt=0; argv[cnt] != NULLCHAR; ++cnt)
            free(argv[cnt]);
        fclose(fp);
        /* If there remains an 'r' character on the line, repeat
         * everything by recursing.
         */
        if(strchr(cp,'r') != NULLCHAR || strchr(cp,'R') != NULLCHAR) {
            if((cp2 = rewrite_address(retstr)) != NULLCHAR) {
                free(retstr);
                return cp2;
            }
        }
        return retstr;
    }
    fclose(fp);
    return NULLCHAR;
}
  
int dorewrite(int argc, char *argv[], void *p) {
    char *address = rewrite_address(argv[1]);
    tprintf("to: %s\n", address ? address : argv[1]);
    if(address)
        free(address);
    return 0;
}
  
