Index: ossp-pkg/lmtp2nntp/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Makefile.in,v rcsdiff -q -kk '-r1.26' '-r1.27' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Makefile.in,v' 2>/dev/null --- Makefile.in 2001/10/02 13:36:33 1.26 +++ Makefile.in 2001/10/04 16:07:16 1.27 @@ -43,9 +43,9 @@ POD2MAN = pod2man PROG = lmtp2nntp -HDRS = lmtp2nntp.h lmtp.h nntp.h argz.h shpat_match.h msg.h -SRCS = lmtp2nntp.c lmtp.c nntp.c argz.c shpat_match.c msg.c version.c -OBJS = lmtp2nntp.o lmtp.o nntp.o argz.o shpat_match.o msg.o version.o +HDRS = lmtp2nntp.h daemon.h lmtp.h nntp.h argz.h shpat_match.h msg.h +SRCS = lmtp2nntp.c daemon.c lmtp.c nntp.c argz.c shpat_match.c msg.c version.c +OBJS = lmtp2nntp.o daemon.o lmtp.o nntp.o argz.o shpat_match.o msg.o version.o SUBDIRS = @SUBDIR_STR@ @SUBDIR_L2@ @SUBDIR_SA@ @@ -137,7 +137,8 @@ $(OBJS): Makefile # AUTOMATICALLY GENERATED DEPENDENCY LIST - DO NOT EDIT -lmtp2nntp.o: lmtp2nntp.c argz.h shpat_match.h lmtp2nntp.h config.h lmtp.h nntp.h msg.h version.c +lmtp2nntp.o: lmtp2nntp.c argz.h shpat_match.h daemon.h lmtp2nntp.h config.h lmtp.h nntp.h msg.h version.c +daemon.o: daemon.c daemon.h lmtp.o: lmtp.c lmtp.h config.h nntp.o: nntp.c nntp.h msg.h lmtp2nntp.h config.h argz.o: argz.c argz.h config.h Index: ossp-pkg/lmtp2nntp/daemon.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/daemon.c,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/daemon.c,v' 2>/dev/null --- daemon.c 2001/10/04 11:00:38 1.2 +++ daemon.c 2001/10/04 16:07:16 1.3 @@ -24,7 +24,7 @@ * no need to become daemon. */ if (getppid() == 1) - return; + return 0; /* * Ignore tty related signals Index: ossp-pkg/lmtp2nntp/lmtp2nntp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v rcsdiff -q -kk '-r1.63' '-r1.64' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v' 2>/dev/null --- 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] */ + 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[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 - * MAIL FROM: - * RCPT TO: - * DATA - * RSET - * NOOP - * QUIT - */ - 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 + * MAIL FROM: + * RCPT TO: + * DATA + * RSET + * NOOP + * QUIT + */ + 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 + * MAIL FROM: + * RCPT TO: + * DATA + * RSET + * NOOP + * QUIT + */ + 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; } Index: ossp-pkg/lmtp2nntp/lmtp2nntp.pod RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp.pod,v rcsdiff -q -kk '-r1.21' '-r1.22' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp.pod,v' 2>/dev/null --- lmtp2nntp.pod 2001/09/13 13:45:12 1.21 +++ lmtp2nntp.pod 2001/10/04 16:07:16 1.22 @@ -33,6 +33,7 @@ =head1 SYNOPSIS B +[B<-a> I] [B<-b> I[I<:port>]] [B<-d> I] [B<-g> I] @@ -112,6 +113,12 @@ In regard to this program they must provide the same groups and talk to each other. +=item B<-a> I + +Alternate IO allows reading and writing from/to a UNIX domain or TCP sockets +instead stdin/stdout. This places the program in daemon mode. The syntax for +altio is either "UNIX://path/to/socket" or "TCP://address:port". + =item B<-m> I "MAIL From:" filter to limit sender addresses. If ommitted, anyone can send