aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2013-07-09 00:04:48 -0700
committerPaul Eggert2013-07-09 00:04:48 -0700
commit4ebbdd6712c1966406b40d2673464949775cbd7a (patch)
tree08667dd241629ca55c2c30ce19777bd7ec107cfa
parent584ee3fc72260acb3cc83f4d1a047b733a08ca17 (diff)
downloademacs-4ebbdd6712c1966406b40d2673464949775cbd7a.tar.gz
emacs-4ebbdd6712c1966406b40d2673464949775cbd7a.zip
Handle errno and exit status a bit more carefully.
* lib/ignore-value.h: Remove this gnulib-imported file. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * admin/merge-gnulib (GNULIB_MODULES): Remove ignore-value. * src/callproc.c (child_setup) [!DOS_NT]: Don't try to stuff an error number into an exit status. Instead, use EXIT_CANCELED. (child_setup) [!MSDOS]: Avoid possible deadlock with vfork. * src/callproc.c (relocate_fd): * src/emacs.c (close_output_streams, main): * src/process.c (create_process): * src/sysdep.c (sys_subshell) [!DOS_NT || !WINDOWSNT]: Use emacs_perror for simplicity. * src/callproc.c (relocate_fd, main): * src/sysdep.c (sys_subshell): Exit with EXIT_CANCELED etc., not 1, when exec setup fails. (shut_down_emacs): Use emacs_write, not write. * src/emacs.c, src/sysdep.c: Don't include <ignore-value.h>. * src/fileio.c (Fcopy_file, e_write): * src/nsterm.m (ns_select): * src/process.c (send_process): * src/sound.c (vox_write): Use emacs_write_sig, not emacs_write. * src/lisp.h (emacs_write_sig, emacs_perror): New decls. * src/process.h (EXIT_CANCELED), EXIT_CANNOT_INVOKE, EXIT_ENOENT): New constants. * src/sysdep.c (emacs_backtrace): Use emacs_write, not ignore_value of write. (emacs_full_write): New function. (emacs_write): Rewrite to use it. (emacswrite_sig, emacs_perror): New functions. * src/xrdb.c (fatal): Don't invoke perror, since errno might be garbage.
-rw-r--r--ChangeLog6
-rw-r--r--admin/ChangeLog5
-rwxr-xr-xadmin/merge-gnulib2
-rw-r--r--lib/gnulib.mk9
-rw-r--r--lib/ignore-value.h48
-rw-r--r--m4/gnulib-comp.m42
-rw-r--r--src/ChangeLog31
-rw-r--r--src/callproc.c21
-rw-r--r--src/emacs.c23
-rw-r--r--src/fileio.c12
-rw-r--r--src/lisp.h3
-rw-r--r--src/nsterm.m4
-rw-r--r--src/process.c10
-rw-r--r--src/process.h8
-rw-r--r--src/sound.c2
-rw-r--r--src/sysdep.c85
-rw-r--r--src/xrdb.c5
17 files changed, 151 insertions, 125 deletions
diff --git a/ChangeLog b/ChangeLog
index 05f87cf2733..c9571aec61c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
12013-07-09 Paul Eggert <eggert@cs.ucla.edu>
2
3 Handle errno and exit status a bit more carefully.
4 * lib/ignore-value.h: Remove this gnulib-imported file.
5 * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
6
12013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change) 72013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change)
2 8
3 * configure.ac (HAVE_IMAGEMAGICK): Check on NS also (Bug#14798). 9 * configure.ac (HAVE_IMAGEMAGICK): Check on NS also (Bug#14798).
diff --git a/admin/ChangeLog b/admin/ChangeLog
index f7d7cbb55d2..deb3059f8d2 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,3 +1,8 @@
12013-07-09 Paul Eggert <eggert@cs.ucla.edu>
2
3 Handle error numbers a bit more reliably.
4 * merge-gnulib (GNULIB_MODULES): Remove ignore-value.
5
12013-07-07 Paul Eggert <eggert@cs.ucla.edu> 62013-07-07 Paul Eggert <eggert@cs.ucla.edu>
2 7
3 Make file descriptors close-on-exec when possible (Bug#14803). 8 Make file descriptors close-on-exec when possible (Bug#14803).
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index f89fe7959fd..be4dfdd409c 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -31,7 +31,7 @@ GNULIB_MODULES='
31 dtoastr dtotimespec dup2 environ execinfo faccessat 31 dtoastr dtotimespec dup2 environ execinfo faccessat
32 fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync 32 fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync
33 getloadavg getopt-gnu gettime gettimeofday 33 getloadavg getopt-gnu gettime gettimeofday
34 ignore-value intprops largefile lstat 34 intprops largefile lstat
35 manywarnings memrchr mktime 35 manywarnings memrchr mktime
36 pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat 36 pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat
37 sig2str socklen stat-time stdalign stdarg stdbool stdio 37 sig2str socklen stat-time stdalign stdarg stdbool stdio
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 9f9ac6c0583..1bb1bea5f93 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
21# the same distribution terms as the rest of that program. 21# the same distribution terms as the rest of that program.
22# 22#
23# Generated by gnulib-tool. 23# Generated by gnulib-tool.
24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=binary-io --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings 24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=binary-io --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -485,13 +485,6 @@ EXTRA_libgnu_a_SOURCES += group-member.c
485 485
486## end gnulib module group-member 486## end gnulib module group-member
487 487
488## begin gnulib module ignore-value
489
490
491EXTRA_DIST += ignore-value.h
492
493## end gnulib module ignore-value
494
495## begin gnulib module intprops 488## begin gnulib module intprops
496 489
497 490
diff --git a/lib/ignore-value.h b/lib/ignore-value.h
deleted file mode 100644
index ebd6bf42f56..00000000000
--- a/lib/ignore-value.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/* ignore a function return without a compiler warning
2
3 Copyright (C) 2008-2013 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */
19
20/* Use "ignore_value" to avoid a warning when using a function declared with
21 gcc's warn_unused_result attribute, but for which you really do want to
22 ignore the result. Traditionally, people have used a "(void)" cast to
23 indicate that a function's return value is deliberately unused. However,
24 if the function is declared with __attribute__((warn_unused_result)),
25 gcc issues a warning even with the cast.
26
27 Caution: most of the time, you really should heed gcc's warning, and
28 check the return value. However, in those exceptional cases in which
29 you're sure you know what you're doing, use this function.
30
31 For the record, here's one of the ignorable warnings:
32 "copy.c:233: warning: ignoring return value of 'fchown',
33 declared with attribute warn_unused_result". */
34
35#ifndef _GL_IGNORE_VALUE_H
36#define _GL_IGNORE_VALUE_H
37
38/* The __attribute__((__warn_unused_result__)) feature
39 is available in gcc versions 3.4 and newer,
40 while the typeof feature has been available since 2.7 at least. */
41#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__)
42# define ignore_value(x) \
43 (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; }))
44#else
45# define ignore_value(x) ((void) (x))
46#endif
47
48#endif
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index e813692aeaf..a909927f319 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -80,7 +80,6 @@ AC_DEFUN([gl_EARLY],
80 # Code from module gettime: 80 # Code from module gettime:
81 # Code from module gettimeofday: 81 # Code from module gettimeofday:
82 # Code from module group-member: 82 # Code from module group-member:
83 # Code from module ignore-value:
84 # Code from module include_next: 83 # Code from module include_next:
85 # Code from module intprops: 84 # Code from module intprops:
86 # Code from module inttypes-incomplete: 85 # Code from module inttypes-incomplete:
@@ -798,7 +797,6 @@ AC_DEFUN([gl_FILE_LIST], [
798 lib/gettime.c 797 lib/gettime.c
799 lib/gettimeofday.c 798 lib/gettimeofday.c
800 lib/group-member.c 799 lib/group-member.c
801 lib/ignore-value.h
802 lib/intprops.h 800 lib/intprops.h
803 lib/inttypes.in.h 801 lib/inttypes.in.h
804 lib/lstat.c 802 lib/lstat.c
diff --git a/src/ChangeLog b/src/ChangeLog
index 9be0b59ee06..8b152f4a176 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,34 @@
12013-07-09 Paul Eggert <eggert@cs.ucla.edu>
2
3 Handle errno and exit status a bit more carefully.
4 * callproc.c (child_setup) [!DOS_NT]: Don't try to stuff an error
5 number into an exit status. Instead, use EXIT_CANCELED.
6 (child_setup) [!MSDOS]: Avoid possible deadlock with vfork.
7 * callproc.c (relocate_fd):
8 * emacs.c (close_output_streams, main):
9 * process.c (create_process):
10 * sysdep.c (sys_subshell) [!DOS_NT || !WINDOWSNT]:
11 Use emacs_perror for simplicity.
12 * callproc.c (relocate_fd, main):
13 * sysdep.c (sys_subshell):
14 Exit with EXIT_CANCELED etc., not 1, when exec setup fails.
15 (shut_down_emacs): Use emacs_write, not write.
16 * emacs.c, sysdep.c: Don't include <ignore-value.h>.
17 * fileio.c (Fcopy_file, e_write):
18 * nsterm.m (ns_select):
19 * process.c (send_process):
20 * sound.c (vox_write):
21 Use emacs_write_sig, not emacs_write.
22 * lisp.h (emacs_write_sig, emacs_perror): New decls.
23 * process.h (EXIT_CANCELED), EXIT_CANNOT_INVOKE, EXIT_ENOENT):
24 New constants.
25 * sysdep.c (emacs_backtrace): Use emacs_write, not ignore_value
26 of write.
27 (emacs_full_write): New function.
28 (emacs_write): Rewrite to use it.
29 (emacswrite_sig, emacs_perror): New functions.
30 * xrdb.c (fatal): Don't invoke perror, since errno might be garbage.
31
12013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change). 322013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change).
2 33
3 * image.c (imagemagick_load_image): Do not use MagickExportImagePixels 34 * image.c (imagemagick_load_image): Do not use MagickExportImagePixels
diff --git a/src/callproc.c b/src/callproc.c
index 369d6eda909..fc274f3d9c0 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1221,7 +1221,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1221 are changed between the check and this chdir, but we should 1221 are changed between the check and this chdir, but we should
1222 at least check. */ 1222 at least check. */
1223 if (chdir (temp) < 0) 1223 if (chdir (temp) < 0)
1224 _exit (errno); 1224 _exit (EXIT_CANCELED);
1225#else /* DOS_NT */ 1225#else /* DOS_NT */
1226 /* Get past the drive letter, so that d:/ is left alone. */ 1226 /* Get past the drive letter, so that d:/ is left alone. */
1227 if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2])) 1227 if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2]))
@@ -1366,10 +1366,12 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1366 1366
1367 execve (new_argv[0], new_argv, env); 1367 execve (new_argv[0], new_argv, env);
1368 1368
1369 emacs_write (1, "Can't exec program: ", 20); 1369 /* Don't output the program name here, as it can be arbitrarily long,
1370 emacs_write (1, new_argv[0], strlen (new_argv[0])); 1370 and a long write from a vforked child to its parent can cause a
1371 emacs_write (1, "\n", 1); 1371 deadlock. */
1372 _exit (1); 1372 emacs_perror ("child process");
1373
1374 _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1373 1375
1374#else /* MSDOS */ 1376#else /* MSDOS */
1375 pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); 1377 pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1395,13 +1397,8 @@ relocate_fd (int fd, int minfd)
1395 int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd); 1397 int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd);
1396 if (new == -1) 1398 if (new == -1)
1397 { 1399 {
1398 const char *message_1 = "Error while setting up child: "; 1400 emacs_perror ("while setting up child");
1399 const char *errmessage = strerror (errno); 1401 _exit (EXIT_CANCELED);
1400 const char *message_2 = "\n";
1401 emacs_write (2, message_1, strlen (message_1));
1402 emacs_write (2, errmessage, strlen (errmessage));
1403 emacs_write (2, message_2, strlen (message_2));
1404 _exit (1);
1405 } 1402 }
1406 emacs_close (fd); 1403 emacs_close (fd);
1407 return new; 1404 return new;
diff --git a/src/emacs.c b/src/emacs.c
index edf98d8cdb5..ee72095f705 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -28,7 +28,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include <unistd.h> 28#include <unistd.h>
29 29
30#include <close-stream.h> 30#include <close-stream.h>
31#include <ignore-value.h>
32 31
33#include "lisp.h" 32#include "lisp.h"
34 33
@@ -646,9 +645,7 @@ close_output_streams (void)
646{ 645{
647 if (close_stream (stdout) != 0) 646 if (close_stream (stdout) != 0)
648 { 647 {
649 fprintf (stderr, "Write error to standard output: %s\n", 648 emacs_perror ("Write error to standard output");
650 strerror (errno));
651 fflush (stderr);
652 _exit (EXIT_FAILURE); 649 _exit (EXIT_FAILURE);
653 } 650 }
654 651
@@ -789,7 +786,7 @@ main (int argc, char **argv)
789 execvp (argv[0], argv); 786 execvp (argv[0], argv);
790 787
791 /* If the exec fails, try to dump anyway. */ 788 /* If the exec fails, try to dump anyway. */
792 perror ("execvp"); 789 emacs_perror (argv[0]);
793 } 790 }
794#endif /* HAVE_PERSONALITY_LINUX32 */ 791#endif /* HAVE_PERSONALITY_LINUX32 */
795 792
@@ -1020,8 +1017,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1020 } 1017 }
1021 if (f < 0) 1018 if (f < 0)
1022 { 1019 {
1023 fprintf (stderr, "Cannot fork!\n"); 1020 emacs_perror ("fork");
1024 exit (1); 1021 exit (EXIT_CANCELED);
1025 } 1022 }
1026 1023
1027#ifdef DAEMON_MUST_EXEC 1024#ifdef DAEMON_MUST_EXEC
@@ -1038,14 +1035,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1038 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) 1035 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr))
1039 { 1036 {
1040 fprintf (stderr, "daemon: child name too long\n"); 1037 fprintf (stderr, "daemon: child name too long\n");
1041 exit (1); 1038 exit (EXIT_CANNOT_INVOKE);
1042 } 1039 }
1043 1040
1044 argv[skip_args] = fdStr; 1041 argv[skip_args] = fdStr;
1045 1042
1046 execvp (argv[0], argv); 1043 execvp (argv[0], argv);
1047 fprintf (stderr, "emacs daemon: exec failed: %d\n", errno); 1044 emacs_perror (argv[0]);
1048 exit (1); 1045 exit (errno == ENOENT : EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1049 } 1046 }
1050 1047
1051 /* In exec'd: parse special dname into pipe and name info. */ 1048 /* In exec'd: parse special dname into pipe and name info. */
@@ -1053,7 +1050,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1053 || strlen (dname_arg) < 1 || strlen (dname_arg) > 70) 1050 || strlen (dname_arg) < 1 || strlen (dname_arg) > 70)
1054 { 1051 {
1055 fprintf (stderr, "emacs daemon: daemon name absent or too long\n"); 1052 fprintf (stderr, "emacs daemon: daemon name absent or too long\n");
1056 exit (1); 1053 exit (EXIT_CANNOT_INVOKE);
1057 } 1054 }
1058 dname_arg2[0] = '\0'; 1055 dname_arg2[0] = '\0';
1059 sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]), 1056 sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]),
@@ -1916,8 +1913,8 @@ shut_down_emacs (int sig, Lisp_Object stuff)
1916 char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)]; 1913 char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)];
1917 int buflen = sprintf (buf, format, sig); 1914 int buflen = sprintf (buf, format, sig);
1918 char const *sig_desc = safe_strsignal (sig); 1915 char const *sig_desc = safe_strsignal (sig);
1919 ignore_value (write (STDERR_FILENO, buf, buflen)); 1916 emacs_write (STDERR_FILENO, buf, buflen);
1920 ignore_value (write (STDERR_FILENO, sig_desc, strlen (sig_desc))); 1917 emacs_write (STDERR_FILENO, sig_desc, strlen (sig_desc));
1921 } 1918 }
1922 } 1919 }
1923 } 1920 }
diff --git a/src/fileio.c b/src/fileio.c
index 89ae89e1613..d030c78c422 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2122,7 +2122,7 @@ entries (depending on how Emacs was built). */)
2122 immediate_quit = 1; 2122 immediate_quit = 1;
2123 QUIT; 2123 QUIT;
2124 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) 2124 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
2125 if (emacs_write (ofd, buf, n) != n) 2125 if (emacs_write_sig (ofd, buf, n) != n)
2126 report_file_error ("I/O error", Fcons (newname, Qnil)); 2126 report_file_error ("I/O error", Fcons (newname, Qnil));
2127 immediate_quit = 0; 2127 immediate_quit = 0;
2128 2128
@@ -5317,12 +5317,10 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
5317 5317
5318 if (coding->produced > 0) 5318 if (coding->produced > 0)
5319 { 5319 {
5320 coding->produced 5320 char *buf = (STRINGP (coding->dst_object)
5321 -= emacs_write (desc, 5321 ? SSDATA (coding->dst_object)
5322 STRINGP (coding->dst_object) 5322 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte));
5323 ? SSDATA (coding->dst_object) 5323 coding->produced -= emacs_write_sig (desc, buf, coding->produced);
5324 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
5325 coding->produced);
5326 5324
5327 if (coding->produced) 5325 if (coding->produced)
5328 return 0; 5326 return 0;
diff --git a/src/lisp.h b/src/lisp.h
index c7e36fbf9de..33e9309de34 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3998,6 +3998,7 @@ extern void init_process_emacs (void);
3998extern void syms_of_process (void); 3998extern void syms_of_process (void);
3999extern void setup_process_coding_systems (Lisp_Object); 3999extern void setup_process_coding_systems (Lisp_Object);
4000 4000
4001/* Defined in callproc.c. */
4001#ifndef DOS_NT 4002#ifndef DOS_NT
4002 _Noreturn 4003 _Noreturn
4003#endif 4004#endif
@@ -4090,6 +4091,8 @@ extern int emacs_open (const char *, int, int);
4090extern int emacs_close (int); 4091extern int emacs_close (int);
4091extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); 4092extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
4092extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); 4093extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t);
4094extern ptrdiff_t emacs_write_sig (int, char const *, ptrdiff_t);
4095extern void emacs_perror (char const *);
4093 4096
4094extern void unlock_all_files (void); 4097extern void unlock_all_files (void);
4095extern void lock_file (Lisp_Object); 4098extern void lock_file (Lisp_Object);
diff --git a/src/nsterm.m b/src/nsterm.m
index 074a5adf78c..d7cea5c189a 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3603,7 +3603,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3603 3603
3604 /* Inform fd_handler that select should be called */ 3604 /* Inform fd_handler that select should be called */
3605 c = 'g'; 3605 c = 'g';
3606 emacs_write (selfds[1], &c, 1); 3606 emacs_write_sig (selfds[1], &c, 1);
3607 } 3607 }
3608 else if (nr == 0 && timeout) 3608 else if (nr == 0 && timeout)
3609 { 3609 {
@@ -3636,7 +3636,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3636 if (nr > 0 && readfds) 3636 if (nr > 0 && readfds)
3637 { 3637 {
3638 c = 's'; 3638 c = 's';
3639 emacs_write (selfds[1], &c, 1); 3639 emacs_write_sig (selfds[1], &c, 1);
3640 } 3640 }
3641 unblock_input (); 3641 unblock_input ();
3642 3642
diff --git a/src/process.c b/src/process.c
index 1c210649024..36ca1cf6784 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1752,7 +1752,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1752 tcgetattr (xforkin, &t); 1752 tcgetattr (xforkin, &t);
1753 t.c_lflag = LDISC1; 1753 t.c_lflag = LDISC1;
1754 if (tcsetattr (xforkin, TCSANOW, &t) < 0) 1754 if (tcsetattr (xforkin, TCSANOW, &t) < 0)
1755 emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39); 1755 emacs_perror ("create_process/tcsetattr LDISC1");
1756 } 1756 }
1757#else 1757#else
1758#if defined (NTTYDISC) && defined (TIOCSETD) 1758#if defined (NTTYDISC) && defined (TIOCSETD)
@@ -1799,10 +1799,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1799 1799
1800 if (xforkin < 0) 1800 if (xforkin < 0)
1801 { 1801 {
1802 emacs_write (1, "Couldn't open the pty terminal ", 31); 1802 emacs_perror (pty_name);
1803 emacs_write (1, pty_name, strlen (pty_name)); 1803 _exit (EXIT_CANCELED);
1804 emacs_write (1, "\n", 1);
1805 _exit (1);
1806 } 1804 }
1807 1805
1808 } 1806 }
@@ -5503,7 +5501,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
5503 written = emacs_gnutls_write (p, cur_buf, cur_len); 5501 written = emacs_gnutls_write (p, cur_buf, cur_len);
5504 else 5502 else
5505#endif 5503#endif
5506 written = emacs_write (outfd, cur_buf, cur_len); 5504 written = emacs_write_sig (outfd, cur_buf, cur_len);
5507 rv = (written ? 0 : -1); 5505 rv = (written ? 0 : -1);
5508#ifdef ADAPTIVE_READ_BUFFERING 5506#ifdef ADAPTIVE_READ_BUFFERING
5509 if (p->read_output_delay > 0 5507 if (p->read_output_delay > 0
diff --git a/src/process.h b/src/process.h
index e7ee5f9adde..8ae33aebf39 100644
--- a/src/process.h
+++ b/src/process.h
@@ -198,6 +198,14 @@ extern Lisp_Object QCspeed;
198extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; 198extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
199extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; 199extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
200 200
201/* Exit statuses for GNU programs that exec other programs. */
202enum
203{
204 EXIT_CANCELED = 125, /* Internal error prior to exec attempt. */
205 EXIT_CANNOT_INVOKE = 126, /* Program located, but not usable. */
206 EXIT_ENOENT = 127 /* Could not find program to exec. */
207};
208
201/* Defined in callproc.c. */ 209/* Defined in callproc.c. */
202 210
203extern void block_child_signal (void); 211extern void block_child_signal (void);
diff --git a/src/sound.c b/src/sound.c
index 7f0ede5b398..5ce185ea60e 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -879,7 +879,7 @@ vox_init (struct sound_device *sd)
879static void 879static void
880vox_write (struct sound_device *sd, const char *buffer, ptrdiff_t nbytes) 880vox_write (struct sound_device *sd, const char *buffer, ptrdiff_t nbytes)
881{ 881{
882 if (emacs_write (sd->fd, buffer, nbytes) != nbytes) 882 if (emacs_write_sig (sd->fd, buffer, nbytes) != nbytes)
883 sound_perror ("Error writing to sound device"); 883 sound_perror ("Error writing to sound device");
884} 884}
885 885
diff --git a/src/sysdep.c b/src/sysdep.c
index faca7fae461..6346b0bbfcd 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -31,7 +31,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31#include <unistd.h> 31#include <unistd.h>
32 32
33#include <c-ctype.h> 33#include <c-ctype.h>
34#include <ignore-value.h>
35#include <utimens.h> 34#include <utimens.h>
36 35
37#include "lisp.h" 36#include "lisp.h"
@@ -538,8 +537,8 @@ sys_subshell (void)
538 if (str && chdir ((char *) str) != 0) 537 if (str && chdir ((char *) str) != 0)
539 { 538 {
540#ifndef DOS_NT 539#ifndef DOS_NT
541 ignore_value (write (1, "Can't chdir\n", 12)); 540 emacs_perror ((char *) str);
542 _exit (1); 541 _exit (EXIT_CANCELED);
543#endif 542#endif
544 } 543 }
545 544
@@ -570,8 +569,8 @@ sys_subshell (void)
570 write (1, "Can't execute subshell", 22); 569 write (1, "Can't execute subshell", 22);
571#else /* not WINDOWSNT */ 570#else /* not WINDOWSNT */
572 execlp (sh, sh, (char *) 0); 571 execlp (sh, sh, (char *) 0);
573 ignore_value (write (1, "Can't execute subshell", 22)); 572 emacs_perror (sh);
574 _exit (1); 573 _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
575#endif /* not WINDOWSNT */ 574#endif /* not WINDOWSNT */
576#endif /* not MSDOS */ 575#endif /* not MSDOS */
577 } 576 }
@@ -2134,10 +2133,10 @@ emacs_backtrace (int backtrace_limit)
2134 2133
2135 if (npointers) 2134 if (npointers)
2136 { 2135 {
2137 ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); 2136 emacs_write (STDERR_FILENO, "\nBacktrace:\n", 12);
2138 backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); 2137 backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
2139 if (bounded_limit < npointers) 2138 if (bounded_limit < npointers)
2140 ignore_value (write (STDERR_FILENO, "...\n", 4)); 2139 emacs_write (STDERR_FILENO, "...\n", 4);
2141 } 2140 }
2142} 2141}
2143 2142
@@ -2246,27 +2245,26 @@ emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
2246} 2245}
2247 2246
2248/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted 2247/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
2249 or if a partial write occurs. Return the number of bytes written, setting 2248 or if a partial write occurs. If interrupted, process pending
2249 signals if PROCESS SIGNALS. Return the number of bytes written, setting
2250 errno if this is less than NBYTE. */ 2250 errno if this is less than NBYTE. */
2251ptrdiff_t 2251static ptrdiff_t
2252emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) 2252emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte,
2253 bool process_signals)
2253{ 2254{
2254 ssize_t rtnval; 2255 ptrdiff_t bytes_written = 0;
2255 ptrdiff_t bytes_written;
2256
2257 bytes_written = 0;
2258 2256
2259 while (nbyte > 0) 2257 while (nbyte > 0)
2260 { 2258 {
2261 rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT)); 2259 ssize_t n = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
2262 2260
2263 if (rtnval < 0) 2261 if (n < 0)
2264 { 2262 {
2265 if (errno == EINTR) 2263 if (errno == EINTR)
2266 { 2264 {
2267 /* I originally used `QUIT' but that might causes files to 2265 /* I originally used `QUIT' but that might causes files to
2268 be truncated if you hit C-g in the middle of it. --Stef */ 2266 be truncated if you hit C-g in the middle of it. --Stef */
2269 if (pending_signals) 2267 if (process_signals && pending_signals)
2270 process_pending_signals (); 2268 process_pending_signals ();
2271 continue; 2269 continue;
2272 } 2270 }
@@ -2274,12 +2272,57 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
2274 break; 2272 break;
2275 } 2273 }
2276 2274
2277 buf += rtnval; 2275 buf += n;
2278 nbyte -= rtnval; 2276 nbyte -= n;
2279 bytes_written += rtnval; 2277 bytes_written += n;
2280 } 2278 }
2281 2279
2282 return (bytes_written); 2280 return bytes_written;
2281}
2282
2283/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if
2284 interrupted or if a partial write occurs. Return the number of
2285 bytes written, setting errno if this is less than NBYTE. */
2286ptrdiff_t
2287emacs_write (int fildes, char const *buf, ptrdiff_t nbyte)
2288{
2289 return emacs_full_write (fildes, buf, nbyte, 0);
2290}
2291
2292/* Like emacs_write, but also process pending signals if interrupted. */
2293ptrdiff_t
2294emacs_write_sig (int fildes, char const *buf, ptrdiff_t nbyte)
2295{
2296 return emacs_full_write (fildes, buf, nbyte, 1);
2297}
2298
2299/* Write a diagnostic to standard error that contains MESSAGE and a
2300 string derived from errno. Preserve errno. Do not buffer stderr.
2301 Do not process pending signals if interrupted. */
2302void
2303emacs_perror (char const *message)
2304{
2305 int err = errno;
2306 char const *error_string = strerror (err);
2307 char const *command = (initial_argv && initial_argv[0]
2308 ? initial_argv[0] : "emacs");
2309 /* Write it out all at once, if it's short; this is less likely to
2310 be interleaved with other output. */
2311 char buf[BUFSIZ];
2312 int nbytes = snprintf (buf, sizeof buf, "%s: %s: %s\n",
2313 command, message, error_string);
2314 if (0 <= nbytes && nbytes < BUFSIZ)
2315 emacs_write (STDERR_FILENO, buf, nbytes);
2316 else
2317 {
2318 emacs_write (STDERR_FILENO, command, strlen (command));
2319 emacs_write (STDERR_FILENO, ": ", 2);
2320 emacs_write (STDERR_FILENO, message, strlen (message));
2321 emacs_write (STDERR_FILENO, ": ", 2);
2322 emacs_write (STDERR_FILENO, error_string, strlen (error_string));
2323 emacs_write (STDERR_FILENO, "\n", 1);
2324 }
2325 errno = err;
2283} 2326}
2284 2327
2285/* Return a struct timeval that is roughly equivalent to T. 2328/* Return a struct timeval that is roughly equivalent to T.
diff --git a/src/xrdb.c b/src/xrdb.c
index c25c25d6f33..7c9cd53fa8c 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -634,10 +634,7 @@ member (char *elt, List list)
634static void 634static void
635fatal (char *msg, char *prog) 635fatal (char *msg, char *prog)
636{ 636{
637 if (errno) 637 fprintf (stderr, msg, prog);
638 perror (prog);
639
640 (void) fprintf (stderr, msg, prog);
641 exit (1); 638 exit (1);
642} 639}
643 640