Index: ossp-pkg/lmtp2nntp/lmtp2nntp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v rcsdiff -q -kk '-r1.7' '-r1.8' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v' 2>/dev/null --- lmtp2nntp.c 2001/08/01 07:08:31 1.7 +++ lmtp2nntp.c 2001/08/02 14:58:39 1.8 @@ -1,17 +1,14 @@ /* - * mail2nntp.c + * lmtp2nntp.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 lmtp2nntp program reads mail as a LMTP server and posts it to one or + * more newsgroups using NNTP. It delivers the message immediately or fails. * * The OSSP Project, Cable & Wireless Deutschland GmbH * Thomas Lotterer, * */ - #include #include #include @@ -54,22 +51,45 @@ 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); -typedef struct { - int option_verbose; - int option_tracing; - int option_mode; - char *azNewsgroups; - size_t asNewsgroups; - char *rfc822message; +static int helo_rfc0821domain(char *msg, char **domain); +static int helo_rfc1035domain(char *msg, char **domain); + +struct session { int lhlo_seen; char *lhlo_domain; +}; +static void resetsession(struct session *session); + + +struct message { + char *rfc822message; + char *mail_from; char *azRcpt; size_t asRcpt; +}; +static void resetmessage(struct message *message); + +typedef struct { + int option_verbose; + int option_tracing; + int option_deliverymode; + int option_groupmode; + char *azArggroups; + size_t asArggroups; + struct session session; + struct message message; } lmtp2nntp_t; enum { - MODE_ONCE, - MODE_MANY + DELIVERYMODE_ONCE, + DELIVERYMODE_MANY, + DELIVERYMODE_FULL +}; + +enum { + GROUPMODE_ARG, + GROUPMODE_ENVELOPE, + GROUPMODE_HEADER }; /* @@ -115,13 +135,15 @@ int main(int argc, char **argv) { - int rc = 0; + //FIXME int rc = 0; lmtp_t *lmtp; lmtp_io_t lmtp_io; lmtp2nntp_t *ctx; - int i; /* general purpose scratch int, index ... */ + int i; /* general purpose scratch int, index ... */ char *progname; +#if 0 + /* begin NNTP posting test */ { int s; nntp_t *nntp; @@ -135,8 +157,8 @@ nntp_destroy(nntp); sock_destroy(s); exit(0); - } +#endif progname = argv[0]; @@ -145,16 +167,13 @@ 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->lhlo_seen = FALSE; - ctx->lhlo_domain = ""; - ctx->azRcpt = NULL; - ctx->asRcpt = 0; + ctx->option_deliverymode = DELIVERYMODE_MANY; + ctx->option_groupmode = GROUPMODE_ARG; + ctx->azArggroups = NULL; + ctx->asArggroups = 0; + resetsession(&ctx->session); + resetmessage(&ctx->message); - /* read in the arguments */ { char buf[1000]; int bufused = 0; @@ -167,33 +186,35 @@ close(tracefile); } } - while ((i = getopt(argc, argv, "p:l:h:m:tvo:c:i:t:")) != -1) { + + /* read in the arguments */ + while ((i = getopt(argc, argv, "d:g:tv")) != -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] + 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 '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; + case 'g': /* -g groupmode */ + if (strcasecmp(optarg, "arg") == 0) + ctx->option_groupmode = GROUPMODE_ARG; + else if (strcasecmp(optarg, "envelope") == 0) + ctx->option_groupmode = GROUPMODE_ENVELOPE; + else if (strcasecmp(optarg, "header") == 0) + ctx->option_groupmode = GROUPMODE_HEADER; else { - fprintf(stderr, "%s:Error: Invalid mode \"%s\" to option -m\n", progname, argv[optind]); + fprintf(stderr, "%s:Error: Invalid mode \"%s\" to option -g\n", progname, optarg); exit(ERR_EXECUTION); } break; - case 'd': // -t (tracing) + case 't': // -t (tracing) ctx->option_tracing = TRUE; break; case 'v': // -v (verbose) @@ -205,9 +226,9 @@ exit(ERR_EXECUTION); } } - /* remaining arguments are newsgroup names */ + /* remaining arguments are groups */ for (i = optind; i < argc; i++) - argz_add(&ctx->azNewsgroups, &ctx->asNewsgroups, argv[i]); + argz_add(&ctx->azArggroups, &ctx->asArggroups, argv[i]); /* initialize LMTP context */ lmtp_io.read = trace_read; @@ -230,6 +251,41 @@ return 0; } +static void resetsession(struct session *session) +{ + + session->lhlo_seen = FALSE; + + // fprintf(stderr, "DEBUG: session->lhlo_domain=***%s***\n", session->lhlo_domain); + if (session->lhlo_domain != NULL) + free(session->lhlo_domain); //FIXME what about non-graceful aborts? + session->lhlo_domain = NULL; + + return; +} + +static void resetmessage(struct message *message) +{ + // fprintf(stderr, "DEBUG: message->mail_from=***%s***\n", message->mail_from); + if (message->mail_from != NULL) + free(message->mail_from); //FIXME what about non-graceful aborts? + message->mail_from = NULL; + + // fprintf(stderr, "DEBUG: message->azRcpt=***%s***\n", message->azRcpt); + if (message->azRcpt != NULL) + free(message->azRcpt); //FIXME what about non-graceful aborts? + message->azRcpt = NULL; + + message->asRcpt = 0; + + // fprintf(stderr, "DEBUG: message->rfc822message=***%s***\n", message->rfc822message); + if (message->rfc822message != NULL) + free(message->rfc822message); //FIXME what about non-graceful aborts? + message->rfc822message = NULL; + + return; +} + static lmtp_rc_t lmtp_cb_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx) { /* @@ -255,102 +311,150 @@ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx; lmtp_rc_t rc = LMTP_OK; lmtp_res_t res; - char errorstring[STDSTRLEN]; - char *cp; + char str[STDSTRLEN]; - cp = NULL; - if (ctx->lhlo_seen == TRUE) { + if (ctx->session.lhlo_seen == TRUE) { res.statuscode = "503"; res.dsncode = "5.0.0"; res.statusmsg = "Duplicate LHLO."; } else { - if (!str_parse(req->msg, - "^.+ (" - - /* - ## - ## The mega Perl regular expression below is generated - ## with the following Perl program. This is only possible - ## because the given grammar is Chomsky-3 (right or left - ## linear grammar, but noth both). - ## - - # BNF grammar for according to RFC 821: - # ::= one, two, or three digits representing a decimal integer value in the range 0 through 255 - # ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case - # ::= any one of the ten digits 0 through 9 - # ::= | | "-" - # ::= | - # ::= | - # ::= "." "." "." - # ::= | - # ::= - # ::= | "#" | "[" "]" - # ::= | "." - - FIXME # BNF grammar for according to RFC1035: - # ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case - # ::= any one of the ten digits 0 through 9 - # ::= | - # ::= | "-" - # ::= | - # ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case + # ::= any one of the ten digits 0 through 9 + # ::= | | "-" + # ::= | + # ::= | + # ::= "." "." "." + # ::= | + # ::= + # ::= | "#" | "[" "]" + # ::= | "." + # + # corresponding Perl regular expression ($domain) + $snum = "(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])"; + $d = "[0-9]"; + $a = "[A-Za-z]"; + $let_dig_hyp = "(?:$a|$d|-)"; + $let_dig = "(?:$a|$d)"; + $ldh_str = "${let_dig_hyp}+"; + $dotnum = "$snum\\.$snum\\.$snum\\.$snum"; + $number = "$d+"; + $name = "$a$ldh_str$let_dig"; + $element = "(?:$name|#$number|\\[$dotnum\\])"; + $domain = "(?:$element\.)*$element"; + # + # translate into C string block suitable for passing to the Perl + # Compatible Regular Expressions (PCRE) based string library Str. + my $cregex = $domain; + $cregex =~ s|\\|\\\\|sg; + $cregex =~ s|(.{70})|"$1"\n|sg; + $cregex =~ s|\n([^\n]+)$|\n"$1"|s; #FIXME this fails when last + #FIXME line matches linelength exacly + print "$cregex\n"; + */ + + "(?:(?:[A-Za-z](?:[A-Za-z]|[0-9]|-)+(?:[A-Za-z]|[0-9])|#[0-9]+|\\[(?:[0" + "-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0" + "-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0" + "-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5" + "])\\]).)*(?:[A-Za-z](?:[A-Za-z]|[0-9]|-)+(?:[A-Za-z]|[0-9])|#[0-9]+|\\" + "[(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]" + "{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{" + "2}|2[0-4][0-9]|25[0-5])\\.(?:[0-9]|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|" + "25[0-5])\\])" + + ")$", domain); + return rc; +} + +static int helo_rfc1035domain(char *msg, char **domain) +{ + int rc; + + rc = str_parse(msg, + "^.+ (" + /* + ## + ## The mega Perl regular expression below is generated + ## with the following Perl program. This is only possible + ## because the given grammar is Chomsky-3 (right or left + ## linear grammar, but noth both). + ## + + # BNF grammar for according to RFC1035: + # ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case + # ::= any one of the ten digits 0 through 9 + # ::= | + # ::= | "-" + # ::= | + #