diff -u --exclude=localqueue.diff --new-file -r ./Makefile.in /home/basher584/prog/nullmailer-lq-1.00RC5/Makefile.in --- ./Makefile.in Fri Dec 29 23:22:51 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/Makefile.in Thu Sep 12 21:19:11 2002 @@ -368,6 +368,7 @@ chown nullmail $(DESTDIR)$(localstatedir)/* chown nullmail $(DESTDIR)$(sbindir)/nullmailer-queue chmod u+s $(DESTDIR)$(sbindir)/nullmailer-queue + chmod u+s $(DESTDIR)$(sbindir)/nullmailer-localqueue chown nullmail $(DESTDIR)$(bindir)/mailq chmod u+s $(DESTDIR)$(bindir)/mailq diff -u --exclude=localqueue.diff --new-file -r ./lib/defines.h /home/basher584/prog/nullmailer-lq-1.00RC5/lib/defines.h --- ./lib/defines.h Wed Feb 16 13:24:26 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/lib/defines.h Thu Sep 12 21:19:11 2002 @@ -9,5 +9,6 @@ extern const char* PROTOCOL_DIR; extern const char* BIN_DIR; extern const char* SBIN_DIR; +extern const char* ADMINFILE; #endif /* NULLMAILER__DEFINES__H__ */ diff -u --exclude=localqueue.diff --new-file -r ./lib/hostname.cc /home/basher584/prog/nullmailer-lq-1.00RC5/lib/hostname.cc --- ./lib/hostname.cc Fri Dec 29 22:02:46 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/lib/hostname.cc Thu Sep 12 21:58:44 2002 @@ -23,6 +23,7 @@ #include "mystring/mystring.h" #include #include +#include static mystring* hostname_cache = 0; static mystring* domainname_cache = 0; @@ -30,7 +31,7 @@ #ifdef HAVE_GETDOMAINNAME // Re-declare the prototype here, as some systems don't declare it // in a predictable header file. -extern "C" int getdomainname(); +extern "C" int getdomainname(char *, size_t); #endif static void getnames() diff -u --exclude=localqueue.diff --new-file -r ./lib/make_defines.sh /home/basher584/prog/nullmailer-lq-1.00RC5/lib/make_defines.sh --- ./lib/make_defines.sh Thu Sep 2 16:13:08 1999 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/lib/make_defines.sh Thu Sep 12 22:26:13 2002 @@ -7,3 +7,4 @@ echo "const char* PROTOCOL_DIR=\"$3/\";" >>defines.cc echo "const char* BIN_DIR=\"$4/\";" >>defines.cc echo "const char* SBIN_DIR=\"$5/\";" >>defines.cc +echo "const char* ADMINFILE=\"/root/mail/nullmail\";" >>defines.cc diff -u --exclude=localqueue.diff --new-file -r ./lib/makefield.cc /home/basher584/prog/nullmailer-lq-1.00RC5/lib/makefield.cc --- ./lib/makefield.cc Thu Jun 15 11:12:21 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/lib/makefield.cc Thu Sep 12 21:19:11 2002 @@ -21,6 +21,7 @@ #include "config.h" #include "defines.h" +#include #include #include #include "itoa.h" diff -u --exclude=localqueue.diff --new-file -r ./protocols/smtp.cc /home/basher584/prog/nullmailer-lq-1.00RC5/protocols/smtp.cc --- ./protocols/smtp.cc Mon Oct 2 14:14:08 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/protocols/smtp.cc Thu Sep 12 21:19:11 2002 @@ -38,6 +38,8 @@ { fdibuf in; fdobuf out; + fdobuf debug; + public: smtp(int fd); ~smtp(); @@ -50,7 +52,7 @@ }; smtp::smtp(int fd) - : in(fd), out(fd) + : in(fd), out(fd), debug("/tmp/smtp.out",fdobuf::append | fdobuf::create) { } @@ -88,10 +90,16 @@ { mystring msg; int code; - if(!cmd) + if(!cmd) { code = get(msg); - else + debug << msg << "\n"; + debug.flush(); + } else { code = put(cmd, msg); + debug << "Cmd: " << cmd << "\n" << "Msg: "<= (range+100)) { int e; diff -u --exclude=localqueue.diff --new-file -r ./src/Makefile.in /home/basher584/prog/nullmailer-lq-1.00RC5/src/Makefile.in --- ./src/Makefile.in Fri Dec 29 23:22:57 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/src/Makefile.in Thu Sep 12 21:19:11 2002 @@ -70,7 +70,7 @@ bin_PROGRAMS = mailq nullmailer-inject -sbin_PROGRAMS = nullmailer-queue nullmailer-send sendmail +sbin_PROGRAMS = nullmailer-queue nullmailer-send sendmail nullmailer-localqueue #noinst_PROGRAMS = address @@ -87,6 +87,9 @@ nullmailer_queue_SOURCES = queue.cc nullmailer_queue_LDADD = ../lib/libnullmailer.a +nullmailer_localqueue_SOURCES = localqueue.cc +nullmailer_localqueue_LDADD = ../lib/libnullmailer.a + nullmailer_send_SOURCES = send.cc nullmailer_send_LDADD = ../lib/libnullmailer.a @@ -112,6 +115,9 @@ nullmailer_queue_OBJECTS = queue.o nullmailer_queue_DEPENDENCIES = ../lib/libnullmailer.a nullmailer_queue_LDFLAGS = +nullmailer_localqueue_OBJECTS = localqueue.o +nullmailer_localqueue_DEPENDENCIES = ../lib/libnullmailer.a +nullmailer_localqueue_LDFLAGS = nullmailer_send_OBJECTS = send.o nullmailer_send_DEPENDENCIES = ../lib/libnullmailer.a nullmailer_send_LDFLAGS = @@ -128,8 +134,8 @@ TAR = gtar GZIP_ENV = --best -SOURCES = $(mailq_SOURCES) $(nullmailer_inject_SOURCES) $(nullmailer_queue_SOURCES) $(nullmailer_send_SOURCES) $(sendmail_SOURCES) -OBJECTS = $(mailq_OBJECTS) $(nullmailer_inject_OBJECTS) $(nullmailer_queue_OBJECTS) $(nullmailer_send_OBJECTS) $(sendmail_OBJECTS) +SOURCES = $(mailq_SOURCES) $(nullmailer_inject_SOURCES) $(nullmailer_queue_SOURCES) $(nullmailer_localqueue_SOURCES) $(nullmailer_send_SOURCES) $(sendmail_SOURCES) +OBJECTS = $(mailq_OBJECTS) $(nullmailer_inject_OBJECTS) $(nullmailer_queue_OBJECTS) $(nullmailer_localqueue_OBJECTS) $(nullmailer_send_OBJECTS) $(sendmail_OBJECTS) all: all-redirect .SUFFIXES: @@ -223,6 +229,10 @@ @rm -f nullmailer-queue $(CXXLINK) $(nullmailer_queue_LDFLAGS) $(nullmailer_queue_OBJECTS) $(nullmailer_queue_LDADD) $(LIBS) +nullmailer-localqueue: $(nullmailer_localqueue_OBJECTS) $(nullmailer_localqueue_DEPENDENCIES) + @rm -f nullmailer-localqueue + $(CXXLINK) $(nullmailer_localqueue_LDFLAGS) $(nullmailer_localqueue_OBJECTS) $(nullmailer_localqueue_LDADD) $(LIBS) + nullmailer-send: $(nullmailer_send_OBJECTS) $(nullmailer_send_DEPENDENCIES) @rm -f nullmailer-send $(CXXLINK) $(nullmailer_send_LDFLAGS) $(nullmailer_send_OBJECTS) $(nullmailer_send_LDADD) $(LIBS) diff -u --exclude=localqueue.diff --new-file -r ./src/inject.cc /home/basher584/prog/nullmailer-lq-1.00RC5/src/inject.cc --- ./src/inject.cc Thu Aug 10 14:45:00 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/src/inject.cc Thu Sep 12 21:19:11 2002 @@ -404,8 +404,8 @@ headers.append("Resent-To: " + make_recipient_list()); } } - if(!header_has_to && !header_has_cc) - headers.append("Cc: recipient list not shown: ;"); + //if(!header_has_to && !header_has_cc) + // headers.append("Cc: recipient list not shown: ;"); return true; } @@ -413,7 +413,35 @@ // Message sending /////////////////////////////////////////////////////////////////////////////// static fdobuf* nqpipe = 0; +static fdobuf* adminfile = 0; //TODO give adminfile a defualt static pid_t pid = 0; +static pid_t adminpid = 0; +static bool adminmsg = false; +static bool adminonly = true; +static int affd; +bool admin_addr(mystring addr); + +void admin_only() { + for(slist::iter iter(recipients); iter; iter++) { + //TODO add config option for sending to local spool like doremap + if(!admin_addr(*iter)) { + adminonly=false; + } else { + adminmsg = true; + } + } +} + +bool admin_addr(mystring addr) { + int i = addr.find_last('@'); + if(i < 0) + return true; + mystring hostname = addr.right(i+1); + if(hostname == defaulthost || hostname == "localhost") + return true; + else + return false; +} void exec_queue() { @@ -429,74 +457,179 @@ exit(1); } -bool start_queue() +void exec_localqueue() { - int pipe1[2]; - if(pipe(pipe1) == -1) - fail_sys("Could not create pipe to nullmailer-queue"); - fout.flush(); - pid = fork(); - if(pid == -1) - fail_sys("Could not fork"); - if(pid == 0) { - close(pipe1[1]); - close(0); - dup2(pipe1[0], 0); - exec_queue(); - } - else { - close(pipe1[0]); - nqpipe = new fdobuf(pipe1[1], true); + if(chdir(SBIN_DIR) == -1) { + fout << "nullmailer-inject: Could not change directory to " << SBIN_DIR + << ": " << strerror(errno) << endl; + exit(1); } + else + execl("nullmailer-localqueue", "nullmailer-localqueue", 0); + fout << "nullmailer-inject: Could not exec nullmailer-localqueue: " + << strerror(errno) << endl; + exit(1); +} + +bool start_queue() +{ + if(!adminonly) { + int pipe1[2]; + if(pipe(pipe1) == -1) + fail_sys("Could not create pipe to nullmailer-queue"); + fout.flush(); + pid = fork(); + if(pid == -1) + fail_sys("Could not fork"); + if(pid == 0) { + close(pipe1[1]); + close(0); + dup2(pipe1[0], 0); + exec_queue(); + } + else { + close(pipe1[0]); + nqpipe = new fdobuf(pipe1[1], true); + } + } + if(adminmsg) { + int pipe2[2]; + if(pipe(pipe2) == -1) + fail_sys("Could not create pipe to nullmailer-localqueue"); + fout.flush(); + adminpid = fork(); + if(adminpid == -1) + fail_sys("Could not fork"); + if(adminpid == 0) { + close(pipe2[1]); + close(0); + dup2(pipe2[0], 0); + exec_localqueue(); + } + else { + close(pipe2[0]); + adminfile = new fdobuf(pipe2[1],true); + } + } return true; } bool send_env() { - if(!(*nqpipe << sender << "\n")) - fail("Error sending sender to nullmailer-queue."); - for(slist::iter iter(recipients); iter; iter++) - if(!(*nqpipe << *iter << "\n")) - fail("Error sending recipients to nullmailer-queue."); - if(!(*nqpipe << endl)) - fail("Error sending recipients to nullmailer-queue."); + if(adminmsg) { + if(!(*adminfile << sender << "\n")) + fail("Error sending sender to adminfile."); + } + if(!adminonly) { + if(!(*nqpipe << sender << "\n")) + fail("Error sending sender to nullmailer-queue."); + } + if(!adminonly) { + for(slist::iter iter(recipients); iter; iter++) { + if(!(admin_addr(*iter))) { + if(!(*nqpipe << *iter << "\n")) + fail("Error sending recipients to nullmailer-queue."); + } + } + if(!(*nqpipe << endl)) + fail("Error sending recipients to nullmailer-queue."); + } return true; } bool send_header() { - for(slist::iter iter(headers); iter; iter++) - if(!(*nqpipe << *iter << "\n")) - fail("Error sending header to nullmailer-queue."); - if(!(*nqpipe << endl)) - fail("Error sending header to nullmailer-queue."); + for(slist::iter iter(headers); iter; iter++) { + if(adminmsg) { + if(!(*adminfile<< *iter << "\n")) + fail("Error sending header to adminfile."); + } + if(!adminonly) { + if(!(*nqpipe << *iter << "\n")) + fail("Error sending header to nullmailer-queue."); + } + } + if(adminmsg) + if(!(*adminfile << "\n")) + fail("Error sending header endl to adminfile."); + if(!adminonly) + if(!(*nqpipe << endl)) + fail("Error sending header endl to nullmailer-queue."); return true; } bool send_body() { - if(!(*nqpipe << cur_line) || - !fdbuf_copy(fin, *nqpipe)) - fail("Error sending message body to nullmailer-queue."); + if(adminonly) { + if(!(*adminfile << cur_line) || + !fdbuf_copy(fin, *adminfile)) + fail("Error sending message body to adminfile."); + if(!(*adminfile << "\n")) + fail("Error sending message body to adminfile."); + if(!(adminfile->flush())) + fail("Error sending message body to adminfile."); + } else if (!adminmsg) { + if(!(*nqpipe << cur_line) || + !fdbuf_copy(fin, *nqpipe)) + fail("Error sending message body to nullmailer-queue."); + } else { + if(!(*nqpipe << cur_line )) + fail("Error sending message body to nullmailer-queue."); + if(!(*adminfile << cur_line )) + fail("Error sending message body to adminfile."); + while(fin.getline(cur_line)) { + if(!(*nqpipe << cur_line << "\n")) + fail("Error sending message body to nullmailer-queue."); + if(!(*adminfile << cur_line << "\n")) + fail("Error sending message body to adminfile."); + } + if(!(nqpipe->flush())) { + fail("Error sending message body to nullmailer-queue."); + } + if(!(*adminfile << "\n")) + fail("Error sending message body to adminfile."); + if(!(adminfile->flush())) { + fail("Error sending message body to adminfile."); + } + } return true; } bool wait_queue() { - if(!nqpipe->close()) - fail("Error closing pipe to nullmailer-queue."); - int status; - if(waitpid(pid, &status, 0) == -1) - fail("Error catching the return value from nullmailer-queue."); - if(WIFEXITED(status)) { - status = WEXITSTATUS(status); - if(status) - fail("nullmailer-queue failed."); - else - return true; - } - else - fail("nullmailer-queue crashed or was killed."); + if(adminmsg) { + if(!adminfile->close()) + fail("Error closing pipe to nullmailer-localqueue."); + int status; + if(waitpid(adminpid, &status, 0) == -1) + fail("Error catching the return value from nullmailer-localqueue."); + if(WIFEXITED(status)) { + status = WEXITSTATUS(status); + if(status) + fail("nullmailer-localqueue failed."); + else + return true; + } + else + fail("nullmailer-localqueue crashed or was killed."); + } + if(!adminonly) { + if(!nqpipe->close()) + fail("Error closing pipe to nullmailer-queue."); + int status; + if(waitpid(pid, &status, 0) == -1) + fail("Error catching the return value from nullmailer-queue."); + if(WIFEXITED(status)) { + status = WEXITSTATUS(status); + if(status) + fail("nullmailer-queue failed."); + else + return true; + } + else + fail("nullmailer-queue crashed or was killed."); + } + return true; } bool send_message() @@ -509,10 +642,11 @@ send_body(); return true; } - else - return start_queue() && - send_env() && send_header() && send_body() && - wait_queue(); + else + admin_only(); + return start_queue() && + send_env() && send_header() && send_body() && + wait_queue(); } /////////////////////////////////////////////////////////////////////////////// diff -u --exclude=localqueue.diff --new-file -r ./src/localqueue.cc /home/basher584/prog/nullmailer-lq-1.00RC5/src/localqueue.cc --- ./src/localqueue.cc Wed Dec 31 19:00:00 1969 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/src/localqueue.cc Thu Sep 12 22:47:24 2002 @@ -0,0 +1,195 @@ +// nullmailer -- a simple relay-only MTA +// Copyright (C) 1999,2000 Bruce Guenter +// +// 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 +// +// You can contact me at . There is also a mailing list +// available to discuss this package. To subscribe, send an email to +// . + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "itoa.h" +#include "defines.h" +#include "mystring/mystring.h" +#include "fdbuf/fdbuf.h" +#include "configio.h" +#include "canonicalize.h" +#include "hostname.h" +#include + +#define BUFSIZ 1024 +extern "C" int lockf(int fd, int cmd, off_t len); +extern "C" off_t lseek(int fildes, off_t offset, int whence); + +#define fail(MSG) do{ fout << "nullmailer-localqueue: " << MSG << endl; return false; }while(0) + +pid_t pid = getpid(); +uid_t uid = getuid(); +time_t timesecs = time(0); +mystring adminaddr; +mystring localhost; +bool remapadmin = false; + +bool is_dir(const char* path) +{ + struct stat buf; + return !stat(path, &buf) && S_ISDIR(buf.st_mode); +} + +bool is_exist(const char* path) +{ + struct stat buf; + return !stat(path, &buf); +} + +int fsyncdir(const char* path) +{ + int fd = open(path, O_RDONLY); + if(fd == -1) + return 0; + int result = fsync(fd); + if(result == -1 && errno != EIO) + result = 0; + close(fd); + return result; +} + +void trigger() +{ + int fd = open(QUEUE_TRIGGER, O_WRONLY|O_NONBLOCK, 0666); + if(fd == -1) + return; + char x = 0; + write(fd, &x, 1); + close(fd); +} + +bool validate_addr(mystring& addr, bool doremap) +{ + int i = addr.find_last('@'); + if(i < 0) + return false; + mystring hostname = addr.right(i+1); + if(doremap && remapadmin) { + if(hostname == localhost || hostname == "localhost") + addr = adminaddr; + } + else if(hostname.find_first('.') < 0) + return false; + return true; +} + +bool copyenv(fdobuf& out) +{ + char str2[BUFSIZ]; + mystring str; + + if(!fin.getline(str) || !str) + fail("Could not read envelope sender."); + if(!validate_addr(str, false)) + fail("Envelope sender address is invalid."); + char buf[100]; + if(!strftime(buf, 100, " %a %b %d %H:%M:%S -0000 %Y", gmtime(×ecs))) + fail("Error generating a date string."); + str+= buf; + if(!(out << "From " << str << endl)) + fail("Could not write envelope sender."); + return true; +} + +bool makereceived(fdobuf& out) +{ + mystring line("Received: (nullmailer pid "); + line += itoa(pid); + line += " invoked by uid "; + line += itoa(uid); + line += ");\n\t"; + char buf[100]; + if(!strftime(buf, 100, "%a, %d %b %Y %H:%M:%S -0000\n", gmtime(×ecs))) + fail("Error generating a date string."); + line += buf; + if(!(out << line)) + fail("Could not write received line to message."); + return true; +} + +bool dump(int fd) +{ + fdobuf out(fd); + if(!copyenv(out)) + return false; + if(!makereceived(out)) + return false; + if(!fdbuf_copy(fin, out)) + fail("Error copying the message to the queue file."); + if(!out.flush()) + fail("Error flushing the output file."); + return true; +} + +bool deliver() +{ + int out = open(ADMINFILE, O_CREAT|O_WRONLY|O_APPEND, 0666); + if(out < 0) + fail("Could not open admin spool file for writing"); + off_t pos=0; + if ((pos = lseek(out,0,SEEK_CUR))<0) + fail("Could not get current seek position"); + while(lockf(out,F_TEST,pos)==-1) { + fout.flush(); + sleep(1); + } + if(lockf(out,F_LOCK,pos)!=0) + fail("Could not lock file."); + if(!dump(out)) { + if(lockf(out,F_ULOCK,pos)!=0) + fail("Error unlocking file."); + if(close(out)!=0) + fail("Error closing the output file."); + unlink(ADMINFILE); + return false; + } + if(lockf(out,F_ULOCK,pos)!=0) + fail("Error unlocking file."); + if(close(out)!=0) + fail("Error closing the output file."); + return true; +} + +mystring defaulthost; +mystring defaultdomain; + +int main(int, char*[]) +{ + if(config_read("adminaddr", adminaddr) && !!adminaddr) { + remapadmin = true; + defaulthost = hostname(); + defaultdomain = domainname(); + canonicalize(localhost); + } + + if(!deliver()) + return 1; + return 0; +} diff -u --exclude=localqueue.diff --new-file -r ./src/send.cc /home/basher584/prog/nullmailer-lq-1.00RC5/src/send.cc --- ./src/send.cc Wed Jul 12 12:48:37 2000 +++ /home/basher584/prog/nullmailer-lq-1.00RC5/src/send.cc Thu Sep 12 22:00:32 2002 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include