--- 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 <string.h>
#include <fcntl.h>
#include <sys/utsname.h>
+#include <sys/time.h>
/* 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 <lmtp2nntp.c -e 'while (<>) { if(m/\/\*POD (.*) .*\*\//) { $_=$1; s/.<(.*?)>/$1/g ; print "$_ " };}'
+ * perl <lmtp2nntp.c -e 'while (<>) { 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<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",
+ 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;
}
|