From xemacs-m  Sun Aug 17 16:06:59 1997
Received: from atreides.eng.mindspring.net (atreides.eng.mindspring.net [207.69.183.11])
	by xemacs.org (8.8.5/8.8.5) with SMTP id QAA24873
	for <xemacs-beta@xemacs.org>; Sun, 17 Aug 1997 16:06:59 -0500 (CDT)
Received: (qmail 25591 invoked by uid 52477); 17 Aug 1997 21:06:30 -0000
To: xemacs-beta@xemacs.org
Subject: Re: [list abuse] change w3 faces?
References: <ocrhgcrywcq.fsf@ml.com> <m2g1s823yk.fsf@altair.xemacs.org>
Mime-Version: 1.0 (generated by tm-edit 7.108)
Content-Type: text/plain; charset=US-ASCII
From: Sudish Joseph <sj@eng.mindspring.net>
Date: 17 Aug 1997 17:06:30 -0400
In-Reply-To: SL Baur's message of "17 Aug 1997 09:01:55 -0700"
Message-ID: <yvia4t8omsdl.fsf@atreides.eng.mindspring.net>
Lines: 152
X-Mailer: Gnus v5.4.65/XEmacs 20.3(beta14) - "Vienna"

SL Baur writes:
> Ack!  ftpds are getting wedged on xemacs.org again. :-(

Try attaching to the wedged ftpd's and see if they're blocked inside
of accept().  If so, you're seeing a problem we had with PASV ftp and
proxies.  Basically, the client issues PASV and then sends the data
connection to the proxy, which has no clue as to where to forward the
new connection.  Meanwhile, ftpd sits inside of accept() waiting for a
dataconn that'll never come.  We used to get quite a few blocked
ftpd's as a result of this.

One workaround is to timeout the accept().  I used select() for the
purpose.  The patch below might or might not patch cleanly for you --
our source has diverged quite a bit from wu-ftpd.  You might also wish 
to merge the s == -1 and s == -2 cases inside dataconn().

-Sudish

Index: ftpd.c
===================================================================
RCS file: /b/cvsroot/ftp/msftpd/src/ftpd.c,v
retrieving revision 1.41
retrieving revision 1.43
diff -u -r1.41 -r1.43
--- ftpd.c	1997/03/22 21:54:08	1.41
+++ ftpd.c	1997/03/25 00:07:37	1.43
@@ -49,6 +49,7 @@
 #include <sys/socket.h>
 #include <sys/file.h>
 #include <sys/wait.h>
+#include <sys/time.h>
 
 #ifdef AIX
 #include <sys/id.h>
@@ -160,13 +160,11 @@
 #endif
 extern char version[];
 extern char *home;              /* pointer to home directory for glob */
-extern FILE *ftpd_popen(char *program, char *type, int closestderr),
- *fopen(const char *, const char *),
- *freopen(const char *, const char *, FILE *);
-extern int ftpd_pclose(FILE *iop),
-  fclose(FILE *);
+extern FILE *ftpd_popen(char *program, char *type, int closestderr);
+extern int ftpd_pclose(FILE *iop);
 extern char *getline();
 void dolog(struct sockaddr_in *sin);
+int timed_accept(int fd, struct sockaddr *from, struct timeval *timeout);
 
 extern char cbuf[];
 extern off_t restart_point;
@@ -241,6 +239,7 @@
 char *MyDomain = "%s";
 int InSane = 0;
 D_FILE doedb;
+int AcceptWait = 15 * 60;       /* seconds */
 
 /* Allow use of lreply(); this is here since some older FTP clients don't
  * support continuation messages.  In violation of the RFCs... */
@@ -395,6 +394,10 @@
                 debug = 1;
                 break;
 
+            case 'w':
+                AcceptWait = atoi(++cp);
+                goto nextopt;
+
             case 'Z':
                 InSane = 1;
                 break;
@@ -1889,16 +1890,34 @@
         (void) strcpy(sizebuf, "");
     if (pdata >= 0) {
         struct sockaddr_in from;
-        int s,
-          fromlen = sizeof(from);
+        struct timeval tv;
+        int s;
 
-        s = accept(pdata, (struct sockaddr *) &from, &fromlen);
-        if (s < 0) {
+        /* we don't want to block in this accept forever */
+        tv.tv_sec  = AcceptWait;
+        tv.tv_usec = 0;
+        s = timed_accept(pdata, (struct sockaddr *) &from, &tv);
+        if (s == -2) {
             reply(425, "Can't open data connection.");
             (void) close(pdata);
             pdata = -1;
             return (NULL);
         }
+        else if (s == -1) {      /* timed out, kick them out */
+            reply(425, "Can't open data connection.");
+            close(pdata);
+            pdata = -1;
+            if (anonymous) {
+                syslog(LOG_INFO, "dataconn timed out: %s [%s], anonymous",
+                       remotehost, remoteaddr);
+            }
+            else {
+                syslog(LOG_INFO, "dataconn timed out: %s [%s], %s%s",
+                       remotehost, remoteaddr, pnam(pw), pdom(MyDomain));
+            }
+            dologout(-1);
+        }
+        
         (void) close(pdata);
         pdata = s;
 #ifdef IPTOS_LOWDELAY
@@ -3109,3 +3128,41 @@
     return -1;
 }
 #endif /* ULTRIX_AUTH */
+
+/* timed_accept: accepts a connection on fd.
+ * the connection is timed out after timeout seconds.
+ * returns new fd on success, -1 on timeout, -2 on error.
+ */
+int
+timed_accept(int fd, struct sockaddr *from, struct timeval *timeout) 
+{
+    fd_set readfds;
+    int n;
+    
+    FD_ZERO(&readfds);
+    FD_SET(fd, &readfds);
+    
+    if (0 > (n = select(fd + 1, &readfds, NULL, NULL, timeout))) {
+        syslog(LOG_ERR, "timed_accept: select failed: %m");
+        return -2;
+    }
+    
+    if (!n) {
+        syslog(LOG_INFO, "timed_accept: select() timed out");
+        return -1;
+    }
+    
+    if (FD_ISSET(fd, &readfds)) {
+        int newfd;
+        int len = sizeof(*from);
+        
+        if (0 > (newfd = accept(fd, from, &len))) {
+            syslog(LOG_ERR, "timed_accept: accept failed: %m");
+            return -2;
+        }
+        
+        return newfd;
+    }
+    
+    return -2;
+}

