aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-07-09 00:04:48 -0700
committerPaul Eggert2013-07-09 00:04:48 -0700
commit4ebbdd6712c1966406b40d2673464949775cbd7a (patch)
tree08667dd241629ca55c2c30ce19777bd7ec107cfa /src
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.
Diffstat (limited to 'src')
-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
11 files changed, 138 insertions, 66 deletions
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