--- lmtp2nntp.c 2001/07/25 11:29:38 1.4
+++ lmtp2nntp.c 2001/07/25 15:02:57 1.5
@@ -1,4 +1,3 @@
-
/*
* mail2nntp.c
*
@@ -13,6 +12,7 @@
*/
+#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
@@ -21,15 +21,25 @@
/* third party */
#include "str.h"
+#include "argz.h"
/* own headers */
#include "lmtp.h"
+#ifndef FALSE
+#define FALSE (1 != 1)
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
#define ERR_EXECUTION -1
#define ERR_DELIVERY -2
#define MESSAGE_MAXLEN 8*1024*1024
+extern void lmtp_debug_dumplmtp(lmtp_t *lmtp);
+
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);
@@ -41,80 +51,25 @@
static lmtp_rc_t lmtp_cb_rset (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 ... */
-
- {
- char buf[1000];
- int bufused = 0;
- int tracefile;
-
-// printf("DEBUG: start of argdump\n", buf);
- for (i=0; i<argc; i++) {
-// printf("DEBUG: [%d]=***%s***\n", i, argv[i]);
- bufused+=sprintf(buf+bufused, "[%d]=\"%s\"\n", i, argv[i]);
- }
-// printf("DEBUG: buffer ***%s***\n", buf);
- if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) {
- write(tracefile, buf, bufused);
-// printf("DEBUG: writing\n", buf);
- close(tracefile);
- }
-// printf("DEBUG: end of argdump\n", buf);
- }
-
- /* read in the arguments */
-
-#if 0
-
- 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
-#endif
-
- //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;
-}
+typedef struct {
+ int option_verbose;
+ int option_tracing;
+ int option_mode;
+ char *azNewsgroups;
+ size_t asNewsgroups;
+ char *rfc822message;
+ int saw_lhlo;
+ char *azRcpt;
+ size_t asRcpt;
+} lmtp2nntp_t;
+
+enum {
+ MODE_ONCE,
+ MODE_MANY
+};
/*
* tracing
- *
*/
ssize_t trace_read(int d, void *buf, size_t nbytes)
{
@@ -143,72 +98,137 @@
}
/*
- * test a function
- *
+ * 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;
+}
-extern void lmtp_debug_dumplmtp(lmtp_t *lmtp);
-static void test(void)
+int main(int argc, char **argv)
{
+ int rc = 0;
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];
- lmtp_cb_t oldcb = NULL;
-
+ lmtp_io_t lmtp_io;
+ lmtp2nntp_t *ctx;
+ int i; /* general purpose scratch int, index ... */
- 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", NULL, NULL,&oldcb,NULL); // printf("DEBUG: 1 oldcb=%d\n", (int)oldcb);
- lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, NULL,&oldcb,NULL); // printf("DEBUG: 2 oldcb=%d\n", (int)oldcb);
- lmtp_register(lmtp, "LHLO", NULL, NULL,&oldcb,NULL); // printf("DEBUG: 3 oldcb=%d\n", (int)oldcb);
- 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, "NOOP", lmtp_cb_noop, NULL, NULL, NULL);
- lmtp_register(lmtp, "RSET", lmtp_cb_rset, 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);
- */
+ char *progname = argv[0];
- /* printf("DEBUG: 08 lmtp_loop=%d\n", */ lmtp_loop(lmtp) /*)*/;
+ /* create application context */
+ if ((ctx = (lmtp2nntp_t *)malloc(sizeof(lmtp2nntp_t))) == NULL)
+ exit(ERR_EXECUTION);
+ ctx->option_verbose = FALSE;
+ ctx->option_tracing = FALSE;
+ ctx->option_mode = MODE_MANY;
+ ctx->azNewsgroups = NULL;
+ ctx->asNewsgroups = 0;
+ ctx->rfc822message = NULL;
+ ctx->saw_lhlo = FALSE;
+ ctx->azRcpt = NULL;
+ ctx->asRcpt = 0;
- /* printf("DEBUG: 99.\n"); */
- return;
+ /* read in the arguments */
+ {
+ char buf[1000];
+ int bufused = 0;
+ int tracefile;
+
+ for (i=0; i<argc; i++)
+ bufused+=sprintf(buf+bufused, "[%d]=\"%s\"\n", i, argv[i]);
+ if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) {
+ write(tracefile, buf, bufused);
+ close(tracefile);
+ }
+ }
+ while ((i = getopt(argc, argv, "p:l:h:m:tvo:c:i:t:")) != -1) {
+ switch (i) {
+ case 'p': // -p protocol
+ break;
+ case 'l': // -l logtarget
+ break;
+ case 'o': // FIXME
+ break;
+ case 'c': // FIXME
+ break;
+ case 'i': // FIXME
+ break;
+ case 't': // FIXME
+ break;
+ case 'h': // -h host[:port]
+ break;
+ case 'm': // -m mode
+ if (strcasecmp(argv[optind], "once") == 0)
+ ctx->option_mode = MODE_ONCE;
+ else if (strcasecmp(argv[optind], "many") == 0)
+ ctx->option_mode = MODE_MANY;
+ else {
+ fprintf(stderr, "%s:Error: Invalid mode \"%s\" to option -m\n", progname, argv[optind]);
+ exit(ERR_EXECUTION);
+ }
+ break;
+ case 'd': // -t (tracing)
+ ctx->option_tracing = TRUE;
+ break;
+ case 'v': // -v (verbose)
+ ctx->option_verbose = TRUE;
+ break;
+ case '?':
+ default:
+ usage(progname);
+ exit(ERR_EXECUTION);
+ }
+ }
+ /* remaining arguments are newsgroup names */
+ for (i = optind; i < argc; i++)
+ argz_add(&ctx->azNewsgroups, &ctx->asNewsgroups, argv[i]);
+
+ /* initialize LMTP context */
+ lmtp_io.read = trace_read;
+ lmtp_io.write = trace_write;
+ if ((lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO, &lmtp_io)) == NULL) {
+ fprintf(stderr, "%s:Error: Unable to initialize LMTP library\n", progname);
+ exit(ERR_EXECUTION);
+ }
+ lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, ctx, NULL, NULL);
+ lmtp_register(lmtp, "MAIL", lmtp_cb_mail, ctx, NULL, NULL);
+ lmtp_register(lmtp, "RCPT", lmtp_cb_rcpt, ctx, NULL, NULL);
+ lmtp_register(lmtp, "DATA", lmtp_cb_data, ctx, NULL, NULL);
+ lmtp_register(lmtp, "NOOP", lmtp_cb_noop, ctx, NULL, NULL);
+ lmtp_register(lmtp, "RSET", lmtp_cb_rset, ctx, NULL, NULL);
+ lmtp_register(lmtp, "QUIT", lmtp_cb_quit, ctx, NULL, NULL);
+
+ /* loop for LMTP protocol */
+ lmtp_loop(lmtp);
+
+ return 0;
}
-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_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
{
- lmtp_res_t res;
+ /*
+ * RFC821 [excerpt] 4.1. SMTP COMMANDS
+ * 4.1.1. COMMAND SEMANTICS, HELO
+ * This command and an OK reply to it confirm that both the sender-SMTP
+ * and the receiver-SMTP are in the initial state, that is, there is no
+ * transaction in progress and all state tables and buffers are cleared.
+ *
+ */
lmtp_rc_t rc = LMTP_OK;
+ lmtp_res_t res;
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+
+ //FIXME use rset() not lmtp_cb_rset()
+ ctx->saw_lhlo = TRUE;
+
res.statuscode = "250";
res.dsncode = NULL; /* DSN not used for greeting */
res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\nPIPELINING\n8BITMIME";
+ res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\n8BITMIME";
/*
* RFC2034 = EHANCEDSTATUSCODES
* RFC1894 = DSN
@@ -219,71 +239,80 @@
return rc;
}
-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_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);
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+
+ if (ctx->saw_lhlo == TRUE) {
+ res.statuscode = "250";
+ res.dsncode = "2.1.0";
+ res.statusmsg = "Sender ok FIXME";
+ lmtp_response(lmtp, &res);
+ } else {
+ res.statuscode = "553";
+ res.dsncode = "5.1.8";
+ res.statusmsg = "friendly people say LHLO to open a transmission channel";
+ 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)
+static lmtp_rc_t lmtp_cb_rcpt(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
{
lmtp_rc_t rc = LMTP_OK;
lmtp_res_t res;
- char **cp;
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+ argz_add(&ctx->azRcpt, &ctx->asRcpt, req->msg);
res.statuscode = "250";
res.dsncode = "2.1.5";
res.statusmsg = "Recipient ok FIXME";
lmtp_response(lmtp, &res);
- cp = lmtp_message(lmtp, "RCPT");
- if (cp == NULL) {
- printf("DEBUG: cp=NULL\n");
- } else {
- printf("DEBUG: cp=%d\n", cp);
- }
-
return rc;
}
-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_data(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
{
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
char *buf;
char errorstring[128];
+ char *rcpt;
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;
+
+ rcpt = NULL;
+ while ((rcpt = argz_next(ctx->azRcpt, ctx->asRcpt, rcpt)) != NULL)
+ {
+ if(rc == LMTP_OK) {
+ res.statuscode = "250";
+ res.dsncode = "2.0.0";
+ // res.statusmsg = "Message accepted for delivery";
+ str_format(errorstring, sizeof(errorstring),
+ "Message accepted for delivery to %s", rcpt);
+ res.statusmsg = errorstring;
+ } 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);
}
- lmtp_response(lmtp, &res);
return rc;
}
@@ -297,10 +326,17 @@
lmtp_response(lmtp, &res);
return rc;
}
-static lmtp_rc_t lmtp_cb_rset(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
+static lmtp_rc_t lmtp_cb_rset(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
{
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
+
+ if (ctx->azRcpt != NULL) {
+ free(ctx->azRcpt);
+ ctx->azRcpt = NULL;
+ ctx->asRcpt = 0;
+ }
res.statuscode = "250";
res.dsncode = "2.0.0";
res.statusmsg = "Reset state.";
|