2006-11-01  Juan M. Guerrero  <juan.guerrero@gmx.de>

	* doc/sed-in.tex: Add DJGPP port specific info about backup names when
	only SFN supports is available.

	* lib/copy-acl.c [__DJGPP__]: Include fcntl.h for _USE_LFN definition.
	(copy_acl) [__DJGPP__]:  If only SFN is available fchmod will fail with
	ENOSYS whhen trying to change the file mode.  In this case do not issue
	the error message.

	* lib/error.c: Include libsupp.h for prototypes of printf family
	of functions.

	* lib/getdelim.c (getdelim) [MSDOS]: For DOS-like systems strip the
	trailing CR.

	* lib/getopt.c: Include libsupp.h for prototypes of printf family
	of functions.

	* lib/mbrtowc.c: If EILSEQ is not defined, define it to the value given
	by djdev204's errno.h.

	* lib/obstack.c: Include libsupp.h for prototypes of printf family
	of functions.

	* lib/regex_internal.h: Check if HAVE_ALLOCA_H has been defined before
	trying to include alloca.h.

	* lib/set-mode-acl.c [__DJGPP__]: Include fcntl.h for _USE_LFN definition.
	(set_acl) [__DJGPP__]:  If only SFN is available fchmod will fail with
	ENOSYS whhen trying to change the file mode.  In this case do not issue
	the error message.

	* lib/strerror.c: Include libsupp.h for prototypes of printf family
	of functions.

	* lib/wcrtomb.c: If EILSEQ is not defined, define it to the value given
	by djdev204's errno.h.

	* sed/execute.c	(dump_append_queue): Call set_read_mode.
	(dump_append_queue) [O_BINARY]: Remove ^M, if before the newline, and
	^Z, if immediately before EOF.
	(get_backup_file_name) [MSDOS, __DJGPP__]: Use LFN_FILE_SYSTEM to check
	if only SFN support is available.  In that case generate a new and 8+3
	conforming backup file name.
	(open_next_file): Call set_read_mode.  Use LAST_SLASH.
	(closedown): Close files to be renamed before issuing the rename() and
	not after.

	* sed/sed.c (main) [SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING]: Set
	system_allow_multiple_cmds in the system_flags variable.

	* sed/sed.h [O_BINARY]: Define macro SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING
	for non POSIX systems where for system() multiple, semicolon separated,
	commands must be explicitly enabled.
	[O_BINARY]: Declare the system_flags variable to change system()
	behaviour.

	* sed/utils.c [O_BINARY]: Include sys/stat.h and make sure S_ISCHR
	is defined.
	(set_read_mode): New function, switches a stream into binary mode.
	This is a no-op unless O_BINARY is defined.
	(ck_mkstemp) [MSDOS]: Check for the TEMP variable too before defaulting
	to P_tmpdir and test that the used tempdir really does exists before
	starting using it.
        (is_a_device): New function, checks if the file pointer is associated
        to stdout.
	(ck_fwrite) [O_BINARY]: If we are writing to a character device,
	replace every ^Z character with an ASCII string "^Z".
	(follow_symlink): Use IS_SLASH and LAST_SLASH to detect directory
	separator character in the file name.

	* sed/utils.h: Include fcntl.h and libsupp.h
	(O_BINARY, setmode): Define if O_BINARY is undefined.
	[O_BINARY]: Include io.h.
	(set_read_mode): Declare a prototype.
	[O_BINARY, __DJGPP__]: New macro IS_TMPDIR to check that the value
	passed really points to an existing directory to be used as tmpdir.
	For no DJGPP system it defaults to the original sed code check.
	[O_BINARY]: New macro IS_SLASH to check if character is a directory
	separator for the particular OS.
	[O_BINARY]: New macro LAST_SLASH defined to check for the last slash or
	backslash as directory separator in the given filename.
	[O_BINARY]: New macro LFN_FILE_SYSTEM to check if the used file system
	supports LFN or only SFN.











diff -aprNU5 sed-4.2.1.orig/doc/sed-in.texi sed-4.2.1/doc/sed-in.texi
--- sed-4.2.1.orig/doc/sed-in.texi	2009-06-25 18:55:34 +0000
+++ sed-4.2.1/doc/sed-in.texi	2009-11-01 23:34:36 +0000
@@ -268,10 +268,31 @@ even to place backup copies of the origi
 directory (provided the directory already exists).
 
 If no extension is supplied, the original file is
 overwritten without making a backup.
 
+For the @acronym{DJGPP} port, if only SFN support is available,
+the backup file name will be truncated to the well known @code{8+3}
+length.  This rule is followed: the suffix will remove as many
+characters as necessary from a potentially existing extension to
+fit into the 3 characters long space available for extensions;
+if a prefix is given, it will shift to the right as many as
+characters are necessary to fit into the 8 characters long space
+available for file names.  As example, the following command:
+
+@example
+sed -ibck_*_up s/foobar/raboof/ filename.txt
+@end example
+
+@noindent
+will produce a backup file for @code{filename.txt} with @code{bck_file._up}
+as backup file name.  As can be seen the suffix @code{_up} is 3
+characters long an overwrites the file name's extension @code{ext}
+completely.  The prefix @code{bck_} is 4 characters long and occupies
+the place of the first 4 characters of the file name, so that the last
+4 characters of the original file name are lost.
+
 @item -l @var{N}
 @itemx --line-length=@var{N}
 @opindex -l
 @opindex --line-length
 @cindex Line length, setting
diff -aprNU5 sed-4.2.1.orig/lib/copy-acl.c sed-4.2.1/lib/copy-acl.c
--- sed-4.2.1.orig/lib/copy-acl.c	2009-06-03 19:10:52 +0000
+++ sed-4.2.1/lib/copy-acl.c	2009-11-01 23:34:36 +0000
@@ -17,10 +17,14 @@
 
    Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible.  */
 
 #include <config.h>
 
+#if __DJGPP__
+# include <fcntl.h>
+#endif
+
 #include "acl.h"
 
 #include "acl-internal.h"
 
 #include "gettext.h"
@@ -542,10 +546,17 @@ copy_acl (const char *src_name, int sour
     case -2:
       error (0, errno, "%s", quote (src_name));
       return -1;
 
     case -1:
+#if __DJGPP__
+      /* If only SFN support available, DJGPP's fchmod will fail
+         with ENOSYS.  For DOS/WINDOWS this will not heard, so do
+         not confuse the user by issuing the error message. */
+      if (!_USE_LFN)
+        return 0;
+#endif
       error (0, errno, _("preserving permissions for %s"), quote (dst_name));
       return -1;
 
     default:
       return 0;
diff -aprNU5 sed-4.2.1.orig/lib/error.c sed-4.2.1/lib/error.c
--- sed-4.2.1.orig/lib/error.c	2009-06-03 19:10:52 +0000
+++ sed-4.2.1/lib/error.c	2009-11-01 23:34:36 +0000
@@ -19,10 +19,14 @@
 
 #if !_LIBC
 # include <config.h>
 #endif
 
+#if __DJGPP__
+# include <libsupp.h>
+#endif
+
 #include "error.h"
 
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
diff -aprNU5 sed-4.2.1.orig/lib/getdelim.c sed-4.2.1/lib/getdelim.c
--- sed-4.2.1.orig/lib/getdelim.c	2009-06-25 18:25:46 +0000
+++ sed-4.2.1/lib/getdelim.c	2009-11-01 23:34:36 +0000
@@ -121,11 +121,18 @@ getdelim (char **lineptr, size_t *n, int
 
       (*lineptr)[cur_len] = i;
       cur_len++;
 
       if (i == delimiter)
-	break;
+        {
+#ifdef MSDOS
+	  /*  For DOS-like systems strip the trailing CR.  */
+	  if ((i = cur_len - 2) >= 0 && (*lineptr)[i] == '\r')
+	    (*lineptr)[i] = (*lineptr)[--cur_len];
+#endif
+	  break;
+        }
     }
   (*lineptr)[cur_len] = '\0';
   result = cur_len ? cur_len : result;
 
  unlock_return:
diff -aprNU5 sed-4.2.1.orig/lib/getopt.c sed-4.2.1/lib/getopt.c
--- sed-4.2.1.orig/lib/getopt.c	2009-06-03 19:10:52 +0000
+++ sed-4.2.1/lib/getopt.c	2009-11-01 23:34:36 +0000
@@ -21,10 +21,14 @@
 
 #ifndef _LIBC
 # include <config.h>
 #endif
 
+#if __DJGPP__
+# include <libsupp.h>
+#endif
+
 #include "getopt.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff -aprNU5 sed-4.2.1.orig/lib/mbrtowc.c sed-4.2.1/lib/mbrtowc.c
--- sed-4.2.1.orig/lib/mbrtowc.c	2009-06-03 19:10:52 +0000
+++ sed-4.2.1/lib/mbrtowc.c	2009-11-01 23:34:36 +0000
@@ -28,10 +28,14 @@
 
 # include "localcharset.h"
 # include "streq.h"
 # include "verify.h"
 
+# ifndef EILSEQ
+#  define EILSEQ  41  /*  To match the value used in djdev204  */
+# endif
+
 
 verify (sizeof (mbstate_t) >= 4);
 
 static char internal_state[4];
 
diff -aprNU5 sed-4.2.1.orig/lib/obstack.c sed-4.2.1/lib/obstack.c
--- sed-4.2.1.orig/lib/obstack.c	2009-06-03 19:10:52 +0000
+++ sed-4.2.1/lib/obstack.c	2009-11-01 23:34:36 +0000
@@ -19,10 +19,13 @@
 
 #ifdef _LIBC
 # include <obstack.h>
 # include <shlib-compat.h>
 #else
+# if __DJGPP__
+#  include <libsupp.h>
+# endif
 # include <config.h>
 # include "obstack.h"
 #endif
 
 /* NOTE BEFORE MODIFYING THIS FILE: This version number must be
diff -aprNU5 sed-4.2.1.orig/lib/regex_internal.h sed-4.2.1/lib/regex_internal.h
--- sed-4.2.1.orig/lib/regex_internal.h	2009-06-03 19:10:50 +0000
+++ sed-4.2.1/lib/regex_internal.h	2009-11-01 23:34:36 +0000
@@ -456,11 +456,13 @@ static unsigned int re_string_context_at
 #define re_string_length(pstr) ((pstr)->len)
 #define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
 #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
 #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
 
-#include <alloca.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
 
 #ifndef _LIBC
 # if HAVE_ALLOCA
 /* The OS usually guarantees only one guard page at the bottom of the stack,
    and a page size can be as small as 4096 bytes.  So we cannot safely
diff -aprNU5 sed-4.2.1.orig/lib/set-mode-acl.c sed-4.2.1/lib/set-mode-acl.c
--- sed-4.2.1.orig/lib/set-mode-acl.c	2009-06-15 09:05:10 +0000
+++ sed-4.2.1/lib/set-mode-acl.c	2009-11-01 23:34:36 +0000
@@ -17,10 +17,14 @@
 
    Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible.  */
 
 #include <config.h>
 
+#if __DJGPP__
+# include <fcntl.h>
+#endif
+
 #include "acl.h"
 
 #include "acl-internal.h"
 
 #include "gettext.h"
@@ -483,8 +487,17 @@ qset_acl (char const *name, int desc, mo
 int
 set_acl (char const *name, int desc, mode_t mode)
 {
   int r = qset_acl (name, desc, mode);
   if (r != 0)
-    error (0, errno, _("setting permissions for %s"), quote (name));
+    {
+#if __DJGPP__
+      /* If only SFN support available, DJGPP's fchmod will fail
+         with ENOSYS.  For DOS/WINDOWS this will not heard, so do
+         not confuse the user by issuing the error message. */
+      if (!_USE_LFN)
+        return 0;
+#endif
+      error (0, errno, _("setting permissions for %s"), quote (name));
+    }
   return r;
 }
diff -aprNU5 sed-4.2.1.orig/lib/strerror.c sed-4.2.1/lib/strerror.c
--- sed-4.2.1.orig/lib/strerror.c	2009-06-27 12:46:46 +0000
+++ sed-4.2.1/lib/strerror.c	2009-11-01 23:34:36 +0000
@@ -15,10 +15,14 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
+#if __DJGPP__
+# include <libsupp.h>
+#endif
+
 #include <string.h>
 
 #if REPLACE_STRERROR
 
 # include <errno.h>
diff -aprNU5 sed-4.2.1.orig/lib/wcrtomb.c sed-4.2.1/lib/wcrtomb.c
--- sed-4.2.1.orig/lib/wcrtomb.c	2009-06-03 19:10:52 +0000
+++ sed-4.2.1/lib/wcrtomb.c	2009-11-01 23:34:36 +0000
@@ -21,10 +21,14 @@
 #include <wchar.h>
 
 #include <errno.h>
 #include <stdlib.h>
 
+#ifndef EILSEQ
+# define EILSEQ  41  /*  To match the value given in djdev204  */
+#endif
+
 
 size_t
 wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
 {
   /* This implementation of wcrtomb on top of wctomb() supports only
diff -aprNU5 sed-4.2.1.orig/sed/execute.c sed-4.2.1/sed/execute.c
--- sed-4.2.1.orig/sed/execute.c	2009-06-26 10:13:52 +0000
+++ sed-4.2.1/sed/execute.c	2009-11-02 20:30:46 +0000
@@ -642,12 +642,56 @@ dump_append_queue()
 	     condition."  IEEE Std 1003.2-1992
 	     So, don't fail. */
 	  fp = ck_fopen(p->fname, read_mode, false);
 	  if (fp)
 	    {
+	      set_read_mode(fp);
 	      while ((cnt = ck_fread(buf, 1, sizeof buf, fp)) > 0)
-		ck_fwrite(buf, 1, cnt, output_file.fp);
+		{
+#ifdef O_BINARY
+		  /* Remove CRs from CR-LF pairs, and the trailing ^Z.  */
+		  register char *src = buf, *dest = buf;
+		  register size_t len = cnt;
+
+		  while (len--)
+		    {
+		      if (*src == '\r' || *src == 0x1a)
+			{
+			  if (!len)
+			    {
+			      if (getc(fp) != EOF)
+				{
+				  if (*src == '\r')
+				    {
+				      fseek(fp, -2L, SEEK_CUR);
+				      cnt--;
+				    }
+				  else
+				    {
+				      fseek(fp, -1L, SEEK_CUR);
+				      *dest++ = *src++;
+				    }
+				  break;
+				}
+			      else if (*src == 0x1a)
+				{
+				  cnt--;
+				  break;
+				}
+			    }
+			  else if (src[1] == '\n')
+			    {
+			      src++;
+			      len--;
+			      cnt--;
+			    }
+			}
+		      *dest++ = *src++;
+		    }
+#endif
+		  ck_fwrite(buf, 1, cnt, output_file.fp);
+		}
 	      ck_fclose(fp);
 	    }
 	}
     }
 
@@ -684,10 +728,85 @@ get_backup_file_name(name)
       p += name_length;
     }
 
   /* Tack on what's after the last asterisk */
   strcpy (p, old_asterisk);
+
+#if defined(MSDOS) && defined(__DJGPP__)
+  /* For file systems with limited file name length, like DOS,
+     the backup file name must be truncated to fullfill
+     with these limitations.  Only designed to work with a
+     DOS file system (8+3) */
+  if (!LFN_FILE_SYSTEM(backup) && !LFN_FILE_SYSTEM(name))
+    {
+      char *dot, *sfn_backup, *new_name, *extension, *prefix, *suffix;
+      int length, suffix_length;
+
+      /* Get the extension of the input file name */
+      new_name = xmalloc(name_length + 1);
+      strcpy(new_name, name);
+      if (extension = strrchr(new_name, '.'))
+        {
+          *extension = '\0';
+          extension++;
+        }
+
+      /* Get the prefix and the suffix for the backup file */
+      length = strlen(in_place_extension);
+      prefix = xmalloc(length + 1);
+      strcpy(prefix, in_place_extension);
+      asterisk = strchr(prefix, '*');
+      if (asterisk)
+        {
+          *asterisk = '\0';
+          asterisk++;
+          suffix = strrchr(asterisk, '*');
+          if (!suffix)
+            suffix = asterisk;
+        }
+      else
+        {
+          suffix = prefix;
+          prefix = NULL;
+        }
+      suffix_length = strlen(suffix);
+
+      /* Compute a SFN for the backup file name */
+      sfn_backup = xmalloc(8 + 1 + 3 + 1);
+      if (length = 0, prefix)
+        for (; (sfn_backup[length] = prefix[length]) && (length < 8); length++)
+          ;  /* Copy the prefix into the sfn backup file name */
+      for (backup_length = length, length = 0; (backup_length < 8) && (sfn_backup[backup_length] = new_name[length]); backup_length++, length++)
+        ;  /* Append the input file name to the sfn backup file name */
+      sfn_backup[backup_length++] = '.';
+      if (extension && (suffix_length < 3))
+        {
+          for (length = 0; (sfn_backup[backup_length] = extension[length]) && (length < 3); backup_length++, length++)
+            ;  /* Append the extension of the input file name to the sfn backup file name */
+          if ((suffix_length + length) > 3)
+            {
+              switch (length)
+                {
+                case 2:
+                  backup_length--;
+                  break;
+                case 3:
+                  backup_length -= suffix_length;
+                  break;
+                }
+            }
+        }
+      for (length = 0; (sfn_backup[backup_length] = suffix[length]) && (length < 3); backup_length++, length++)
+        ;  /* Append the suffix to the sfn backup file name */
+      sfn_backup[backup_length] = '\0';
+      xfree(backup);
+      xfree(new_name);
+      xfree(prefix);
+      backup = sfn_backup;
+    }
+#endif  /* MSDOS && __DJGPP__  */
+
   return backup;
 }
 
 /* Initialize a struct input for the named file. */
 static void open_next_file P_((const char *name, struct input *));
@@ -710,10 +829,12 @@ open_next_file(name, input)
       input->read_fn = read_always_fail; /* a redundancy */
       ++input->bad_count;
       return;
     }
 
+  set_read_mode(input->fp); /* for systems with text/binary schizophrenia */
+
   input->read_fn = read_file_line;
 
   if (in_place_extension)
     {
       int input_fd;
@@ -729,11 +850,11 @@ open_next_file(name, input)
       else
         input->in_file_name = name;
 
       /* get the base name */
       tmpdir = ck_strdup(input->in_file_name);
-      if ((p = strrchr(tmpdir, '/')))
+      if ((p = LAST_SLASH(tmpdir)))
 	*p = 0;
       else
 	strcpy(tmpdir, ".");
 
       if (isatty (fileno (input->fp)))
@@ -800,10 +921,19 @@ closedown(input)
   if (in_place_extension && output_file.fp != NULL)
     {
       const char *target_name;
       int input_fd, output_fd;
 
+
+      /*
+       *  For DOS/WINDOWS and all other OS with non-POSIX like file systems,
+       *  the file that shall be replaced/renamed by rename() must be closed
+       *  before the rename() call can be issued or the call will fail.
+       */
+      if (input->fp != stdin) /* stdin can be reused on tty and tape devices */
+        ck_fclose(input->fp);
+
       target_name = input->in_file_name;
       input_fd = fileno (input->fp);
       output_fd = fileno (output_file.fp);
       copy_acl (input->in_file_name, input_fd,
 		input->out_file_name, output_fd,
diff -aprNU5 sed-4.2.1.orig/sed/sed.c sed-4.2.1/sed/sed.c
--- sed-4.2.1.orig/sed/sed.c	2009-06-03 19:10:50 +0000
+++ sed-4.2.1/sed/sed.c	2009-11-02 00:05:16 +0000
@@ -204,10 +204,19 @@ main(argc, argv)
 
   int opt;
   int return_code;
   const char *cols = getenv("COLS");
 
+#if SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING
+  /*
+   *  For some non posix systems where multiple cmds
+   *  separated by semicolon must be explicitly
+   *  enabled before calling system().
+   */
+  system_flags |= system_allow_multiple_cmds;
+#endif
+
   program_name = argv[0];
   initialize_main (&argc, &argv);
 #if HAVE_SETLOCALE
   /* Set locale according to user's wishes.  */
   setlocale (LC_ALL, "");
diff -aprNU5 sed-4.2.1.orig/sed/sed.h sed-4.2.1/sed/sed.h
--- sed-4.2.1.orig/sed/sed.h	2009-06-25 18:55:34 +0000
+++ sed-4.2.1/sed/sed.h	2009-11-02 00:10:36 +0000
@@ -277,5 +277,23 @@ extern bool is_utf8;
 #endif
 
 extern int brlen P_ ((int ch, mbstate_t *ps));
 extern void initialize_mbcs P_ ((void));
 
+#ifdef O_BINARY
+# if __DJGPP__
+   /*
+    *  For some non posix systems where multiple cmds
+    *  separated by semicolon must be explicitly
+    *  enabled before calling system().
+    */
+#  define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING  1
+#  define system_flags   __system_flags
+#  define system_allow_multiple_cmds  __system_allow_multiple_cmds
+extern int __system_flags;
+# else /*  !__DJGPP_  */
+#  define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING  0
+# endif
+#else /*  !O_BINARY  */
+  /*  posix  */
+# define SYSTEM_CALL_NEED_MULTIPLE_CMDS_ENABLING   0
+#endif
diff -aprNU5 sed-4.2.1.orig/sed/utils.c sed-4.2.1/sed/utils.c
--- sed-4.2.1.orig/sed/utils.c	2009-06-26 10:02:58 +0000
+++ sed-4.2.1/sed/utils.c	2009-11-02 20:38:40 +0000
@@ -145,10 +145,25 @@ register_open_file (fp, name, temp)
   p->name = ck_strdup(name);
   p->fp = fp;
   p->temp = false;
 }
 
+void
+set_read_mode (fp)
+  FILE *fp;
+{
+#ifdef O_BINARY
+  /* For systems that distinguish between text and binary files,
+     switch all input streams to binary mode.  This is so we get all
+     the characters from the file, instead of relying on the
+     misfeatures of the C library conversions (e.g., most of them drop
+     lone ^M characters, stop at the first ^Z character, etc.)  */
+  if (!isatty(fileno(fp)))
+    setmode(fileno(fp), O_BINARY);
+#endif
+}
+
 /* Panic on failing fopen */
 FILE *
 ck_fopen(name, mode, fail)
   const char *name;
   const char *mode;
@@ -200,21 +215,31 @@ ck_mkstemp (p_filename, tmpdir, base)
   char *template;
   FILE *fp;
   int fd;
   int save_umask;
 
-  if (tmpdir == NULL)
+  if (IS_TMPDIR(tmpdir))
     tmpdir = getenv("TMPDIR");
-  if (tmpdir == NULL)
+  if (IS_TMPDIR(tmpdir))
     {
       tmpdir = getenv("TMP");
-      if (tmpdir == NULL)
+      if (IS_TMPDIR(tmpdir))
+	{
+#ifdef MSDOS
+	  tmpdir = getenv("TEMP");
+	  if (IS_TMPDIR(tmpdir))
+#endif
 #ifdef P_tmpdir
-	tmpdir = P_tmpdir;
+	    tmpdir = P_tmpdir;
 #else
-	tmpdir = "/tmp";
+# ifdef MSDOS
+	    tmpdir = ".";
+# else
+	    tmpdir = "/tmp";
+# endif
 #endif
+	}
     }
 
   template = xmalloc (strlen (tmpdir) + strlen (base) + 8);
   sprintf (template, "%s/%sXXXXXX", tmpdir, base);
 
@@ -230,23 +255,73 @@ ck_mkstemp (p_filename, tmpdir, base)
   fp = fdopen (fd, "w");
   register_open_file (fp, template, true);
   return fp;
 }
 
+#ifdef O_BINARY
+static int stdout_is_a_device;
+
+static int __inline__ is_a_device P_((FILE *fp));
+static int __inline__
+is_a_device(fp)
+  FILE *fp;
+{
+  struct stat st;
+
+  if (fp == stdout)
+    {
+      /* Warning!  This assumes stdout is never switched during the
+	 program's run!  */
+      if (stdout_is_a_device == -1
+	  && fstat(fileno(stdout), &st) == 0)
+	stdout_is_a_device = S_ISCHR(st.st_mode) != 0;
+      return stdout_is_a_device == 1;
+    }
+  else
+    return fstat(fileno(fp), &st) == 0 && S_ISCHR(st.st_mode);
+}
+#endif
+
 /* Panic on failing fwrite */
 void
 ck_fwrite(ptr, size, nmemb, stream)
   const VOID *ptr;
   size_t size;
   size_t nmemb;
   FILE *stream;
 {
   clearerr(stream);
-  if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
-    panic(ngettext("couldn't write %d item to %s: %s",
-		   "couldn't write %d items to %s: %s", nmemb), 
-		nmemb, utils_fp_name(stream), strerror(errno));
+#ifdef O_BINARY
+  if (!size)
+    return;
+  if (is_a_device(stream))
+    {
+      char *p;
+      size_t left = nmemb * size;
+
+      /* Text-mode writes to character devices stop at the first ^Z
+	 character.  Repair this lossage.  */
+      while ((p = memchr(ptr, 0x1a, left)) != NULL)
+	{
+	  size_t this_write = p - (char *)ptr;
+
+	  if (fwrite(ptr, 1, this_write, stream) != this_write)
+	    break;
+	  fwrite("^Z", 1, 2, stream);
+	  left -= this_write + 1;
+	  ptr = (char *)ptr + this_write + 1;
+	}
+      if (p == NULL && fwrite(ptr, 1, left, stream) == left)
+	return;
+    }
+  else
+#endif
+  if (!size || fwrite(ptr, size, nmemb, stream) == nmemb)
+    return;
+  panic(ngettext("couldn't write %d item to %s: %s",
+		 "couldn't write %d items to %s: %s", nmemb), 
+	nmemb, utils_fp_name(stream), strerror(errno));
 }
 
 /* Panic on failing fread */
 size_t
 ck_fread(ptr, size, nmemb, stream)
@@ -377,11 +452,11 @@ follow_symlink(const char *fname)
       if (rc < 0)
 	panic (_("couldn't follow symlink %s: %s"), buf, strerror(errno));
       else
 	buf2 [rc] = '\0';
 
-      if (buf2[0] != '/' && (c = strrchr (buf, '/')) != NULL)
+      if (!IS_SLASH (buf2[0]) && LAST_SLASH (buf))
 	{
 	  /* Need to handle relative paths with care.  Reallocate buf1 and
 	     buf2 to be big enough.  */
 	  int len = c - buf + 1;
 	  if (len + rc + 1 > buf_size)
diff -aprNU5 sed-4.2.1.orig/sed/utils.h sed-4.2.1/sed/utils.h
--- sed-4.2.1.orig/sed/utils.h	2009-06-03 19:10:50 +0000
+++ sed-4.2.1/sed/utils.h	2009-11-02 20:50:14 +0000
@@ -14,16 +14,63 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
 
+#if __DJGPP__
+# include <libsupp.h>
+#endif
+
 #include <stdio.h>
 
 #include "basicdefs.h"
 
+#include <fcntl.h>
+#ifndef O_BINARY
+# ifdef _O_BINARY
+#  define O_BINARY _O_BINARY
+#  define setmode  _setmode
+# endif
+#endif
+
+#ifdef O_BINARY
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# ifndef S_ISCHR
+#  define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
+# endif
+# if __DJGPP__
+#  include <crt0.h>
+extern int _crt0_startup_flags;
+#  define IS_TMPDIR(dirname)   ((dirname) == NULL || access((dirname), D_OK))
+# else
+#  define IS_TMPDIR(dirname)   ((dirname) == NULL)
+# endif
+# define IS_SLASH(C)           ((C) == '/' || (C) == '\\')
+# define LAST_SLASH(filename)           \
+  ({                                    \
+     char *_pb, *_ps;                   \
+     _pb = strrchr((filename), '\\');   \
+     _ps = strrchr((filename), '/');    \
+     if (!_pb && !_ps)                  \
+       _ps = strrchr((filename), ':');  \
+     else if (_pb > _ps) _ps = _pb;     \
+     _ps;                               \
+  })
+#else
+# define IS_SLASH(C)           ((C) == '/')
+# define IS_TMPDIR(dirname)    ((dirname) == NULL)
+# define LAST_SLASH(filename)  (strrchr((filename), '/'))
+#endif
+
+#define LFN_FILE_SYSTEM(filename)  (pathconf((filename), _PC_NAME_MAX) > 12)
+
+
 void panic P_((const char *str, ...));
 
+void set_read_mode P_((FILE *stream));
 FILE *ck_fopen P_((const char *name, const char *mode, int fail));
 FILE *ck_fdopen P_((int fd, const char *name, const char *mode, int fail));
 void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream));
 size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream));
 void ck_fflush P_((FILE *stream));
