+ ret = pipe(p);
+ if (ret < 0)
+ return ERRNO_TO_ERROR(errno);
+ ret = fork();
+ if (ret < 0)
+ return ERRNO_TO_ERROR(errno);
+ if (ret) { /* parent */
+ DEBUG_LOG("created process %d\n", ret);
+ close(p[0]);
+ output_file = fdopen(p[1], "w");
+ if (!output_file)
+ return ERRNO_TO_ERROR(errno);
+ return 1;
+ }
+ close(p[1]);
+ if (p[0] != STDIN_FILENO)
+ dup2(p[0], STDIN_FILENO);
+ DEBUG_LOG("executing %s\n", path);
+ argc = split_args(path, &argv, " \t");
+ execvp(argv[0], argv);
+ ERROR_LOG("error executing %s: %s\n", path,
+ adu_strerror(ERRNO_TO_ERROR(errno)));
+ _exit(EXIT_FAILURE);
+}
+
+static int open_output_stream(void)
+{
+ char *p;
+ int ret, flags = O_WRONLY | O_CREAT;
+
+ if (!select_conf.output_given)
+ goto use_stdout;
+ p = select_conf.output_arg;
+ switch (p[0]) {
+ case '\0': /* empty string */
+ goto bad_output_arg;
+ case '-':
+ if (!p[1]) /* "-" means stdout */
+ goto use_stdout;
+ /* string starting with a dash */
+ flags |= O_EXCL;
+ goto open_file;
+ case '>':
+ if (!p[1]) /* ">" is invalid */
+ goto bad_output_arg;
+ if (p[1] != '>') {
+ p++;
+ flags |= O_TRUNC;
+ goto open_file;
+ }
+ /* string starting with ">>" */
+ if (!p[2]) /* ">>" is invalid */
+ goto bad_output_arg;
+ flags |= O_APPEND;
+ p += 2;
+ goto open_file;
+ case '|':
+ if (!p[1]) /* "|" is invalid */
+ goto bad_output_arg;
+ p++;
+ return open_pipe(p);
+ default: /* args starts with no magic character */
+ flags |= O_EXCL;
+ goto open_file;