Index: ossp-pkg/lmtp2nntp/lmtp2nntp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v rcsdiff -q -kk '-r1.58' '-r1.59' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v' 2>/dev/null --- lmtp2nntp.c 2001/09/12 14:43:29 1.58 +++ lmtp2nntp.c 2001/09/13 07:35:03 1.59 @@ -144,9 +144,10 @@ struct utsname uname; } lmtp2nntp_t; -static void lmtp_gfs_lhlo(lmtp2nntp_t *ctx); -static void lmtp_gfs_rset(lmtp2nntp_t *ctx); -static void lmtp_gfs_quit(lmtp2nntp_t *ctx); +static void lmtp_gfs_ns(struct ns *); +static void lmtp_gfs_lhlo(lmtp2nntp_t *); +static void lmtp_gfs_rset(lmtp2nntp_t *); +static void lmtp_gfs_quit(lmtp2nntp_t *); enum { GROUPMODE_ARG, @@ -171,7 +172,6 @@ */ fprintf(stderr, "USAGE: %s " - "lmtp2nntp " "[-b bindaddr[:port]] " "[-d deliverymode] " "[-g groupmode] " @@ -288,9 +288,10 @@ int main(int argc, char **argv) { - lmtp_t *lmtp; + int rc; + lmtp_t *lmtp = NULL; lmtp_io_t lmtp_io; - lmtp2nntp_t *ctx; + lmtp2nntp_t *ctx = NULL; int i; /* general purpose scratch int, index ... */ char *cp; /* general purpose character pointer */ char *azHosts; @@ -305,16 +306,16 @@ /* library version check (run-time) */ if (l2_version.v_hex < L2_VERSION_HEX_REQ) { fprintf(stderr, "require OSSP L2 >= %s, found %s\n", L2_VERSION_STR_REQ, L2_VERSION_STR); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (str_version.v_hex < STR_VERSION_HEX_REQ) { fprintf(stderr, "require OSSP Str >= %s, found %s\n", STR_VERSION_STR_REQ, STR_VERSION_STR); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } /* create application context */ if ((ctx = (lmtp2nntp_t *)malloc(sizeof(lmtp2nntp_t))) == NULL) - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); ctx->progname = strdup(argv[0]); ctx->option_logfile = NULL; ctx->option_groupmode = GROUPMODE_ARG; @@ -344,24 +345,9 @@ ctx->msg = NULL; if (uname(&ctx->uname) == -1) { fprintf(stderr, "%s:Error: uname failed \"%s\"\n", ctx->progname, strerror(errno)); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } -#if 0 - { - char buf[1000]; - int bufused = 0; - int tracefile; - - for (i=0; i */ /* use @@ -388,7 +374,7 @@ ctx->cpBindh, ctx->cpBindp, strerror(errno)); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } break; case 'd': /*POD [B<-d> I] */ @@ -399,12 +385,12 @@ else { if (strlen(optarg) != 9) { fprintf(stderr, "%s:Error: Invalid format or length \"%s\" to option -d\n", ctx->progname, optarg); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (optarg[3] != '/') { fprintf(stderr, "%s:Error: Invalid format or missing slash \"%s\" to option -d\n", ctx->progname, optarg); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } optarg[3] = NUL; @@ -416,7 +402,7 @@ || !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); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if ( (strlen(ctx->option_deliverymodefakedsn) != 5) @@ -427,7 +413,7 @@ || !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); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } } break; @@ -440,17 +426,17 @@ ctx->option_groupmode = GROUPMODE_HEADER; else { fprintf(stderr, "%s:Error: Invalid mode \"%s\" to option -g\n", ctx->progname, optarg); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } break; case 'h': /*POD [B<-h> I[I<:port>][,I[I<:port>], ...]] */ if (argz_create_sep(optarg, ',', &azHosts, &asHosts) != 0) - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); cp = NULL; while ((cp = argz_next(azHosts, asHosts, cp)) != NULL) { if (ctx->nsc >= MAXNEWSSERVICES) { fprintf(stderr, "%s:Error: Too many services (%d) using option -h\n", ctx->progname, ctx->nsc); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } /* parse host[:port] string into host and port */ @@ -472,7 +458,7 @@ ctx->ns[ctx->nsc].h, ctx->ns[ctx->nsc].p, strerror(errno)); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } ctx->ns[ctx->nsc].sa = sa; if ((ctx->ns[ctx->nsc].s = @@ -482,7 +468,7 @@ ctx->ns[ctx->nsc].h, ctx->ns[ctx->nsc].p, strerror(errno)); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } ctx->ns[ctx->nsc].nntp = NULL; ctx->nsc++; @@ -494,7 +480,7 @@ *cp++ = NUL; if (*cp == NUL) { fprintf(stderr, "%s:Error: empty logfile to option -l\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } else ctx->option_logfile = strdup(cp); @@ -504,7 +490,7 @@ if (l2_util_s2l(optarg, strlen(optarg), ',', &ctx->option_levelmask) != L2_OK) { fprintf(stderr, "%s:Error: invalid level \"%s\" to option -l\n", ctx->progname, optarg); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } ctx->option_levelmask = L2_LEVEL_UPTO(ctx->option_levelmask); break; @@ -521,13 +507,13 @@ } if (str_parse("<>", ctx->option_mailfrom) == -1) { fprintf(stderr, "%s:Error: illegal regex \"%s\" to option -m.\n", ctx->progname, ctx->option_mailfrom); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } break; case 'n': /*POD [B<-n> I] */ if (strlen(optarg) > sizeof(ctx->uname.nodename)-1) { fprintf(stderr, "%s:Error: nodename \"%s\" to long to option -n.\n", ctx->progname, optarg); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } strcpy(ctx->uname.nodename, optarg); break; @@ -535,24 +521,24 @@ ctx->option_maxmessagesize = atoi(optarg); if(ctx->option_maxmessagesize < 64) { fprintf(stderr, "%s:Error: maximum message size is unacceptable small.\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } break; case 'v': /*POD [B<-v>] (version)*/ fprintf(stdout, "%s\n", lmtp2nntp_version.v_gnu); - exit(0); + CU(0); break; case 'w': /*POD [B<-w> I] */ 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); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } break; case '?': default: usage(ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } } /*POD I [I ...] */ @@ -562,81 +548,81 @@ if ((ctx->l2 = l2_stream_create()) == NULL) { fprintf(stderr, "%s:Error: logging failed to create stream\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_stream_levels(ctx->l2, L2_LEVEL_UPTO(L2_LEVEL_DEBUG), L2_LEVEL_NONE) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to set global logging level\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_stream_formatter(ctx->l2, 'P', formatter_prefix, (l2_context_t *)&ctx) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to register formatter\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_stream_formatter(ctx->l2, 'D', l2_util_fmt_dump, NULL) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to register dump formatter\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_stream_formatter(ctx->l2, 'S', l2_util_fmt_string, NULL) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to register string formatter\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_stream_formatter(ctx->l2, 'm', formatter_errno, NULL) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to register errno formatter\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if((ctx->option_levelmask != L2_LEVEL_NONE) && (ctx->option_logfile != NULL)) { if ((chPrefix = l2_channel_create(&l2_handler_prefix)) == NULL) { fprintf(stderr, "%s:Error: logging failed to create prefix channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_channel_configure(chPrefix, "prefix,timezone", "%b %d %H:%M:%S <%L> lmtp2nntp[%P]: ", "local") != L2_OK) { fprintf(stderr, "%s:Error: logging failed to configure prefix channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if ((chBuf = l2_channel_create(&l2_handler_buffer)) == NULL) { fprintf(stderr, "%s:Error: logging failed to create buffer channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_channel_configure(chBuf, "size", 65536) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to configure buffer channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if ((chFile = l2_channel_create(&l2_handler_file)) == NULL) { fprintf(stderr, "%s:Error: logging failed to create file channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_channel_configure(chFile, "path,append,perm", ctx->option_logfile, TRUE, 0644) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to configure file channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_channel_stack(chFile, chBuf) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to stack buffer channel on top of file channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_channel_stack(chBuf, chPrefix) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to stack prefix channel on top of buffer channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_channel_open(chPrefix) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to open buffer channel\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } if (l2_stream_channel(ctx->l2, chPrefix, ctx->option_levelmask, L2_LEVEL_NONE) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to attach channel into stream\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } } if (log1(ctx, NOTICE, "startup, version %s", lmtp2nntp_version.v_gnu) != L2_OK) { fprintf(stderr, "%s:Error: logging failed to log startup message to stream\n", ctx->progname); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } catchsignal(0, ctx); @@ -661,7 +647,7 @@ (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); - exit(ERR_EXECUTION); + CU(ERR_EXECUTION); } /* RFC0821, 4.5.1. MINIMUM IMPLEMENTATION * In order to make SMTP workable, the following minimum implementation @@ -688,8 +674,10 @@ /* loop for LMTP protocol */ lmtp_loop(lmtp); + CU(0); /* graceful shutdown */ + CUS: lmtp_gfs_quit(ctx); lmtp_gfs_lhlo(ctx); log0(ctx, NOTICE, "graceful shutdown shortly before exit - no more logging"); @@ -705,7 +693,7 @@ free(ctx); str_parse(NULL, NULL); - return 0; + return rc; } /* taken from "UNIX Network Programming", Volume 1, second edition W. Richard @@ -921,6 +909,7 @@ else { log2(ctx, WARNING, "NNTP session establishment to %s:%s failed", ctx->ns[i].h, ctx->ns[i].p); log1(ctx, DEBUG, "removing ns[%d] from list", i); + lmtp_gfs_ns(&ctx->ns[i]); if (i < --ctx->nsc) { memcpy(&ctx->ns[i], &ctx->ns[i+1], (ctx->nsc - i ) * sizeof(struct ns)); } @@ -954,7 +943,7 @@ "ENHANCEDSTATUSCODES\n" /* RFC2034 */ "DSN\n" /* RFC1894 */ "PIPELINING\n" /* RFC1854 */ - "8BITMIME\n", /* RFC1652 */ + "8BITMIME", /* RFC1652 */ ctx->uname.nodename, ctx->session.lhlo_domain); res.statuscode = "250"; @@ -967,24 +956,39 @@ return rc; } +static void lmtp_gfs_ns(struct ns *ns) +{ + if (ns->nntp != NULL) { + nntp_destroy(ns->nntp); + ns->nntp = NULL; + } + if (ns->s != -1) { + close(ns->s); + ns->s = -1; + } + if (ns->sa != NULL) { + sa_destroy(ns->sa); + ns->sa = NULL; + } + if (ns->p != NULL) { + free(ns->p); + ns->p = NULL; + } + if (ns->h != NULL) { + free(ns->h); + ns->h = NULL; + } +} + static void lmtp_gfs_lhlo(lmtp2nntp_t *ctx) { int i; log0(ctx, TRACE, "LMTP service LHLO command - graceful shutdown"); - for (i = 0; i < ctx->nsc; i++) { - if (ctx->ns[i].nntp != NULL) - nntp_destroy(ctx->ns[i].nntp); - if (ctx->ns[i].s != -1) - close(ctx->ns[i].s); - if (ctx->ns[i].sa != NULL) - sa_destroy(ctx->ns[i].sa); - if (ctx->ns[i].p != NULL) - free(ctx->ns[i].p); - if (ctx->ns[i].h != NULL) - free(ctx->ns[i].h); - } + for (i = 0; i < ctx->nsc; i++) + lmtp_gfs_ns(&ctx->ns[i]); + if (ctx->option_mailfrom != NULL) free(ctx->option_mailfrom); if (ctx->cpBindh != NULL)