summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-06-26 20:21:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2024-06-26 20:21:34 -0700
commite1f183b388bb9c6e8d13b0154f82a08ed30522b0 (patch)
treeb9cf064e57c1d2c64a98fb4bad7ef1250ce27d2d /stream.c
parent8e8258ed0fab433fd6fb8d5e8480eabae9a807ca (diff)
downloadtxr-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.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/stream.c b/stream.c
index 953dc76a..7114a123 100644
--- a/stream.c
+++ b/stream.c
@@ -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]);
}