summaryrefslogblamecommitdiffstats
path: root/util/outmail.c
blob: d6b19bb4d5b36054700168a3d888296fe0e066e3 (plain) (tree)

















































































































































































































































































                                                                            
/* $Id: outmail.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
#include "pttstruct.h"


#ifdef HAVE_SETPROCTITLE

#include <sys/types.h>
#include <libutil.h>

void initsetproctitle(int argc, char **argv, char **envp) {
}

#else

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

char **Argv = NULL;          /* pointer to argument vector */
char *LastArgv = NULL;       /* end of argv */
extern char **environ;

void initsetproctitle(int argc, char **argv, char **envp) {
    register int i;
    
    /* Move the environment so setproctitle can use the space at
       the top of memory. */
    for(i = 0; envp[i]; i++);
    environ = malloc(sizeof(char *) * (i + 1));
    for(i = 0; envp[i]; i++)
    environ[i] = strdup(envp[i]);
    environ[i] = NULL;
    
    /* Save start and extent of argv for setproctitle. */
    Argv = argv;
    if(i > 0)
    LastArgv = envp[i - 1] + strlen(envp[i - 1]);
    else
    LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
}

static void do_setproctitle(const char *cmdline) {
    char buf[256], *p;
    int i;
    
    strncpy(buf, cmdline, 256);
    buf[255] = '\0';
    i = strlen(buf);
    if(i > LastArgv - Argv[0] - 2) {
    i = LastArgv - Argv[0] - 2;
    }
    strcpy(Argv[0], buf);
    p = &Argv[0][i];
    while(p < LastArgv)
    *p++='\0';
    Argv[1] = NULL;
}

void setproctitle(const char* format, ...) {
    char buf[256];
    
    va_list args;
    va_start(args, format);
    vsprintf(buf, format,args);
    do_setproctitle(buf);
    va_end(args);
}
#endif





#define SPOOL BBSHOME "/out"
#define INDEX SPOOL "/.DIR"
#define NEWINDEX SPOOL "/.DIR.sending"
#define FROM ".bbs@" MYHOSTNAME
#define SMTPPORT 25

int waitReply(int sock) {
    char buf[256];
    
    if(read(sock, buf, sizeof(buf)) <= 0)
    return -1;
    else
    return buf[0] - '0';
}

int sendRequest(int sock, char *request) {
    return write(sock, request, strlen(request)) < 0 ? -1 : 0;
}

int connectMailServer() {
    int sock;
    struct sockaddr_in addr;
    
    if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    perror("socket");
    return -1;
    }
    
    memset(&addr, 0, sizeof(addr));
#ifdef FreeBSD
    addr.sin_len = sizeof(addr);
#endif
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SMTPPORT);
    addr.sin_addr.s_addr = inet_addr(RELAY_SERVER_IP);
    
    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    perror(RELAY_SERVER_IP);
    close(sock);
    return -1;
    }
    
    if(waitReply(sock) != 2) {
    close(sock);
    return -1;
    }
    
    if(sendRequest(sock, "helo " MYHOSTNAME "\n") || waitReply(sock) != 2) {
    close(sock);
    return -1;
    } else
    return sock;
}

void disconnectMailServer(int sock) {
    sendRequest(sock, "quit\n");
    /* drop the reply :p */
    close(sock);
}

void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) {
    int n;
    char buf[2048];
    
    n = snprintf(buf, sizeof(buf), "From: %s\nTo: %s\nSubject: %s\n\n",
         from, to, subject);
    write(sock, buf, n);
    
    while(fgets(buf, sizeof(buf), fp)) {
    if(buf[0] == '.' && buf[1] == '\n')
        strcpy(buf, "..\n");
    write(sock, buf, strlen(buf));
    }
}

void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) {
    char buf[256];
    
    snprintf(buf, sizeof(buf), "mail from: %s\n", from);
    if(sendRequest(sock, buf) || waitReply(sock) != 2)
    return;
    
    snprintf(buf, sizeof(buf), "rcpt to: %s\n", to);
    if(sendRequest(sock, buf) || waitReply(sock) != 2)
    return;
    
    if(sendRequest(sock, "data\n") || waitReply(sock) != 3)
    return;
    
    doSendBody(sock, fp, from, to, subject);

    if(sendRequest(sock, "\n.\n") || waitReply(sock) != 2)
    return;
}

void sendMail() {
    int fd, sock;
    MailQueue mq;
    
    if(access(NEWINDEX, R_OK | W_OK)) {
    if(link(INDEX, NEWINDEX) || unlink(INDEX))
        /* nothing to do */
        return;
    }
    
    if((sock = connectMailServer()) < 0) {
    fprintf(stderr, "connect server failed...\n");
    return;
    }
    
    fd = open(NEWINDEX, O_RDONLY);
    flock(fd, LOCK_EX);
    while(read(fd, &mq, sizeof(mq)) > 0) {
    FILE *fp;
    char buf[256];
    
    snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM);
    if((fp = fopen(mq.filepath, "r"))) {
        setproctitle("outmail: sending %s", mq.filepath);
        doSendMail(sock, fp, buf, mq.rcpt, mq.subject);
        fclose(fp);
        unlink(mq.filepath);
    } else {
        perror(mq.filepath);
    }
    }
    flock(fd, LOCK_UN);
    close(fd);
    unlink(NEWINDEX);
    
    disconnectMailServer(sock);
}

void listQueue() {
    int fd;
    
    if((fd = open(INDEX, O_RDONLY)) >= 0) {
    int counter = 0;
    MailQueue mq;
    
    flock(fd, LOCK_EX);
    while(read(fd, &mq, sizeof(mq)) > 0) {
        printf("%s:%s -> %s:%s\n", mq.filepath, mq.username, mq.rcpt,
           mq.subject);
        counter++;
    }
    flock(fd, LOCK_UN);
    close(fd);
    printf("\nTotal: %d mails in queue\n", counter);
    } else {
    perror(INDEX);
    }
}

void usage() {
    fprintf(stderr, "usage: outmail [-qh]\n");
}

void wakeup(int s) {
}

int main(int argc, char **argv, char **envp) {
    int ch;
 
    signal(SIGHUP, wakeup);
    initsetproctitle(argc, argv, envp);
    
    if(chdir(BBSHOME))
    return 1;
    while((ch = getopt(argc, argv, "qh")) != -1) {
    switch(ch) {
    case 'q':
        listQueue();
        return 0;
    default:
        usage();
        return 0;
    }
    }
    for(;;) {
    sendMail();
    setproctitle("outmail: sleeping");
    sleep(60 * 3); /* send mail every 3 minute */
    }
    return 0;
}