diff options
| author | Paul Eggert | 2016-04-04 09:36:30 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-04-04 09:44:19 -0700 |
| commit | 6bccb19c9bef1189c8e853ff7cc16b889a3a57e3 (patch) | |
| tree | 9555d6605362ec0c452b343d549d2af3c983415d /src | |
| parent | a11756ad0e2ee719266c0081150c20996cce8e0d (diff) | |
| download | emacs-6bccb19c9bef1189c8e853ff7cc16b889a3a57e3.tar.gz emacs-6bccb19c9bef1189c8e853ff7cc16b889a3a57e3.zip | |
Port redirect-debugging-output to non-GNU/Linux
Problem reported by Kylie McClain for musl in:
http://lists.gnu.org/archive/html/emacs-devel/2016-03/msg01592.html
* etc/DEBUG, etc/NEWS: Mention this.
* src/callproc.c (child_setup) [!MSDOS]:
* src/dispnew.c (init_display):
* src/emacs.c (main, Fdaemon_initialized):
* src/minibuf.c (read_minibuf_noninteractive):
* src/regex.c (xmalloc, xrealloc):
Prefer symbolic names like STDERR_FILENO to magic numbers like 2,
to make file-descriptor manipulation easier to follow.
* src/emacs.c (relocate_fd) [!WINDOWSNT]: Remove; no longer needed
now that we make sure stdin, stdout and stderr are open. All uses
removed.
(main): Make sure standard FDs are OK. Prefer symbolic names like
EXIT_FAILURE to magic numbers like 1. Use bool for boolean.
* src/lisp.h (init_standard_fds): New decl.
* src/print.c (WITH_REDIRECT_DEBUGGING_OUTPUT) [GNU_LINUX]:
Remove; no longer needed.
(Fredirect_debugging_output): Define on all platforms, not just
GNU/Linux. Redirect file descriptor, not stream, so that the code
works even if stderr is not an lvalue. Report an error if the
file arg is neither a string nor nil.
(syms_of_print): Always define redirect-debugging-output.
* src/sysdep.c (force_open, init_standard_fds): New functions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/callproc.c | 58 | ||||
| -rw-r--r-- | src/dispnew.c | 2 | ||||
| -rw-r--r-- | src/emacs.c | 28 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/minibuf.c | 12 | ||||
| -rw-r--r-- | src/print.c | 51 | ||||
| -rw-r--r-- | src/regex.c | 4 | ||||
| -rw-r--r-- | src/sysdep.c | 29 |
8 files changed, 81 insertions, 104 deletions
diff --git a/src/callproc.c b/src/callproc.c index db602f538c9..8578556b695 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -1078,10 +1078,6 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r | |||
| 1078 | return unbind_to (count, val); | 1078 | return unbind_to (count, val); |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 1081 | #ifndef WINDOWSNT | ||
| 1082 | static int relocate_fd (int fd, int minfd); | ||
| 1083 | #endif | ||
| 1084 | |||
| 1085 | static char ** | 1081 | static char ** |
| 1086 | add_env (char **env, char **new_env, char *string) | 1082 | add_env (char **env, char **new_env, char *string) |
| 1087 | { | 1083 | { |
| @@ -1310,37 +1306,14 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1310 | return cpid; | 1306 | return cpid; |
| 1311 | 1307 | ||
| 1312 | #else /* not WINDOWSNT */ | 1308 | #else /* not WINDOWSNT */ |
| 1313 | /* Make sure that in, out, and err are not actually already in | ||
| 1314 | descriptors zero, one, or two; this could happen if Emacs is | ||
| 1315 | started with its standard in, out, or error closed, as might | ||
| 1316 | happen under X. */ | ||
| 1317 | { | ||
| 1318 | int oin = in, oout = out; | ||
| 1319 | |||
| 1320 | /* We have to avoid relocating the same descriptor twice! */ | ||
| 1321 | |||
| 1322 | in = relocate_fd (in, 3); | ||
| 1323 | |||
| 1324 | if (out == oin) | ||
| 1325 | out = in; | ||
| 1326 | else | ||
| 1327 | out = relocate_fd (out, 3); | ||
| 1328 | |||
| 1329 | if (err == oin) | ||
| 1330 | err = in; | ||
| 1331 | else if (err == oout) | ||
| 1332 | err = out; | ||
| 1333 | else | ||
| 1334 | err = relocate_fd (err, 3); | ||
| 1335 | } | ||
| 1336 | 1309 | ||
| 1337 | #ifndef MSDOS | 1310 | #ifndef MSDOS |
| 1338 | /* Redirect file descriptors and clear the close-on-exec flag on the | 1311 | /* Redirect file descriptors and clear the close-on-exec flag on the |
| 1339 | redirected ones. IN, OUT, and ERR are close-on-exec so they | 1312 | redirected ones. IN, OUT, and ERR are close-on-exec so they |
| 1340 | need not be closed explicitly. */ | 1313 | need not be closed explicitly. */ |
| 1341 | dup2 (in, 0); | 1314 | dup2 (in, STDIN_FILENO); |
| 1342 | dup2 (out, 1); | 1315 | dup2 (out, STDOUT_FILENO); |
| 1343 | dup2 (err, 2); | 1316 | dup2 (err, STDERR_FILENO); |
| 1344 | 1317 | ||
| 1345 | setpgid (0, 0); | 1318 | setpgid (0, 0); |
| 1346 | tcsetpgrp (0, pid); | 1319 | tcsetpgrp (0, pid); |
| @@ -1359,31 +1332,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1359 | #endif /* not WINDOWSNT */ | 1332 | #endif /* not WINDOWSNT */ |
| 1360 | } | 1333 | } |
| 1361 | 1334 | ||
| 1362 | #ifndef WINDOWSNT | ||
| 1363 | /* Move the file descriptor FD so that its number is not less than MINFD. | ||
| 1364 | If the file descriptor is moved at all, the original is closed on MSDOS, | ||
| 1365 | but not elsewhere as the caller will close it anyway. */ | ||
| 1366 | static int | ||
| 1367 | relocate_fd (int fd, int minfd) | ||
| 1368 | { | ||
| 1369 | if (fd >= minfd) | ||
| 1370 | return fd; | ||
| 1371 | else | ||
| 1372 | { | ||
| 1373 | int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd); | ||
| 1374 | if (new == -1) | ||
| 1375 | { | ||
| 1376 | emacs_perror ("while setting up child"); | ||
| 1377 | _exit (EXIT_CANCELED); | ||
| 1378 | } | ||
| 1379 | #ifdef MSDOS | ||
| 1380 | emacs_close (fd); | ||
| 1381 | #endif | ||
| 1382 | return new; | ||
| 1383 | } | ||
| 1384 | } | ||
| 1385 | #endif /* not WINDOWSNT */ | ||
| 1386 | |||
| 1387 | static bool | 1335 | static bool |
| 1388 | getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value, | 1336 | getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value, |
| 1389 | ptrdiff_t *valuelen, Lisp_Object env) | 1337 | ptrdiff_t *valuelen, Lisp_Object env) |
diff --git a/src/dispnew.c b/src/dispnew.c index 3a0532a693b..51caa5b10e7 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -6038,7 +6038,7 @@ init_display (void) | |||
| 6038 | #endif | 6038 | #endif |
| 6039 | 6039 | ||
| 6040 | /* If no window system has been specified, try to use the terminal. */ | 6040 | /* If no window system has been specified, try to use the terminal. */ |
| 6041 | if (! isatty (0)) | 6041 | if (! isatty (STDIN_FILENO)) |
| 6042 | fatal ("standard input is not a tty"); | 6042 | fatal ("standard input is not a tty"); |
| 6043 | 6043 | ||
| 6044 | #ifdef WINDOWSNT | 6044 | #ifdef WINDOWSNT |
diff --git a/src/emacs.c b/src/emacs.c index 95d1905ae22..c21c9e3971c 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -721,6 +721,7 @@ main (int argc, char **argv) | |||
| 721 | unexec_init_emacs_zone (); | 721 | unexec_init_emacs_zone (); |
| 722 | #endif | 722 | #endif |
| 723 | 723 | ||
| 724 | init_standard_fds (); | ||
| 724 | atexit (close_output_streams); | 725 | atexit (close_output_streams); |
| 725 | 726 | ||
| 726 | #ifdef HAVE_MODULES | 727 | #ifdef HAVE_MODULES |
| @@ -899,24 +900,25 @@ main (int argc, char **argv) | |||
| 899 | char *term; | 900 | char *term; |
| 900 | if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args)) | 901 | if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args)) |
| 901 | { | 902 | { |
| 902 | int result; | 903 | emacs_close (STDIN_FILENO); |
| 903 | emacs_close (0); | 904 | emacs_close (STDOUT_FILENO); |
| 904 | emacs_close (1); | 905 | int result = emacs_open (term, O_RDWR, 0); |
| 905 | result = emacs_open (term, O_RDWR, 0); | 906 | if (result != STDIN_FILENO |
| 906 | if (result < 0 || fcntl (0, F_DUPFD_CLOEXEC, 1) < 0) | 907 | || (fcntl (STDIN_FILENO, F_DUPFD_CLOEXEC, STDOUT_FILENO) |
| 908 | != STDOUT_FILENO)) | ||
| 907 | { | 909 | { |
| 908 | char *errstring = strerror (errno); | 910 | char *errstring = strerror (errno); |
| 909 | fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring); | 911 | fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring); |
| 910 | exit (1); | 912 | exit (EXIT_FAILURE); |
| 911 | } | 913 | } |
| 912 | if (! isatty (0)) | 914 | if (! isatty (STDIN_FILENO)) |
| 913 | { | 915 | { |
| 914 | fprintf (stderr, "%s: %s: not a tty\n", argv[0], term); | 916 | fprintf (stderr, "%s: %s: not a tty\n", argv[0], term); |
| 915 | exit (1); | 917 | exit (EXIT_FAILURE); |
| 916 | } | 918 | } |
| 917 | fprintf (stderr, "Using %s\n", term); | 919 | fprintf (stderr, "Using %s\n", term); |
| 918 | #ifdef HAVE_WINDOW_SYSTEM | 920 | #ifdef HAVE_WINDOW_SYSTEM |
| 919 | inhibit_window_system = 1; /* -t => -nw */ | 921 | inhibit_window_system = true; /* -t => -nw */ |
| 920 | #endif | 922 | #endif |
| 921 | } | 923 | } |
| 922 | else | 924 | else |
| @@ -1209,7 +1211,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1209 | /* Started from GUI? */ | 1211 | /* Started from GUI? */ |
| 1210 | /* FIXME: Do the right thing if getenv returns NULL, or if | 1212 | /* FIXME: Do the right thing if getenv returns NULL, or if |
| 1211 | chdir fails. */ | 1213 | chdir fails. */ |
| 1212 | if (! inhibit_window_system && ! isatty (0) && ! ch_to_dir) | 1214 | if (! inhibit_window_system && ! isatty (STDIN_FILENO) && ! ch_to_dir) |
| 1213 | chdir (getenv ("HOME")); | 1215 | chdir (getenv ("HOME")); |
| 1214 | if (skip_args < argc) | 1216 | if (skip_args < argc) |
| 1215 | { | 1217 | { |
| @@ -2357,9 +2359,9 @@ from the parent process and its tty file descriptors. */) | |||
| 2357 | /* Get rid of stdin, stdout and stderr. */ | 2359 | /* Get rid of stdin, stdout and stderr. */ |
| 2358 | nfd = emacs_open ("/dev/null", O_RDWR, 0); | 2360 | nfd = emacs_open ("/dev/null", O_RDWR, 0); |
| 2359 | err |= nfd < 0; | 2361 | err |= nfd < 0; |
| 2360 | err |= dup2 (nfd, 0) < 0; | 2362 | err |= dup2 (nfd, STDIN_FILENO) < 0; |
| 2361 | err |= dup2 (nfd, 1) < 0; | 2363 | err |= dup2 (nfd, STDOUT_FILENO) < 0; |
| 2362 | err |= dup2 (nfd, 2) < 0; | 2364 | err |= dup2 (nfd, STDERR_FILENO) < 0; |
| 2363 | err |= emacs_close (nfd) != 0; | 2365 | err |= emacs_close (nfd) != 0; |
| 2364 | 2366 | ||
| 2365 | /* Closing the pipe will notify the parent that it can exit. | 2367 | /* Closing the pipe will notify the parent that it can exit. |
diff --git a/src/lisp.h b/src/lisp.h index 7c8b452dd5f..65335fbc052 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4248,6 +4248,7 @@ struct tty_display_info; | |||
| 4248 | struct terminal; | 4248 | struct terminal; |
| 4249 | 4249 | ||
| 4250 | /* Defined in sysdep.c. */ | 4250 | /* Defined in sysdep.c. */ |
| 4251 | extern void init_standard_fds (void); | ||
| 4251 | extern char *emacs_get_current_dir_name (void); | 4252 | extern char *emacs_get_current_dir_name (void); |
| 4252 | extern void stuff_char (char c); | 4253 | extern void stuff_char (char c); |
| 4253 | extern void init_foreground_group (void); | 4254 | extern void init_foreground_group (void); |
diff --git a/src/minibuf.c b/src/minibuf.c index 238a04a8ad2..41814c2b54b 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -194,7 +194,7 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, | |||
| 194 | int c; | 194 | int c; |
| 195 | unsigned char hide_char = 0; | 195 | unsigned char hide_char = 0; |
| 196 | struct emacs_tty etty; | 196 | struct emacs_tty etty; |
| 197 | bool etty_valid; | 197 | bool etty_valid IF_LINT (= false); |
| 198 | 198 | ||
| 199 | /* Check, whether we need to suppress echoing. */ | 199 | /* Check, whether we need to suppress echoing. */ |
| 200 | if (CHARACTERP (Vread_hide_char)) | 200 | if (CHARACTERP (Vread_hide_char)) |
| @@ -203,10 +203,10 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, | |||
| 203 | /* Manipulate tty. */ | 203 | /* Manipulate tty. */ |
| 204 | if (hide_char) | 204 | if (hide_char) |
| 205 | { | 205 | { |
| 206 | etty_valid = emacs_get_tty (fileno (stdin), &etty) == 0; | 206 | etty_valid = emacs_get_tty (STDIN_FILENO, &etty) == 0; |
| 207 | if (etty_valid) | 207 | if (etty_valid) |
| 208 | set_binary_mode (fileno (stdin), O_BINARY); | 208 | set_binary_mode (STDIN_FILENO, O_BINARY); |
| 209 | suppress_echo_on_tty (fileno (stdin)); | 209 | suppress_echo_on_tty (STDIN_FILENO); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | fwrite (SDATA (prompt), 1, SBYTES (prompt), stdout); | 212 | fwrite (SDATA (prompt), 1, SBYTES (prompt), stdout); |
| @@ -240,8 +240,8 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, | |||
| 240 | fprintf (stdout, "\n"); | 240 | fprintf (stdout, "\n"); |
| 241 | if (etty_valid) | 241 | if (etty_valid) |
| 242 | { | 242 | { |
| 243 | emacs_set_tty (fileno (stdin), &etty, 0); | 243 | emacs_set_tty (STDIN_FILENO, &etty, 0); |
| 244 | set_binary_mode (fileno (stdin), O_TEXT); | 244 | set_binary_mode (STDIN_FILENO, O_TEXT); |
| 245 | } | 245 | } |
| 246 | } | 246 | } |
| 247 | 247 | ||
diff --git a/src/print.c b/src/print.c index 2b53d7580b1..db2918ff478 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -775,15 +775,6 @@ debug_output_compilation_hack (bool x) | |||
| 775 | print_output_debug_flag = x; | 775 | print_output_debug_flag = x; |
| 776 | } | 776 | } |
| 777 | 777 | ||
| 778 | #if defined (GNU_LINUX) | ||
| 779 | |||
| 780 | /* This functionality is not vitally important in general, so we rely on | ||
| 781 | non-portable ability to use stderr as lvalue. */ | ||
| 782 | |||
| 783 | #define WITH_REDIRECT_DEBUGGING_OUTPUT 1 | ||
| 784 | |||
| 785 | static FILE *initial_stderr_stream = NULL; | ||
| 786 | |||
| 787 | DEFUN ("redirect-debugging-output", Fredirect_debugging_output, Sredirect_debugging_output, | 778 | DEFUN ("redirect-debugging-output", Fredirect_debugging_output, Sredirect_debugging_output, |
| 788 | 1, 2, | 779 | 1, 2, |
| 789 | "FDebug output file: \nP", | 780 | "FDebug output file: \nP", |
| @@ -793,30 +784,38 @@ Optional arg APPEND non-nil (interactively, with prefix arg) means | |||
| 793 | append to existing target file. */) | 784 | append to existing target file. */) |
| 794 | (Lisp_Object file, Lisp_Object append) | 785 | (Lisp_Object file, Lisp_Object append) |
| 795 | { | 786 | { |
| 796 | if (initial_stderr_stream != NULL) | 787 | /* If equal to STDERR_FILENO, stderr has not been duplicated and is OK as-is. |
| 797 | { | 788 | Otherwise, this is a close-on-exec duplicate of the original stderr. */ |
| 798 | block_input (); | 789 | static int stderr_dup = STDERR_FILENO; |
| 799 | fclose (stderr); | 790 | int fd = stderr_dup; |
| 800 | unblock_input (); | ||
| 801 | } | ||
| 802 | stderr = initial_stderr_stream; | ||
| 803 | initial_stderr_stream = NULL; | ||
| 804 | 791 | ||
| 805 | if (STRINGP (file)) | 792 | if (! NILP (file)) |
| 806 | { | 793 | { |
| 807 | file = Fexpand_file_name (file, Qnil); | 794 | file = Fexpand_file_name (file, Qnil); |
| 808 | initial_stderr_stream = stderr; | 795 | |
| 809 | stderr = emacs_fopen (SSDATA (file), NILP (append) ? "w" : "a"); | 796 | if (stderr_dup == STDERR_FILENO) |
| 810 | if (stderr == NULL) | ||
| 811 | { | 797 | { |
| 812 | stderr = initial_stderr_stream; | 798 | int n = fcntl (STDERR_FILENO, F_DUPFD_CLOEXEC, STDERR_FILENO + 1); |
| 813 | initial_stderr_stream = NULL; | 799 | if (n < 0) |
| 814 | report_file_error ("Cannot open debugging output stream", file); | 800 | report_file_error ("dup", file); |
| 801 | stderr_dup = n; | ||
| 815 | } | 802 | } |
| 803 | |||
| 804 | fd = emacs_open (SSDATA (ENCODE_FILE (file)), | ||
| 805 | (O_WRONLY | O_CREAT | ||
| 806 | | (! NILP (append) ? O_APPEND : O_TRUNC)), | ||
| 807 | 0666); | ||
| 808 | if (fd < 0) | ||
| 809 | report_file_error ("Cannot open debugging output stream", file); | ||
| 816 | } | 810 | } |
| 811 | |||
| 812 | fflush (stderr); | ||
| 813 | if (dup2 (fd, STDERR_FILENO) < 0) | ||
| 814 | report_file_error ("dup2", file); | ||
| 815 | if (fd != stderr_dup) | ||
| 816 | emacs_close (fd); | ||
| 817 | return Qnil; | 817 | return Qnil; |
| 818 | } | 818 | } |
| 819 | #endif /* GNU_LINUX */ | ||
| 820 | 819 | ||
| 821 | 820 | ||
| 822 | /* This is the interface for debugging printing. */ | 821 | /* This is the interface for debugging printing. */ |
| @@ -2305,9 +2304,7 @@ priorities. */); | |||
| 2305 | defsubr (&Sprint); | 2304 | defsubr (&Sprint); |
| 2306 | defsubr (&Sterpri); | 2305 | defsubr (&Sterpri); |
| 2307 | defsubr (&Swrite_char); | 2306 | defsubr (&Swrite_char); |
| 2308 | #ifdef WITH_REDIRECT_DEBUGGING_OUTPUT | ||
| 2309 | defsubr (&Sredirect_debugging_output); | 2307 | defsubr (&Sredirect_debugging_output); |
| 2310 | #endif | ||
| 2311 | 2308 | ||
| 2312 | DEFSYM (Qprint_escape_newlines, "print-escape-newlines"); | 2309 | DEFSYM (Qprint_escape_newlines, "print-escape-newlines"); |
| 2313 | DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte"); | 2310 | DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte"); |
diff --git a/src/regex.c b/src/regex.c index d5c58aeaf8b..af379367be6 100644 --- a/src/regex.c +++ b/src/regex.c | |||
| @@ -215,7 +215,7 @@ xmalloc (size_t size) | |||
| 215 | void *val = malloc (size); | 215 | void *val = malloc (size); |
| 216 | if (!val && size) | 216 | if (!val && size) |
| 217 | { | 217 | { |
| 218 | write (2, "virtual memory exhausted\n", 25); | 218 | write (STDERR_FILENO, "virtual memory exhausted\n", 25); |
| 219 | exit (1); | 219 | exit (1); |
| 220 | } | 220 | } |
| 221 | return val; | 221 | return val; |
| @@ -233,7 +233,7 @@ xrealloc (void *block, size_t size) | |||
| 233 | val = realloc (block, size); | 233 | val = realloc (block, size); |
| 234 | if (!val && size) | 234 | if (!val && size) |
| 235 | { | 235 | { |
| 236 | write (2, "virtual memory exhausted\n", 25); | 236 | write (STDERR_FILENO, "virtual memory exhausted\n", 25); |
| 237 | exit (1); | 237 | exit (1); |
| 238 | } | 238 | } |
| 239 | return val; | 239 | return val; |
diff --git a/src/sysdep.c b/src/sysdep.c index 6154c1325d8..67c9bd90df7 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -130,6 +130,35 @@ static const int baud_convert[] = | |||
| 130 | 1800, 2400, 4800, 9600, 19200, 38400 | 130 | 1800, 2400, 4800, 9600, 19200, 38400 |
| 131 | }; | 131 | }; |
| 132 | 132 | ||
| 133 | /* If FD is not already open, arrange for it to be open with FLAGS. */ | ||
| 134 | static void | ||
| 135 | force_open (int fd, int flags) | ||
| 136 | { | ||
| 137 | if (dup2 (fd, fd) < 0 && errno == EBADF) | ||
| 138 | { | ||
| 139 | int n = open (NULL_DEVICE, flags); | ||
| 140 | if (n < 0 || (fd != n && (dup2 (n, fd) < 0 || emacs_close (n) != 0))) | ||
| 141 | { | ||
| 142 | emacs_perror (NULL_DEVICE); | ||
| 143 | exit (EXIT_FAILURE); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | /* Make sure stdin, stdout, and stderr are open to something, so that | ||
| 149 | their file descriptors are not hijacked by later system calls. */ | ||
| 150 | void | ||
| 151 | init_standard_fds (void) | ||
| 152 | { | ||
| 153 | /* Open stdin for *writing*, and stdout and stderr for *reading*. | ||
| 154 | That way, any attempt to do normal I/O will result in an error, | ||
| 155 | just as if the files were closed, and the file descriptors will | ||
| 156 | not be reused by later opens. */ | ||
| 157 | force_open (STDIN_FILENO, O_WRONLY); | ||
| 158 | force_open (STDOUT_FILENO, O_RDONLY); | ||
| 159 | force_open (STDERR_FILENO, O_RDONLY); | ||
| 160 | } | ||
| 161 | |||
| 133 | /* Return the current working directory. The result should be freed | 162 | /* Return the current working directory. The result should be freed |
| 134 | with 'free'. Return NULL on errors. */ | 163 | with 'free'. Return NULL on errors. */ |
| 135 | char * | 164 | char * |