--- lmtp2nntp.c 2001/08/02 14:58:39 1.8
+++ lmtp2nntp.c 2001/08/07 09:05:55 1.9
@@ -23,7 +23,7 @@
/* own headers */
#include "lmtp.h"
#include "nntp.h"
-#include "sock.h"
+#include "sa.h"
#ifndef FALSE
#define FALSE (1 != 1)
@@ -37,6 +37,7 @@
#define MESSAGE_MAXLEN 8*1024*1024
#define STDSTRLEN 128
+#define MAXNEWSSERVICES 3
extern void lmtp_debug_dumplmtp(lmtp_t *lmtp);
@@ -69,11 +70,20 @@
};
static void resetmessage(struct message *message);
+struct newsservice {
+ char *h; /* host */
+ char *p; /* port */
+ sa_t *sa;
+ int s; /* socket */
+ nntp_t *nntp;
+};
+
typedef struct {
int option_verbose;
int option_tracing;
- int option_deliverymode;
int option_groupmode;
+ int newsservicecount;
+ struct newsservice newsservice[MAXNEWSSERVICES];
char *azArggroups;
size_t asArggroups;
struct session session;
@@ -81,12 +91,6 @@
} lmtp2nntp_t;
enum {
- DELIVERYMODE_ONCE,
- DELIVERYMODE_MANY,
- DELIVERYMODE_FULL
-};
-
-enum {
GROUPMODE_ARG,
GROUPMODE_ENVELOPE,
GROUPMODE_HEADER
@@ -141,18 +145,13 @@
lmtp2nntp_t *ctx;
int i; /* general purpose scratch int, index ... */
char *progname;
+ char *cpHost;
+ char *cpPort;
+ sa_t *sa;
#if 0
/* begin NNTP posting test */
{
- int s;
- nntp_t *nntp;
-
- if ((s = sock_create(argv[1])) == -1) {
- fprintf(stderr, "fuck socket\n");
- exit(1);
- }
- nntp = nntp_create(s, s, NULL);
nntp_post(nntp, "...");
nntp_destroy(nntp);
sock_destroy(s);
@@ -167,8 +166,13 @@
exit(ERR_EXECUTION);
ctx->option_verbose = FALSE;
ctx->option_tracing = FALSE;
- ctx->option_deliverymode = DELIVERYMODE_MANY;
ctx->option_groupmode = GROUPMODE_ARG;
+ ctx->newsservicecount = 0;
+ for (i=0; i < MAXNEWSSERVICES; i++) {
+ ctx->newsservice[i].h = "";
+ ctx->newsservice[i].s = -1;
+ ctx->newsservice[i].nntp = NULL;
+ }
ctx->azArggroups = NULL;
ctx->asArggroups = 0;
resetsession(&ctx->session);
@@ -188,20 +192,8 @@
}
/* read in the arguments */
- while ((i = getopt(argc, argv, "d:g:tv")) != -1) {
+ while ((i = getopt(argc, argv, "g:h:tv")) != -1) {
switch (i) {
- case 'd': /* -d deliverymode */
- if (strcasecmp(optarg, "once") == 0)
- ctx->option_deliverymode = DELIVERYMODE_ONCE;
- else if (strcasecmp(optarg, "many") == 0)
- ctx->option_deliverymode = DELIVERYMODE_MANY;
- else if (strcasecmp(optarg, "full") == 0)
- ctx->option_deliverymode = DELIVERYMODE_FULL;
- else {
- fprintf(stderr, "%s:Error: Invalid mode \"%s\" to option -d\n", progname, optarg);
- exit(ERR_EXECUTION);
- }
- break;
case 'g': /* -g groupmode */
if (strcasecmp(optarg, "arg") == 0)
ctx->option_groupmode = GROUPMODE_ARG;
@@ -214,6 +206,47 @@
exit(ERR_EXECUTION);
}
break;
+ case 'h': /* -h host */
+ if (ctx->newsservicecount >= MAXNEWSSERVICES) {
+ fprintf(stderr, "%s:Error: Too many services (%d) using option -h\n", progname, ctx->newsservicecount);
+ exit(ERR_EXECUTION);
+ }
+
+ /* parse host[:port] string into host and port */
+ cpHost = strdup(optarg);
+ if ((cpPort = strrchr(cpHost, ':')) != NULL) {
+ *cpPort++ = '\0';
+ cpPort = strdup(cpPort);
+ }
+ else
+ cpPort = strdup("nntp");
+ ctx->newsservice[ctx->newsservicecount].h = cpHost;
+ ctx->newsservice[ctx->newsservicecount].p = cpPort;
+
+ if ((sa = sa_create(SA_IP, "tcp",
+ ctx->newsservice[ctx->newsservicecount].h,
+ ctx->newsservice[ctx->newsservicecount].p)) == NULL) {
+ fprintf(stderr, "%s:Error: creating TCP socket address failed for \"%s:%s\": %s\n",
+ progname,
+ ctx->newsservice[ctx->newsservicecount].h,
+ ctx->newsservice[ctx->newsservicecount].p,
+ strerror(errno));
+ exit(ERR_EXECUTION);
+ }
+ if ((ctx->newsservice[ctx->newsservicecount].s =
+ socket(sa->sa_buf->sa_family, SOCK_STREAM, sa->sa_proto)) == -1) {
+ fprintf(stderr, "%s:Error: Creating TCP socket failed for \"%s:%s\": %s\n",
+ progname,
+ ctx->newsservice[ctx->newsservicecount].h,
+ ctx->newsservice[ctx->newsservicecount].p,
+ strerror(errno));
+ exit(ERR_EXECUTION);
+ }
+ ctx->newsservice[ctx->newsservicecount].sa = sa;
+ //FIXME sa_destroy(sa);
+ ctx->newsservice[ctx->newsservicecount].nntp = NULL;
+ ctx->newsservicecount++;
+ break;
case 't': // -t (tracing)
ctx->option_tracing = TRUE;
break;
@@ -309,37 +342,84 @@
* HELO <SP> <domain> <CRLF>
*/
lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
- lmtp_rc_t rc = LMTP_OK;
lmtp_res_t res;
+ nntp_rc_t rc;
char str[STDSTRLEN];
+ int bOk;
+ int i;
if (ctx->session.lhlo_seen == TRUE) {
res.statuscode = "503";
res.dsncode = "5.0.0";
res.statusmsg = "Duplicate LHLO.";
- } else {
- if ( helo_rfc0821domain(req->msg, &ctx->session.lhlo_domain)
- || helo_rfc1035domain(req->msg, &ctx->session.lhlo_domain)) {
- ctx->session.lhlo_seen = TRUE;
- res.statuscode = "250";
- res.dsncode = NULL; /* DSN not used for greeting */
- str_format(str, sizeof(str),
- "FIXME.dev.de.cw.net" /* RFC2821 4.1.1.1 */
- " Hello %s, pleased to meet you.\n"
- "ENHANCEDSTATUSCODES\n" /* RFC2034 */
- "DSN\n" /* RFC1894 */
- "PIPELINING\n" /* RFC1854 */
- "8BITMIME", /* RFC1652 */
- ctx->session.lhlo_domain);
- res.statusmsg = str;
- } else {
- res.statuscode = "501";
- res.dsncode = "5.0.0";
- res.statusmsg = "Please identify yourself. Domain must match RFC0821/RFC1035.";
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
+ }
+
+ if (! ( helo_rfc0821domain(req->msg, &ctx->session.lhlo_domain)
+ || helo_rfc1035domain(req->msg, &ctx->session.lhlo_domain)
+ )) {
+ res.statuscode = "501";
+ res.dsncode = "5.0.0";
+ res.statusmsg = "Please identify yourself. Domain must match RFC0821/RFC1035.";
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
+ }
+
+ if (ctx->newsservicecount == 0) {
+ res.statuscode = "501";
+ res.dsncode = "5.0.0";
+ res.statusmsg = "No valid NNTP Services specified.";
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
+ }
+
+ i = 0;
+ do {
+ bOk = TRUE;
+ if (connect(ctx->newsservice[i].s, ctx->newsservice[i].sa->sa_buf, ctx->newsservice[i].sa->sa_len) < 0) {
+ fprintf(stderr, "DEBUG: connect failed: %s\n", strerror(errno));
+ bOk = FALSE;
+ }
+ if (bOk && ((ctx->newsservice[i].nntp = nntp_create(ctx->newsservice[i].s, ctx->newsservice[i].s, NULL)) == NULL)) {
+ fprintf(stderr, "DEBUG: nntp_create failed: %s\n", strerror(errno));
+ bOk = FALSE;
+ }
+ if (bOk && ((rc = nntp_init(ctx->newsservice[i].nntp)) != NNTP_OK)) {
+ fprintf(stderr, "DEBUG: nntp_init failed: %s\n", nntp_error(ctx->newsservice[i].nntp, rc));
+ bOk = FALSE;
+ }
+ if (bOk)
+ i++;
+ else {
+ if (i < --ctx->newsservicecount) {
+ memcpy(&ctx->newsservice[i], &ctx->newsservice[i+1], (ctx->newsservicecount - i ) * sizeof(struct newsservice));
+ }
}
+ } while (i < ctx->newsservicecount);
+
+ if (ctx->newsservicecount == 0) {
+ res.statuscode = "501";
+ res.dsncode = "5.0.0";
+ res.statusmsg = "No connection to any NNTP Service."; //FIXME add error strings from above DEBUGs
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
}
+
+ ctx->session.lhlo_seen = TRUE;
+ str_format(str, sizeof(str),
+ "FIXME.dev.de.cw.net" /* RFC2821 4.1.1.1 */
+ " Hello %s, pleased to meet you.\n"
+ "ENHANCEDSTATUSCODES\n" /* RFC2034 */
+ "DSN\n" /* RFC1894 */
+ "PIPELINING\n" /* RFC1854 */
+ "8BITMIME", /* RFC1652 */
+ ctx->session.lhlo_domain);
+ res.statuscode = "250";
+ res.dsncode = NULL; /* DSN not used for greeting */
+ res.statusmsg = str;
lmtp_response(lmtp, &res);
- return rc;
+ return LMTP_OK;
}
static int helo_rfc0821domain(char *msg, char **domain)
@@ -494,7 +574,6 @@
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;
lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
char *cp;
@@ -525,7 +604,7 @@
if (ctx->option_groupmode == GROUPMODE_ENVELOPE) {
// fprintf(stderr, "DEBUG: before transform cp=***%s***\n", cp);
- if (!str_parse(cp, "m/^.+?\\+(.+)?@.+$/i", &group)) {
+ if (!str_parse(cp, "m/^.+?\\+(.+)?@.+$/i", &group)) { //FIXME >=2 * @
res.statuscode = "550";
res.dsncode = "5.1.1";
res.statusmsg = "Recipient did not transform into Group.";
@@ -543,7 +622,7 @@
return LMTP_OK;
}
}
-
+
if ((cp == NULL) || (strlen(cp) == 0)) {
res.statuscode = "550";
res.dsncode = "5.1.1";
@@ -551,17 +630,15 @@
lmtp_response(lmtp, &res);
return LMTP_OK;
}
- else {
- // fprintf(stderr, "DEBUG: cp=***%s***\n", cp);
- argz_add(&ctx->message.azRcpt, &ctx->message.asRcpt, cp);
- res.statuscode = "250";
- res.dsncode = "2.1.5";
- res.statusmsg = "Recipient/ Group accepted";
- lmtp_response(lmtp, &res);
- }
- return rc;
-}
+ // fprintf(stderr, "DEBUG: cp=***%s***\n", cp);
+ argz_add(&ctx->message.azRcpt, &ctx->message.asRcpt, cp);
+ res.statuscode = "250";
+ res.dsncode = "2.1.5";
+ res.statusmsg = "Recipient/ Group accepted";
+ lmtp_response(lmtp, &res);
+ return LMTP_OK;
+}
static lmtp_rc_t lmtp_cb_data(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx)
{
|