/* $Id: outmail.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "pttstruct.h" #ifdef HAVE_SETPROCTITLE #include #include void initsetproctitle(int argc, char **argv, char **envp) { } #else #include #include #include #include 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; }