about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Ackersviller <packersv@users.sourceforge.net>2007-12-04 01:24:20 +0000
committerPaul Ackersviller <packersv@users.sourceforge.net>2007-12-04 01:24:20 +0000
commit98b0c9dfba7e5c413668f833934dace92372bbe3 (patch)
tree724fbd8a7d58a1619b875dd619bdfbf5180e11b0
parenta7ed374430f5da323bd69ee3bf21035c18698582 (diff)
downloadzsh-98b0c9dfba7e5c413668f833934dace92372bbe3.tar.gz
zsh-98b0c9dfba7e5c413668f833934dace92372bbe3.tar.xz
zsh-98b0c9dfba7e5c413668f833934dace92372bbe3.zip
Slight tweak of pws's 24148: attempt to use strerror_r() to make
error messages in signal handle safer.
-rw-r--r--Src/utils.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/Src/utils.c b/Src/utils.c
index e1459cb2b..a71eddf16 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -129,6 +129,13 @@ zz_plural_z_alpha(void)
 void
 zerrmsg(const char *fmt, const char *str, int num)
 {
+#ifdef HAVE_STRERROR_R
+#define ERRBUFSIZE (80)
+    int olderrno;
+    char errbuf[ERRBUFSIZE];
+#endif
+    char *errmsg;
+
     if ((unset(SHINSTDIN) || locallevel) && lineno)
 	fprintf(stderr, "%ld: ", (long)lineno);
     else
@@ -166,12 +173,39 @@ zerrmsg(const char *fmt, const char *str, int num)
 		    errflag = 1;
 		    return;
 		}
+#ifdef HAVE_STRERROR_R
+		/*
+		 * There are two incompatible strerror_r()s floating round.
+		 * The GNU extension refuses to copy the message into the
+		 * buffer if it can return a constant string.  To suppress it
+		 * we need to define _XOPEN_SOURCE to 600.  I don't dare do
+		 * this because we're already depending on _GNU_SOURCE.  So
+		 * try to handle both by looking for errno being set (for the
+		 * standard version failing) or errbuf being left untouched
+		 * (for the GNU version).  One presumes that if strerror_r()
+		 * didn't copy anything to errbuf, then it's safe to
+		 * call strerror() to get the string.
+		 *
+		 * This is a mess, but it's about a decade and half
+		 * too late to shirk from messes in the source.
+		 */
+		olderrno = errno;
+		errno = 0;
+		errbuf[0] = '\0';
+		strerror_r(num, errbuf, ERRBUFSIZE);
+		if (errno || errbuf[0] == '\0')
+		    errmsg = strerror(num);
+		else
+		    errmsg = errbuf;
+		errno = olderrno;
+#else
+		errmsg = strerror(num);
+#endif
 		/* If the message is not about I/O problems, it looks better *
 		 * if we uncapitalize the first letter of the message        */
 		if (num == EIO)
-		    fputs(strerror(num), stderr);
+		    fputs(errmsg, stderr);
 		else {
-		    char *errmsg = strerror(num);
 		    fputc(tulower(errmsg[0]), stderr);
 		    fputs(errmsg + 1, stderr);
 		}