+ int fds[2];
+
+ /* Create a pipe for communicating with the filter process. */
+ if (pipe(fds) < 0) {
+ throw IOException("Unable to create pipe for filter");
+ }
+
+ /* Create a child process which can exec() the filter program. */
+ filter_pid = fork();
+ if (filter_pid < 0)
+ throw IOException("Unable to fork filter process");
+
+ if (filter_pid > 0) {
+ /* Parent process */
+ close(fds[0]);
+ cloexec(fds[1]);
+ } else {
+ /* Child process. Rearrange file descriptors. stdin is fds[0], stdout
+ * is fd_out, stderr is unchanged. */
+ close(fds[1]);
+
+ if (dup2(fds[0], 0) < 0)
+ exit(1);
+ close(fds[0]);
+
+ if (dup2(fd_out, 1) < 0)
+ exit(1);
+ close(fd_out);
+
+ /* Exec the filter program. */
+ execlp("/bin/sh", "/bin/sh", "-c", filter_program, NULL);
+
+ /* Should not reach here except for error cases. */
+ fprintf(stderr, "Could not exec filter: %m\n");
+ exit(1);
+ }
+
+ return fds[1];