view pipes.cpp @ 2:00b62a080354

fix numerous bugs
author Yasuri <yasuri@charliesmp.net>
date Sun, 13 Sep 2026 19:40:11 +0000
parents 21b543c7aa14
children
line wrap: on
line source

#include <iostream>
#include <unistd.h>
#include <spawn.h>
#include <cstring>
#include <cerrno>
#include <string>
#include <sys/wait.h>
#include "process.h"
extern char** environ;
std::string run_piped(char* const argv[], const std::string& input) 
{
    int status;
    pid_t pid;
    int pipeA[2];
    int pipeB[2];
    if (pipe(pipeA) < 0)
        return "error";
    if (pipe(pipeB) < 0)
        return "error";
    posix_spawn_file_actions_t actions;
    posix_spawn_file_actions_init(&actions); // initialize actions
    posix_spawn_file_actions_adddup2(&actions, pipeA[0], STDIN_FILENO);
    posix_spawn_file_actions_adddup2(&actions, pipeB[1], STDOUT_FILENO);
    posix_spawn_file_actions_addclose(&actions, pipeA[1]); // closes write end in child
    posix_spawn_file_actions_addclose(&actions, pipeB[0]); // makes sure child doesn't read its own output pipe
    posix_spawn_file_actions_addclose(&actions, pipeA[0]); // close read fd in child
    posix_spawn_file_actions_addclose(&actions, pipeB[1]); // close read fd in child, part 2
    status = posix_spawnp(&pid, argv[0], &actions, NULL, const_cast<char* const*>(argv), environ);
    close(pipeA[0]);
    close(pipeB[1]);
    if (status != 0) {
        posix_spawn_file_actions_destroy(&actions);
        close(pipeA[1]);
        close(pipeB[0]);
        std::cerr << "posix_spawnp failed for " << argv[0] << ": " << strerror(status) << std::endl;
        return "error";
    }
    size_t total_written = 0;
    while (total_written < input.size()) {
        ssize_t n = write(pipeA[1], input.c_str() + total_written, input.size() - total_written);
        if (n < 0) {
            if (errno == EINTR) {
                continue; // interrupted
            }
            perror("write");
            break; // error, give up
        }
        total_written += n;
    }
    close(pipeA[1]);
    char buf[256];
std::string result;
ssize_t n;
while ((n = read(pipeB[0], buf, sizeof(buf))) > 0) {
    result.append(buf, n);
}
    close(pipeB[0]);
    if (waitpid(pid, &status, 0) == -1) {
        posix_spawn_file_actions_destroy(&actions);
        close(pipeA[1]);
        close(pipeB[0]);
        perror("waitpid");
        return "error";
    }
    posix_spawn_file_actions_destroy(&actions);
    return result; 
}