--- lmtp2nntp.c 2001/10/09 09:08:02 1.71
+++ lmtp2nntp.c 2001/10/09 10:19:12 1.72
@@ -127,16 +127,22 @@
char *progname;
char *option_logfile;
int option_groupmode;
- int option_deliverymode;
- char *option_deliverymodefakestatus;
- char *option_deliverymodefakedsn;
+ int option_operationmode;
+ char *option_operationmodefakestatus;
+ char *option_operationmodefakedsn;
int option_maxmessagesize;
int option_waittime;
- int option_timeout;
+ int option_timeout_lmtp_accept;
+ int option_timeout_lmtp_read;
+ int option_timeout_lmtp_write;
+ int option_timeout_nntp_connect;
+ int option_timeout_nntp_read;
+ int option_timeout_nntp_write;
char *option_mailfrom;
unsigned int option_levelmask;
char *option_pidfile;
int option_killflag;
+ int option_daemon;
l2_stream_t *l2;
sa_addr_t *saaAltio;
sa_t *saAltio;
@@ -169,9 +175,9 @@
};
enum {
- DELIVERYMODE_FAKE,
- DELIVERYMODE_POST,
- DELIVERYMODE_FEED
+ OPERATIONMODE_FAKE,
+ OPERATIONMODE_POST,
+ OPERATIONMODE_FEED
};
/*
@@ -185,20 +191,21 @@
*/
fprintf(stderr,
"USAGE: %s "
- "[-a altio] "
- "[-b bindaddr[:port]] "
- "[-d deliverymode] "
+ "[-D] "
+ "[-K] "
+ "[-P pidfile] "
+ "[-a addr/mask[,addr/mask[,...]] "
+ "[-b -|path|addr[:port]] "
+ "[-c addr[:port]] "
+ "[-d addr[:port][,addr[:port], ...]] "
"[-g groupmode] "
- "[-h host[:port][,host[:port], ...]] "
- "[-k] "
"[-l level[:logfile]] "
"[-m mailfrom] "
"[-n nodename] "
- "[-p pidfile] "
+ "[-o operationmode] "
"[-s size] "
- "[-t timeout] "
+ "[-t name=sec[,name=sec[,...]] "
"[-v] "
- "[-w waittime] "
"newsgroup [newsgroup ...] "
"\n",
command);
@@ -339,6 +346,8 @@
char *cp; /* general purpose character pointer */
char *azHosts;
size_t asHosts;
+ char *azTimeout;
+ size_t asTimeout;
char *cpHost;
char *cpPort;
l2_channel_t *chPrefix;
@@ -364,16 +373,22 @@
ctx->progname = strdup(argv[0]);
ctx->option_logfile = NULL;
ctx->option_groupmode = GROUPMODE_ARG;
- ctx->option_deliverymode = DELIVERYMODE_FAKE;
- ctx->option_deliverymodefakestatus = "553"; /* Requested action not taken: mailbox name not allowed */
- ctx->option_deliverymodefakedsn = "5.7.1"; /* Delivery not authorized, message refused */
+ ctx->option_operationmode = OPERATIONMODE_FAKE;
+ ctx->option_operationmodefakestatus = "553"; /* Requested action not taken: mailbox name not allowed */
+ ctx->option_operationmodefakedsn = "5.7.1"; /* Delivery not authorized, message refused */
ctx->option_maxmessagesize = 8 * 1024 * 1024;
ctx->option_waittime = -1;
- ctx->option_timeout = 3;
+ ctx->option_timeout_lmtp_accept = 0;
+ ctx->option_timeout_lmtp_read = 10;
+ ctx->option_timeout_lmtp_write = 10;
+ ctx->option_timeout_nntp_connect = 360;
+ ctx->option_timeout_nntp_read = 60;
+ ctx->option_timeout_nntp_write = 60;
ctx->option_mailfrom = NULL;
ctx->option_levelmask = L2_LEVEL_NONE;
ctx->option_pidfile = NULL;
ctx->option_killflag = FALSE;
+ ctx->option_daemon = FALSE;
ctx->l2 = NULL;
ctx->saaAltio = NULL;
ctx->saAltio = NULL;
@@ -407,21 +422,26 @@
*/
/* read in the arguments */
- while ((i = getopt(argc, argv, "a:b:d:g:h:kl:m:n:p:s:t:vw:")) != -1) {
+ while ((i = getopt(argc, argv, "D:KP:a:b:c:d:g:l:m:n:o:s:t:v")) != -1) {
switch (i) {
- case 'a': /*POD [B<-a> I<altio>] */
- if ((rc = sa_addr_create(&ctx->saaAltio)) != SA_OK) {
- fprintf(stderr, "%s:Error: Creating address failed for -a option (%d)\n",
- ctx->progname, rc);
- }
- if ((strncasecmp(optarg, "inet://", 7) == 0) ||
- (strncasecmp(optarg, "unix:/" , 6) == 0) ) {
- if ((rc = sa_addr_u2a(ctx->saaAltio, "%s", optarg)) != SA_OK) {
- fprintf(stderr, "%s:Error: Parsing alternate IO URL failed for \"%s\" (%d)\n",
- ctx->progname, optarg, rc);
- CU(ERR_EXECUTION);
+ case 'D': /*POD [B<-D>] */
+ ctx->option_daemon = TRUE;
+ break;
+ case 'K': /*POD [B<-K>] */
+ ctx->option_killflag = TRUE;
+ break;
+ case 'P': /*POD [B<-P> I<pidfile>] */
+ ctx->option_pidfile = strdup(optarg);
+ break;
+ case 'a': /*POD [B<-a> I<addr>/I<mask>[,I<addr>/I<mask>[,...]] */
+ /* FIXME */
+ break;
+ case 'b': /*POD [B<-b> C<->|I<path>|I<addr>[I<:port>]] */
+ if (strcmp(optarg, "-") != 0) {
+ if ((rc = sa_addr_create(&ctx->saaAltio)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Creating address failed for -a option (%d)\n",
+ ctx->progname, rc);
}
- } else {
if (optarg[0] == '/') {
if ((rc = sa_addr_u2a(ctx->saaAltio, "unix:%s", optarg)) != SA_OK) {
fprintf(stderr, "%s:Error: Parsing alternate IO guessing UNIX domain socket failed for \"%s\" (%d)\n",
@@ -436,24 +456,24 @@
CU(ERR_EXECUTION);
}
}
- }
- if ((rc = sa_create(&ctx->saAltio)) != SA_OK) {
- fprintf(stderr, "%s:Error: Creating TCP socket failed for \"%s\": %s\n",
- ctx->progname, optarg, strerror(errno));
- CU(ERR_EXECUTION);
- }
- if ((rc = sa_bind(ctx->saAltio, ctx->saaAltio)) != SA_OK) {
- fprintf(stderr, "%s:Error: Bind failed for \"%s\": %s\n",
- ctx->progname, optarg, strerror(errno));
- CU(ERR_EXECUTION);
- }
- if ((rc = sa_listen(ctx->saAltio, -1)) != SA_OK) {
- fprintf(stderr, "%s:Error: Listen to failed for \"%s\": %s\n",
- ctx->progname, optarg, strerror(errno));
- CU(ERR_EXECUTION);
+ if ((rc = sa_create(&ctx->saAltio)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Creating TCP socket failed for \"%s\": %s\n",
+ ctx->progname, optarg, strerror(errno));
+ CU(ERR_EXECUTION);
+ }
+ if ((rc = sa_bind(ctx->saAltio, ctx->saaAltio)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Bind failed for \"%s\": %s\n",
+ ctx->progname, optarg, strerror(errno));
+ CU(ERR_EXECUTION);
+ }
+ if ((rc = sa_listen(ctx->saAltio, -1)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Listen to failed for \"%s\": %s\n",
+ ctx->progname, optarg, strerror(errno));
+ CU(ERR_EXECUTION);
+ }
}
break;
- case 'b': /*POD [B<-b> I<bindaddr>[I<:port>]] */
+ case 'c': /*POD [B<-c> I<addr>[I<:port>]] */
ctx->cpBindh = strdup(optarg);
if ((ctx->cpBindp = strrchr(ctx->cpBindh, ':')) != NULL) {
*ctx->cpBindp++ = NUL;
@@ -471,59 +491,7 @@
CU(ERR_EXECUTION);
}
break;
- case 'd': /*POD [B<-d> I<deliverymode>] */
- if (strcasecmp(optarg, "post") == 0)
- ctx->option_deliverymode = DELIVERYMODE_POST;
- else if (strcasecmp(optarg, "feed") == 0)
- ctx->option_deliverymode = DELIVERYMODE_FEED;
- else {
- if (strlen(optarg) != 9) {
- fprintf(stderr, "%s:Error: Invalid format or length \"%s\" to option -d\n", ctx->progname, optarg);
- CU(ERR_EXECUTION);
- }
-
- if (optarg[3] != '/') {
- fprintf(stderr, "%s:Error: Invalid format or missing slash \"%s\" to option -d\n", ctx->progname, optarg);
- CU(ERR_EXECUTION);
- }
-
- optarg[3] = NUL;
- ctx->option_deliverymodefakestatus = &optarg[0];
- ctx->option_deliverymodefakedsn = &optarg[4];
-
- if ( strlen(ctx->option_deliverymodefakestatus) != 3
- || !isdigit((int)ctx->option_deliverymodefakestatus[0])
- || !isdigit((int)ctx->option_deliverymodefakestatus[1])
- || !isdigit((int)ctx->option_deliverymodefakestatus[2])) {
- fprintf(stderr, "%s:Error: Invalid status in format \"%s\" to option -d\n", ctx->progname, optarg);
- CU(ERR_EXECUTION);
- }
-
- if ( (strlen(ctx->option_deliverymodefakedsn) != 5)
- || !isdigit((int)ctx->option_deliverymodefakedsn[0])
- || (ctx->option_deliverymodefakedsn[1] != '.')
- || !isdigit((int)ctx->option_deliverymodefakedsn[2])
- || (ctx->option_deliverymodefakedsn[3] != '.')
- || !isdigit((int)ctx->option_deliverymodefakedsn[4])
- || (ctx->option_deliverymodefakedsn[0] != ctx->option_deliverymodefakestatus[0])) {
- fprintf(stderr, "%s:Error: Invalid dsn in format \"%s\" to option -d\n", ctx->progname, optarg);
- CU(ERR_EXECUTION);
- }
- }
- break;
- case 'g': /*POD [B<-g> I<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 -g\n", ctx->progname, optarg);
- CU(ERR_EXECUTION);
- }
- break;
- case 'h': /*POD [B<-h> I<host>[I<:port>][,I<host>[I<:port>], ...]] */
+ case 'd': /*POD [B<-d> I<addr>[I<:port>][,I<addr>[I<:port>], ...]] */
if (argz_create_sep(optarg, ',', &azHosts, &asHosts) != 0)
CU(ERR_EXECUTION);
cp = NULL;
@@ -561,8 +529,17 @@
}
free(azHosts);
break;
- case 'k': /*POD [B<-k>] */
- ctx->option_killflag = TRUE;
+ case 'g': /*POD [B<-g> I<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 -g\n", ctx->progname, optarg);
+ CU(ERR_EXECUTION);
+ }
break;
case 'l': /*POD [B<-l> I<level>[:I<logfile>]] */
if ((cp = strrchr(optarg, ':')) != NULL) {
@@ -606,8 +583,45 @@
}
strcpy(ctx->uname.nodename, optarg);
break;
- case 'p': /*POD [B<-p> I<pidfile>] */
- ctx->option_pidfile = strdup(optarg);
+ case 'o': /*POD [B<-o> I<operationmode>] */
+ if (strcasecmp(optarg, "post") == 0)
+ ctx->option_operationmode = OPERATIONMODE_POST;
+ else if (strcasecmp(optarg, "feed") == 0)
+ ctx->option_operationmode = OPERATIONMODE_FEED;
+ else {
+ if (strlen(optarg) != 9) {
+ fprintf(stderr, "%s:Error: Invalid format or length \"%s\" to option -d\n", ctx->progname, optarg);
+ CU(ERR_EXECUTION);
+ }
+
+ if (optarg[3] != '/') {
+ fprintf(stderr, "%s:Error: Invalid format or missing slash \"%s\" to option -d\n", ctx->progname, optarg);
+ CU(ERR_EXECUTION);
+ }
+
+ optarg[3] = NUL;
+ ctx->option_operationmodefakestatus = &optarg[0];
+ ctx->option_operationmodefakedsn = &optarg[4];
+
+ if ( strlen(ctx->option_operationmodefakestatus) != 3
+ || !isdigit((int)ctx->option_operationmodefakestatus[0])
+ || !isdigit((int)ctx->option_operationmodefakestatus[1])
+ || !isdigit((int)ctx->option_operationmodefakestatus[2])) {
+ fprintf(stderr, "%s:Error: Invalid status in format \"%s\" to option -d\n", ctx->progname, optarg);
+ CU(ERR_EXECUTION);
+ }
+
+ if ( (strlen(ctx->option_operationmodefakedsn) != 5)
+ || !isdigit((int)ctx->option_operationmodefakedsn[0])
+ || (ctx->option_operationmodefakedsn[1] != '.')
+ || !isdigit((int)ctx->option_operationmodefakedsn[2])
+ || (ctx->option_operationmodefakedsn[3] != '.')
+ || !isdigit((int)ctx->option_operationmodefakedsn[4])
+ || (ctx->option_operationmodefakedsn[0] != ctx->option_operationmodefakestatus[0])) {
+ fprintf(stderr, "%s:Error: Invalid dsn in format \"%s\" to option -d\n", ctx->progname, optarg);
+ CU(ERR_EXECUTION);
+ }
+ }
break;
case 's': /*POD [B<-s> I<size>] */
ctx->option_maxmessagesize = atoi(optarg);
@@ -616,24 +630,55 @@
CU(ERR_EXECUTION);
}
break;
- case 't': /*POD [B<-t> I<timeout>] */
- ctx->option_timeout = atoi(optarg);
- if(ctx->option_timeout < 0) {
- fprintf(stderr, "%s:Error: timeout %d to option -t must be a positive integer.\n", ctx->progname, ctx->option_waittime);
+ case 't': /*POD [B<-t> I<name>=I<sec>[,I<name>=I<sec>[,...]] */
+ if (argz_create_sep(optarg, ',', &azTimeout, &asTimeout) != 0)
CU(ERR_EXECUTION);
+ cp = NULL;
+ while ((cp = argz_next(azTimeout, asTimeout, cp)) != NULL) {
+ cpName = strdup(cp);
+ if ((cpValue = strrchr(cpName, '=')) == NULL) {
+ fprintf(stderr, "%s:Error: comma-seperated argument %s to option -t have to be name=value.\n", ctx->progname, cp);
+ CU(ERR_EXECUTION);
+ }
+ *cpValue++ = NUL;
+ nValue = atoi(cpValue);
+ if (nValue < 0) {
+ fprintf(stderr, "%s:Error: timeout %s=%d to option -t must be a positive integer.\n", ctx->progname, cpName, nValue)
+ CU(ERR_EXECUTION);
+ }
+ if (strcmp(cpName, "lmtp") == 0) {
+ ctx->option_timeout_lmtp_accept = nValue;
+ ctx->option_timeout_lmtp_read = nValue;
+ ctx->option_timeout_lmtp_write = nValue;
+ }
+ else if (strcmp(cpName, "lmtp:accept") == 0)
+ ctx->option_timeout_lmtp_accept = nValue;
+ else if (strcmp(cpName, "lmtp:read") == 0)
+ ctx->option_timeout_lmtp_read = nValue;
+ else if (strcmp(cpName, "lmtp:write") == 0)
+ ctx->option_timeout_lmtp_write = nValue;
+ else if (strcmp(cpName, "nntp") == 0) {
+ ctx->option_timeout_nntp_connect = nValue;
+ ctx->option_timeout_nntp_read = nValue;
+ ctx->option_timeout_nntp_write = nValue;
+ }
+ else if (strcmp(cpName, "nntp:connect") == 0)
+ ctx->option_timeout_nntp_connect = nValue;
+ else if (strcmp(cpName, "nntp:read") == 0)
+ ctx->option_timeout_nntp_read = nValue;
+ else if (strcmp(cpName, "nntp:write") == 0)
+ ctx->option_timeout_nntp_write = nValue;
+ else {
+ fprintf(stderr, "%s:Error: unknown timeout %s to option -t.\n", ctx->progname, cpName);
+ CU(ERR_EXECUTION);
+ }
}
+ free(azTimeout);
break;
case 'v': /*POD [B<-v>] (version)*/
fprintf(stdout, "%s\n", lmtp2nntp_version.v_gnu);
CU(0);
break;
- case 'w': /*POD [B<-w> I<waittime>] */
- ctx->option_waittime = atoi(optarg);
- if(ctx->option_waittime < 1) {
- fprintf(stderr, "%s:Error: waittime %d to option -w must be greater 1 second.\n", ctx->progname, ctx->option_waittime);
- CU(ERR_EXECUTION);
- }
- break;
case '?':
default:
usage(ctx->progname);
@@ -797,7 +842,8 @@
lmtp_destroy(lmtp);
} else {
pid = getpid();
- daemonize();
+ if (ctx->option_daemon)
+ daemonize();
if (ctx->option_pidfile != NULL) {
if ((fd = fopen(ctx->option_pidfile, "w+")) == NULL)
log1(ctx, ERROR, "cannot open pidfile \"%s\" for writing %m", ctx->option_pidfile);
@@ -808,8 +854,10 @@
}
log1(ctx, NOTICE, "startup daemonized, previous pid[%d]", pid); l2_stream_flush(ctx->l2);
- sa_timeout(ctx->saAltio, SA_TIMEOUT_ALL, ctx->option_timeout, 0);
- sa_timeout(ctx->saAltio, SA_TIMEOUT_ACCEPT, 0, 0);
+ sa_timeout(ctx->saAltio, SA_TIMEOUT_ALL, 0, 0);
+ sa_timeout(ctx->saAltio, SA_TIMEOUT_ACCEPT, ctx->option_timeout_lmtp_accept, 0);
+ sa_timeout(ctx->saAltio, SA_TIMEOUT_READ, ctx->option_timeout_lmtp_read, 0);
+ sa_timeout(ctx->saAltio, SA_TIMEOUT_WRITE, ctx->option_timeout_lmtp_write, 0);
while ((rc = sa_accept(ctx->saAltio, &ctx->saaIO, &ctx->saIO)) == SA_OK) {
l2_stream_flush(ctx->l2); /* must flush before fork() */
pid = fork();
@@ -969,7 +1017,7 @@
* RFC1893 2. Status Codes 4.X.X Persistent Transient Failure
* RFC1893 3.5 Network and Routing Status X.3.5 System incorrectly configured
*/
- if (ctx->option_deliverymode != DELIVERYMODE_FAKE) {
+ if (ctx->option_operationmode != OPERATIONMODE_FAKE) {
log0(ctx, TRACE, "check if at least one NNTP service was successfully configured");
if (ctx->nsc == 0) {
res.statuscode = "451";
@@ -980,7 +1028,7 @@
}
log0(ctx, TRACE, "try to establish a session to any configured NNTP services");
- if (ctx->option_deliverymode == DELIVERYMODE_FAKE)
+ if (ctx->option_operationmode == OPERATIONMODE_FAKE)
log0(ctx, NOTICE, "NNTP running in fake mode, network connections will be executed but result is ignored");
i = 0;
do {
@@ -1048,7 +1096,7 @@
}
} while (i < ctx->nsc);
- if (ctx->option_deliverymode == DELIVERYMODE_FAKE)
+ if (ctx->option_operationmode == OPERATIONMODE_FAKE)
log1(ctx, NOTICE, "NNTP running in fake mode, network connections successfully established=%d but ignored", ctx->nsc);
else
{
@@ -1665,14 +1713,14 @@
log0(ctx, TRACE, "deliver message");
bSuccess = NNTP_ERR_DELIVERY; /* assume a hard error for the worst case */
for (i = 0; i < ctx->nsc; i++) {
- switch (ctx->option_deliverymode) {
- case DELIVERYMODE_FAKE:
+ switch (ctx->option_operationmode) {
+ case OPERATIONMODE_FAKE:
ctx->ns[i].rc = NNTP_FAKE;
break;
- case DELIVERYMODE_POST:
+ case OPERATIONMODE_POST:
ctx->ns[i].rc = nntp_post(ctx->ns[i].nntp, ctx->msg);
break;
- case DELIVERYMODE_FEED:
+ case OPERATIONMODE_FEED:
ctx->ns[i].rc = nntp_feed(ctx->ns[i].nntp, ctx->msg);
break;
}
@@ -1688,14 +1736,14 @@
bSuccess = NNTP_DEFER;
}
- if (ctx->option_deliverymode == DELIVERYMODE_FAKE) {
+ if (ctx->option_operationmode == OPERATIONMODE_FAKE) {
str_format(errorstring, sizeof(errorstring),
"NNTP running in fake mode, delivery of %s [%d bytes] %s but delivery status forced to",
ctx->msg->cpMsgid,
strlen(ctx->msg->cpMsg),
((bSuccess == NNTP_OK) ? "succeeded" :
(bSuccess == NNTP_DEFER) ? "deferred" : "failed"));
- switch (ctx->option_deliverymodefakestatus[0]) {
+ switch (ctx->option_operationmodefakestatus[0]) {
case '5':
bSuccess = NNTP_ERR_UNKNOWN;
log2(ctx, NOTICE, "%s %s", errorstring, "failed");
@@ -1711,8 +1759,8 @@
}
} else {
str_format(errorstring, sizeof(errorstring), "%sdelivery of %s [%d bytes]",
- ((ctx->option_deliverymode == DELIVERYMODE_POST) ? "post " :
- (ctx->option_deliverymode == DELIVERYMODE_FEED) ? "feed " : ""),
+ ((ctx->option_operationmode == OPERATIONMODE_POST) ? "post " :
+ (ctx->option_operationmode == OPERATIONMODE_FEED) ? "feed " : ""),
ctx->msg->cpMsgid,
strlen(ctx->msg->cpMsg));
if (bSuccess == NNTP_OK)
@@ -1735,9 +1783,9 @@
*/
rcpt = NULL;
while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) {
- if (ctx->option_deliverymode == DELIVERYMODE_FAKE) {
- res.statuscode = ctx->option_deliverymodefakestatus;
- res.dsncode = ctx->option_deliverymodefakedsn;
+ if (ctx->option_operationmode == OPERATIONMODE_FAKE) {
+ res.statuscode = ctx->option_operationmodefakestatus;
+ res.dsncode = ctx->option_operationmodefakedsn;
str_format(errorstring, sizeof(errorstring),
"NNTP noop fake return for %s", rcpt);
} else {
|