Re: perror() changes the orientation of stderr to byte-oriented mode if stderr is not oriented yet.

Takashi Yano <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
Hi Corinna,

On Mon, 2 Jul 2018 12:28:38 +0200
Corinna Vinschen wrote:
> Not sure if I'm missing something, but doesn't that mean the perror
> output won't use text mode even if it's requested?

It seems that the text mode only affects to outputting '\n'. So, this
is maintained in the patch. However, this is not so smart.

> I guess the simplest solution is to use the FreeBSD/OpenBSD method
> all the time.

How about the patch attached?

-- 
Takashi Yano <[email protected]>
0001-Fix-a-bug-of-perror-psignal-that-changes-the-orienta.patch (application/octet-stream, 2.8 KB)
From 80be9c95f8e48a516705b61077f8dd84e2e26878 Mon Sep 17 00:00:00 2001
From: Takashi Yano <[email protected]>
Date: Tue, 3 Jul 2018 18:04:31 +0900
Subject: [PATCH] Fix a bug of perror()/psignal() that changes the orientation
 of stderr.

* perror.c: Fix the problem that perror() changes the orientation
  of stderr ty byte-oriented mode if stderr is not oriented yet.
* psignal.c: Ditto.
---
 newlib/libc/signal/psignal.c | 30 +++++++++++++++++++++++++++---
 newlib/libc/stdio/perror.c   | 32 +++++++++++++++++++++++++++-----
 2 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/newlib/libc/signal/psignal.c b/newlib/libc/signal/psignal.c
index 602714f49..9a584869d 100644
--- a/newlib/libc/signal/psignal.c
+++ b/newlib/libc/signal/psignal.c
@@ -32,13 +32,37 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
 #include <_ansi.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/uio.h>
+
+#define ADD(str) \
+{ \
+  v->iov_base = (void *)(str); \
+  v->iov_len = strlen (v->iov_base); \
+  v ++; \
+  iov_cnt ++; \
+}
 
 void
 psignal (int sig,
        const char *s)
 {
+  struct iovec iov[4];
+  struct iovec *v = iov;
+  int iov_cnt = 0;
+
   if (s != NULL && *s != '\0')
-    fprintf (stderr, "%s: %s\n", s, strsignal (sig));
-  else
-    fprintf (stderr, "%s\n", strsignal (sig));
+    {
+      ADD (s);
+      ADD (": ");
+    }
+  ADD (strsignal (sig));
+
+#ifdef __SCLE
+  ADD ((stderr->_flags & __SCLE) ? "\r\n" : "\n");
+#else
+  ADD ("\n");
+#endif
+
+  fflush (stderr);
+  writev (fileno (stderr), iov, iov_cnt);
 }
diff --git a/newlib/libc/stdio/perror.c b/newlib/libc/stdio/perror.c
index d98e17e19..831c67eef 100644
--- a/newlib/libc/stdio/perror.c
+++ b/newlib/libc/stdio/perror.c
@@ -56,26 +56,48 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
 #include <reent.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/uio.h>
 #include "local.h"
 
+#define ADD(str) \
+{ \
+  v->iov_base = (void *)(str); \
+  v->iov_len = strlen (v->iov_base); \
+  v ++; \
+  iov_cnt ++; \
+}
+
 void
 _perror_r (struct _reent *ptr,
        const char *s)
 {
   char *error;
   int dummy;
+  struct iovec iov[4];
+  struct iovec *v = iov;
+  int iov_cnt = 0;
+  FILE *fp = _stderr_r (ptr);
 
-  _REENT_SMALL_CHECK_INIT (ptr);
+  CHECK_INIT (ptr, fp);
   if (s != NULL && *s != '\0')
     {
-      fputs (s, _stderr_r (ptr));
-      fputs (": ", _stderr_r (ptr));
+      ADD (s);
+      ADD (": ");
     }
 
   if ((error = _strerror_r (ptr, ptr->_errno, 1, &dummy)) != NULL)
-    fputs (error, _stderr_r (ptr));
+    ADD (error);
+
+#ifdef __SCLE
+  ADD ((fp->_flags & __SCLE) ? "\r\n" : "\n");
+#else
+  ADD ("\n");
+#endif
 
-  fputc ('\n', _stderr_r (ptr));
+  _newlib_flockfile_start (fp);
+  fflush (fp);
+  writev (fileno (fp), iov, iov_cnt);
+  _newlib_flockfile_end (fp);
 }
 
 #ifndef _REENT_ONLY
-- 
2.17.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.