*** lib/backupfile.c~0	Wed Dec 18 03:29:38 1996
--- lib/backupfile.c	Sat Mar 22 17:25:26 1997
*************** max_backup_version (file, dir)
*** 164,170 ****
  
    while ((dp = readdir (dirp)) != 0)
      {
!       if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length)
  	continue;
  
        this_version = version_number (file, dp->d_name, file_name_length);
--- 164,179 ----
  
    while ((dp = readdir (dirp)) != 0)
      {
!       if (!REAL_DIR_ENTRY (dp)
! #if !defined(MSDOS) || defined(__DJGPP__)
! 	  || (NLENGTH (dp) <= file_name_length
! #ifdef __DJGPP__
! 	      /* When long filenames aren't supported, examine all files.  */
! 	      && _use_lfn (dir)
! #endif
! 	      )
! #endif
! 	  )
  	continue;
  
        this_version = version_number (file, dp->d_name, file_name_length);
*************** make_version_name (file, version)
*** 190,195 ****
--- 199,221 ----
    if (backup_name == 0)
      return 0;
    sprintf (backup_name, "%s.~%d~", file, version);
+ #ifdef MSDOS
+ #ifdef __DJGPP__
+   /* If long filenames are supported on the filesystem where FILE belongs,
+      we don't need to squeeze the backup suffix into 8+3 namespace.  */
+   if (!_use_lfn (file))
+ #endif
+     {
+       char *short_name;
+ 
+       /* Let `concat' do the hard job (see below) when we
+ 	 cannot use long filenames.  */
+       sprintf (backup_name, ".~%d~", version);
+       short_name = concat (file, backup_name);
+       free (backup_name);
+       backup_name = short_name;
+     }
+ #endif
    return backup_name;
  }
  
*************** version_number (base, backup, base_lengt
*** 207,212 ****
--- 233,264 ----
    const char *p;
  
    version = 0;
+ #ifdef MSDOS
+ #ifdef __DJGPP__
+   /* Neither BASE nor BACKUP don't include a full pathname, so we
+      don't have a pathname to call `_use_lfn'.  But since we already
+      called `_use_lfn' with a full pathname of this file (in
+      max_backup_version above), we are asking here about the same
+      filesystem, and so the call to _use_lfn (0) should do.  */
+   if (!_use_lfn (0))
+ #endif
+     {
+       /* When long filenames aren't supported, the numbered backup
+ 	 suffix moves into the name; see `concat'.  We want filenames
+ 	 like e.g. "foo.bar" and "foo1234~" to match here.
+ 	 The call to `strncmp' is of course superflous after this,
+ 	 but letting the non-LFN systems suffer leaves the code cleaner.  */
+       const char *pbase = base, *pbackup = backup;
+       int len;
+ 
+       for (len = base_length; len; len--)
+ 	if (*pbase++ != *pbackup++)
+ 	  {
+ 	    base_length -= len;
+ 	    break;
+ 	  }
+     }
+ #endif
    if (!strncmp (base, backup, base_length) && ISDIGIT (backup[base_length]))
      {
        for (p = &backup[base_length]; ISDIGIT (*p); ++p)
*************** concat (str1, str2)
*** 233,237 ****
--- 285,392 ----
      return 0;
    strcpy (newstr, str1);
    strcpy (newstr + str1_length, str2);
+ #ifdef MSDOS
+ #ifdef __DJGPP__
+   if (!_use_lfn (newstr))
+ #endif
+     {
+       /* Without long filenames, we have to live with the darn 8+3
+ 	 basename restriction.  The only way to have numbered
+ 	 backups in that case is to eat some characters off the end
+ 	 of the original name.  */
+       char *base = basename (newstr);
+       int baselen = strlen (base);
+       char *dot;
+       char *str2_start = newstr + str1_length;
+       int s2_len = strlen (str2_start);
+       int extlen;
+       int str2_starts_with_dot;
+ 
+       /* Kludgy feature: if `STR1' already has an extension, and
+ 	 `STR2' begins with ".~", we remove the `~'.  This is so
+ 	 we could salvage at least 1 character of the original
+ 	 extension for the first 9 backups (e.g., "foo.c" + ".~7~"
+ 	 is ``concatenated'' into "foo.c7~", not "foo.~7~").  */
+       if (memchr (base, '.', baselen - s2_len)
+ 	  && (*str2_start == '.' && str2_start[1] == '~'))
+ 	{
+ 	  memmove (str2_start + 1, str2_start + 2, s2_len - 1);
+ 	  s2_len--;
+ 	  baselen--;
+ 	}
+ 
+       /* Weed out all but the first dot in `base'.  */
+       dot = memchr (base, '.', baselen);
+       if (dot)
+ 	{
+ 	  char *s = dot + 1;
+ 	  char *d = s;
+ 	  int dots_before_str2 = 0;
+ 
+ 	  do {
+ 	    while (*s == '.')
+ 	      {
+ 		if (s < str2_start)
+ 		  dots_before_str2++;
+ 		else
+ 		  s2_len--;
+ 		s++;
+ 		baselen--;
+ 	      }
+ 	  } while ((*d++ = *s++));
+ 
+ 	  str2_start -= dots_before_str2;
+ 	  extlen = baselen - (dot - base) - 1; /* 1 for the dot itself */
+ 	}
+       else
+ 	{
+ 	  dot = base + baselen;
+ 	  extlen = 0;
+ 	}
+ 
+       /* Make sure `STR2' will not be truncated by the OS.  If `STR2' is
+ 	 in the extension, it must be in the first 3 characters after the
+ 	 dot; if it's before the dot, it must be one of the first 8
+ 	 characters of the basename.  */
+       str2_starts_with_dot = str2_start[0] == '.';
+       if (extlen > 3)
+ 	{
+ 	  char *new_str2_start;
+ 
+ 	  s2_len = strlen (str2_start);
+ 	  if (s2_len <= 3 + str2_starts_with_dot)
+ 	    new_str2_start = dot + !str2_starts_with_dot + 3 - s2_len;
+ 	  else
+ 	    {
+ 	      new_str2_start = dot;
+ 	      if (str2_start == new_str2_start)
+ 		{
+ 		  /* The case of foo -> foo.~10~
+ 		     The original file has no extension, but the backup
+ 		     extension is longer than 3 characters.  We need to
+ 		     move the extension into the name (make it foo10~).  */
+ 		  if (*++str2_start == '~')
+ 		    str2_start++;
+ 		  s2_len -= str2_start - dot;
+ 		}
+ 	      dot += s2_len;
+ 	    }
+ 	  memmove (new_str2_start, str2_start, s2_len + 1);
+ 	  str2_start = new_str2_start;
+ 	}
+       /* If the name part (before the dot) is longer than 8 characters,
+ 	 we cannot be sure it won't clash with an existing file.  So we
+ 	 must move `STR2' into the name.  */
+       if (dot - base > 8)
+ 	{
+ 	  if (str2_starts_with_dot)
+ 	    {
+ 	      str2_start++;
+ 	      s2_len--;
+ 	    }
+ 	  memmove (base + 8 - s2_len, str2_start, s2_len + 1);
+ 	}
+     }
+ #endif /* MSDOS */
    return newstr;
  }
*** lib/basename.c~0	Mon Jul 15 03:56:28 1996
--- lib/basename.c	Sat Mar  8 16:39:48 1997
*************** basename (name)
*** 30,36 ****
  
    while (*name)
      {
!       if (*name == '/')
  	base = name + 1;
        ++name;
      }
--- 30,40 ----
  
    while (*name)
      {
!       if (*name == '/'
! #ifdef MSDOS
! 	  || *name == ':'
! #endif
! 	  )
  	base = name + 1;
        ++name;
      }
*** lib/dirname.c~0	Mon Jul 15 03:35:12 1996
--- lib/dirname.c	Sat Mar  8 16:42:38 1997
*************** char *malloc ();
*** 35,41 ****
  
  /* Return the leading directories part of PATH,
     allocated with malloc.  If out of memory, return 0.
!    Assumes that trailing slashes have already been
     removed.  */
  
  char *
--- 35,41 ----
  
  /* Return the leading directories part of PATH,
     allocated with malloc.  If out of memory, return 0.
!    Does NOT assume that trailing slashes have already been
     removed.  */
  
  char *
*************** dirname (path)
*** 47,52 ****
--- 47,61 ----
    int length;			/* Length of result, not including NUL.  */
  
    slash = strrchr (path, '/');
+ #ifdef MSDOS
+   /* If we have "d:file", make the directory be "d:"  */
+   if (slash == 0 && path[1] == ':')
+     slash = path + 1;
+   /* If we have "d:/file", make the directory be "d:/", not "d:"  */
+   if (slash && slash == path + 2 && path[1] == ':' && path[2] == '/')
+     length = 3;
+   else
+ #endif
    if (slash == 0)
      {
        /* File is in the current directory.  */
*** lib/euidaccess.c~0	Mon Jul 15 03:37:44 1996
--- lib/euidaccess.c	Sat Mar  8 12:25:50 1997
*************** euidaccess (path, mode)
*** 152,157 ****
--- 152,158 ----
      /* If we are not set-uid or set-gid, access does the same.  */
      return access (path, mode);
  
+ #ifndef MSDOS
    if (stat (path, &stats))
      return -1;
  
*************** euidaccess (path, mode)
*** 179,182 ****
--- 180,184 ----
      return 0;
    errno = EACCESS;
    return -1;
+ #endif /* !MSDOS */
  }
*** lib/fileblocks.c~0	Mon Jul 15 03:35:12 1996
--- lib/fileblocks.c	Sat Mar  8 12:24:14 1997
***************
*** 21,27 ****
  # include <config.h>
  #endif
  
! #if !defined (HAVE_ST_BLOCKS) && !defined(_POSIX_VERSION)
  # include <sys/types.h>
  # include <sys/param.h>
  
--- 21,27 ----
  # include <config.h>
  #endif
  
! #if !defined (HAVE_ST_BLOCKS) && !defined(_POSIX_VERSION) && !defined(MSDOS)
  # include <sys/types.h>
  # include <sys/param.h>
  
*** lib/getdate.y~0	Sun Jan 19 04:11:34 1997
--- lib/getdate.y	Sat Mar 22 18:09:32 1997
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 347,353 ****
  	    yyRelYear += $1 * $2;
  	}
  	| tYEAR_UNIT {
! 	    yyRelYear++;
  	}
  	| tUNUMBER tMONTH_UNIT {
  	    yyRelMonth += $1 * $2;
--- 347,353 ----
  	    yyRelYear += $1 * $2;
  	}
  	| tYEAR_UNIT {
! 	    yyRelYear += $1;
  	}
  	| tUNUMBER tMONTH_UNIT {
  	    yyRelMonth += $1 * $2;
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 356,362 ****
  	    yyRelMonth += $1 * $2;
  	}
  	| tMONTH_UNIT {
! 	    yyRelMonth++;
  	}
  	| tUNUMBER tDAY_UNIT {
  	    yyRelDay += $1 * $2;
--- 356,362 ----
  	    yyRelMonth += $1 * $2;
  	}
  	| tMONTH_UNIT {
! 	    yyRelMonth += $1;
  	}
  	| tUNUMBER tDAY_UNIT {
  	    yyRelDay += $1 * $2;
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 365,371 ****
  	    yyRelDay += $1 * $2;
  	}
  	| tDAY_UNIT {
! 	    yyRelDay++;
  	}
  	| tUNUMBER tHOUR_UNIT {
  	    yyRelHour += $1 * $2;
--- 365,371 ----
  	    yyRelDay += $1 * $2;
  	}
  	| tDAY_UNIT {
! 	    yyRelDay += $1;
  	}
  	| tUNUMBER tHOUR_UNIT {
  	    yyRelHour += $1 * $2;
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 374,380 ****
  	    yyRelHour += $1 * $2;
  	}
  	| tHOUR_UNIT {
! 	    yyRelHour++;
  	}
  	| tUNUMBER tMINUTE_UNIT {
  	    yyRelMinutes += $1 * $2;
--- 374,380 ----
  	    yyRelHour += $1 * $2;
  	}
  	| tHOUR_UNIT {
! 	    yyRelHour += $1;
  	}
  	| tUNUMBER tMINUTE_UNIT {
  	    yyRelMinutes += $1 * $2;
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 383,389 ****
  	    yyRelMinutes += $1 * $2;
  	}
  	| tMINUTE_UNIT {
! 	    yyRelMinutes++;
  	}
  	| tUNUMBER tSEC_UNIT {
  	    yyRelSeconds += $1 * $2;
--- 383,389 ----
  	    yyRelMinutes += $1 * $2;
  	}
  	| tMINUTE_UNIT {
! 	    yyRelMinutes += $1;
  	}
  	| tUNUMBER tSEC_UNIT {
  	    yyRelSeconds += $1 * $2;
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 392,398 ****
  	    yyRelSeconds += $1 * $2;
  	}
  	| tSEC_UNIT {
! 	    yyRelSeconds++;
  	}
  	;
  
--- 392,398 ----
  	    yyRelSeconds += $1 * $2;
  	}
  	| tSEC_UNIT {
! 	    yyRelSeconds += $1;
  	}
  	;
  
*** lib/makepath.c~0	Mon Nov  4 17:59:24 1996
--- lib/makepath.c	Sat Mar  8 16:45:08 1997
*************** extern int errno;
*** 71,77 ****
  # endif
  #endif
  
! #ifdef __MSDOS__
  typedef int uid_t;
  typedef int gid_t;
  #endif
--- 71,77 ----
  # endif
  #endif
  
! #if defined(__MSDOS__) && !defined(HAVE_CONFIG_H)
  typedef int uid_t;
  typedef int gid_t;
  #endif
*** lib/path-concat.c~0	Tue Oct  1 01:08:38 1996
--- lib/path-concat.c	Sat Mar  8 17:00:54 1997
*************** path_concat (dir, base, base_in_result)
*** 49,54 ****
--- 49,63 ----
  
    if (*(p - 1) == '/' && *base == '/')
      --p;
+ #ifdef MSDOS
+   /* Make sure "path1"+"d:/path2" yields "path1/path2".  */
+   else if (base[1] == ':' && (base += 2) == 0)
+     /* Fall-through to next else-if clause (base += 2 is never 0).  */
+     ;
+   /* Make sure "d:"+"path" yields "d:path", not "d:/path".  */
+   else if (*(p - 1) == ':')
+     ;
+ #endif
    else if (*(p - 1) != '/' && *base != '/')
      p = stpcpy (p, "/");
  
*** lib/stripslash.c~0	Tue Oct 29 13:42:54 1996
--- lib/stripslash.c	Sat Mar  8 16:46:22 1997
*************** strip_trailing_slashes (path)
*** 38,43 ****
--- 38,52 ----
    int last;
  
    last = strlen (path) - 1;
+ #ifdef MSDOS
+   /* Leave alone a single slash in "d:/".  "d:" means something
+      VERY different on MSDOS.  */
+   if (path[1] == ':')
+     {
+       path += 2;
+       last -= 2;
+     }
+ #endif
    while (last > 0 && path[last] == '/')
      path[last--] = '\0';
  }
*** lib/userspec.c~0	Mon Jul 15 03:35:14 1996
--- lib/userspec.c	Sat Mar  8 16:50:10 1997
*************** parse_user_spec (spec_arg, uid, gid, use
*** 160,166 ****
--- 160,171 ----
  	{
  
  	  if (!is_number (u))
+ #ifdef  MSDOS
+ 	    /* Under MS-DOS we allow to give away files to ANY user.  */
+ 	    *uid = 2*getuid();	/* why twice, you ask? why not? */
+ #else
  	    error_msg = "invalid user";
+ #endif
  	  else
  	    {
  	      int use_login_group;
*************** parse_user_spec (spec_arg, uid, gid, use
*** 206,212 ****
--- 211,222 ----
        if (grp == NULL)
  	{
  	  if (!is_number (g))
+ #ifdef  MSDOS
+ 	    /* Under MS-DOS we allow to give away files to ANY group.  */
+ 	    *gid = 2*getgid();
+ #else
  	    error_msg = "invalid group";
+ #endif
  	  else
  	    *gid = atoi (g);
  	}
*** src/cp.c~0	Sun Jan 26 04:26:28 1997
--- src/cp.c	Mon Mar 24 18:02:34 1997
*************** do_copy (int argc, char **argv)
*** 414,419 ****
--- 414,433 ----
  
    dest = argv[argc - 1];
  
+ #ifdef MSDOS
+   /* "d:" means current dir on drive d:  */
+   if (dest[1] == ':' && dest[2] != '/')
+     {
+       char *newname = alloca (PATH_MAX + 1);
+       int   add_slash = dest[strlen (dest) - 1] == '/';
+ 
+       FIXPATH (dest, newname);	/* convert "d:" into an absolute pathname */
+       dest = newname;
+       if (add_slash)		/* dest/ has a special meaning in `cp' */
+ 	strcat (dest, "/");
+     }
+ #endif
+ 
    if (lstat (dest, &sb))
      {
        if (errno != ENOENT)
*************** do_copy (int argc, char **argv)
*** 452,457 ****
--- 466,482 ----
  
  	  arg = argv[optind];
  
+ #ifdef  MSDOS
+ 	  /* Convert "d:path" into a full path.  */
+ 	  if (arg[1] == ':' && arg[2] != '/')
+ 	    {
+ 	      char *newarg = alloca (PATH_MAX);
+ 
+ 	      FIXPATH (arg, newarg);
+ 	      arg = newarg;
+ 	    }
+ #endif
+ 
  	  strip_trailing_slashes (arg);
  
  	  if (flag_path)
*************** do_copy (int argc, char **argv)
*** 521,526 ****
--- 546,562 ----
  
        source = argv[optind];
  
+ #ifdef  MSDOS
+ 	  /* Convert "d:path" into a full path.  */
+ 	  if (source[1] == ':' && source[2] != '/')
+ 	    {
+ 	      char *newsource = alloca (PATH_MAX + 1);
+ 
+ 	      FIXPATH (source, newsource);
+ 	      source = newsource;
+ 	    }
+ #endif
+ 
        /* When the force and backup options have been specified and
  	 the source and destination are the same name for an existing
  	 regular file, convert the user's command, e.g.,
*************** copy (const char *src_path, const char *
*** 690,695 ****
--- 726,739 ----
  		}
  	      if (!yesno ())
  		return 0;
+ #ifdef MSDOS
+ 	      /* Make it writable, so the copy will succeed.  */
+ 	      if (chmod (dst_path, 0200))
+ 		{
+ 		  error (0, errno, "%s", dst_path);
+ 		  return 1;
+ 		}
+ #endif
  	    }
  
  	  if (backup_type != none && !S_ISDIR (dst_sb.st_mode))
*************** copy (const char *src_path, const char *
*** 966,972 ****
        utb.actime = src_sb.st_atime;
        utb.modtime = src_sb.st_mtime;
  
!       if (utime (dst_path, &utb))
  	{
  	  error (0, errno, "%s", dst_path);
  	  return 1;
--- 1010,1022 ----
        utb.actime = src_sb.st_atime;
        utb.modtime = src_sb.st_mtime;
  
!       if (utime (dst_path, &utb)
! #ifdef  MSDOS
! 	  /* MS-DOS doesn't allow to change timestamp of a directory :-(
! 	     If we try, we'll get an ugly error message.  */
! 	  && !S_ISDIR (src_type)
! #endif
! 	  )
  	{
  	  error (0, errno, "%s", dst_path);
  	  return 1;
*************** copy_dir (const char *src_path_in, const
*** 1245,1251 ****
--- 1295,1311 ----
        dst_path = xmalloc (strlen (dst_path_in) + fn_length + 1);
        src_path = xmalloc (strlen (src_path_in) + fn_length + 1);
  
+ #ifdef MSDOS
+       if (src_path_in[strlen (src_path_in) - 1] == '/')
+ 	stpcpy (stpcpy (src_path, src_path_in), namep);
+       else
+ #endif
        stpcpy (stpcpy (stpcpy (src_path, src_path_in), "/"), namep);
+ #ifdef MSDOS
+       if (dst_path_in[strlen (dst_path_in) - 1] == '/')
+ 	stpcpy (stpcpy (dst_path, dst_path_in), namep);
+       else
+ #endif
        stpcpy (stpcpy (stpcpy (dst_path, dst_path_in), "/"), namep);
  
        ret |= copy (src_path, dst_path, new_dst, src_sb->st_dev, ancestors);
*** src/dd.c~0	Sat Nov  2 23:42:12 1996
--- src/dd.c	Sat Mar  8 17:54:42 1997
*************** static unsigned r_truncate = 0;
*** 169,174 ****
--- 169,178 ----
  /* Output representation of newline and space characters.
     They change if we're converting to EBCDIC.  */
  static unsigned char newline_character = '\n';
+ #ifdef MSDOS
+ static unsigned char cr_character = '\r';
+ static int pending_cr = 0;
+ #endif
  static unsigned char space_character = ' ';
  
  struct conversion
*************** copy (void)
*** 659,664 ****
--- 663,677 ----
        /* If the final input line didn't end with a '\n', pad
  	 the output block to `conversion_blocksize' chars.  */
        int pending_spaces = max (0, conversion_blocksize - col);
+ 
+ #ifdef MSDOS
+       if (pending_cr)
+ 	{
+ 	  output_char (cr_character);
+ 	  if (pending_spaces)
+ 	    pending_spaces--;
+ 	}
+ #endif
        while (pending_spaces)
  	{
  	  output_char (space_character);
*************** copy (void)
*** 667,675 ****
      }
  
    if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
!     /* Add a final '\n' if there are exactly `conversion_blocksize'
!        characters in the final record. */
!     output_char (newline_character);
  
    /* Write out the last block. */
    if (oc > 0)
--- 680,694 ----
      }
  
    if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
!     {
!       /* Add a final '\n' if there are exactly `conversion_blocksize'
! 	 characters in the final record. */
! #ifdef MSDOS
!       /* Make DOS-style text file (we do I/O in binary mode!).  */
!       output_char (cr_character);
! #endif
!       output_char (newline_character);
!     }
  
    /* Write out the last block. */
    if (oc > 0)
*************** copy_with_block (unsigned char *buf, int
*** 727,732 ****
--- 746,777 ----
  
    for (i = nread; i; i--, buf++)
      {
+ #ifdef MSDOS
+       /* Output the CR left from the previous buffer, if the first
+ 	 character of this buffer isn't a newline.  */
+       if (i == nread && pending_cr && *buf != newline_character)
+ 	{
+ 	  output_char (cr_character);
+ 	  pending_cr = 0;
+ 	  col++;
+ 	}
+ 
+       /* If we have CR-LF pair, lose the CR character too.  */
+       if (*buf == cr_character)
+ 	{
+ 	  if (i == 1)	/* last char, defer decision until next BUF */
+ 	    {
+ 	      pending_cr = 1;
+ 	      continue;
+ 	    }
+ 	  else if (buf[1] == newline_character)
+ 	    {
+ 	      buf++;
+ 	      i--;
+ 	      pending_cr = 0;
+ 	    }
+ 	}
+ #endif /* MSDOS */
        if (*buf == newline_character)
  	{
  	  int pending_spaces = max (0, conversion_blocksize - col);
*************** copy_with_unblock (unsigned char *buf, i
*** 767,772 ****
--- 812,821 ----
  	{
  	  col = pending_spaces = 0; /* Wipe out any pending spaces.  */
  	  i--;			/* Push the char back; get it later. */
+ #ifdef MSDOS
+ 	  /* Make DOS-style text file (we do BINARY I/O!).  */
+ 	  output_char (cr_character);
+ #endif
  	  output_char (newline_character);
  	}
        else if (c == space_character)
*************** only one conv in {ascii,ebcdic,ibm}, {lc
*** 1001,1012 ****
--- 1050,1063 ----
      {
        translate_charset (ascii_to_ebcdic);
        newline_character = ascii_to_ebcdic['\n'];
+       cr_character = ascii_to_ebcdic['\r'];
        space_character = ascii_to_ebcdic[' '];
      }
    else if (conversions_mask & C_IBM)
      {
        translate_charset (ascii_to_ibm);
        newline_character = ascii_to_ibm['\n'];
+       cr_character = ascii_to_ebcdic['\r'];
        space_character = ascii_to_ibm[' '];
      }
  }
*** src/df.c~0	Tue Dec 10 00:05:38 1996
--- src/df.c	Sat Mar  8 21:11:26 1997
*************** show_dev (const char *disk, const char *
*** 254,259 ****
--- 254,262 ----
    long inodes_used;
    long inodes_percent_used;
    const char *stat_file;
+ #ifdef __DJGPP__
+   char real_drive_name[4];
+ #endif
  
    if (!selected_fstype (fstype) || excluded_fstype (fstype))
      return;
*************** show_dev (const char *disk, const char *
*** 263,268 ****
--- 266,289 ----
       It would be better to report on the unmounted filesystem,
       but statfs doesn't do that on most systems.  */
    stat_file = mount_point ? mount_point : disk;
+ 
+ #ifdef __DJGPP__
+   /* JOINed disks seem like a directory on another disk.
+      We want to see the info about the real drive.  */
+   if (strcmp (fstype, "join") == 0)
+     {
+       struct stat real_drive_stats;
+ 
+       if (stat (stat_file, &real_drive_stats))
+         {
+           error (0, errno, "%s", stat_file);
+           exit_status = 1;
+           return;
+         }
+       sprintf (real_drive_name, "%c:/", real_drive_stats.st_dev + 'A');
+       stat_file = real_drive_name;
+     }
+ #endif
  
    if (get_fs_usage (stat_file, disk, &fsu))
      {
*** src/dircolors.c~0	Sun Jan 26 05:54:16 1997
--- src/dircolors.c	Sat Mar  8 18:17:32 1997
*************** dc_parse_stream (FILE *fp, const char *f
*** 261,266 ****
--- 261,270 ----
  
    /* Get terminal type */
    term = getenv ("TERM");
+ #ifdef __DJGPP__
+   /* DJGPP port can always colorize, but TERM is not usually defined there.  */
+   term = "console";
+ #endif
    if (term == NULL || *term == '\0')
      term = "none";
  
*** src/du.c~0	Sun Jan 19 03:53:02 1997
--- src/du.c	Sat Mar 15 17:04:34 1997
***************
*** 54,60 ****
  #include "save-cwd.h"
  #include "error.h"
  
! #undef	convert_blocks
  #define	convert_blocks(b, size) (size == size_kilobytes ? ((b) + 1) / 2 : \
      size == size_megabytes ? ((b) + 1024) / 2048 : (b))
  
--- 54,65 ----
  #include "save-cwd.h"
  #include "error.h"
  
! #ifdef MSDOS
! #include <signal.h>
! static struct saved_cwd start_cwd;
! static RETSIGTYPE interrupt_handler ();
! #endif
! 
  #define	convert_blocks(b, size) (size == size_kilobytes ? ((b) + 1) / 2 : \
      size == size_megabytes ? ((b) + 1024) / 2048 : (b))
  
*************** du_files (char **files)
*** 432,437 ****
--- 437,449 ----
    initial_ino = stat_buf.st_ino;
    initial_dev = stat_buf.st_dev;
  
+ #ifdef MSDOS
+   /* We need to install a signal handler to make sure we return to
+      the original directory even if we are aborted.  */
+   signal (SIGINT, interrupt_handler);
+   save_cwd (&start_cwd);
+ #endif
+ 
    for (i = 0; files[i]; i++)
      {
        char *arg;
*************** du_files (char **files)
*** 441,446 ****
--- 453,470 ----
  
        /* Delete final slash in the argument, unless the slash is alone.  */
        s = strlen (arg) - 1;
+ #ifdef MSDOS
+       if (s == 1 && arg[1] == ':')
+ 	{
+ 	  /* Make "d:" explicit so we don't have to handle it specially.  */
+ 	  char full_path[FILENAME_MAX+5];
+ 	  FIXPATH (arg, full_path);
+ 	  str_copyc (path, full_path);
+ 	}
+       else if (s == 2 && arg[2] == '/')
+ 	str_copyc (path, arg);	/* leave alone the slash in "d:/" */
+       else
+ #endif
        if (s != 0)
  	{
  	  if (arg[s] == '/')
*************** du_files (char **files)
*** 478,485 ****
  	}
        else
  	{
! 	  printf (_("%ld\ttotal\n"), output_size == size_bytes ? tot_size
! 		  : convert_blocks (tot_size, output_size == size_kilobytes));
  	}
        fflush (stdout);
      }
--- 502,508 ----
  	}
        else
  	{
! 	  printf (_("%ld\ttotal\n"), convert_blocks (tot_size, output_size));
  	}
        fflush (stdout);
      }
*************** count_entry (char *ent, int top, dev_t l
*** 536,541 ****
--- 559,595 ----
  #ifndef S_ISDIR
  # define S_ISDIR(s) 0
  #endif
+ 
+ #ifdef MSDOS
+       /* Every drive has its own ``working directory''.  If we're about
+ 	 to change drive, we need to save and restore that directory to
+ 	 prevent side-effects.  To this end, we will first chdir to the
+ 	 working directory on that drive so it is remembered by save_cwd.  */
+       if (ent[1] == ':')
+ 	{
+ 	  char work_dir[4];
+ 
+ 	  work_dir[0] = ent[0];
+ 	  work_dir[1] = ':';
+ 	  work_dir[2] = '.';
+ 	  work_dir[3] = '\0';
+ 	  if (chdir (work_dir) < 0)
+ 	    {
+ 	      error (0, errno, _("cannot change to directory %s"), work_dir);
+ 	      exit_status = 1;
+ 	      return 0;
+ 	    }
+ 
+ 	  /* This will return us to work_dir after every chdir, so the
+ 	     working directory is indeed preserved.  */
+ 	  through_symlink = 1;
+ 	}
+ 
+       if (save_cwd (&cwd))
+ 	exit (1);
+ 
+ #else  /* !MSDOS */
+ 
        /* If we're dereferencing symlinks and we're about to chdir through
  	 a symlink, remember the current directory so we can return to it
  	 later.  In other cases, chdir ("..") works fine.  */
*************** count_entry (char *ent, int top, dev_t l
*** 546,551 ****
--- 600,607 ----
  	if (save_cwd (&cwd))
  	  exit (1);
  
+ #endif /* !MSDOS */
+ 
        if (chdir (ent) < 0)
  	{
  	  error (0, errno, _("cannot change to directory %s"), path->text);
*************** count_entry (char *ent, int top, dev_t l
*** 578,583 ****
--- 634,644 ----
  
        /* Remember the current path.  */
  
+ #ifdef MSDOS
+       /* Avoid adding extra slash in the case of a root directory.  */
+       if (path->text[path->length-2] != ':'
+ 	  || path->text[path->length-1] != '/')
+ #endif
        str_concatc (path, "/");
        pathlen = path->length;
  
*************** count_entry (char *ent, int top, dev_t l
*** 601,606 ****
--- 662,671 ----
          error (1, errno,
  	       _("cannot change to `..' from directory %s"), path->text);
  
+ #ifdef MSDOS
+       /* Avoid printing excess slash in the case of a root directory.  */
+       if (path->text[pathlen-2] != ':')
+ #endif
        str_trunc (path, pathlen - 1); /* Remove the "/" we added.  */
        if (!opt_summarize_only || top)
  	{
*************** count_entry (char *ent, int top, dev_t l
*** 613,621 ****
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", (output_size == size_bytes
! 				    ? size
! 				    : convert_blocks (size, output_size)),
  		      path->length > 0 ? path->text : "/");
  	    }
  	  fflush (stdout);
--- 678,684 ----
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", convert_blocks (size, output_size),
  		      path->length > 0 ? path->text : "/");
  	    }
  	  fflush (stdout);
*************** count_entry (char *ent, int top, dev_t l
*** 637,644 ****
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", output_size == size_bytes ? size
! 		      : convert_blocks (size, output_size),
  		      path->text);
  	    }
  	  fflush (stdout);
--- 700,706 ----
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", convert_blocks (size, output_size),
  		      path->text);
  	    }
  	  fflush (stdout);
*************** str_trunc (string s1, unsigned int lengt
*** 854,856 ****
--- 916,927 ----
        s1->length = length;
      }
  }
+ 
+ #ifdef MSDOS
+ static RETSIGTYPE
+ interrupt_handler (void)
+ {
+   restore_cwd (&start_cwd, _("starting directory"), NULL);
+   exit (1);
+ }
+ #endif
*** src/install.c~0	Wed Dec 11 04:24:44 1996
--- src/install.c	Sat Mar 22 17:51:02 1997
***************
*** 63,68 ****
--- 63,72 ----
  #include <pwd.h>
  #include <grp.h>
  
+ #ifdef __DJGPP__
+ # include <process.h>
+ #endif
+ 
  #include "system.h"
  #include "backupfile.h"
  #include "modechange.h"
*************** install_file_in_file (char *from, char *
*** 317,322 ****
--- 321,362 ----
    int to_created;
    int no_need_to_chown;
  
+ #ifdef __DJGPP__
+   char *dot = from + strlen (from) - 4;
+   static char STUBIFY[] = "stubify.exe";
+ 
+   /* If FROM is a COFF executable, make a DOS program on the fly.
+      This makes Unix-born Makefiles happy.  */
+   if (!STREQ (dot, ".exe") && !STREQ (dot, ".com"))
+     {
+       char *new_from, *new_to;
+       unsigned short magic;
+       int status, fd = open (from, O_RDONLY | O_BINARY);
+ 
+       if (read (fd, &magic, 2) == 2
+ 	  && (magic == 0x010b || magic == 0x014c)
+ 	  && close (fd) == 0)
+ 	{
+ 	  new_from = alloca (strlen (from) + 1 + 4);
+ 	  stpcpy (stpcpy (new_from, from), ".exe");
+ 	  /* Don't overwrite a stubified .exe if it already exists
+ 	     (it may have been stubedited to change default stub info).  */
+ 	  if (!__file_exists (new_from))
+ 	    {
+ 	      status = spawnlp (P_WAIT, STUBIFY, STUBIFY, from, (char *) NULL);
+ 	      if (status == -1)
+ 		error (1, errno, _("cannot run stubify"));
+ 	    }
+ 	  from = new_from;
+ 	  new_to = alloca (strlen (to) + 1 + 4);
+ 	  stpcpy (stpcpy (new_to, to), ".exe");
+ 	  to = new_to;
+ 	}
+       else if (fd != -1)
+ 	close (fd);
+     }
+ #endif
+ 
    if (copy_file (from, to, &to_created))
      return 1;
    if (strip_files)
*************** install_file_in_dir (char *from, char *t
*** 340,345 ****
--- 380,391 ----
  
    from_base = basename (from);
    to = xmalloc ((unsigned) (strlen (to_dir) + strlen (from_base) + 2));
+ #ifdef MSDOS
+   /* If we get "d:" in FROM, make "d:to_dir", not "d:/to_dir".  */
+   if (strlen (to_dir) == 2 && to_dir[1] == ':')
+     stpcpy (stpcpy (to, to_dir), from_base);
+   else
+ #endif
    stpcpy (stpcpy (stpcpy (to, to_dir), "/"), from_base);
    ret = install_file_in_file (from, to);
    free (to);
*************** change_attributes (char *path, int no_ne
*** 514,519 ****
--- 560,567 ----
     magic numbers vary so much from system to system that making
     it portable would be very difficult.  Not worth the effort. */
  
+ #ifndef MSDOS
+ 
  static void
  strip (char *path)
  {
*************** strip (char *path)
*** 537,542 ****
--- 585,614 ----
      }
  }
  
+ #else  /* MSDOS */
+ #ifdef __DJGPP__
+ 
+ static char STRIP[]   = "strip.exe";
+ 
+ static void
+ strip (char *path)
+ {
+   int status = spawnlp (P_WAIT, STRIP, STRIP, path, (char *) NULL);
+ 
+   if (status == -1)
+     error (1, errno, _("cannot run strip"));
+ }
+ 
+ #else  /* not __DJGPP__ */
+ 
+ static void
+ strip (char *path)
+ {
+ }
+ 
+ #endif /* __DJGPP__ */
+ #endif /* MSDOS */
+ 
  /* Initialize the user and group ownership of the files to install. */
  
  static void
*************** get_ids (void)
*** 553,559 ****
--- 625,636 ----
  	  long int tmp_long;
  	  if (xstrtol (owner_name, NULL, 0, &tmp_long, NULL) != LONGINT_OK
  	      || tmp_long < 0 || tmp_long > UID_T_MAX)
+ #ifdef  MSDOS
+             /* Under MS-DOS, allow any owner name, since it's meaningless. */
+             owner_id = 2*getuid ();  /* Why twice, you ask?  Why not?? */
+ #else
  	    error (1, 0, _("invalid user `%s'"), owner_name);
+ #endif
  	  owner_id = (uid_t) tmp_long;
  	}
        else
*************** get_ids (void)
*** 571,577 ****
--- 648,659 ----
  	  long int tmp_long;
  	  if (xstrtol (group_name, NULL, 0, &tmp_long, NULL) != LONGINT_OK
  	      || tmp_long < 0 || tmp_long > (long) GID_T_MAX)
+ #ifdef  MSDOS
+             /* Under MS-DOS, allow any group name. */
+             group_id = 2*getgid ();
+ #else
  	    error (1, 0, _("invalid group `%s'"), group_name);
+ #endif
  	  group_id = (gid_t) tmp_long;
  	}
        else
*** src/ln.c~0	Sat Nov 23 22:11:10 1996
--- src/ln.c	Sat Mar  8 19:06:44 1997
***************
*** 30,35 ****
--- 30,45 ----
  #include "backupfile.h"
  #include "error.h"
  
+ #ifdef  __DJGPP__
+ /* DJGPP doesn't have S_ISLNK defined, because MS-DOS doesn't support links.
+    However, DJGPP's `link' simulates hard links by copying, and we can
+    have ``symbolic links'' for DJGPP .EXE programs.  Therefore, just
+    for the purpose of this program, it makes sense to define S_ISLNK
+    so we could have working `ln'.  */
+ 
+ #define S_ISLNK(x)  (0)     /* defined, but no file is a link */
+ #endif
+ 
  int link ();			/* Some systems don't declare this anywhere. */
  
  #ifdef S_ISLNK
*** src/ls.c~0	Sun Jan 26 05:56:10 1997
--- src/ls.c	Sat Mar 15 17:04:34 1997
***************
*** 47,52 ****
--- 47,55 ----
  #ifdef GWINSZ_IN_SYS_IOCTL
  # include <sys/ioctl.h>
  #endif
+ #ifdef __DJGPP__
+ # include <pc.h>
+ #endif
  
  #include <stdio.h>
  #include <grp.h>
***************
*** 83,88 ****
--- 86,95 ----
  # define longdiff(a, b) ((a) - (b))
  #endif
  
+ /* Convert B 512-byte blocks to kilobytes if K is nonzero,
+    otherwise return it unchanged. */
+ #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
+ 
  /* The maximum number of digits required to print an inode number
     in an unsigned format.  */
  #ifndef INODE_DIGITS
*************** struct fileinfo
*** 116,121 ****
--- 123,132 ----
      int linkok;
  
      enum filetype filetype;
+ #ifdef  MSDOS
+     /* On MS-DOS we also get DOS-specific file attribute bits. */
+     int msdos_attribs;
+ #endif
    };
  
  #define LEN_STR_PAIR(s) sizeof (s) - 1, s
*************** char *xmalloc ();
*** 145,150 ****
--- 156,166 ----
  char *xrealloc ();
  void invalid_arg ();
  
+ #ifdef  MSDOS
+ void dos_mode_string __P ((int, char *));
+ #endif
+ 
+ 
  static char *make_link_path __P ((const char *path, const char *linkname));
  static int compare_atime __P ((const struct fileinfo *file1,
  			       const struct fileinfo *file2));
*************** enum indicator_no
*** 360,371 ****
    {
      C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
      C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC
    };
  
  static const char *const indicator_name[]=
    {
      "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
!     "bd", "cd", "mi", "or", "ex", NULL
    };
  
  struct col_ext_type
--- 376,394 ----
    {
      C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
      C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC
+ #ifdef MSDOS
+     , C_LABEL			/* MSDOS volume label */
+ #endif
    };
  
  static const char *const indicator_name[]=
    {
      "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
!     "bd", "cd", "mi", "or", "ex"
! #ifdef MSDOS
!     , "lb"			/* MSDOS volume label */
! #endif
!     , NULL
    };
  
  struct col_ext_type
*************** static struct bin_str color_indicator[] 
*** 391,396 ****
--- 414,422 ----
      { 0, NULL },			/* mi: Missing file: undefined */
      { 0, NULL },			/* or: Orphanned symlink: undefined */
      { LEN_STR_PAIR ("01;32") }		/* ex: Executable: bright green */
+ #ifdef MSDOS
+     , { LEN_STR_PAIR ("37;07") }	/* lb: Volume Label: black on white */
+ #endif
    };
  
  /* FIXME: comment  */
*************** static int show_help;
*** 490,495 ****
--- 516,527 ----
  /* If nonzero, print the version on standard output and exit.  */
  static int show_version;
  
+ #ifdef  MSDOS
+ /* If non-zero, use DOS-style permission mode, and don't show UID and GID
+    in long format. */
+ static int msdos_long_format;
+ #endif
+ 
  static struct option const long_options[] =
  {
    {"all", no_argument, 0, 'a'},
*************** static struct option const long_options[
*** 518,523 ****
--- 550,558 ----
    {"sort", required_argument, 0, 10},
    {"tabsize", required_argument, 0, 'T'},
    {"time", required_argument, 0, 11},
+ #ifdef MSDOS
+   {"msdos-long-format", no_argument, 0, 'g'},
+ #endif
    {"help", no_argument, &show_help, 1},
    {"version", no_argument, &show_version, 1},
    {"color", optional_argument, 0, 13},
*************** main (int argc, char **argv)
*** 683,688 ****
--- 718,735 ----
      || trace_links || trace_dirs || indicator_style != none
      || print_block_size || print_inode || print_with_color;
  
+ #if defined(__DJGPP__) && !defined(_POSIX_SOURCE)
+   /* Some members of `struct stat' are very expensive to compute on
+      MSDOS.  This requests the fastest `stat' operation for given
+      combination of options; see `ls-msdos.c'.    */
+   if (format_needs_stat)
+     set_stat_bits_for_ls (sort_type == sort_time,
+ 			  sort_type == sort_size || print_block_size,
+ 			  format == long_format, msdos_long_format,
+ 			  indicator_style == all, print_with_color,
+ 			  all_files);
+ #endif  /* __DJGPP__ && !_POSIX_SOURCE */
+ 
    if (dired && format == long_format)
      {
        obstack_init (&dired_obstack);
*************** decode_switches (int argc, char **argv)
*** 846,851 ****
--- 893,902 ----
    }
  #endif
  
+ #ifdef __DJGPP__
+   line_length = ScreenCols ();
+ #endif
+ 
    /* Using the TABSIZE environment variable is not POSIX-approved.
       Ignore it when POSIXLY_CORRECT is set.  */
    tabsize = 8;
*************** decode_switches (int argc, char **argv)
*** 905,910 ****
--- 956,964 ----
  	  break;
  
  	case 'g':
+ #ifdef  MSDOS
+           msdos_long_format = 1;
+ #endif
  	  /* No effect.  For BSD compatibility. */
  	  break;
  
*************** parse_ls_color (void)
*** 1326,1333 ****
    struct col_ext_type *ext;	/* Extension we are working on */
    struct col_ext_type *ext2;	/* Extra pointer */
  
!   if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
      return;
  
    ext = NULL;
    strcpy (label, "??");
--- 1380,1392 ----
    struct col_ext_type *ext;	/* Extension we are working on */
    struct col_ext_type *ext2;	/* Extra pointer */
  
!   if ((p = getenv ("LS_COLORS")) == NULL)
      return;
+   if (*p == '\0')
+     {
+       print_with_color = 0;
+       return;
+     }
  
    ext = NULL;
    strcpy (label, "??");
*************** gobble_file (const char *name, int expli
*** 1613,1618 ****
--- 1672,1684 ----
      {
        /* `path' is the absolute pathname of this file. */
  
+ #ifdef MSDOS
+       /* Any filename with a drive specification should be
+ 	 treated as an absolute pathname on MS-DOS.  */
+       if (name[1] == ':')
+ 	path = (char *)name;
+       else
+ #endif
        if (name[0] == '/' || dirname[0] == 0)
  	path = (char *) name;
        else
*************** gobble_file (const char *name, int expli
*** 1638,1643 ****
--- 1704,1730 ----
  	  return 0;
  	}
  
+ #ifdef MSDOS
+       /* Get the MS-DOS attribute bits if they requested them.  */
+       if (msdos_long_format && format == long_format)
+ 	{
+ 	  if (S_ISCHR (files[files_index].stat.st_mode))
+ 	    files[files_index].msdos_attribs = 0x20; /* Modified only */
+ 	  else if (S_ISLABEL (files[files_index].stat.st_mode))
+ 	    /* Argh!  `_chmod' fails for volume labels!!  */
+ 	    files[files_index].msdos_attribs = 0x28;
+ 	  else
+ 	    {
+ 	      char fullpath[PATH_MAX];
+ 
+ 	      FIXPATH (path, fullpath);
+ 	      files[files_index].msdos_attribs = _chmod (fullpath, 0, 0);
+ 	      if (files[files_index].msdos_attribs == -1)
+ 		files[files_index].msdos_attribs = 0x20;
+ 	    }
+ 	}
+ #endif /* MSDOS */
+ 
  #ifdef S_ISLNK
        if (S_ISLNK (files[files_index].stat.st_mode)
  	  && (explicit_arg || format == long_format || print_with_color))
*************** extract_dirs_from_files (const char *dir
*** 1800,1805 ****
--- 1887,1898 ----
      if ((files[i].filetype == directory || files[i].filetype == arg_directory)
  	&& (!recursive || is_not_dot_or_dotdot (files[i].name)))
        {
+ #ifdef MSDOS
+ 	/* DOS-specific case of absolute pathnames.  */
+ 	if (files[i].name[1] == ':')
+ 	  queue_directory (files[i].name, files[i].linkname);
+ 	else
+ #endif
  	if (files[i].name[0] == '/' || dirname[0] == 0)
  	  {
  	    queue_directory (files[i].name, files[i].linkname);
*************** is_not_dot_or_dotdot (const char *name)
*** 1833,1838 ****
--- 1926,1936 ----
    char *t;
  
    t = strrchr (name, '/');
+ #ifdef MSDOS
+   /* We can have "d:." or "d:.."  */
+   if (!t && name[1] == ':')
+     t = (char *)(name + 1);
+ #endif
    if (t)
      name = t + 1;
  
*************** print_long_format (const struct fileinfo
*** 2049,2054 ****
--- 2147,2157 ----
    time_t when;
    const char *fmt;
  
+ #ifdef MSDOS
+   if (msdos_long_format)
+     dos_mode_string (f->msdos_attribs, modebuf);
+   else
+ #endif  /* MSDOS */
  #ifdef HAVE_ST_DM_MODE
    mode_string (f->stat.st_dm_mode, modebuf);
  #else
*************** print_long_format (const struct fileinfo
*** 2109,2119 ****
--- 2212,2231 ----
        p += strlen (p);
      }
  
+ #ifdef MSDOS
+   if (msdos_long_format)
+     sprintf (p, "%s  ", modebuf);
+   else
+ #endif
    /* The space between the mode and the number of links is the POSIX
       "optional alternate access method flag". */
    sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink);
    p += strlen (p);
  
+ #ifdef MSDOS
+   if (!msdos_long_format)
+     {
+ #endif
    if (numeric_users)
      sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
    else
*************** print_long_format (const struct fileinfo
*** 2128,2133 ****
--- 2240,2248 ----
  	sprintf (p, "%-8.8s ", getgroup (f->stat.st_gid));
        p += strlen (p);
      }
+ #ifdef MSDOS
+     }
+ #endif
  
    if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
      sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
*************** print_long_format (const struct fileinfo
*** 2139,2145 ****
    /* Use strftime rather than ctime, because the former can produce
       locale-dependent names for the weekday (%a) and month (%b).  */
  
!   while (! (s = strftime (p, buf + bufsize - p, fmt, localtime (&when))))
      {
        char *newbuf = (char *) alloca (bufsize *= 2);
        memcpy (newbuf, buf, p - buf);
--- 2254,2260 ----
    /* Use strftime rather than ctime, because the former can produce
       locale-dependent names for the weekday (%a) and month (%b).  */
  
!   while (! (s = strftime (p, buf + bufsize - p - 1, fmt, localtime (&when))))
      {
        char *newbuf = (char *) alloca (bufsize *= 2);
        memcpy (newbuf, buf, p - buf);
*************** quote_filename (register const char *p, 
*** 2205,2211 ****
  	    case '\t':
  	    case '\f':
  	    case ' ':
- 	    case '"':
  	      found_quotable = 1;
  	      break;
  
--- 2320,2325 ----
*************** quote_filename (register const char *p, 
*** 2231,2237 ****
      }
  
    p = p0;
!   quoted = xmalloc (4 * strlen (p) + 1);
    q = quoted;
  
  #define SAVECHAR(c) *q++ = (c)
--- 2345,2351 ----
      }
  
    p = p0;
!   quoted = xmalloc (4 * strlen (p) + 3);
    q = quoted;
  
  #define SAVECHAR(c) *q++ = (c)
*************** print_type_indicator (unsigned int mode)
*** 2385,2390 ****
--- 2499,2511 ----
      PUTCHAR ('=');
  #endif
  
+ #ifdef MSDOS
+ #ifdef S_ISLABEL     /* MS-DOS Volume label */
+   if (S_ISLABEL (mode))
+     PUTCHAR ('+');
+ #endif
+ #endif
+ 
    if (S_ISREG (mode) && indicator_style == all
        && (mode & S_IXUGO))
      PUTCHAR ('*');
*************** print_color_indicator (const char *name,
*** 2435,2440 ****
--- 2556,2567 ----
  	type = C_CHR;
  #endif
  
+ #ifdef MSDOS
+ #ifdef S_ISLABEL     /* MS-DOS Volume label */
+ 	  else if (S_ISLABEL (mode))
+ 	    type = C_LABEL;
+ #endif
+ #endif
        if (type == C_FILE && (mode & S_IXUGO) != 0)
  	type = C_EXEC;
  
*************** print_color_indicator (const char *name,
*** 2449,2456 ****
  	  for (ext = col_ext_list; ext != NULL; ext = ext->next)
  	    {
  	      if (ext->ext.len <= len
! 		  && strncmp (name - ext->ext.len, ext->ext.string,
! 			      ext->ext.len) == 0)
  		break;
  	    }
  	}
--- 2576,2588 ----
  	  for (ext = col_ext_list; ext != NULL; ext = ext->next)
  	    {
  	      if (ext->ext.len <= len
! #ifdef MSDOS
! 	    /* Don't let the letter case affect the colorization on MSDOS.  */
! 	    && strncasecmp (name - ext->ext.len, ext->ext.string,
! #else
! 	    && strncmp (name - ext->ext.len, ext->ext.string,
! #endif
! 			ext->ext.len) == 0)
  		break;
  	    }
  	}
*************** length_of_file_name_and_frills (const st
*** 2544,2549 ****
--- 2676,2686 ----
  #ifdef S_ISSOCK
  	       || S_ISSOCK (filetype)
  #endif
+ #ifdef MSDOS
+ #ifdef S_ISLABEL
+ 	       || S_ISLABEL (filetype)
+ #endif
+ #endif
  	)
  	len += 1;
      }
*************** attach (char *dest, const char *dirname,
*** 2721,2726 ****
--- 2858,2868 ----
      {
        while (*dirnamep)
  	*dest++ = *dirnamep++;
+ #ifdef  MSDOS
+       /* "d:" does NOT mean "d:/"  */
+       if (dirnamep <= dirname + 1
+ 	  || dirname[1] != ':' || dirname[2] != '\0')
+ #endif
        /* Add '/' if `dirname' doesn't already end with it. */
        if (dirnamep > dirname && dirnamep[-1] != '/')
  	*dest++ = '/';
*** src/mv.c~0	Sat Nov 23 22:11:12 1996
--- src/mv.c	Sat Apr 12 21:13:18 1997
*************** do_move (const char *source, const char 
*** 347,352 ****
--- 347,362 ----
  static int
  movefile (const char *source, const char *dest)
  {
+ #ifdef MSDOS
+   /* Make sure the directory is explicit in SOURCE.  */
+   if (source[1] == ':' && source[2] != '/')
+     {
+       char *newsource = alloca (PATH_MAX + 1);
+ 
+       FIXPATH (source, newsource);
+       source = newsource;
+     }
+ #endif
    strip_trailing_slashes (source);
  
    if ((dest[strlen (dest) - 1] == '/' && !is_real_dir (source))
*************** main (int argc, char **argv)
*** 491,496 ****
--- 501,526 ----
    if (argc > optind + 2 && !isdir (argv[argc - 1]))
      error (1, 0,
  	   _("when moving multiple files, last argument must be a directory"));
+ 
+ #ifdef MSDOS
+     /* Destination = "d:path" is relative to current dir on drive d:  */
+   if (argv[argc - 1][1] == ':' && argv[argc - 1][2] != '/')
+     {
+       char *newname   = alloca (PATH_MAX + 1);
+       char *dest      = argv[argc - 1];
+       /* Make sure "d:" is treated as "d:./".  It doesn't make sense not
+ 	 to, since you cannot remove the current directory on another
+ 	 drive, so we will get an error any other way.  */
+       int   add_slash = dest[strlen (dest) - 1] == '/' || dest[2] == '\0';
+ 
+       /* Convert "d:" into an absolute pathname.  */
+       FIXPATH (dest, newname);
+       if (add_slash		/* dest/ has a special meaning in `mv' */
+ 	  && newname[strlen (newname) - 1] != '/')
+ 	strcat (newname, "/");
+       argv[argc - 1] = newname;
+     }
+ #endif
  
    /* Move each arg but the last onto the last. */
    for (; optind < argc - 1; ++optind)
*** src/rm.c~0	Sat Nov 23 22:11:12 1996
--- src/rm.c	Fri Apr 18 18:52:56 1997
*************** main (int argc, char **argv)
*** 155,160 ****
--- 155,167 ----
  	}
      }
  
+ #ifdef __DJGPP__
+   /* If they said `rm -r', let us find hidden files also,
+      otherwise we cannot remove directories with such files.  */
+   if (recursive)
+     __opendir_flags |= __OPENDIR_FIND_HIDDEN;
+ #endif
+ 
    if (show_version)
      {
        printf ("rm (%s) %s\n", GNU_PACKAGE, VERSION);
*************** main (int argc, char **argv)
*** 192,197 ****
--- 199,220 ----
  	  pathname = xmalloc (pnsize);
  	}
        strcpy (pathname, argv[optind]);
+ #ifdef MSDOS
+   /* pathname = "d:" means current dir on drive d:  */
+       if (pathname[0] && pathname[1] == ':' && pathname[2] == '\0')
+ 	{
+ 	  char fullname[PATH_MAX + 1];
+ 
+ 	  FIXPATH (pathname, fullname);	/* convert into an absolute pathname */
+ 	  if ((len = strlen (fullname)) + 1 > pnsize)
+ 	    {
+ 	      free (pathname);
+ 	      pnsize = 2 * (len + 1);
+ 	      pathname = xmalloc (pnsize);
+ 	    }
+ 	  memcpy (pathname, fullname, len + 1);
+ 	}
+ #endif
        err += rm ();
      }
  
*************** clear_directory (struct stat *statp)
*** 457,462 ****
--- 480,490 ----
  	     the file (which could result in recursive calls), and take
  	     the filename back off.  */
  
+ #ifdef MSDOS
+ 	  /* Don't generate ugly double slashes after a drive letter.  */
+ 	  if (pathstack->pathp[-1] == '/')
+ 	    pathstack->pathp--;
+ #endif
  	  *pathstack->pathp = '/';
  	  strcpy (pathstack->pathp + 1, namep);
  
*************** clear_directory (struct stat *statp)
*** 466,471 ****
--- 494,505 ----
  	  else if (rm ())
  	    err++;
  
+ #ifdef MSDOS
+           /* Don't delete a slash, if it is preceded by the drive
+              specifier (meaning we're in a root directory).  */
+           if (pathstack->pathp[-1] == ':')
+             pathstack->pathp++;
+ #endif
  	  *pathstack->pathp = '\0';
  	  pathstack = pathstack->next;	/* Pop the stack.  */
  	}
*** src/sync.c~0	Sat Nov  2 23:42:12 1996
--- src/sync.c	Sat Mar  8 20:50:18 1997
***************
*** 21,26 ****
--- 21,30 ----
  #include <stdio.h>
  #include <sys/types.h>
  
+ #ifdef __DJGPP__
+ #include <io.h>
+ #endif
+ 
  #include "system.h"
  #include "long-options.h"
  #include "error.h"
*************** main (int argc, char **argv)
*** 62,66 ****
--- 66,74 ----
      error (0, 0, _("ignoring all arguments"));
  
    sync ();
+ #ifdef __DJGPP__
+   /* Try to cause write-back caches to flush their buffers.  */
+   _flush_disk_cache ();
+ #endif
    exit (0);
  }
*** src/system.h~0	Wed Dec 18 03:19:24 1996
--- src/system.h	Sat Mar 15 17:04:36 1997
*************** char *getenv ();
*** 249,255 ****
     ST_NBLOCKS: Number of 512-byte blocks in the file
     (including indirect blocks). */
  #ifndef HAVE_ST_BLOCKS
! # define ST_BLKSIZE(statbuf) DEV_BSIZE
  # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE.  */
  #  define ST_NBLOCKS(statbuf) (((statbuf).st_size + 512 - 1) / 512)
  # else /* !_POSIX_SOURCE && BSIZE */
--- 249,260 ----
     ST_NBLOCKS: Number of 512-byte blocks in the file
     (including indirect blocks). */
  #ifndef HAVE_ST_BLOCKS
! # ifdef MSDOS
! #  define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
! 			        ? (statbuf).st_blksize : DEV_BSIZE)
! # else /* !MSDOS */
! #  define ST_BLKSIZE(statbuf) DEV_BSIZE
! #endif /* !MSDOS */
  # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE.  */
  #  define ST_NBLOCKS(statbuf) (((statbuf).st_size + 512 - 1) / 512)
  # else /* !_POSIX_SOURCE && BSIZE */
*************** char *getenv ();
*** 277,286 ****
  # endif /* !hpux */
  #endif /* HAVE_ST_BLOCKS */
  
- /* Convert B 512-byte blocks to kilobytes if K is nonzero,
-    otherwise return it unchanged. */
- #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
- 
  #ifndef RETSIGTYPE
  #define RETSIGTYPE void
  #endif
--- 282,287 ----
*************** char *alloca ();
*** 386,389 ****
  # define _(Text) Text
  #endif
  
! #define STREQ(a,b) (strcmp((a), (b)) == 0)
--- 387,405 ----
  # define _(Text) Text
  #endif
  
! #ifdef MSDOS
! /* MSDOS and compatible systems are case-insensitive in filenames.  */
! # define STREQ(a,b) (strcasecmp((a), (b)) == 0)
! /* Define a way to convert a pathname into absolute form.
!    Examples:
!                file		-> d:/dir/subdir/file
! 	       d:path		-> d:/curdir/path
! 	       /dir/subdir	-> x:/dir/subdir              */
! # ifdef __DJGPP__
! #  define FIXPATH(x,y)  _fixpath(x,y)
! # else  /* !__DJGPP__ */
! #  error FIXPATH macro not defined on MSDOS!
! # endif /* !__DJGPP__ */
! #else  /* !MSDOS */
! # define STREQ(a,b) (strcmp((a), (b)) == 0)
! #endif /* !MSDOS */
*** src/touch.c~0	Mon Nov 18 02:52:48 1996
--- src/touch.c	Sat Mar  8 21:01:26 1997
*************** touch (char *file)
*** 194,200 ****
  	utb.actime = sbuf.st_atime;
  
        if (!(change_times & CH_MTIME))
! 	utb.modtime = sbuf.st_mtime;
  
        status = utime (file, &utb);
      }
--- 194,214 ----
  	utb.actime = sbuf.st_atime;
  
        if (!(change_times & CH_MTIME))
! 	{
! 	  utb.modtime = sbuf.st_mtime;
! #ifdef MSDOS
! #ifdef __DJGPP__
! 	  /* DJGPP supports long filename API on Windows 9x, which does
! 	     allow to set all the 3 timestamps.  This support is only
! 	     switched on at run time, and only if the filesystem where
! 	     FILE belongs supports that API.  */
! 	  if (!_use_lfn (file))
! #endif
! 	  /* Plain MS-DOS has only 1 timestamp for files.
! 	     Use the modtime field for that.  */
! 	  utb.modtime = utb.actime;
! #endif
! 	}
  
        status = utime (file, &utb);
      }
*** configure	Sun Jan 26 19:04:58 1997
--- djgpp/configure	Fri Apr  4 19:56:08 1997
***************
*** 535,545 ****
  
  ac_aux_dir=
  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
!   if test -f $ac_dir/install-sh; then
      ac_aux_dir=$ac_dir
      ac_install_sh="$ac_aux_dir/install-sh -c"
      break
!   elif test -f $ac_dir/install.sh; then
      ac_aux_dir=$ac_dir
      ac_install_sh="$ac_aux_dir/install.sh -c"
      break
--- 535,545 ----
  
  ac_aux_dir=
  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
!   if test -x $ac_dir/install-sh; then
      ac_aux_dir=$ac_dir
      ac_install_sh="$ac_aux_dir/install-sh -c"
      break
!   elif test -x $ac_dir/install.sh; then
      ac_aux_dir=$ac_dir
      ac_install_sh="$ac_aux_dir/install.sh -c"
      break
***************
*** 576,582 ****
      *)
        # OSF1 and SCO ODT 3.0 have their own names for install.
        for ac_prog in ginstall installbsd scoinst install; do
!         if test -f $ac_dir/$ac_prog; then
  	  if test $ac_prog = install &&
              grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
  	    # AIX install.  It has an incompatible calling convention.
--- 576,582 ----
      *)
        # OSF1 and SCO ODT 3.0 have their own names for install.
        for ac_prog in ginstall installbsd scoinst install; do
!         if test -x $ac_dir/$ac_prog; then
  	  if test $ac_prog = install &&
              grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
  	    # AIX install.  It has an incompatible calling convention.
***************
*** 726,739 ****
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$LN" in
!   /*)
    ac_cv_path_LN="$LN" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_LN="$ac_dir/$ac_word"
        break
      fi
--- 726,739 ----
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$LN" in
!   */*)
    ac_cv_path_LN="$LN" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_LN="$ac_dir/$ac_word"
        break
      fi
***************
*** 758,771 ****
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$MV" in
!   /*)
    ac_cv_path_MV="$MV" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_MV="$ac_dir/$ac_word"
        break
      fi
--- 758,771 ----
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$MV" in
!   */*)
    ac_cv_path_MV="$MV" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_MV="$ac_dir/$ac_word"
        break
      fi
***************
*** 790,803 ****
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$RM" in
!   /*)
    ac_cv_path_RM="$RM" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_RM="$ac_dir/$ac_word"
        break
      fi
--- 790,803 ----
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$RM" in
!   */*)
    ac_cv_path_RM="$RM" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_RM="$ac_dir/$ac_word"
        break
      fi
***************
*** 822,835 ****
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$PERL" in
!   /*)
    ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_PERL="$ac_dir/$ac_word"
        break
      fi
--- 822,835 ----
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    case "$PERL" in
!   */*)
    ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
    ;;
    *)
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_PERL="$ac_dir/$ac_word"
        break
      fi
***************
*** 858,864 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_prog_CC="gcc"
        break
      fi
--- 858,864 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_prog_CC="gcc"
        break
      fi
***************
*** 888,894 ****
    ac_prog_rejected=no
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
          ac_prog_rejected=yes
  	continue
--- 888,894 ----
    ac_prog_rejected=no
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
          ac_prog_rejected=yes
  	continue
***************
*** 1136,1142 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_prog_RANLIB="ranlib"
        break
      fi
--- 1136,1142 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_prog_RANLIB="ranlib"
        break
      fi
***************
*** 1167,1173 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_prog_YACC="$ac_prog"
        break
      fi
--- 1167,1173 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_prog_YACC="$ac_prog"
        break
      fi
***************
*** 6017,6023 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
  	ac_cv_path_MSGFMT="$ac_dir/$ac_word"
  	break
--- 6017,6023 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
  	ac_cv_path_MSGFMT="$ac_dir/$ac_word"
  	break
***************
*** 6106,6112 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
        break
      fi
--- 6106,6112 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
        break
      fi
***************
*** 6138,6144 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
  	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
  	break
--- 6138,6144 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
  	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
  	break
***************
*** 6307,6313 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_GENCAT="$ac_dir/$ac_word"
        break
      fi
--- 6307,6313 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_GENCAT="$ac_dir/$ac_word"
        break
      fi
***************
*** 6339,6345 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
        break
      fi
--- 6339,6345 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
        break
      fi
***************
*** 6372,6378 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
  	ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
  	break
--- 6372,6378 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
  	ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
  	break
***************
*** 6407,6413 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
  	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
  	break
--- 6407,6413 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
  	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
  	break
***************
*** 6465,6471 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
  	ac_cv_path_MSGFMT="$ac_dir/$ac_word"
  	break
--- 6465,6471 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
  	ac_cv_path_MSGFMT="$ac_dir/$ac_word"
  	break
***************
*** 6499,6505 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
        break
      fi
--- 6499,6505 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
        break
      fi
***************
*** 6531,6537 ****
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -f $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
  	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
  	break
--- 6531,6537 ----
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
    for ac_dir in $PATH; do
      test -z "$ac_dir" && ac_dir=.
!     if test -x $ac_dir/$ac_word; then
        if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
  	ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
  	break
***************
*** 6665,6671 ****
                 sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
     fi
        sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
!      $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
  
              if test "$PACKAGE" = "gettext"; then
       GT_NO="#NO#"
--- 6665,6671 ----
                 sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
     fi
        sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
!      $srcdir/intl/po2tblin.sed > intl/po2tbl.sed
  
              if test "$PACKAGE" = "gettext"; then
       GT_NO="#NO#"
***************
*** 6800,6806 ****
  done
  
  ac_given_srcdir=$srcdir
! ac_given_INSTALL="$INSTALL"
  
  trap 'rm -fr `echo "Makefile doc/Makefile intl/Makefile lib/Makefile man/Makefile \
  m4/Makefile po/Makefile.in src/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
--- 6800,6806 ----
  done
  
  ac_given_srcdir=$srcdir
! ac_given_INSTALL='$INSTALL'
  
  trap 'rm -fr `echo "Makefile doc/Makefile intl/Makefile lib/Makefile man/Makefile \
  m4/Makefile po/Makefile.in src/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
***************
*** 6873,6878 ****
--- 6873,6903 ----
  s%@GT_NO@%$GT_NO%g
  s%@GT_YES@%$GT_YES%g
  s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g
+ s,\.h\.in,.h-i,g
+ s,\.tab\.,_tab.,g
+ s,=yacclockdir,\~yacclockdir.\~\~,g
+ s,winsz2,wins2,g
+ s% ls.\\\$o%& ls-msdos.\$o%
+ /_OBJECTS *=/s%[^\]$%& djstart.\$o%
+ /^ginstall: */s/\$/ ln/
+ /^	\\\$(LINK) *\\\$(ginstall_LDFLAGS)/a\\
+ 	./ln -s \$@ install
+ /^dir: */s/\$/ ln/
+ /^	\\\$(LINK) *\\\$(dir_LDFLAGS)/a\\
+ 	./ln -s \$@ d\\
+ 	stubedit d.exe argv0=dir
+ /^vdir: */s/\$/ ln/
+ /^	\\\$(LINK) *\\\$(vdir_LDFLAGS)/a\\
+ 	./ln -s \$@ v\\
+ 	stubedit v.exe argv0=vdir
+ /^mkdir: */s/\$/ ln/
+ /^	\\\$(LINK) *\\\$(mkdir_LDFLAGS)/a\\
+ 	./ln -s \$@ gmkdir\\
+ 	stubedit gmkdir.exe argv0=mkdir
+ /^rmdir: */s/\$/ ln/
+ /^	\\\$(LINK) *\\\$(rmdir_LDFLAGS)/a\\
+ 	./ln -s \$@ grmdir\\
+ 	stubedit grmdir.exe argv0=rmdir
  
  CEOF
  EOF
***************
*** 6915,6921 ****
  cat >> $CONFIG_STATUS <<EOF
  
  CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile intl/Makefile lib/Makefile man/Makefile \
! m4/Makefile po/Makefile.in src/Makefile"}
  EOF
  cat >> $CONFIG_STATUS <<\EOF
  for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
--- 6940,6946 ----
  cat >> $CONFIG_STATUS <<EOF
  
  CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile intl/Makefile lib/Makefile man/Makefile \
! m4/Makefile po/Makefile.in:po/Makefile.in-in src/Makefile"}
  EOF
  cat >> $CONFIG_STATUS <<\EOF
  for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
***************
*** 6996,7002 ****
  if test "${CONFIG_HEADERS+set}" != set; then
  EOF
  cat >> $CONFIG_STATUS <<EOF
!   CONFIG_HEADERS="config.h"
  EOF
  cat >> $CONFIG_STATUS <<\EOF
  fi
--- 7021,7027 ----
  if test "${CONFIG_HEADERS+set}" != set; then
  EOF
  cat >> $CONFIG_STATUS <<EOF
!   CONFIG_HEADERS="config.h:config.h-in"
  EOF
  cat >> $CONFIG_STATUS <<\EOF
  fi
*** src/ls-msdos.c~0	Fri Feb 21 18:14:28 1997
--- src/ls-msdos.c	Fri Apr 18 19:01:10 1997
***************
*** 0 ****
--- 1,334 ----
+ /* MSDOS-specific functions for `ls'.
+ 
+    Written by Eli Zaretskii <eliz@is.elta.co.il>  */
+ 
+ #ifdef MSDOS
+ 
+ #include <string.h>
+ 
+ /*  dos_mode_string -- convert MS-DOS file attribute bits into a character
+     string.  The characters stored in STR are:
+ 
+     0   'r'  if file is read-only, '-' otherwise.
+     1   'h'  if file is hidden, '-' otherwise.
+     2   's'  if file has its system bit set, '-' otherwise.
+     3   'v'  if file is a volume label, '-' otherwise.
+     4   'd'  if file is a directory, '-' otherwise.
+     5   'm'  if file was modified since last backup, '-' otherwise.
+     
+     For instance, for a write-protected, hidden file the function
+     will return a string "rh----".  */
+ 
+ void
+ dos_mode_string (bits, str)
+     int bits;
+     char *str;
+ {
+   unsigned mask = 1 << 5;
+   
+   strcpy(str, "rhsvdm");          /* assume all bits set */
+   for (str += 5; mask; mask >>= 1, --str)
+     if ((bits & mask) == 0)
+       *str = '-';                 /* put hyphen instead of unused bit */
+ }
+ 
+ #ifdef __DJGPP__
+ 
+ /* What follows won't work with anything but DJGPP.  */
+ 
+ #include <sys/stat.h>
+ #include <dirent.h>
+ 
+ static int colorization_required;
+ 
+ /* Ls is a heavy user of `stat' whose full emulation on MS-DOS is
+    sometimes very expensive.  Let's punish the user as little as we
+    can by requesting the fastest possible version of `stat'.
+ 
+    The default bits, suitable for just displaying the names of the files
+    are defined on `djstart.c'; below are the bits required by various
+    Ls options. */
+ void set_stat_bits_for_ls (int need_time, int need_size,
+ 			   int need_long_format, int msdos_long_format,
+ 			   int indicate_type, int use_color, int show_hidden)
+ {
+ #ifndef _POSIX_SOURCE
+   if (need_time)
+     _djstat_flags &= ~_STAT_ROOT_TIME;
+   if (need_size)
+     _djstat_flags &= ~_STAT_DIRSIZE;
+   if (need_long_format)
+     {
+       _djstat_flags &= ~(_STAT_ROOT_TIME
+ 			 | _STAT_DIRSIZE);
+       if (msdos_long_format)
+ 	_djstat_flags &= ~_STAT_EXEC_EXT;
+       else
+ 	_djstat_flags &= ~(_STAT_EXEC_MAGIC
+ 			   | _STAT_EXEC_EXT);
+     }
+   if (indicate_type)
+     _djstat_flags &= ~(_STAT_EXEC_EXT
+ 		       | _STAT_EXEC_MAGIC);
+   if (use_color)
+     _djstat_flags &= ~_STAT_EXEC_EXT;
+ 
+   /* Find hidden files only if user specified -a.  */
+   if (show_hidden)
+     {
+       __opendir_flags |= __OPENDIR_FIND_HIDDEN;
+       /* Find volume labels only if user specified both -a and -g.  */
+       if (msdos_long_format)
+ 	__opendir_flags |= __OPENDIR_FIND_LABEL;
+     }
+ 
+ #endif /* _POSIX_SOURCE */
+ 
+   /* Our screen redirector (below) wants to know if
+      colorization was actually required.  */
+   if (use_color)
+     colorization_required = 1;
+   else
+     colorization_required = 0;
+ }
+ 
+ /*  Screen write redirector.  We need this to support colorization
+     without requiring ANSI.SYS driver (or its work-alike) to be loaded.
+ 
+     This function uses the DJGPP filesystem extensions mechanism.  It is
+     installed as a handler for handle-based functions (read/write/close)
+     for the standard output (but actually only handles writes, only if
+     the standard output is connected to the terminal, and only if user
+     asked for colorization).  When a buffer is written to the screen by
+     low-level functions of the DJGPP C library, our handler will be
+     called.  For any request that doesn't require colored screen writes
+     we return a zero to the caller, in which case the caller will handle
+     the output in the usual way (by eventually calling DOS).
+ 
+     When colorization *is* required, the buffer is written directly to
+     the screen while converting the ANSI escape sequences into calls to
+     DJGPP conio functions which change text attributes.  A non-zero value is
+     then returned to the caller to signal that the output has been handled.
+ 
+     Warning: this function relies on the fact that `ls' disables the use
+     of TAB characters when colorization is required, and therefore it
+     does NOT expand TABs!  It also doesn't check for NULL characters in
+     the buffer, and might end the output prematurely if there are NULLs.  */
+ 
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <conio.h>
+ #include <sys/fsext.h>
+ #include <go32.h>	/* for `_dos_ds' */
+ #include <sys/farptr.h>
+ 
+ static int norm_blink = -1, cur_blink = -1;
+ static unsigned char norm_attr = 0, cur_attr = 0;
+ static int isatty_stdout = -1;
+ 
+ /* Restore the BIOS blinking bit to its original value.  Called at exit.  */
+ static void
+ restore_blink_bit (void)
+ {
+   if (cur_blink != norm_blink)
+     {
+       if (norm_blink > 0)
+ 	blinkvideo ();
+       else
+ 	intensevideo ();
+     }
+ }
+ 
+ #define ESC '\033'
+ 
+ static int
+ msdos_screen_write (__FSEXT_Fnumber func, int *retval, va_list rest_args)
+ {
+   static char *cbuf = 0;
+   static size_t cbuf_len = 0;
+   /* Only dark colors mentioned here, so that bold has visible effect.  */
+   static enum COLORS screen_color[] = {BLACK, RED, GREEN, BROWN,
+ 				       BLUE, MAGENTA, CYAN, LIGHTGRAY};
+   char *anchor, *p_next;
+   unsigned char fg, bg;
+ 
+   int handle;
+   char *buf;
+   size_t buflen;
+ 
+   /* Avoid direct screen writes unless colorization was actually requested.
+      Otherwise, we will break programs that catch I/O from their children.  */
+   handle = va_arg (rest_args, int);
+   if (!colorization_required || func != __FSEXT_write
+       || !(handle == STDOUT_FILENO ? isatty_stdout : isatty (handle)))
+     return 0;
+ 
+   buf = va_arg (rest_args, char *);
+   if (!buf)
+     {
+       errno = EINVAL;
+       *retval = -1;
+       return 1;
+     }
+ 
+   /* Allocate a sufficiently large buffer to hold the output.  */
+   buflen = va_arg (rest_args, size_t);
+   if (!cbuf)
+     {
+       struct text_info txtinfo;
+ 
+       cbuf_len = buflen + 1;
+       cbuf = (char *)xmalloc (cbuf_len);
+       gettextinfo (&txtinfo);
+       norm_attr = txtinfo.attribute; /* save the original text attribute */
+       cur_attr = norm_attr;
+       /* Does it normally blink when bg has its 3rd bit set?  */
+       norm_blink = (_farpeekb (_dos_ds, 0x465) & 0x20) ? 1 : 0;
+       cur_blink = norm_blink;
+     }
+   else if (buflen >= cbuf_len)
+     {
+       cbuf_len = buflen + 1;
+       cbuf = (char *)xrealloc (cbuf, cbuf_len);
+     }
+   memcpy (cbuf, buf, buflen);
+   cbuf[buflen] = '\0';
+ 
+   /* Current text attributes are used as baseline.  */
+   fg = cur_attr & 15;
+   bg = (cur_attr >> 4) & 15;
+ 
+   /* Walk the buffer, writing text directly to video RAM,
+      changing color attributes when an escape sequence is seen.  */
+   for (anchor = p_next = cbuf;
+        (p_next = memchr (p_next, ESC, buflen - (p_next - cbuf))) != 0; )
+     {
+       char *p = p_next;
+ 
+       if (p[1] == '[')	/* "Esc-[" sequence */
+ 	{
+ 	  /* If some chars seen since the last escape sequence,
+ 	     write it out to the screen using current text attributes.  */
+ 	  if (p > anchor)
+ 	    {
+ 	      *p = '\0';	/* `cputs' needs ASCIIZ string */
+ 	      cputs (anchor);
+ 	      *p = ESC;		/* restore the ESC character */
+ 	      anchor = p;
+ 	    }
+ 	  p += 2;		/* get past "Esc-[" sequence */
+ 	  p_next = p;
+ 	  while (*p != 'm')	/* `m' ends the escape sequence */
+ 	    {
+ 	      char *q;
+ 	      long code = strtol (p, &q, 10);
+ 
+ 	      /* Sanity checks:
+ 
+ 		   q > p unless p doesn't point to a number;
+ 		   ANSI codes are between 0 and 47;
+ 		   Each ANSI code ends with a `;' or an `m'.
+ 
+ 		 If any of the above is violated, we just ignore the bogon. */
+ 	      if (q == p || code > 47 || code < 0 || (*q != 'm' && *q != ';'))
+ 		{
+ 		  p_next = q;
+ 		  break;
+ 		}
+ 	      if (*q == ';')	/* more codes to follow */
+ 		q++;
+ 
+ 	      /* Convert ANSI codes to color fore- and background.  */
+ 	      switch (code)
+ 		{
+ 		  case 0:	/* all attributes off */
+ 		    fg = norm_attr & 15;
+ 		    bg = (norm_attr >> 4) & 15;
+ 		    break;
+ 		  case 1:	/* intensity on */
+ 		    fg |= 8;
+ 		    break;
+ 		  case 4:	/* underline on */
+ 		    fg |= 8;	/* we can't, so make it bold instead */
+ 		    break;
+ 		  case 5:	/* blink */
+ 		    if (cur_blink != 1)
+ 		      {
+ 			blinkvideo (); /* ensure we are'nt in bright bg mode */
+ 			cur_blink = 1;
+ 		      }
+ 		    bg |= 8;
+ 		    break;
+ 		  case 7:	/* reverse video */
+ 		    {
+ 		      unsigned char t = fg;
+ 		      fg = bg;
+ 		      bg = t;
+ 
+ 		      /* If it was blinking before, let it blink after.  */
+ 		      if (fg & 8)
+ 			bg |= 8;
+ 
+ 		      /* If the fg was bold, let the background be bold.  */
+ 		      if ((t & 8) && cur_blink != 0)
+ 			{
+ 			  intensevideo ();
+ 			  cur_blink = 0;
+ 			}
+ 		    }
+ 		    break;
+ 		  case 8:	/* concealed on */ 
+ 		    fg = (bg & 7) | 8;	/* make fg be like bg, only bright */
+ 		    break;
+ 		  case 30: case 31: case 32: case 33: /* foreground color */
+ 		  case 34: case 35: case 36: case 37:
+ 		    fg = (fg & 8) | (screen_color[code - 30] & 15);
+ 		    break;
+ 		  case 40: case 41: case 42: case 43: /* background color */
+ 		  case 44: case 45: case 46: case 47:
+ 		    bg = (bg & 8) | (screen_color[code - 40] & 15);
+ 		    break;
+ 		  default:
+ 		    p_next = q;	/* ignore unknown codes */
+ 		    break;
+ 		}
+ 	      p = q;
+ 	    }
+ 	  if (*p == 'm' && p > p_next)
+ 	    {
+ 	      /* They don't *really* want it invisible, do they?  */
+ 	      if (fg == (bg & 7))
+ 		fg |= 8;	/* make it concealed instead */
+ 
+ 	      /* Construct the text attribute and set it.  */
+ 	      cur_attr = (bg << 4) | fg;
+ 	      textattr (cur_attr);
+ 	      p_next = anchor = p + 1;
+ 	    }
+ 	  else
+ 	    break;
+ 	}
+       else
+ 	p_next++;
+     }
+ 
+   /* Output what's left in the buffer.  */
+   cputs (anchor);
+   *retval = buflen;
+   return 1;
+ }
+ 
+ /* This is called before `main' to install our STDOUT redirector.  */
+ 
+ static void __attribute__((constructor))
+ djgpp_ls_startup (void)
+ {
+   __FSEXT_set_function (STDOUT_FILENO, msdos_screen_write);
+   isatty_stdout = isatty (STDOUT_FILENO);
+   atexit (restore_blink_bit);
+ }
+ 
+ #endif  /* __DJGPP__ */
+ #endif  /* MSDOS */
*** src/djstart.c~0	Fri Feb 21 18:14:28 1997
--- src/djstart.c	Sat Mar  8 21:30:12 1997
***************
*** 0 ****
--- 1,189 ----
+ /* dj_startup -- Start-up code for GNU Fileutils under MS-DOS/DJGPP
+ 
+    Written by Eli Zaretskii <eliz@is.elta.co.il>
+ 
+    This code may be freely distributed, provided that this
+    copyright notice is left intact.  There is no warranty on
+    this code.
+ 
+    Commentary:
+    ----------
+ 
+    GNU Fileutils deal with files, and are notorious (as most other
+    Unix file-related utilities) for hardcoded assumptions about
+    filenames, especially regarding the slash character and the
+    insistance on knowing the fact that a filename that begins with
+    anything other than a slash is a relative filename (what about
+    DOS d:/file pathnames?).  To make these programs work on MSDOS,
+    it makes sense to convert all the filename arguments to the
+    forward-slash Unix-style notation at start-up.  This would
+    eliminate multiple #ifdef's in the programs' code.  The only
+    thing to take care of is to leave the options alone.
+ 
+    This module is supplied to do this kind of automagic, by using the
+    static constructor hooks provided in DJGPP v2.0 and above.  It
+    should be linked with every program from this package and will be
+    called automatically by the DJGPP start-up code (on crt1.c) just
+    before the `main' function is called.
+ 
+    There are a few other small services that this module does, while
+    at that:
+ 
+    * It sets the default file open mode to BINARY, which is
+      appropriate for file I/O in this package and removes another
+      reason for #ifdef's in the main code;
+ 
+    * It sets the flag bits for the `stat' and `fstat' functions so
+      as to avoid computing fields of `struct stat' that are expensive,
+      unless that program really needs these fields.
+ 
+    WARNING WARNING WARNING!!!
+ 
+    This code relies heavily on the assumption that it will be called
+    for a single command-line only once during the entire life of the
+    program!  Thus all the flag variables are static.
+ 
+    Also note that some of the code below relies on the program name
+    in argv[0] and will break if you rename the program executable file!
+ 
+    You HAVE been warned!
+ 
+    WARNING WARNING WARNING!!!
+ */
+ 
+ #ifdef __DJGPP__
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <io.h>
+ #include <crt0.h>
+ 
+ int _crt0_startup_flags = _CRT0_FLAG_DROP_EXE_SUFFIX;
+ 
+ #ifndef _POSIX_SOURCE
+ /* Let's punish the user as little as we can by requesting
+    the fastest possible version of `stat' for each program.
+    Note that `ls' is not here because it sets the bits at
+    run time, given the options on its command line.  */
+ #define  DEFAULT_STAT_BITS  (_STAT_WRITEBIT   | \
+ 			     _STAT_ROOT_TIME  | \
+ 			     _STAT_DIRSIZE    | \
+ 			     _STAT_EXEC_MAGIC | \
+ 			     _STAT_EXEC_EXT)
+ 
+ static struct {
+   char *name;
+   unsigned short stat_bits;
+ } prog_bits[] = {
+     {"chmod",   ~(_STAT_DIRSIZE | _STAT_EXEC_EXT | _STAT_EXEC_MAGIC)},
+     {"chown",   ~_STAT_DIRSIZE},
+     {"cp",      ~(_STAT_DIRSIZE | _STAT_EXEC_EXT)},
+     {"ln",      ~_STAT_EXEC_EXT},
+     {"mv",	~(_STAT_DIRSIZE | _STAT_EXEC_EXT)},
+     {"rm",	~(_STAT_DIRSIZE | _STAT_EXEC_EXT)},
+     {"touch",	~_STAT_ROOT_TIME}
+ };
+ #endif
+ 
+ static void
+ init_stat_bits (const char *prog_name)
+ {
+ #ifndef _POSIX_SOURCE
+   int i;
+ 
+   _djstat_flags = DEFAULT_STAT_BITS;
+ 
+   for (i = 0; i < sizeof (prog_bits) / sizeof (prog_bits[0]); i++)
+     if (strcasecmp (prog_name, prog_bits[i].name) == 0)
+       {
+ 	_djstat_flags &= prog_bits[i].stat_bits;
+ 	break;
+       }
+ #endif
+ }
+ 
+ static void
+ init_file_io (const char *prog_name)
+ {
+   _fmode = O_BINARY;
+ 
+   /* Only `dd' needs to switch standard streams to binary.  */
+   if (strcasecmp (prog_name, "dd") == 0)
+     {
+       if (!isatty (fileno (stdin)))
+ 	setmode (fileno (stdin), O_BINARY);
+       if (!isatty (fileno (stdout)))
+ 	setmode (fileno (stdout), O_BINARY);
+     }
+ }
+ 
+ static int options_first;       /* options preceed non-options */
+ static int no_more_options = 0; /* did we see all of the options yet? */
+ 
+ extern int    __crt0_argc;	/* defined by the DJGPP startup code */
+ extern char **__crt0_argv;
+ 
+ static void __attribute__((constructor))
+ djgpp_fileutils_startup (void)
+ {
+   char *  argv0base, *dot;
+   char ** arg_walker = __crt0_argv;
+   int     arg_count  = __crt0_argc;
+ 
+   /* Convert all non-option ARGV[] elements to forward slashes.  */
+   if (!options_first)
+     options_first = getenv("POSIXLY_CORRECT") != (char *)0;
+ 
+   while (arg_count--)
+     {
+       char *p = *arg_walker++;
+ 
+       if (no_more_options == 0)
+ 	{
+ 	  if (p[0] == '-')
+ 	    {
+ 	      if (p[1] == '-' && p[2] == '\0')
+ 		no_more_options = 1;
+ 	      continue;
+ 	    }
+ 	  else if (options_first)
+ 	    no_more_options = 1;
+ 	}
+       while (*p)
+ 	{
+ 	  if (*p == '\\')
+ 	    *p = '/';
+ 	  p++;
+ 	}
+     }
+ 
+   /* Find out what's the name of the program.  */
+   argv0base = strrchr (*__crt0_argv, '/');
+   if (!argv0base)
+     argv0base = strrchr (*__crt0_argv, ':');
+   if (argv0base)
+     argv0base++;
+   else
+     argv0base = *__crt0_argv;
+ 
+   /* When we are called by another DJGPP program, the
+      _CRT0_FLAG_DROP_EXE_SUFFIX bit does not always work.  */
+   if ((dot = strchr (argv0base, '.')))
+     *dot = '\0';
+ 
+   init_stat_bits (argv0base);
+   init_file_io (argv0base);
+ }
+ 
+ /* DJGPP doesn't have `lstat', since MS-DOS doesn't
+    support links.  Here's a trivial substitute that will do.  */
+ int lstat (const char *fname, struct stat *st_buf)
+ {
+   return stat (fname, st_buf);
+ }
+ 
+ #endif /* __DJGPP__ */
