ossp-pkg/lmtp2nntp/lmtp2nntp.c
1.3
/*
* mail2nntp.c
*
* The mail2nntp program reads mail from stdin and posts it
* to one or more newsgroups using NNTP. It delivers the mes-
* sage immediately or fails. If queuing is desired it can
* operate as a LMTP server.
*
* The OSSP Project, Cable & Wireless Deutschland GmbH
* Thomas Lotterer, <thomas.lotterer@cw.com>
*
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
/* third party */
#include "str.h"
/* own headers */
#include "lmtp.h"
#define ERR_EXECUTION -1
#define ERR_DELIVERY -2
#define MESSAGE_MAXLEN 8*1024*1024
static ssize_t trace_read(int d, void *buf, size_t nbytes);
static ssize_t trace_write(int d, const void *buf, size_t nbytes);
static lmtp_rc_t lmtp_cb_lhlo (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
static lmtp_rc_t lmtp_cb_mail (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
static lmtp_rc_t lmtp_cb_rcpt (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
static lmtp_rc_t lmtp_cb_data (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
static lmtp_rc_t lmtp_cb_quit (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
static void usage(char *command);
static void test(void);
int main(int argc, char **argv)
{
int i; // general purpose scratch int, index ...
// read in the arguments
while ((i = getopt(argc, argv, "p:l:h:m:tv")) != -1)
switch (i) {
case 'p': // -p protocol
break;
case 'l': // -l logtarget
break;
case 'h': // -h host[:port]
break;
case 'm': // -m mode
break;
case 'd': // -t (tracing)
break;
case 'v': // -v (verbose)
break;
case '?':
default:
//FIXME usage(argv[0]);
//FIXME exit(ERR_EXECUTION);
}
argc -= optind; argv += optind; // remaining args is/are newsgroup/s
//FIXME printf("Hello, World!\n");
test();
//FIXME printf("Hello, Again!\n");
return 0;
}
/*
* print usage information
*
*/
static void usage(char *command)
{
fprintf(stderr, "USAGE: %s [-p protocol] [-l logtarget] "\
"[-h host[:port]] [-m mode] [-t] [-v] newsgroup [newsgroup ...]\n",
command);
return;
}
/*
* tracing
*
*/
ssize_t trace_read(int d, void *buf, size_t nbytes)
{
ssize_t rc;
int tracefile;
rc = read(d, buf, nbytes);
if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) {
write(tracefile, buf, rc);
close(tracefile);
}
return rc;
}
ssize_t trace_write(int d, const void *buf, size_t nbytes)
{
ssize_t rc;
int tracefile;
rc = write(d, buf, nbytes);
if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) {
write(tracefile, buf, rc);
close(tracefile);
}
return rc;
}
/*
* test a function
*
*/
extern void lmtp_debug_dumplmtp(lmtp_t *lmtp);
static void test(void)
{
lmtp_t *lmtp;
lmtp_rc_t rc;
lmtp_req_t req;
lmtp_res_t res;
lmtp_io_t io;
#define BUFLEN 100
char buf[BUFLEN];
io.read=trace_read;
io.write=trace_write;
io.select=select;
lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO, &io);
// lmtp_debug_dumplmtp(lmtp);
lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, NULL, NULL, NULL);
lmtp_register(lmtp, "MAIL", lmtp_cb_mail, NULL, NULL, NULL);
lmtp_register(lmtp, "RCPT", lmtp_cb_rcpt, NULL, NULL, NULL);
lmtp_register(lmtp, "DATA", lmtp_cb_data, NULL, NULL, NULL);
lmtp_register(lmtp, "QUIT", lmtp_cb_quit, NULL, NULL, NULL);
// lmtp_debug_dumplmtp(lmtp);
/*
printf("DEBUG: 05 lmtp_response\n"); res.statuscode="123";
res.dsncode="1.2.3";
res.statusmsg="Hello,\nthis is a\nmultiline\nmessage";
lmtp_response(lmtp, &res);
*/
/*
do {
rc = lmtp_readline(lmtp, buf, BUFLEN);
printf("DEBUG: 06 lmtp_readline=%d ***%s***\n", rc, buf);
} while(rc == LMTP_OK);
*/
/*
do {
rc = lmtp_request(lmtp, &req);
printf("DEBUG: 07 lmtp_request=%d ***%s***%s***\n", rc, req.verb, req.msg);
} while(rc == LMTP_OK || rc == LMTP_ERR_VERB);
*/
/* printf("DEBUG: 08 lmtp_loop=%d\n", */ lmtp_loop(lmtp) /*)*/;
/* printf("DEBUG: 99.\n"); */
return;
}
static lmtp_rc_t lmtp_cb_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
res.statuscode = "250";
res.dsncode = NULL; /* DSN not used for greeting */
res.statusmsg = "ENHANCEDSTATUSCODES\nDSN"; /* RFC2034, RFC1894 */
lmtp_response(lmtp, &res);
return rc;
}
static lmtp_rc_t lmtp_cb_mail(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
res.statuscode = "553";
res.dsncode = "5.1.8";
res.statusmsg = "bad sender FIXME";
res.statuscode = "250";
res.dsncode = "2.1.0";
res.statusmsg = "sender ok FIXME";
lmtp_response(lmtp, &res);
return rc;
}
static lmtp_rc_t lmtp_cb_rcpt(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
res.statuscode = "250";
res.dsncode = "2.1.5";
res.statusmsg = "Recipient ok FIXME";
lmtp_response(lmtp, &res);
return rc;
}
static lmtp_rc_t lmtp_cb_data(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
char *buf;
char errorstring[128];
res.statuscode = "354";
res.dsncode = NULL; /* DSN not used for data */
res.statusmsg = "Enter mail, end with \".\" on a line by itself";
lmtp_response(lmtp, &res);
rc = lmtp_readmsg(lmtp, &buf, MESSAGE_MAXLEN);
if(rc == LMTP_OK) {
// printf("DEBUG: message=***%s***\n", buf);
res.statuscode = "250";
res.dsncode = "2.0.0";
res.statusmsg = "Message accepted for delivery";
} else if (rc == LMTP_ERR_OVERFLOW) {
res.statuscode = "500";
res.dsncode = "5.0.0";
res.statusmsg = "Message accepted for delivery";
} else if (rc == LMTP_ERR_SYSTEM) {
res.statuscode = "500";
res.dsncode = "5.0.0";
str_format(errorstring, sizeof(errorstring),
"Message accepted for delivery %s", strerror(errno));
res.statusmsg = errorstring;
}
lmtp_response(lmtp, &res);
return rc;
}
static lmtp_rc_t lmtp_cb_quit(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
lmtp_res_t res;
lmtp_rc_t rc = LMTP_EOF;
res.statuscode = "221";
res.dsncode = "2.0.0";
res.statusmsg = "Closing connection.";
lmtp_response(lmtp, &res);
return rc;
}