Index: ossp-pkg/lmtp2nntp/lmtp2nntp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v rcsdiff -q -kk '-r1.36' '-r1.37' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v' 2>/dev/null --- lmtp2nntp.c 2001/08/30 09:01:59 1.36 +++ lmtp2nntp.c 2001/08/30 11:53:25 1.37 @@ -16,6 +16,7 @@ #include #include #include +#include /* third party */ #include "str.h" @@ -73,6 +74,7 @@ char *lhlo_domain; }; +static int connect_nonb(int, const struct sockaddr *, socklen_t, int); static void initsession(struct session *session); static void resetsession(struct session *session); int groupmatch(char *, size_t, char *); @@ -94,6 +96,7 @@ char *option_deliverymodefakestatus; char *option_deliverymodefakedsn; int option_maxmessagesize; + int option_waittime; int nsc; struct ns ns[MAXNEWSSERVICES]; char *azGroupargs; @@ -125,13 +128,21 @@ static void usage(char *command) { /* use - * perl ) { if(m/\/\*POD (.*) .*\*\//) { $_=$1; s/.<(.*?)>/$1/g ; print "$_ " };}' + * perl ) { if(m/\/\*POD (.*) .*\*\//) { $_=$1; s/.<(.*?)>/$1/g ; print "\"$_\"\n" };}' * to pull the USAGE string out of this source */ fprintf(stderr, "USAGE: %s " - "[-V] [-d deliverymode] [-g groupmode] [-h host[:port][,host[:port], ...]] " - "[-m maxmessagesize] [-n hostname] [-t tracefile] [-v] newsgroup [newsgroup ...]" + "[-V]" + "[-d deliverymode]" + "[-g groupmode]" + "[-h host[:port][,host[:port], ...]]" + "[-m maxmessagesize]" + "[-n hostname]" + "[-t tracefile]" + "[-v]" + "[-w waittime]" + "newsgroup [newsgroup ...]" "\n", command); return; @@ -164,6 +175,7 @@ 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_maxmessagesize = 8 * 1024 * 1024; + ctx->option_waittime = -1; ctx->nsc = 0; for (i=0; i < MAXNEWSSERVICES; i++) { ctx->ns[i].h = NULL; @@ -205,7 +217,7 @@ */ /* read in the arguments */ - while ((i = getopt(argc, argv, "Vd:g:h:m:n:t:v")) != -1) { + while ((i = getopt(argc, argv, "Vd:g:h:m:n:t:vw:")) != -1) { switch (i) { case 'V': /*POD [B<-V>] (version)*/ fprintf(stdout, "%s\n", lmtp2nntp_version.v_gnu); @@ -331,6 +343,14 @@ case 'v': /*POD [B<-v>] (verbose)*/ ctx->option_verbose = TRUE; 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", + progname, ctx->option_waittime); + exit(ERR_EXECUTION); + } + break; case '?': default: usage(progname); @@ -389,6 +409,61 @@ return rc; } +/* taken from "UNIX Network Programming", Volume 1, second edition W. Richard + * Stevens, connect_nonb.c from section 15.4 "Nonblocking connect", page 411, + * http://www.kohala.com/start/ + */ +int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec) +{ + int flags, n, error; + socklen_t len; + fd_set rset, wset; + struct timeval tval; + + flags = fcntl(sockfd, F_GETFL, 0); + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + + error = 0; + if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0) + if (errno != EINPROGRESS) + return(-1); + + /* Do whatever we want while the connect is taking place. */ + + if (n == 0) + goto done; /* connect completed immediately */ + + FD_ZERO(&rset); + FD_SET(sockfd, &rset); + wset = rset; + tval.tv_sec = nsec; + tval.tv_usec = 0; + + if ( (n = select(sockfd+1, &rset, &wset, NULL, + nsec ? &tval : NULL)) == 0) { + close(sockfd); /* timeout */ + errno = ETIMEDOUT; + return(-1); + } + + if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { + len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + return(-1); /* Solaris pending error */ + } else + return(-1); /* err_quit("select error: sockfd not set"); */ + +done: + fcntl(sockfd, F_SETFL, flags); /* restore file status flags */ + + if (error) { + close(sockfd); /* just in case */ + errno = error; + return(-1); + } + return(0); +} + static void resetsession(struct session *session) { if (session->lhlo_domain != NULL) @@ -478,13 +553,24 @@ i = 0; do { bOk = TRUE; - if (connect(ctx->ns[i].s, ctx->ns[i].sa->sa_buf, ctx->ns[i].sa->sa_len) < 0) { - bOk = FALSE; + if (ctx->option_waittime > 0) { + if (connect_nonb(ctx->ns[i].s, ctx->ns[i].sa->sa_buf, ctx->ns[i].sa->sa_len, + ctx->option_waittime) < 0) { + bOk = FALSE; + } + } + else { + if (connect(ctx->ns[i].s, ctx->ns[i].sa->sa_buf, ctx->ns[i].sa->sa_len) < 0) { + bOk = FALSE; + } } if (bOk && ((ctx->ns[i].nntp = nntp_create(ctx->ns[i].s, ctx->ns[i].s, ctx->option_tracing ? &nntp_io : NULL)) == NULL)) { bOk = FALSE; } + if (bOk && ctx->option_waittime >= 0) { + nntp_timeout(ctx->ns[i].nntp, ctx->option_waittime); + } if (bOk && ((rc = nntp_init(ctx->ns[i].nntp)) != NNTP_OK)) { bOk = FALSE; } Index: ossp-pkg/lmtp2nntp/lmtp2nntp.pod RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp.pod,v rcsdiff -q -kk '-r1.11' '-r1.12' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp.pod,v' 2>/dev/null --- lmtp2nntp.pod 2001/08/30 09:01:59 1.11 +++ lmtp2nntp.pod 2001/08/30 11:53:25 1.12 @@ -16,11 +16,12 @@ [B<-n> I] [B<-t> I] [B<-v>] +[B<-w> I] I [I ...] + B [B<-o> I] [B<-i> I] -[B<-T> I] [B<-l> I] =head1 DESCRIPTION @@ -101,6 +102,13 @@ Enable verbose processing messages in logfile. When using C these messages are logged with C level. +=item B<-w> I + +Specify the time the NNTP client waits for the initial connect to complete and +the time to wait for every server's response. Value is given in seconds and +must be greater than or equal to 1 second. The default is OS dependent for the +connect and a 3 second timeout waiting for a server's response. + =item I [I ...] Newsgroup to post the message to or filter, depending on groupmode. Multiple