/* This program, intended as a Maildir++-aware replacement for qmail-local
 * has not been maintained and may never have worked properly.  It
 * should not be used.
 */

/*
 * $Id: vqmaillocal.c,v 1.9 2007/05/22 03:59:02 rwidmer Exp $
 * Copyright (C) 2002 Inter7 Internet Technologies, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

/* include files */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include "config.h"
#include "vpopmail.h"
#include "vauth.h"

/* Globals */
#define AUTH_SIZE 300
char TheUser[AUTH_SIZE];
char TheHomeDir[AUTH_SIZE];
char TheLocal[AUTH_SIZE];
char TheDash[AUTH_SIZE];
char TheExt[AUTH_SIZE];
char TheSender[AUTH_SIZE];
char TheDefaultDelivery[AUTH_SIZE];
char TheUserFull[AUTH_SIZE];
char TheDomain[AUTH_SIZE];
char TheDir[AUTH_SIZE];
char CurrentDir[AUTH_SIZE];
char DeliveredTo[AUTH_SIZE];
struct vqpasswd *vpw;
off_t message_size = 0;
char bounce[AUTH_SIZE];
int CurrentQuotaSizeFd;

#ifdef QMAIL_EXT
char TheUserExt[AUTH_SIZE]; /* the User with '-' and following chars out if any */
#endif

#define FILE_SIZE 156
char hostname[FILE_SIZE];
char loop_buf[FILE_SIZE];

#define MSG_BUF_SIZE 5000
char msgbuf[MSG_BUF_SIZE];

#define BUFF_SIZE 300
int fdm;
static char *binqqargs[4];

/* Forward declarations */
int process_valias(void);
int is_delete(char *deliverto);
int is_bounce(char *deliverto);
void get_arguments(int argc, char **argv);
off_t get_message_size();
int deliver_mail(char *address, char *quota);
int user_over_quota(char *address, char *quota);
int check_forward_deliver(char *dir);
off_t count_dir(char *dir_name);
int is_looping( char *address );
void run_command(char *prog);
void checkuser(void);
void usernotfound(void);

static char local_file[156];
static char local_file_new[156];

/* 
 * The email message comes in on file descriptor 0 - stanard in
 * The user to deliver the email to is in the EXT environment variable
 * The domain to deliver the email to is in the HOST environment variable
 */
int main(int argc, char **argv)
{
    /* get the arguments to the program and setup things */
    get_arguments(argc, argv);

#ifdef VALIAS
    /* process valiases if configured */
    if ( process_valias() == 1 ) {
        printf("vdelivermail: valiases processed\n");
        vexit(0);
    }
#endif

    /* get the user from vpopmail database */
    if ((vpw=vauth_getpw(TheUser, TheDomain)) != NULL ) {
        checkuser();
    } 
#ifdef QMAIL_EXT
    /* try and find user that matches the QmailEXT address if: no user found, */
    /* and the QmailEXT address is different, meaning there was an extension */
    else if ( strncmp(TheUser, TheUserExt, AUTH_SIZE) != 0 ) {
        /* get the user from vpopmail database */
        if ((vpw=vauth_getpw(TheUserExt, TheDomain)) != NULL ) {
	    checkuser();
        }
	else {
	    usernotfound();
	}
    }
#endif
    else {
        if ( verrori != 0 ) {
            vexit(111);
        }
        usernotfound();
    } 

    /* exit successfully and have qmail delete the email */
    return(vexit(0));
            
}

/* 
 * Get the command line arguments and the environment variables.
 * Force addresses to be lower case and set the default domain
 */
void get_arguments(int argc, char **argv)
{
#ifdef QMAIL_EXT 
 int i;
#endif

    if (argc != 10) {
        printf("vqmaillocal: wrong number of parameters\n"); 
        vexit(0);
    }


    strncpy(TheHomeDir, argv[3], sizeof(TheHomeDir)); 
    strncpy(TheUser, argv[6], sizeof(TheHomeDir)); 
    strncpy(TheDomain, argv[7], sizeof(TheHomeDir)); 

    printf("%s,%s,%s\n", TheHomeDir, TheUser, TheDomain);

    chdir(TheHomeDir);

    lowerit(TheUser);
    lowerit(TheDomain);

    strncpy(TheUserFull, TheUser, AUTH_SIZE);
#ifdef QMAIL_EXT 
    /* delete the '-' and following chars if any and store in TheUserExt */
    for(i = 0; TheUser[i] != 0; i++) {
        if (TheUser[i] == '-' ) {
            break;
        }

        TheUserExt[i] = TheUser[i];
    }

    TheUserExt[i] = 0;
#endif

}

#ifdef VALIAS
/* 
 * Process any valiases for this user@domain
 * 
 * This will look up any valiases in vpopmail and
 * deliver the email to the entries
 *
 * Return 1 if aliases found
 * Return 0 if no aliases found 
 */
int process_valias(void)
{
 int found = 0;
 char *tmpstr;

    /* Get the first alias for this user@domain */
    tmpstr = valias_select( TheUser, TheDomain );

    /* tmpstr will be NULL if there are no more aliases */
    while (tmpstr != NULL ) {

        /* We found one */
        found = 1;

        /* deliver the mail */
        deliver_mail(tmpstr, "NOQUOTA");

        /* Get the next alias for this user@domain */
        tmpstr = valias_select_next();
    }

#ifdef QMAIL_EXT 
    /* try and find alias that matches the QmailEXT address 
     * if: no alias found, 
     * and the QmailEXT address is different, meaning there was an extension 
     */
    if ( (!found) && ( strncmp(TheUser, TheUserExt, AUTH_SIZE) != 0 )  ) {
        /* Get the first alias for this user@domain */
        tmpstr = valias_select( TheUserExt, TheDomain );

        /* tmpstr will be NULL if there are no more aliases */
        while (tmpstr != NULL ) {

            /* We found one */
            found = 1;

            /* deliver the mail */
            deliver_mail(tmpstr, "NOQUOTA");

            /* Get the next alias for this user@domain */
            tmpstr = valias_select_next();
        } 
    }	
#endif

    /* Return whether we found an alias or not */
    return(found);
}
#endif

/* If the .qmail-default file has bounce all in it
 * Then return 1
 * otherwise return 0
 */
int is_bounce(char *deliverto)
{
    if ( strcmp( deliverto, BOUNCE_ALL ) == 0 ) return(1);
    return(0);
}

/* If the .qmail-default file has delete all in it
 * Then return 1
 * otherwise return 0
 */
int is_delete(char *deliverto)
{
    if ( strcmp( deliverto, DELETE_ALL ) == 0 ) return(1);
    return(0);
}



/*
 * Assumes the current working directory is user/Maildir
 *
 * We go off to look at cur and tmp dirs
 * 
 * return size of files
 *
 */
ssize_t check_quota(char *maildir)
{
 ssize_t mail_size = 0;
 char tmpbuf[156];

    snprintf(tmpbuf, 156, "%s.current_size", maildir);
    if ((CurrentQuotaSizeFd=open(tmpbuf,O_CREAT|O_RDWR,S_IWUSR|S_IRUSR))==-1){
       return(mail_size);
    }
    read(CurrentQuotaSizeFd, tmpbuf, 100);
    mail_size = (off_t)atoi(tmpbuf);
    return(mail_size);
}

off_t recalc_quota(char *dir_name)
{
 off_t mail_size = 0;
 char tmpbuf[100];

        getcwd(CurrentDir, AUTH_SIZE);
	mail_size = count_dir(dir_name);
        chdir(CurrentDir);
	snprintf(tmpbuf, 100, "%d\n", (int)mail_size);
	lseek(CurrentQuotaSizeFd, 0L, SEEK_SET);
	write(CurrentQuotaSizeFd, tmpbuf, strlen(tmpbuf));
	return(mail_size);
}

void update_quota(off_t new_size)
{
 char tmpbuf[100];

	snprintf(tmpbuf, 100, "%d\n", (int)new_size);
	lseek(CurrentQuotaSizeFd, 0L, SEEK_SET);
	write(CurrentQuotaSizeFd, tmpbuf, strlen(tmpbuf));
	close(CurrentQuotaSizeFd);
}

off_t count_dir(char *dir_name)
{
 DIR *mydir;
 struct dirent *mydirent;
 struct stat statbuf;
 off_t file_size = 0;
 char *tmpstr;

    if ( dir_name == NULL ) return(0);
    if (chdir(dir_name) == -1) {
        return(0);
    }

	if ( (mydir = opendir(".")) == NULL )  {
            return(0);
        }

	while( (mydirent=readdir(mydir)) != NULL ) {
		if ( strcmp( mydirent->d_name, "..") == 0 ) continue;
		if ( strcmp( mydirent->d_name, ".") == 0 ) continue;
		if ( (tmpstr=strstr(mydirent->d_name, ",S="))!=NULL) {
			tmpstr += 3;
			file_size += atoi(tmpstr);
		} else if (stat(mydirent->d_name,&statbuf)==0 && 
		           (statbuf.st_mode & S_IFDIR) ) {
			file_size +=  count_dir(mydirent->d_name);
		}
	}
	closedir(mydir);
	if ( dir_name != NULL && strcmp(dir_name, ".." )!=0 && 
	                         strcmp(dir_name, "." )!=0) {
		chdir("..");
	}
	return(file_size);
}

long unsigned qmail_inject_open(char *address)
{
 int pim[2];
 long unsigned pid;
 static char *in_address;

        in_address = malloc(strlen(address)+1);
        strcpy( in_address, address);
 
        /* skip over an & sign if there */
        if (*in_address == '&') ++in_address;

        if ( pipe(pim) == -1) return(-1);

        switch(pid=vfork()){
        case -1:
                close(pim[0]);
                close(pim[1]);
                return(-1);
        case 0:
                close(pim[1]);
                if (vfd_move(0,pim[0]) == -1 ) _exit(-1);
                binqqargs[0] = QMAILINJECT;
                binqqargs[1] = in_address;
                execv(*binqqargs, binqqargs);
        }
        fdm = pim[1];
        close(pim[0]);
        free(in_address);
        return(pid);
}



/* 
 * Deliver an email to an address
 * Return 0 on success
 * Return less than zero on failure
 * 
 * -1 = user is over quota
 * -2 and below are system failures
 * -3 mail is looping 
 */
int deliver_mail(char *address, char *quota)
{
 time_t tm;
 off_t file_count;
 long unsigned pid;
 int write_fd;
 int inject = 0;

    /* check if the email is looping to this user */
    if ( is_looping( address ) == 1 ) {
        printf("message is looping %s\n", address );
        return(-3);
    }

    /* This is a directory/Maildir location */
    if ( *address == '/' ) {

        /* if the user has a quota set */
        if ( strncmp(quota, "NOQUOTA", 2) != 0 ) {

            /* If the message is greater than 1000 bytes and
             * the user is over thier quota, return it back
             * to the sender. We allow messages less than 1000 bytes
             * to go through. This is so system admins can send a
             * user over quota message 
             */
            if (user_over_quota(address, quota)==1 && message_size>1000 ) {
                printf("user is over quota\n");
                return(-1);
            }
        }

        /* Format the email file name */
        gethostname(hostname,sizeof(hostname));
        pid=getpid();
        time (&tm);
        snprintf(local_file, 156, "%stmp/%lu.%lu.%s,S=%lu",
            address,(long unsigned)tm,(long unsigned)pid,
            hostname, (long unsigned)message_size);
        snprintf(local_file_new, 156, "%snew/%lu.%lu.%s,S=%lu",
            address,(long unsigned)tm,(long unsigned)pid,hostname, 
		(long unsigned)message_size);

        /* open the new email file */
        if ((write_fd=open(local_file,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR))== -1) {
            printf("can not open new email file errno=%d file=%s\n", 
                errno, local_file);
            return(-2);
        }
        if ( strcmp( address, bounce) == 0 ) {
            snprintf(DeliveredTo, AUTH_SIZE, 
                "%s%s", getenv("RPLINE"), getenv("DTLINE"));
        } else {
            snprintf(DeliveredTo, AUTH_SIZE, 
                "%sDelivered-To: %s\n", getenv("RPLINE"), 
                maildir_to_email(address));
        }

    /* This is an command */
    } else if ( *address == '|' ) { 

	/* run the command */ 
	run_command(address);
	return(0);

    /* must be an email address */
    } else {
       char *dtline;
       char *tstr;

	qmail_inject_open(address);
	write_fd = fdm;
        inject = 1;

	/* use the DTLINE variable, but skip past the dash in 
         * domain-user@domain 
         */
	if ( (dtline = getenv("DTLINE")) != NULL ) {
		while (*dtline!=0 && *dtline!=':' ) ++dtline;
		while (*dtline!=0 && *dtline!='-' ) ++dtline;
		if ( *dtline != 0 ) ++dtline;
                for(tstr=dtline;*tstr!=0;++tstr) if (*tstr=='\n') *tstr=0;
	} else {
	        if (*address=='&') ++address;
		dtline = address;
	}
        snprintf(DeliveredTo, AUTH_SIZE, 
            "%sDelivered-To: %s\n", getenv("RPLINE"), dtline);
    }

    if ( lseek(0, 0L, SEEK_SET) < 0 ) {
        printf("lseek errno=%d\n", errno);
        return(errno);
    }

    /* write the Return-Path: and Delivered-To: headers */
    if (write(write_fd,DeliveredTo,strlen(DeliveredTo))!= strlen(DeliveredTo)) {
        close(write_fd);
        /* Check if the user is over quota */
        if ( errno == EDQUOT ) {
            return(-1);
        } else {
            printf("failed to write delivered to line errno=%d\n",errno);
           return(errno);
        }
    }


    /* read it in chunks and write it to the new file */
    while((file_count=read(0,msgbuf,MSG_BUF_SIZE))>0) {
        if ( write(write_fd,msgbuf,file_count) == -1 ) {
            close(write_fd);

            /* if the write fails and we are writing to a Maildir
             * then unlink the file
             */
	    if ( unlink(local_file) != 0 ) {
                printf("unlink failed %s errno = %d\n", local_file, errno);
	        return(errno);
            }

            /* Check if the user is over quota */
            if ( errno == EDQUOT ) {
                return(-1);
            } else {
                printf("write failed errno = %d\n", errno);
                return(errno);
            }
        }
    }
    if ( inject == 1 ) {
	close(write_fd);
	return(0);
    }

    /* if we are writing to a Maildir, move it
     * into the new directory
     */

    /* sync the data to disk and close the file */
    errno = 0;
    if ( 
#ifdef FILE_SYNC
#ifdef HAVE_FDATASYNC
    fdatasync(write_fd) == 0 &&
#else
    fsync(write_fd) == 0 &&
#endif
#endif
         close(write_fd) == 0 ) {

        /* if this succeeds link the file to the new directory */
        if ( link( local_file, local_file_new ) == 0 ) {
	    if ( unlink(local_file) != 0 ) {
                printf("unlink failed %s errno = %d\n", local_file, errno);
            }
        } else {

            /* coda fs has problems with link, check for that error */
            if ( errno==EXDEV ) {

                /* try to rename the file instead */
                if (rename(local_file, local_file_new)!=0) {

                    /* even rename failed, time to give up */
                    printf("rename failed %s %s errno = %d\n", 
                        local_file, local_file_new, errno);
			return(errno);

                /* rename worked, so we are okay now */
                } else {
                    errno = 0;
                }

            /* link failed and we are not on coda */
            } else {
                printf("link failed %s %s errno = %d\n", 
                    local_file, local_file_new, errno);
            }
        }
    }

    /* return success */
    return(0);
}

/* Check if the vpopmail user has a .qmail file in thier directory
 * and foward to each email address, Maildir or program 
 *  that is found there in that file
 *
 * Return: 1 if we found and delivered email
 *       : 0 if not found
 *       : -1 if no user .qmail file 
 *
 */
int check_forward_deliver(char *dir)
{
 static char qmail_line[500];
 char tmpbuf[500];
 FILE *fs;
 int i;
 int return_value = 0;

    /* format the file name */
    snprintf(tmpbuf, 500, "%s/.qmail", dir);
    if ( (fs = fopen(tmpbuf,"r")) == NULL ) {

        /* no file, so just return */
        return(-1);
    }

    /* format a simple loop checker name */
    snprintf(tmpbuf, 500, "%s@%s", TheUser, TheDomain);

    /* read the file, line by line */
    while ( fgets(qmail_line, 500, fs ) != NULL ) {

        /* remove the trailing new line */
        for(i=0;qmail_line[i]!=0;++i) {
            if (qmail_line[i] == '\n') qmail_line[i] = 0;
        }

        /* simple loop check, if they are sending it to themselves
         * then skip this line
         */
        if ( strcmp( qmail_line, tmpbuf) == 0 ) continue;

        deliver_mail(qmail_line, "NOQUOTA");
        return_value = 1;
    }

    /* close the file */
    fclose(fs);

    /* return if we found one or not */
    return(return_value);
}

void sig_catch(sig,f)
int sig;
void (*f)();
{
#ifdef HAVE_SIGACTION
  struct sigaction sa;
  sa.sa_handler = f;
  sa.sa_flags = 0;
  sigemptyset(&sa.sa_mask);
  sigaction(sig,&sa,(struct sigaction *) 0);
#else
  signal(sig,f); /* won't work under System V, even nowadays---dorks */
#endif
}


/* open a pipe to a command 
 * return the pid or -1 if error
 */
void run_command(char *prog)
{
 int child;
 char *(args[4]);
 int wstat;

 while (*prog==' ') ++prog;
 while (*prog=='|') ++prog;

    if ( lseek(0, 0L, SEEK_SET) < 0 ) {
        printf("lseek errno=%d\n", errno);
        return;
    }

 switch(child = fork())
  {
   case -1:
     printf("unable to fork\n"); 
     exit(0);
   case 0:
     args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
     sig_catch(SIGPIPE,SIG_DFL);
     execv(*args,args);
     printf("Unable to run /bin/sh: ");
     exit(-1);
  }

  waitpid(child,&wstat,0);

}

/* Check for a looping message
 * This is done by checking for a matching line
 * in the email headers for Delivered-To: which
 * we put in each email
 * 
 * Return 1 if looping
 * Return 0 if not looping
 * Return -1 on error 
 */
int is_looping( char *address ) 
{
 int i;
 int found;
 char *dtline;

    /* if we don't know the message size then get it */
    if ( message_size == 0 ) {
        /* read the message to get the size */
        message_size = get_message_size();
    }
    if (*address=='&') ++address;

    /* check the DTLINE */
    dtline = getenv("DTLINE");
    if ( dtline != NULL && strstr(dtline, address) != NULL ) {
	return(1);
    }

    lseek(0,0L,SEEK_SET);
    while(fgets(loop_buf,sizeof(loop_buf),stdin)!=NULL){

        /* if we find the line, return error (looping) */
        if (strstr(loop_buf, "Delivered-To")!= 0 && 
            strstr(loop_buf, address)!=0 ) {

            /* return the loop found */
            return(1);

            /* check for the start of the body, we only need
            * to check the headers. 
            */
        } else {

            /* walk through the charaters in the body */
            for(i=0,found=0;loop_buf[i]!=0&&found==0;++i){
                switch(loop_buf[i]){

                    /* skip blank spaces and new lines */
                    case ' ':
                    case '\n':
                    case '\t':
                    case '\r':
                    break;

                    /* found a non blank, so we are still
                    * in the headers
                    */
                    default:
	
                        /* set the found non blank char flag */
                        found = 1;
                        break;
                }
            }

            /* if the line only had blanks, then it is the
             * delimiting line between the headers and the
             * body. We don't need to check the body for
             * the duplicate Delivered-To: line. Hence, we
             * are done with our search and can return the
             * looping not found value
            */
            if ( found == 0 ) {
                /* return not found looping message value */
                return(0);
            }
        }
    }

    /* if we get here then the there is either no body 
     * or the logic above failed and we scanned
     * the whole email, headers and body. 
     */
    return(0);
}

/* 
 * Get the size of the email message 
 * return the size 
 */
off_t get_message_size()
{
 ssize_t message_size;
 ssize_t bytes;

    if ( lseek(0, 0L,SEEK_SET) < 0 ) {
        printf("lseek error %d\n", errno);
        return(-1);
    }

    message_size = 0;
    while((bytes=read(0,msgbuf,MSG_BUF_SIZE))>0) {
        message_size += bytes;
    }
    return(message_size);
}

/* 
 * Check if the user is over quota
 *
 * Do all quota recalculation needed
 *
 * Return 1 if user is over quota
 * Return 0 if user is not over quota
 */
int user_over_quota(char *maildir, char *quota)
{
 ssize_t per_user_limit;
 off_t cur_msg_bytes;
 int i;
 int ret_value = 0;
 off_t new_size;

    /* translate the quota to a number */
    per_user_limit = atol(quota);
    for(i=0;quota[i]!=0;++i){
        if ( quota[i] == 'k' || 
            quota[i] == 'K' ) {
            per_user_limit = per_user_limit * 1000;
            break;
        }
        if ( quota[i] == 'm' || quota[i] == 'M' ) {
            per_user_limit = per_user_limit * 1000000;
            break;
        }
    }

    /* Get thier current total */
    cur_msg_bytes = check_quota(maildir);

    /* Check if this email would bring them over quota */
    if ( cur_msg_bytes + message_size > per_user_limit ) {

        /* recalculate thier quota since they might have
         * deleted email 
         */
        cur_msg_bytes = recalc_quota(maildir);
        if ( cur_msg_bytes + message_size > per_user_limit ) {
            ret_value = 1;
        }
    }

    /* If we are going to deliver it, then add in the size */
    if ( ret_value == 0 ) {
        new_size = message_size + cur_msg_bytes;
        update_quota(new_size);
    } 
    close(CurrentQuotaSizeFd);
    return(ret_value);
}


/*
 * check for locked account
 * deliver to .qmail file if any
 * deliver to user if no .qmail file
 */
void checkuser() 
{
    if (vpw->pw_gid & BOUNCE_MAIL ) {
        printf("vdelivermail: account is locked email bounced %s@%s\n",
            TheUser, TheDomain);
        vexit(100);
    }

    /* If thier directory path is empty make them a new one */
    if ( vpw->pw_dir == NULL || vpw->pw_dir[0]==0 ) {
      uid_t pw_uid;
      gid_t pw_gid;

	vget_assign(TheDomain,NULL,0,&pw_uid,&pw_gid);
        if ( make_user_dir(vpw->pw_name, TheDomain, pw_uid, pw_gid)==NULL){
            printf("Auto creation of maildir failed. vpopmail (#5.9.8)\n");
            vexit(100);
        }
    }

    /* check for a .qmail file in thier Maildir
     * If it exists, then deliver to the contents and exit
     */
    if ( check_forward_deliver(vpw->pw_dir) == 1 ) {
        vexit(0);
    }

    snprintf(TheDir, AUTH_SIZE, "%s/Maildir/", vpw->pw_dir);
    if ( deliver_mail(TheDir, vpw->pw_shell) != 0 ) {
        vexit(100);
    }
}


/*
 * the vpopmail user does not exist. Follow the rest of
 * the directions in the .qmail-default file
 */
void usernotfound() 
{
 int ret;

    /* If they want to delete email for non existant users
     * then just exit 0. Qmail will delete the email for us
     */
    if ( strcmp(bounce, DELETE_ALL) == 0 ) {
        /* just exit 0 and qmail will delete the email from the system */
        vexit(0);

    /* If they want to bounce the email back then
     * print a message and exit 100
     */
    } else if ( strcmp(bounce, BOUNCE_ALL) == 0 ) {
        printf("Sorry, no mailbox here by that name. vpopmail (#5.1.1)\n");

        /* exit 100 causes the email to be bounced back */
        vexit(100);

    }

    /* check if it is a path add the /Maildir/ for delivery */
    if ( strstr( bounce, VPOPMAILDIR ) != 0 ) {
        strcat( bounce, "/Maildir/");
    }

    ret = deliver_mail(bounce, "NOQUOTA" );

    /* Send the email out, if we get a -1 then the user is over quota */
    if ( ret == -1 ) {
        printf("user is over quota, mail bounced\n");
        vexit(100);
    } else if ( ret == -2 ) {
        printf("system error\n");
        vexit(100);
    } else if ( ret != 0 ) {
        printf("mail is looping\n");
        vexit(100);
    }

}


syntax highlighted by Code2HTML, v. 0.9.1