--- lmtp2nntp.c 2001/10/02 14:34:51 1.63
+++ lmtp2nntp.c 2001/10/04 16:07:16 1.64
@@ -39,6 +39,7 @@
#include "argz.h"
#include "shpat_match.h"
#include "l2.h"
+#include "daemon.h"
/* library version check (compile-time) */
#define L2_VERSION_HEX_REQ 0x001200
@@ -132,6 +133,8 @@
char *option_mailfrom;
unsigned int option_levelmask;
l2_stream_t *l2;
+ sa_addr_t *saaAltio;
+ sa_t *saAltio;
char *cpBindh;
char *cpBindp;
sa_addr_t *saaBind;
@@ -177,10 +180,11 @@
"[-d deliverymode] "
"[-g groupmode] "
"[-h host[:port][,host[:port], ...]] "
+ "[-i inputbind] "
+ "[-l level[:logfile]] "
"[-m mailfrom] "
"[-n nodename] "
"[-s size] "
- "[-l level[:logfile]] "
"[-v] "
"[-w waittime] "
"newsgroup [newsgroup ...] "
@@ -302,6 +306,10 @@
l2_channel_t *chPrefix;
l2_channel_t *chBuf;
l2_channel_t *chFile;
+ sa_addr_t *caddr;
+ sa_t *csa;
+ int fd;
+ pid_t pid;
/* library version check (run-time) */
if (l2_version.v_hex < L2_VERSION_HEX_REQ) {
@@ -328,6 +336,8 @@
ctx->option_mailfrom = NULL;
ctx->option_levelmask = L2_LEVEL_NONE;
ctx->l2 = NULL;
+ ctx->saaAltio = NULL;
+ ctx->saAltio = NULL;
ctx->cpBindh = NULL;
ctx->cpBindp = NULL;
ctx->saaBind = NULL;
@@ -358,10 +368,35 @@
*/
/* read in the arguments */
- while ((i = getopt(argc, argv, "b:d:g:h:l:m:n:s:vw:")) != -1) {
+ while ((i = getopt(argc, argv, "a:b:d:g:h:l:m:n:s:vw:")) != -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 -i option (%d)\n",
+ ctx->progname, rc);
+ }
+ if ((rc = sa_addr_u2a(ctx->saaAltio, "%s", optarg)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Parsing inputbind address failed for \"%s\" (%d)\n",
+ ctx->progname, optarg, rc);
+ 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>]] */
- /* parse host[:port] string into host and port */
ctx->cpBindh = strdup(optarg);
if ((ctx->cpBindp = strrchr(ctx->cpBindh, ':')) != NULL) {
*ctx->cpBindp++ = NUL;
@@ -370,7 +405,11 @@
else
ctx->cpBindp = strdup("0");
//FIXME
- if ((rc = sa_u2a(&ctx->saaBind, "tcp://%s:%s", ctx->cpBindh, ctx->cpBindp)) != SA_OK) {
+ if ((rc = sa_addr_create(&ctx->saaBind)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Creating address failed for -b option (%d)\n",
+ ctx->progname, rc);
+ }
+ if ((rc = sa_addr_u2a(ctx->saaBind, "tcp://%s:%s", ctx->cpBindh, ctx->cpBindp)) != SA_OK) {
fprintf(stderr, "%s:Error: Parsing bind address failed for \"%s:%s\" (%d)\n",
ctx->progname, ctx->cpBindh, ctx->cpBindp, rc);
CU(ERR_EXECUTION);
@@ -437,8 +476,6 @@
fprintf(stderr, "%s:Error: Too many services (%d) using option -h\n", ctx->progname, ctx->nsc);
CU(ERR_EXECUTION);
}
-
- /* parse host[:port] string into host and port */
cpHost = strdup(cp);
if ((cpPort = strrchr(cpHost, ':')) != NULL) {
*cpPort++ = NUL;
@@ -448,23 +485,19 @@
cpPort = strdup("nntp");
ctx->ns[ctx->nsc].h = cpHost;
ctx->ns[ctx->nsc].p = cpPort;
-
- if ((rc = sa_u2a(&ctx->ns[ctx->nsc].saa, "tcp://%s:%s",
+ if ((rc = sa_addr_create(&ctx->ns[ctx->nsc].saa)) != SA_OK) {
+ fprintf(stderr, "%s:Error: Creating address failed for -h option (%d)\n",
+ ctx->progname, rc);
+ }
+ if ((rc = sa_addr_u2a(ctx->ns[ctx->nsc].saa, "tcp://%s:%s",
ctx->ns[ctx->nsc].h, ctx->ns[ctx->nsc].p)) != SA_OK) {
fprintf(stderr, "%s:Error: Parsing host address failed for \"%s:%s\" (%d)\n",
- ctx->progname,
- ctx->ns[ctx->nsc].h,
- ctx->ns[ctx->nsc].p,
- rc);
+ ctx->progname, ctx->ns[ctx->nsc].h, ctx->ns[ctx->nsc].p, rc);
CU(ERR_EXECUTION);
}
-
if ((rc = sa_create(&ctx->ns[ctx->nsc].sa)) != SA_OK) {
fprintf(stderr, "%s:Error: Creating TCP socket failed for \"%s:%s\": %s\n",
- ctx->progname,
- ctx->ns[ctx->nsc].h,
- ctx->ns[ctx->nsc].p,
- strerror(errno));
+ ctx->progname, ctx->ns[ctx->nsc].h, ctx->ns[ctx->nsc].p, strerror(errno));
CU(ERR_EXECUTION);
}
ctx->ns[ctx->nsc].nntp = NULL;
@@ -634,51 +667,113 @@
signal(SIGUSR1, SIG_IGN );
signal(SIGUSR2, SIG_IGN );
- /* initialize LMTP context */
- lmtp_io.ctx = ctx;
- lmtp_io.select = NULL;
- lmtp_io.read = trace_lmtp_read;
- lmtp_io.write = trace_lmtp_write;
- if ((lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO,
- (ctx->option_logfile && (ctx->option_levelmask >= L2_LEVEL_TRACE)) ?
- &lmtp_io : NULL )) == NULL) {
- fprintf(stderr, "%s:Error: Unable to initialize LMTP library\n", ctx->progname);
- CU(ERR_EXECUTION);
- }
- /* RFC0821, 4.5.1. MINIMUM IMPLEMENTATION
- * In order to make SMTP workable, the following minimum implementation
- * is required for all receivers: [...]
- * RFC0821, 4.1.2. COMMAND SYNTAX
- *
- * Verb Parameter
- * ----+-------------------------------
- * HELO <SP> <domain> <CRLF>
- * MAIL <SP> FROM:<reverse-path> <CRLF>
- * RCPT <SP> TO:<forward-path> <CRLF>
- * DATA <CRLF>
- * RSET <CRLF>
- * NOOP <CRLF>
- * QUIT <CRLF>
- */
- 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, "RSET", lmtp_cb_rset, ctx, NULL, NULL);
- lmtp_register(lmtp, "NOOP", lmtp_cb_noop, ctx, NULL, NULL);
- lmtp_register(lmtp, "QUIT", lmtp_cb_quit, ctx, NULL, NULL);
-
- /* loop for LMTP protocol */
- lmtp_loop(lmtp);
+
+ /* loop for LMTP protocol with support for alternate io through daemon */
+ if (ctx->saAltio == NULL) {
+ /* initialize LMTP context */
+ lmtp_io.ctx = ctx;
+ lmtp_io.select = NULL;
+ lmtp_io.read = trace_lmtp_read;
+ lmtp_io.write = trace_lmtp_write;
+ if ((lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO,
+ (ctx->option_logfile && (ctx->option_levelmask >= L2_LEVEL_TRACE)) ?
+ &lmtp_io : NULL )) == NULL) {
+ fprintf(stderr, "%s:Error: Unable to initialize LMTP library\n", ctx->progname);
+ CU(ERR_EXECUTION);
+ }
+ /* RFC0821, 4.5.1. MINIMUM IMPLEMENTATION
+ * In order to make SMTP workable, the following minimum implementation
+ * is required for all receivers: [...]
+ * RFC0821, 4.1.2. COMMAND SYNTAX
+ *
+ * Verb Parameter
+ * ----+-------------------------------
+ * HELO <SP> <domain> <CRLF>
+ * MAIL <SP> FROM:<reverse-path> <CRLF>
+ * RCPT <SP> TO:<forward-path> <CRLF>
+ * DATA <CRLF>
+ * RSET <CRLF>
+ * NOOP <CRLF>
+ * QUIT <CRLF>
+ */
+ 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, "RSET", lmtp_cb_rset, ctx, NULL, NULL);
+ lmtp_register(lmtp, "NOOP", lmtp_cb_noop, ctx, NULL, NULL);
+ lmtp_register(lmtp, "QUIT", lmtp_cb_quit, ctx, NULL, NULL);
+ lmtp_loop(lmtp);
+ lmtp_gfs_quit(ctx);
+ lmtp_gfs_lhlo(ctx);
+ lmtp_destroy(lmtp);
+ } else {
+ pid = getpid();
+ daemonize();
+ log1(ctx, NOTICE, "startup daemonized, previous pid[%d]", pid); l2_stream_flush(ctx->l2);
+ while ((rc = sa_accept(ctx->saAltio, &caddr, &csa)) == SA_OK) {
+ sa_getfd(csa, &fd);
+ l2_stream_flush(ctx->l2); /* must flush before fork() */
+ pid = fork();
+ if (pid == -1) {
+ log0(ctx, ERROR, "daemon cannot spawn child %m"); l2_stream_flush(ctx->l2);
+ continue;
+ }
+ if (pid != 0) {
+ log1(ctx, INFO, "daemon forked process, new child pid[%d]", pid); l2_stream_flush(ctx->l2);
+ close(fd);
+ continue;
+ }
+ log1(ctx, NOTICE, "startup new child process, parent pid[%d]", getppid());
+
+ fprintf(stderr, "DEBUG: fd=%d\n", fd);
+ /* initialize LMTP context */
+ lmtp_io.ctx = ctx;
+ lmtp_io.select = NULL;
+ lmtp_io.read = trace_lmtp_read;
+ lmtp_io.write = trace_lmtp_write;
+ if ((lmtp = lmtp_create(fd, fd,
+ (ctx->option_logfile && (ctx->option_levelmask >= L2_LEVEL_TRACE)) ?
+ &lmtp_io : NULL )) == NULL) {
+ fprintf(stderr, "%s:Error: Unable to initialize LMTP library\n", ctx->progname);
+ CU(ERR_EXECUTION);
+ }
+ /* RFC0821, 4.5.1. MINIMUM IMPLEMENTATION
+ * In order to make SMTP workable, the following minimum implementation
+ * is required for all receivers: [...]
+ * RFC0821, 4.1.2. COMMAND SYNTAX
+ *
+ * Verb Parameter
+ * ----+-------------------------------
+ * HELO <SP> <domain> <CRLF>
+ * MAIL <SP> FROM:<reverse-path> <CRLF>
+ * RCPT <SP> TO:<forward-path> <CRLF>
+ * DATA <CRLF>
+ * RSET <CRLF>
+ * NOOP <CRLF>
+ * QUIT <CRLF>
+ */
+ 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, "RSET", lmtp_cb_rset, ctx, NULL, NULL);
+ lmtp_register(lmtp, "NOOP", lmtp_cb_noop, ctx, NULL, NULL);
+ lmtp_register(lmtp, "QUIT", lmtp_cb_quit, ctx, NULL, NULL);
+ lmtp_loop(lmtp);
+ lmtp_gfs_quit(ctx);
+ lmtp_gfs_lhlo(ctx);
+ lmtp_destroy(lmtp);
+ close(fd);
+ CU(0);
+ }
+ }
CU(0);
/* graceful shutdown */
CUS:
- lmtp_gfs_quit(ctx);
- lmtp_gfs_lhlo(ctx);
log0(ctx, NOTICE, "graceful shutdown shortly before exit - no more logging");
l2_stream_destroy(ctx->l2);
- lmtp_destroy(lmtp);
if (ctx->option_logfile != NULL)
free(ctx->option_logfile);
if (ctx->progname != NULL)
@@ -688,6 +783,7 @@
if (ctx != NULL)
free(ctx);
str_parse(NULL, NULL);
+ //FIXME 2 * sa_addr_destroy()
return rc;
}
|