aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-08-05 22:11:52 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-09-25 22:57:28 +0900
commit7e2775b057d19d5ed06877c3b02299e3b5d2beb7 (patch)
treebc78bf65a2be58d00212e1eb4dcbc927be968560 /io.c
parent0f642907046e98cc026b50416bd63212b92112cd (diff)
downloadruby-7e2775b057d19d5ed06877c3b02299e3b5d2beb7.tar.gz
Invoke the command when RUBY_BUGREPORT_PATH starts with `|`
Diffstat (limited to 'io.c')
-rw-r--r--io.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/io.c b/io.c
index 48cdc5b9a7..779f671876 100644
--- a/io.c
+++ b/io.c
@@ -170,6 +170,7 @@ off_t __syscall(quad_t number, ...);
#define open rb_w32_uopen
#undef rename
#define rename(f, t) rb_w32_urename((f), (t))
+#include "win32/file.h"
#endif
VALUE rb_cIO;
@@ -7955,6 +7956,60 @@ popen_finish(VALUE port, VALUE klass)
return port;
}
+#if defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)
+struct popen_writer_arg {
+ char *const *argv;
+ struct popen_arg popen;
+};
+
+static int
+exec_popen_writer(void *arg, char *errmsg, size_t buflen)
+{
+ struct popen_writer_arg *pw = arg;
+ pw->popen.modef = FMODE_WRITABLE;
+ popen_redirect(&pw->popen);
+ execv(pw->argv[0], pw->argv);
+ strlcpy(errmsg, strerror(errno), buflen);
+ return -1;
+}
+#endif
+
+FILE *
+ruby_popen_writer(char *const *argv, rb_pid_t *pid)
+{
+#if (defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)) || defined(_WIN32)
+# ifdef HAVE_WORKING_FORK
+ struct popen_writer_arg pw;
+ int *const write_pair = pw.popen.pair;
+# else
+ int write_pair[2];
+# endif
+
+ int result = rb_cloexec_pipe(write_pair);
+ *pid = -1;
+ if (result == 0) {
+# ifdef HAVE_WORKING_FORK
+ pw.argv = argv;
+ int status;
+ char errmsg[80] = {'\0'};
+ *pid = rb_fork_async_signal_safe(&status, exec_popen_writer, &pw, Qnil, errmsg, sizeof(errmsg));
+# else
+ *pid = rb_w32_uspawn_process(P_NOWAIT, argv[0], argv, write_pair[0], -1, -1, 0);
+ const char *errmsg = (*pid < 0) ? strerror(errno) : NULL;
+# endif
+ close(write_pair[0]);
+ if (*pid < 0) {
+ close(write_pair[1]);
+ fprintf(stderr, "ruby_popen_writer(%s): %s\n", argv[0], errmsg);
+ }
+ else {
+ return fdopen(write_pair[1], "w");
+ }
+ }
+#endif
+ return NULL;
+}
+
static void
rb_scan_open_args(int argc, const VALUE *argv,
VALUE *fname_p, int *oflags_p, int *fmode_p,