Skip to content

Commit

Permalink
It is working now ...
Browse files Browse the repository at this point in the history
git-svn-id: svn://localhost/home/matthias/source/svn/matthias_wimmer@116 4ea7d500-c7de-0310-95d6-fef3d14ee6ae
  • Loading branch information
matthias committed Mar 16, 2007
1 parent bbe5c41 commit 9a588eb
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 1 deletion.
3 changes: 3 additions & 0 deletions configure.ac
Expand Up @@ -83,5 +83,8 @@ if test "$libpopt" != "yes"; then
AC_MSG_ERROR([Couldn't find required libpopt installation])
fi

dnl define where the configuration file is located
AC_DEFINE_DIR(CONFIG_DIR,sysconfdir,[where the configuration file can be found])

dnl Create the makefiles
AC_OUTPUT(Makefile intl/Makefile po/Makefile.in m4/Makefile )
273 changes: 272 additions & 1 deletion couriersrs.cc
Expand Up @@ -23,6 +23,277 @@
#endif

#include "couriersrs.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
#include <cerrno>
#include <cstring>

int main() {
namespace couriersrs {
/**
* read a message from stdin and pass to sendmail
*
* @return 0 on success, 1 on error
*/
int pass2sendmail(char const* const sendmail, const std::string& prepended_header, char const* const sender, char const* const recipient) {
// create a pipe for passing the message to sendmail
int pipe_fd[2];
if (pipe(pipe_fd)) {
std::cerr << N_("Error creating pipe: ") << std::strerror(errno) << std::endl;
return 1;
}

// run sendmail as a child process
pid_t pid = fork();
if (pid == -1) {
close(pipe_fd[0]);
close(pipe_fd[1]);
std::cerr << N_("Error forking process: ") << std::strerror(errno) << std::endl;
return 1;
}
if (pid == 0) {
// inside child process
close(pipe_fd[1]);
close(0);
dup2(pipe_fd[0], 0);
close(pipe_fd[0]);
execl(sendmail, sendmail, "-f", sender, recipient, NULL);

// there has been an error, if we reach this point
return 1;
}

// inside parent process
close(pipe_fd[0]);

// pass message to sendmail

// write prepended header
if (prepended_header != "") {
write(pipe_fd[1], prepended_header.c_str(), prepended_header.length());
}

// Pass the real message
while (std::cin) {
std::string line;
std::getline(std::cin, line);
line += "\n";

write(pipe_fd[1], line.c_str(), line.length());
}

// close the pipe
close(pipe_fd[1]);

// wait for sendmail to terminate
int status = 0;
waitpid(pid, &status, 0);

// error?
if (WEXITSTATUS(status)) {
std::cerr << N_("Error in sendmail coprocess") << std::endl;
return 1;
}

return 0;
}
}

int main(int argc, char const** argv) {
int do_version = 0;
char const* secret = NULL;
char const* secret_file = CONFIG_DIR "/srs_secret";
char const* separator = "-";
int ret = 0;
int noforward = 0;
int noreverse = 0;
int reverse = 0;
char const* dest_address = NULL;
char const* sender = std::getenv("SENDER");
char const* recipient = std::getenv("RECIPIENT");
char const* sendmail = "/usr/sbin/sendmail";

struct poptOption options[] = {
{ "version", 'v', POPT_ARG_NONE, &do_version, 0, N_("print server version"), NULL},
{ "secret", 's', POPT_ARG_STRING, &secret, 0, N_("use this as the secret"), "secret"},
{ "secretfile", 'S', POPT_ARG_STRING, &secret_file, 0, N_("load SRS secret from a file"), "filename"},
{ "separator", 0, POPT_ARG_STRING, &separator, 0, N_("address separator character"), "separator character"},
{ "noforward", 0, POPT_ARG_NONE, &noforward, 0, N_("disable SRS forward rewriting"), NULL},
{ "noreverse", 0, POPT_ARG_NONE, &noreverse, 0, N_("disable SRS reverse rewriting"), NULL},
{ "reverse", 'r', POPT_ARG_NONE, &reverse, 0, N_("do reverse instead of forward transformation"), NULL},
{ "address", 0, POPT_ARG_STRING, &sender, 0, N_("overwrite sender address"), "address"},
{ "alias", 0, POPT_ARG_STRING, &recipient, 0, N_("overwrite recipient address"), "address"},
{ "sendmail", 0, POPT_ARG_STRING, &sendmail, 0, N_("sendmail executable to use"), "file"},
POPT_AUTOHELP
POPT_TABLEEND
};

// parse command line options
poptContext pCtx = poptGetContext(NULL, argc, argv, options, 0);
while ((ret = poptGetNextOpt(pCtx)) >= 0) {
switch (ret) {
// access argument by poptGetOptArg(pCtx)
}
}

// error parsing command line?
if (ret < -1) {
std::cerr << poptBadOption(pCtx, POPT_BADOPTION_NOALIAS) << ": " << poptStrerror(ret) << std::endl;
return 1;
}

// get destination address
if (!reverse && !do_version) {
dest_address = poptGetArg(pCtx);
if (!dest_address) {
std::cerr << N_("No destination address given.") << std::endl;
return 1;
}
}

// anything left?
if (poptPeekArg(pCtx) != NULL) {
// XXX i20n
std::cerr << N_("Invalid argument: ") << poptGetArg(pCtx) << std::endl;
return 1;
}

// print version information?
if (do_version) {
// XXX i20n
std::cout << PACKAGE << N_(" version ") << VERSION << std::endl << std::endl;
std::cout << N_("Default location of the SRS secret file is: ") << CONFIG_DIR "/srs_secret" << std::endl;
return 0;
}

// create srs instance
srs_t* srs = srs_new();

// set the secret
if (secret) {
srs_add_secret(srs, secret);
} else {
// we have to read it from the secret file
std::ifstream secret_file_stream(secret_file, std::ios::in);
if (!secret_file_stream) {
std::cerr << N_("Could not open secret file: ") << secret_file << std::endl;
return 1;
}

char secret[1024] = "";
secret_file_stream.getline(secret, sizeof(secret));

if (secret_file_stream.bad()) {
std::cerr << N_("Could not read secret from file: ") << secret_file << std::endl;
return 1;
}

srs_add_secret(srs, secret);

secret_file_stream.close();
}

// set the separator character
if (std::string(separator).length() != 1) {
std::cerr << N_("Address separator must be exactly one character.") << std::endl;
return 1;
}
ret = srs_set_separator(srs, separator[0]);
if (ret != SRS_SUCCESS) {
std::cerr << N_("Could not set separator character: ") << srs_strerror(ret) << std::endl;
return 1;
}

// noforward?
ret = srs_set_noforward(srs, noforward);
if (ret != SRS_SUCCESS) {
std::cerr << N_("Could not set the noforward flag: ") << srs_strerror(ret) << std::endl;
return 1;
}

// noreverse?
ret = srs_set_noreverse(srs, noreverse);
if (ret != SRS_SUCCESS) {
std::cerr << N_("Could not set the noreverse flag: ") << srs_strerror(ret) << std::endl;
return 1;
}

// forward or reverse operation?
if (!reverse) {
// check addresses are present
if (!sender || !sender[0]) {
std::cerr << N_("Sender address could not be determined.") << std::endl;
return 1;
}
if (!recipient || !recipient[0]) {
std::cerr << N_("Recipient address could not be determined.") << std::endl;
return 1;
}

// forward operation
size_t buffer_size = std::string(sender).length()+std::string(recipient).length()+65;
char *buffer = new char[buffer_size];

// rewrite address
ret = srs_forward(srs, buffer, buffer_size, sender, recipient);
if (ret != SRS_SUCCESS) {
delete buffer;
std::cerr << N_("Could not rewrite address in forward mode: ") << srs_strerror(ret) << std::endl;
return 1;
}


// Create 'Delivered-To' header
std::string delivered_to_header = std::string("Delivered-To: ")+recipient+"\r\n";

// forward the message by passing it to sendmail
ret = couriersrs::pass2sendmail(sendmail, delivered_to_header, buffer, dest_address);

// free memory
delete buffer;

// we're done
return ret;
}

// reverse operation

// check that we have the recipient address
if (!recipient || !recipient[0]) {
std::cerr << N_("Recipient address could not be determined.") << std::endl;
return 1;
}

// unmap the address
size_t buffer_size = std::string(recipient).length()+1;
char *buffer = new char[buffer_size];

// reverse address
ret = srs_reverse(srs, buffer, buffer_size, recipient);
if (ret == SRS_ENOTSRSADDRESS || ret == SRS_ENOSRS0HOST || ret == SRS_ENOSRS0USER || ret == SRS_ENOSRS0HASH || ret == SRS_ENOSRS0STAMP ||
ret == SRS_ENOSRS1HOST || ret == SRS_ENOSRS1USER || ret == SRS_ENOSRS1HASH || ret == SRS_EBADTIMESTAMPCHAR || ret == SRS_EHASHTOOSHORT ||
ret == SRS_ETIMESTAMPOUTOFDATE || ret == SRS_EHASHINVALID) {
delete buffer;
std::cout << srs_strerror(ret) << std::endl;
return 64;
}
if (ret != SRS_SUCCESS) {
delete buffer;
std::cout << "Error reverting address: " << srs_strerror(ret) << std::endl;
return 1;
}

// Create 'Delivered-To' header
std::string delivered_to_header = std::string("Delivered-To: ")+recipient+"\r\n";

// forward the message by passing it to sendmail
ret = couriersrs::pass2sendmail(sendmail, delivered_to_header, "", buffer);

// free memory
delete buffer;

// we're done
return ret;
}
9 changes: 9 additions & 0 deletions couriersrs.h
Expand Up @@ -21,12 +21,21 @@
#ifndef COURIERSRS_H
#define COURIERSRS_H

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stddef.h>
#include <time.h>

extern "C" { // yes, this is bad ... it should be in srs2.h itself
#include <srs2.h>
}

#include <popt.h>

#ifndef N_
# define N_(n) (n)
#endif

#endif // COURIERSRS_H

0 comments on commit 9a588eb

Please sign in to comment.