--- 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<argc; i++)
- bufused+=sprintf(buf+bufused, "[%d]=\"%s\"\n", i, argv[i]);
- if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) {
- write(tracefile, buf, bufused);
- close(tracefile);
- }
- }
-#endif
-
/*POD B<lmtp2nntp> */
/* use
@@ -388,7 +374,7 @@
ctx->cpBindh,
ctx->cpBindp,
strerror(errno));
- exit(ERR_EXECUTION);
+ CU(ERR_EXECUTION);
}
break;
case 'd': /*POD [B<-d> I<deliverymode>] */
@@ -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<host>[I<:port>][,I<host>[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<nodename>] */
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<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);
- exit(ERR_EXECUTION);
+ CU(ERR_EXECUTION);
}
break;
case '?':
default:
usage(ctx->progname);
- exit(ERR_EXECUTION);
+ CU(ERR_EXECUTION);
}
}
/*POD I<newsgroup> [I<newsgroup> ...] */
@@ -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)
|