GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#include <float.h>
#include <ftoastr.h>
+#ifdef WINDOWSNT
+# include <sys/socket.h> /* for F_DUPFD_CLOEXEC */
+#endif
+
struct terminal;
/* Avoid actual stack overflow in print. */
static void
printchar_to_stream (unsigned int ch, FILE *stream)
{
- Lisp_Object dv IF_LINT (= Qnil);
+ Lisp_Object dv UNINIT;
ptrdiff_t i = 0, n = 1;
Lisp_Object coding_system = Vlocale_coding_system;
bool encode_p = false;
print_output_debug_flag = x;
}
-#if defined (GNU_LINUX)
-
-/* This functionality is not vitally important in general, so we rely on
- non-portable ability to use stderr as lvalue. */
-
-#define WITH_REDIRECT_DEBUGGING_OUTPUT 1
-
-static FILE *initial_stderr_stream = NULL;
-
DEFUN ("redirect-debugging-output", Fredirect_debugging_output, Sredirect_debugging_output,
1, 2,
"FDebug output file: \nP",
append to existing target file. */)
(Lisp_Object file, Lisp_Object append)
{
- if (initial_stderr_stream != NULL)
- {
- block_input ();
- fclose (stderr);
- unblock_input ();
- }
- stderr = initial_stderr_stream;
- initial_stderr_stream = NULL;
+ /* If equal to STDERR_FILENO, stderr has not been duplicated and is OK as-is.
+ Otherwise, this is a close-on-exec duplicate of the original stderr. */
+ static int stderr_dup = STDERR_FILENO;
+ int fd = stderr_dup;
- if (STRINGP (file))
+ if (! NILP (file))
{
file = Fexpand_file_name (file, Qnil);
- initial_stderr_stream = stderr;
- stderr = emacs_fopen (SSDATA (file), NILP (append) ? "w" : "a");
- if (stderr == NULL)
+
+ if (stderr_dup == STDERR_FILENO)
{
- stderr = initial_stderr_stream;
- initial_stderr_stream = NULL;
- report_file_error ("Cannot open debugging output stream", file);
+ int n = fcntl (STDERR_FILENO, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
+ if (n < 0)
+ report_file_error ("dup", file);
+ stderr_dup = n;
}
+
+ fd = emacs_open (SSDATA (ENCODE_FILE (file)),
+ (O_WRONLY | O_CREAT
+ | (! NILP (append) ? O_APPEND : O_TRUNC)),
+ 0666);
+ if (fd < 0)
+ report_file_error ("Cannot open debugging output stream", file);
}
+
+ fflush (stderr);
+ if (dup2 (fd, STDERR_FILENO) < 0)
+ report_file_error ("dup2", file);
+ if (fd != stderr_dup)
+ emacs_close (fd);
return Qnil;
}
-#endif /* GNU_LINUX */
/* This is the interface for debugging printing. */
DEFVAR_BOOL ("print-escape-nonascii", print_escape_nonascii,
doc: /* Non-nil means print unibyte non-ASCII chars in strings as \\OOO.
-(OOO is the octal representation of the character code.)
+\(OOO is the octal representation of the character code.)
Only single-byte characters are affected, and only in `prin1'.
When the output goes in a multibyte buffer, this feature is
enabled regardless of the value of the variable. */);
DEFVAR_BOOL ("print-escape-multibyte", print_escape_multibyte,
doc: /* Non-nil means print multibyte characters in strings as \\xXXXX.
-(XXXX is the hex representation of the character code.)
+\(XXXX is the hex representation of the character code.)
This affects only `prin1'. */);
print_escape_multibyte = 0;
defsubr (&Sprint);
defsubr (&Sterpri);
defsubr (&Swrite_char);
-#ifdef WITH_REDIRECT_DEBUGGING_OUTPUT
defsubr (&Sredirect_debugging_output);
-#endif
DEFSYM (Qprint_escape_newlines, "print-escape-newlines");
DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte");