diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-06-26 20:21:34 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-06-26 20:21:34 -0700 |
commit | e1f183b388bb9c6e8d13b0154f82a08ed30522b0 (patch) | |
tree | b9cf064e57c1d2c64a98fb4bad7ef1250ce27d2d /stream.c | |
parent | 8e8258ed0fab433fd6fb8d5e8480eabae9a807ca (diff) | |
download | txr-e1f183b388bb9c6e8d13b0154f82a08ed30522b0.tar.gz txr-e1f183b388bb9c6e8d13b0154f82a08ed30522b0.tar.bz2 txr-e1f183b388bb9c6e8d13b0154f82a08ed30522b0.zip |
open-process: new ?fdno option for selecting stream fd.
If, for instance ?2 is specified in the mode string argument
of open-process and related functions, this means that the
file descriptor 2 of the process will be used as the data
source (or sink) for the stream that is returned by the
function. With this feature we can easily read the standard
error of a process while leaving its standard output
unredirected.
* stream.c (do_parse_mode): Parse the ? mode option.
(open_subprocess): Check for the presence of the alternative
file descriptor in the stdio_mode structure, and and use it
isntead of STDIN_FILENO or STDOUT_FILENO.
* stream.h (struct stdio_mode): New member, streamfd.
(stdio_mode_init_blank, stdio_mode_init_r,
stdio_mode_init_rpb, stdio_mode_init_blank, stdio_mode_init_r,
stdio_mode_init_rpb): Update initializer macros to cover the
new member, setting it to the default value -1 (not
specified).
* txr.1: Documented.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 24 |
1 files changed, 20 insertions, 4 deletions
@@ -1584,6 +1584,20 @@ static struct stdio_mode do_parse_mode(val mode_str, struct stdio_mode m_dfl, nredir++; break; } + case '?': + { + wchar_t *past; + long val = wcstol(ms + 1, &past, 10); + + if (past == ms + 1 || val < 0 || val >= INT_MAX) { + m.malformed = 1; + return m; + } + + m.streamfd = val; + ms = past - 1; + break; + } case 'z': m.gzip = 1; if (isdigit(convert(unsigned char, ms[1]))) { @@ -4526,6 +4540,8 @@ static val open_subprocess(val name, val mode_str, val args, val fun) struct save_fds sfds; val ret = nil; int fds_flags = (input ? FDS_IN : FDS_OUT) | FDS_ERR; + int streamfd_in = m.streamfd != -1 ? m.streamfd : STDIN_FILENO; + int streamfd_out = m.streamfd != -1 ? m.streamfd : STDOUT_FILENO; args = default_null_arg(args); fun = default_null_arg(fun); @@ -4579,13 +4595,13 @@ static val open_subprocess(val name, val mode_str, val args, val fun) fds_clobber(&sfds, fds_flags); if (input) { - dup2(fd[1], STDOUT_FILENO); - if (fd[1] != STDOUT_FILENO) /* You never know */ + dup2(fd[1], streamfd_out); + if (fd[1] != streamfd_out) /* You never know */ close(fd[1]); close(fd[0]); } else { - dup2(fd[0], STDIN_FILENO); - if (fd[0] != STDIN_FILENO) /* You never know */ + dup2(fd[0], streamfd_in); + if (fd[0] != streamfd_in) /* You never know */ close(fd[0]); close(fd[1]); } |