Subject: Current fixes for BETA 17

From: Gregory A Lundberg <[email-masked]>
Date: Wed, 3 Jun 1998 13:02:02 -0400 (EDT)

This is my current list of fixes for BETA 17.  Some of them you may have
seen before, some are new.  Below is the FIXES files included in the
patch.

----

This is a list of fixes to BETA 17 from [email-masked]
------------------------------------------------------------------------------
The CD command supports ~<username> but gives errors when just ~ is found.
The patch fixes this for the CD command.  Note: there are still problems with
other commands which may or may not accept tilde-user notation and may or may
not understand a tilde by itself means the current user's home directory.
This only effects chroot'd users.  From patches submitted to the mailing list
by [email-masked] and [email-masked] on Nov 16, 1997.

Prevent NOOP resetting idle timer.  From a patch submitted to the mailing
list by [email-masked] on Feb 4, 1998.

Add -X command-line option and syslog option to log statement in ftpaccess.
These options eliminate xferlog output and direct transfer logs to syslog
instead.  From a patch posted to the mailing list by [email-masked]
on Mar 12, 1998.  Corrected and cleaned up during testing.

Somewhere along the way the upload statement was broken.  The fix adds a new
parameter to upload so admins can determine the permissions for any new
directories permitted.  New features are documented in ftpaccess manpage.
>From original patches submitted to the mailing list by [email-masked]
and [email-masked] on Apr 29, 1998.

Move Linux to use POSIX regex included with the system instead of the routines
included with wu-ftpd.  This allows us to define path-filter statements which
allow spaces in the pathnames.  For example:
path-filter  anonymous  /etc/pathmsg  ^[-A-Za-z0-9_.[:space:]]*$  ^\.  ^-
>From a patch submitted to the mailing list by [email-masked]
on Apr 30, 1998.

Added 'hostname' configuration statement.  Normally the server determines its
host name from the system.  This allows the admin to set the name on machines
with several names (multihomed) where the default name is not the desired name.
Manpage updated.  Discovered in testing.

Shutdown warnings were not given to normal (non-anonymous) users on login.
Discovered in testing.

----

Gregory A Lundberg		Senior Partner, VRnet Company
1441 Elmdale Drive              [email-masked]
Kettering, OH 45409-1615 USA    1-800-809-2195
*** FIXES-2.4.2-BETA-17-VR1.orig	Tue Jun  2 14:43:36 1998
--- FIXES-2.4.2-BETA-17-VR1	Wed Jun  3 12:53:05 1998
***************
*** 0 ****
--- 1,38 ----
+ This is a list of fixes to BETA 17 from [email-masked]
+ ------------------------------------------------------------------------------
+ The CD command supports ~<username> but gives errors when just ~ is found.
+ The patch fixes this for the CD command.  Note: there are still problems with
+ other commands which may or may not accept tilde-user notation and may or may
+ not understand a tilde by itself means the current user's home directory.
+ This only effects chroot'd users.  From patches submitted to the mailing list
+ by [email-masked] and [email-masked] on Nov 16, 1997.
+ 
+ Prevent NOOP resetting idle timer.  From a patch submitted to the mailing
+ list by [email-masked] on Feb 4, 1998.
+ 
+ Add -X command-line option and syslog option to log statement in ftpaccess.
+ These options eliminate xferlog output and direct transfer logs to syslog
+ instead.  From a patch posted to the mailing list by [email-masked]
+ on Mar 12, 1998.  Corrected and cleaned up during testing.
+ 
+ Somewhere along the way the upload statement was broken.  The fix adds a new
+ parameter to upload so admins can determine the permissions for any new
+ directories permitted.  New features are documented in ftpaccess manpage.
+ From original patches submitted to the mailing list by [email-masked]
+ and [email-masked] on Apr 29, 1998.
+ 
+ Move Linux to use POSIX regex included with the system instead of the routines
+ included with wu-ftpd.  This allows us to define path-filter statements which
+ allow spaces in the pathnames.  For example:
+ path-filter  anonymous  /etc/pathmsg  ^[-A-Za-z0-9_.[:space:]]*$  ^\.  ^-
+ From a patch submitted to the mailing list by [email-masked]
+ on Apr 30, 1998.
+ 
+ Added 'hostname' configuration statement.  Normally the server determines its
+ host name from the system.  This allows the admin to set the name on machines
+ with several names (multihomed) where the default name is not the desired name.
+ Manpage updated.  Discovered in testing.
+ 
+ Shutdown warnings were not given to normal (non-anonymous) users on login.
+ Discovered in testing.
+ 
*** vr1.sh.orig	Tue Jun  2 14:43:36 1998
--- vr1.sh	Tue Jun  2 14:43:36 1998
***************
*** 0 ****
--- 1,9 ----
+ diff -c FIXES-2.4.2-BETA-17-VR1.orig	FIXES-2.4.2-BETA-17-VR1		>  ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c vr1.sh.orig			vr1.sh				>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c doc/ftpaccess.5.orig		doc/ftpaccess.5			>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c doc/ftpd.8.orig			doc/ftpd.8			>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c src/access.c.orig		src/access.c			>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c src/extensions.c.orig		src/extensions.c		>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c src/ftpcmd.y.orig		src/ftpcmd.y			>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c src/ftpd.c.orig			src/ftpd.c			>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
+ diff -c src/config/config.lnx.orig	src/config/config.lnx		>> ../wu-ftpd-2.4.2-beta-17-vr1.patch
*** doc/ftpaccess.5.orig	Sun Dec 21 18:03:32 1997
--- doc/ftpaccess.5	Wed Jun  3 11:48:40 1998
***************
*** 140,145 ****
--- 140,151 ----
  can handle multi-line responses (which is how the banner is
  displayed).
  .TP 0.5i
+ .B hostname <some.host.name>
+ Defines the default host name of the ftp server.  This string will be
+ printed on the greeting message and every time the %L magic cookie
+ is used.  The host name for virtual servers overrides this value.  If
+ not specified, the default host name for the local machine is used.
+ .TP 0.5i
  .B email <name>
  Defines the email address of the ftp archive maintainer.  This string
  will be printed every time the %E magic cookie is used.
***************
*** 216,221 ****
--- 222,231 ----
  of any of the two keywords "inbound" and "outbound", and will
  respectively cause transfers to be logged for files sent to the
  server and sent from the server.
+ .TP 0.5i
+ .B log syslog
+ Redirects the logging messages for incoming and outgoing transfers
+ to syslog.  Without this option the messages are written to xferlog.
  .SH Miscellaneous Capabilities
  .TP 0.5i
  .B alias <string> <dir>
***************
*** 358,364 ****
  begin with a "." or a "-".  If the filename is invalid, /etc/pathmsg
  will be displayed to the user.
  .TP 0.5i
! .B upload <root-dir> <dirglob> <yes|no> <owner> <group> <mode> ["dirs"|"nodirs"]
  Define a directory with <dirglob> that permits or
  denies uploads.
  
--- 368,374 ----
  begin with a "." or a "-".  If the filename is invalid, /etc/pathmsg
  will be displayed to the user.
  .TP 0.5i
! .B upload <root-dir> <dirglob> <yes|no> <owner> <group> <mode> ["dirs"|"nodirs"] [<d_mode>]
  Define a directory with <dirglob> that permits or
  denies uploads.
  
***************
*** 386,394 ****
  specified to allow or disallow the creation of
  new subdirectories using the mkdir command.
  
  The upload keyword only applies to users who
  have a home directory (the argument to the chroot() )
! of <root-dir>.
  .SH Files
  FTPLIB/ftpaccess
  .SH See Also
--- 396,411 ----
  specified to allow or disallow the creation of
  new subdirectories using the mkdir command.
  
+ If directories are permitted, the optional
+ <d_mode> determines the permissions for the a newly
+ created directory.  If <d_mode> is omitted, the
+ permissions are inferred from <mode> or are 0777 if
+ <mode> is also omitted.
+ 
  The upload keyword only applies to users who
  have a home directory (the argument to the chroot() )
! of <root-dir>.  <root-dir> may be specified as "*" to
! match any home directory.
  .SH Files
  FTPLIB/ftpaccess
  .SH See Also
*** doc/ftpd.8.orig	Sun Dec 21 18:03:34 1997
--- doc/ftpd.8	Tue Jun  2 14:43:36 1998
***************
*** 45,52 ****
  .BR \-i
  ] [
  .BR \-o
! ]
  .BR \-u umask
  ]
  .SH DESCRIPTION
  .I Ftpd
--- 45,54 ----
  .BR \-i
  ] [
  .BR \-o
! ] [
  .BR \-u umask
+ ] [
+ .BR \-X
  ]
  .SH DESCRIPTION
  .I Ftpd
***************
*** 132,138 ****
  The 
  .B \-o option is overridden by the use of the
  .IR ftpaccess (5)
! file.
  .PP
  If the
  .B \-u
--- 134,147 ----
  The 
  .B \-o option is overridden by the use of the
  .IR ftpaccess (5)
! file.  If the
! .B \-X
! option is specified, the output created by the
! .B \-i
! and
! .B \-o
! options is not saved to the xferlog file but saved via syslog
! so you can collect output from several hosts on one central loghost.
  .PP
  If the
  .B \-u
*** src/access.c.orig	Sun Dec 21 18:24:54 1997
--- src/access.c	Tue Jun  2 14:43:36 1998
***************
*** 341,346 ****
--- 341,347 ----
        log_outbound_xfers,
        mangleopts,
        log_commands,
+       syslogmsg,
        lgi_failure_threshold;
  
      struct aclmember *entry = NULL;
***************
*** 355,360 ****
--- 356,362 ----
      log_incoming_xfers = 0;
      log_outbound_xfers = 0;
      log_commands = 0;
+     syslogmsg = 0;
  
      memset((void *)&class[0], 0, sizeof(class));
   
***************
*** 427,432 ****
--- 429,436 ----
              if (set)
                  log_outbound_xfers = outbound;
          }
+         if (!strcasecmp(ARG0, "syslog"))
+             syslogmsg = 1;
      }
  }
  
*** src/extensions.c.orig	Sun Dec 21 18:24:56 1997
--- src/extensions.c	Tue Jun  2 14:43:36 1998
***************
*** 883,888 ****
--- 883,892 ----
    regmatch_t regmatchbuf;
  #endif
  
+ #ifdef LINUX
+   re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
+ #endif
+ 
    while (getaclentry("path-filter", &entry) && ARG0 != NULL) {
        if (type_match(ARG0) && ARG1 && ARG2) {
  
***************
*** 966,977 ****
  
  int
  #ifdef __STDC__
! dir_check(char *name, uid_t *uid, gid_t *gid, int *valid)
  #else
! dir_check(name,uid,gid,valid)
  char *name;
  uid_t *uid;
  gid_t *gid;
  int *valid;
  #endif
  {
--- 970,982 ----
  
  int
  #ifdef __STDC__
! dir_check(char *name, uid_t *uid, gid_t *gid, int *d_mode, int *valid)
  #else
! dir_check(name,uid,gid,d_mode,valid)
  char *name;
  uid_t *uid;
  gid_t *gid;
+ int *d_mode;
  int *valid;
  #endif
  {
***************
*** 982,988 ****
    char *ap2 = NULL,
         *ap3 = NULL,
         *ap4 = NULL,
!        *ap6 = NULL;
    char cwdir[BUFSIZ];
    char path[BUFSIZ];
    char *sp;
--- 987,995 ----
    char *ap2 = NULL,
         *ap3 = NULL,
         *ap4 = NULL,
!        *ap5 = NULL,
!        *ap6 = NULL,
!        *ap7 = NULL;
    char cwdir[BUFSIZ];
    char path[BUFSIZ];
    char *sp;
***************
*** 1000,1006 ****
      return(-1);
    }
    while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
!       if ( (!strcmp(ARG0, pw->pw_dir)) &&
             ((i = path_compare(ARG1, cwdir)) >= match_value) ) {
            match_value = i;
            ap2 = ARG2;
--- 1007,1013 ----
      return(-1);
    }
    while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
!       if ( (!strcmp(ARG0, "*") || !strcmp(ARG0, pw->pw_dir)) &&
             ((i = path_compare(ARG1, cwdir)) >= match_value) ) {
            match_value = i;
            ap2 = ARG2;
***************
*** 1008,1015 ****
--- 1015,1026 ----
            else       ap3 = NULL;
            if (ARG4)  ap4 = ARG4;
            else       ap4 = NULL;
+           if (ARG5)  ap5 = ARG5;
+           else       ap5 = NULL;
            if (ARG6)  ap6 = ARG6;
            else       ap6 = NULL;
+           if (ARG7)  ap7 = ARG7;
+           else       ap7 = NULL;
        }
    }
    if ( (ap3 && !strcasecmp(ap3, "nodirs")) ||
***************
*** 1019,1026 ****
    }
    if (ap3)
       *uid = atoi(ap3);    /* the uid  */
!   if (ap4) {
       *gid = atoi(ap4);    /* the gid */
       *valid = 1;
     }
    return(1);
--- 1030,1048 ----
    }
    if (ap3)
       *uid = atoi(ap3);    /* the uid  */
!   if (ap4)
       *gid = atoi(ap4);    /* the gid */
+   if (ap7) {
+      sscanf(ap7, "%o", d_mode);
+      *valid = 1;
+    } else if (ap5) {
+      sscanf(ap5, "%o", d_mode);
+      if (*d_mode & 0600)
+         *d_mode |= 0100;
+      if (*d_mode & 0060)
+         *d_mode |= 0010;
+      if (*d_mode & 0006)
+         *d_mode |= 0001;
       *valid = 1;
     }
    return(1);
*** src/ftpcmd.y.orig	Fri May  8 11:31:45 1998
--- src/ftpcmd.y	Tue Jun  2 14:43:36 1998
***************
*** 1155,1161 ****
                  reply(221, "You could at least say goodbye.");
                  dologout(0);
              }
-             (void) alarm(0);
              if ((cp = strchr(cbuf, '\r'))) {
                  *cp++ = '\n';
                  *cp = '\0';
--- 1155,1160 ----
***************
*** 1167,1172 ****
--- 1166,1173 ----
              c = cbuf[cpos];
              cbuf[cpos] = '\0';
              upper(cbuf);
+             if (strncasecmp(cbuf, "NOOP", 4) != 0)
+                 (void) alarm(0);
              p = lookup(cmdtab, cbuf);
              cbuf[cpos] = c;
              if (strncasecmp(cbuf, "PASS", 4) != 0 &&
*** src/ftpd.c.orig	Sat May  9 17:23:53 1998
--- src/ftpd.c	Wed Jun  3 12:47:48 1998
***************
*** 239,244 ****
--- 239,245 ----
     sense.  -L is way noisy; -l we'll change to be "just right".  _H*/
  int logging = 0;
  int log_commands = 0;
+ int syslogmsg = 0;
  
  #ifdef SECUREOSF
  #define SecureWare
***************
*** 446,452 ****
      data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
      debug = 0;
  
!     while ((c = getopt(argc, argv, ":aAvdlLiot:T:u:")) != -1) {
          switch (c) {
  
          case 'a':
--- 447,453 ----
      data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
      debug = 0;
  
!     while ((c = getopt(argc, argv, ":aAvdlLiot:T:u:X")) != -1) {
          switch (c) {
  
          case 'a':
***************
*** 506,511 ****
--- 507,516 ----
                  break;
              }
  
+         case 'X':
+             syslogmsg = 1;
+             break;
+ 
          case ':':
              syslog(LOG_ERR, "option -%c requires an argument", optopt);
              break;
***************
*** 724,729 ****
--- 729,739 ----
      tmpline[0] = '\0';
      yyerrorcalled = 0;
  
+     access_init();
+   if ( (getaclentry("hostname", &entry)) && ARG0 ) {
+       (void) strncpy(hostname, ARG0, sizeof(hostname));
+       hostname[sizeof(hostname)-1]='\0';
+   } else {
  #ifdef HAVE_SYSINFO
      sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
  #else
***************
*** 735,741 ****
        (void) strncpy(hostname, shp->h_name, sizeof(hostname));
        hostname[sizeof(hostname)-1]='\0';
      }
!     access_init();
      authenticate();
      conv_init();
  #ifdef VIRTUAL
--- 745,751 ----
        (void) strncpy(hostname, shp->h_name, sizeof(hostname));
        hostname[sizeof(hostname)-1]='\0';
      }
!   }
      authenticate();
      conv_init();
  #ifdef VIRTUAL
***************
*** 1526,1532 ****
      }
  
      /* if logging is enabled, open logfile before chroot or set group ID */
!     if (log_outbound_xfers || log_incoming_xfers) {
          xferlog = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0660);
          if (xferlog < 0) {
              syslog(LOG_ERR, "cannot open logfile %s: %s", logfile,
--- 1536,1542 ----
      }
  
      /* if logging is enabled, open logfile before chroot or set group ID */
!     if ((log_outbound_xfers || log_incoming_xfers) && !syslogmsg) {
          xferlog = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0660);
          if (xferlog < 0) {
              syslog(LOG_ERR, "cannot open logfile %s: %s", logfile,
***************
*** 1597,1608 ****
--- 1607,1631 ----
              if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
                  reply(530, "Can't set guest privileges.");
                  goto bad;
+             } else {
+                 if ((pw->pw_dir [0] == '\0')
+                 ||  ((pw->pw_dir [0] == '/') && (pw->pw_dir[1] == '\0'))) {
+                   reply(530, "Can't set guest privileges.");
+                   goto bad;
+                 } else {
+                   pw->pw_dir [0] = '/';
+                   pw->pw_dir [1] = '\0';
+                 }
              }
          } else{
  	  *sp++ = '\0';
  	  if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
  	    reply(550, "Can't set guest privileges.");
  	    goto bad;
+           } else {
+             char *pp;
+             pp = pw->pw_dir;
+             do *pp++ = *sp; while (*sp++ != '\0');
  	  }
          }
      }
***************
*** 1670,1677 ****
      }
  #endif /* ULTRIX_AUTH */    
  
      if (anonymous) {
-         (void) is_shutdown(0, 0);  /* display any shutdown messages now */
  
          reply(230, "Guest login ok, access restrictions apply.");
          sprintf(proctitle, "%s: anonymous/%.*s", remotehost,
--- 1693,1701 ----
      }
  #endif /* ULTRIX_AUTH */    
  
+     (void) is_shutdown(0, 0);  /* display any shutdown messages now */
+ 
      if (anonymous) {
  
          reply(230, "Guest login ok, access restrictions apply.");
          sprintf(proctitle, "%s: anonymous/%.*s", remotehost,
***************
*** 1913,1919 ****
      (void) fclose(dout);
  
    dolog:
!     if (log_outbound_xfers && xferlog && (cmd == 0)) {
          char msg[MAXPATHLEN];
  	char *msg2;		/* for stupid_sprintf */
          int xfertime = time(NULL) - start_time;
--- 1937,1943 ----
      (void) fclose(dout);
  
    dolog:
!     if (log_outbound_xfers && (xferlog || syslogmsg) && (cmd == 0)) {
          char msg[MAXPATHLEN];
  	char *msg2;		/* for stupid_sprintf */
          int xfertime = time(NULL) - start_time;
***************
*** 1978,1984 ****
--- 2002,2011 ----
                  authenticated ? authuser : "*"
              );
  #endif /* stupid_sprintf */
+       if (!syslogmsg)
          write(xferlog, msg, strlen(msg));
+       else
+         syslog(LOG_INFO, "xferlog (send): %s", msg+25);
      }
      data = -1;
      pdata = -1;
***************
*** 2156,2162 ****
      (void) fclose(din);
  
    dolog:
!     if (log_incoming_xfers && xferlog) {
          char namebuf[MAXPATHLEN],
            msg[MAXPATHLEN];
  	char *msg2;		/* for stupid_sprintf */
--- 2183,2189 ----
      (void) fclose(din);
  
    dolog:
!     if (log_incoming_xfers && (xferlog || syslogmsg)) {
          char namebuf[MAXPATHLEN],
            msg[MAXPATHLEN];
  	char *msg2;		/* for stupid_sprintf */
***************
*** 2222,2228 ****
--- 2249,2259 ----
                  authenticated ? authuser : "*"
              );
  #endif /* STUPID_SPRINTF */
+ syslog (LOG_ERR, "syslogmsg: %i", syslogmsg);
+       if (!syslogmsg)
          write(xferlog, msg, strlen(msg));
+       else
+         syslog(LOG_INFO, "xferlog (recv): %s", msg+25);
      }
      data = -1;
      pdata = -1;
***************
*** 2949,2960 ****
      if ((st.st_mode & S_IFMT) == S_IFDIR) {
          uid_t uid;
          gid_t gid;
          int valid;
  
          /*
           * check the directory, can we rmdir here?
           */
!         if ( (dir_check(name, &uid, &gid, &valid)) <= 0 )
              return;
  
          if (rmdir(name) < 0) {
--- 2980,2992 ----
      if ((st.st_mode & S_IFMT) == S_IFDIR) {
          uid_t uid;
          gid_t gid;
+         int d_mode;
          int valid;
  
          /*
           * check the directory, can we rmdir here?
           */
!         if ( (dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0 )
              return;
  
          if (rmdir(name) < 0) {
***************
*** 3039,3050 ****
  {
  	uid_t uid;
  	gid_t gid;
  	int   valid;
  
      /*
       * check the directory, can we mkdir here?
       */
!     if ( (dir_check(name, &uid, &gid, &valid)) <= 0 )
          return;
  
      /*
--- 3071,3084 ----
  {
  	uid_t uid;
  	gid_t gid;
+ 	int   d_mode;
  	int   valid;
+ 	uid_t oldid;
  
      /*
       * check the directory, can we mkdir here?
       */
!     if ( (dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0 )
          return;
  
      /*
***************
*** 3053,3065 ****
      if ( (fn_check(name)) <= 0 )
          return;
  
!     if (mkdir(name, 0777) < 0) {
          if (errno == EEXIST)
              perror_reply(553, name);
          else
              perror_reply(550, name);
  	return;
      }
      reply(257, "MKD command successful.");
  }
  
--- 3087,3114 ----
      if ( (fn_check(name)) <= 0 )
          return;
  
!     if (valid <= 0)
!         d_mode = 0777;
!     if (mkdir(name, d_mode) < 0) {
          if (errno == EEXIST)
              perror_reply(553, name);
          else
              perror_reply(550, name);
  	return;
      }
+     if (valid > 0) {
+         oldid = geteuid();
+         delay_signaling(); /* we can't allow any signals while euid==0: kinch */
+         (void) seteuid((uid_t) 0);
+         if ((chown(name, uid, gid)) < 0) {
+             (void) seteuid(oldid);
+             enable_signaling(); /* we can allow signals once again: kinch */
+             perror_reply(550, "chown");
+             return;
+         }
+         (void) seteuid(oldid);
+         enable_signaling(); /* we can allow signals once again: kinch */
+     }
      reply(257, "MKD command successful.");
  }
  
***************
*** 3073,3078 ****
--- 3122,3128 ----
  {
      uid_t uid;
      gid_t gid;
+     int d_mode;
      int valid;
  
      /*
***************
*** 3084,3090 ****
      /*
       * check the directory, can we rmdir here?
       */
!     if ( (dir_check(name, &uid, &gid, &valid)) <= 0 )
          return;
  
      if (rmdir(name) < 0) {
--- 3134,3140 ----
      /*
       * check the directory, can we rmdir here?
       */
!     if ( (dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0 )
          return;
  
      if (rmdir(name) < 0) {
*** src/config/config.lnx.orig	Sun May 10 21:01:22 1998
--- src/config/config.lnx	Tue Jun  2 14:43:36 1998
***************
*** 25,30 ****
--- 25,31 ----
  #define LINUX
  #define OVERWRITE
  #undef  REGEX
+ #define HAVE_REGEX_H
  #define SPT_TYPE SPT_REUSEARGV
  #undef  SHADOW_PASSWORD
  #define UPLOAD