User Tools

Site Tools


Unix execute command with redirect std input/output to pipes.

“Yet another” variant of classic algorithm. =)

pipe.cpp
/*
 * pipe.cpp
 *
 * Author, Copyright: Oleg Borodin <onborodin@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */
 
#include <iostream>
 
namespace unistd {
#include <unistd.h>
#include <sys/wait.h>
}
 
std::string execv3(const std::string& cmd, const std::string& msg = "") {
    std::string result = "";
 
    const int pipeout = 1;
    const int pipein = 0;
 
    int pipe_out[2];
    int pipe_in[2];
 
    if (unistd::pipe(pipe_out) < 0) {
        return result;
    }
    if (unistd::pipe(pipe_in) < 0) {
        return result;
    }
 
    pid_t pid = unistd::fork();
    if (pid < 0) {
        return result;
    }
    // child process
    if (pid == 0) {
        // close unised ends and reasign std in/out
        unistd::close(pipe_out[pipein]);
        unistd::dup2(pipe_out[pipeout], fileno(stdout));
 
        unistd::close(pipe_in[pipeout]);
        unistd::dup2(pipe_in[pipein], fileno(stdin));
 
        unistd::execl(cmd.c_str(), cmd.c_str(), NULL);
 
        unistd::close(pipe_out[pipeout]);
        unistd::close(pipe_in[pipein]);
        exit(0);
    }
    // parent process
    if (pid > 0) {
        const size_t buffer_size = 1024;
        char buffer[buffer_size];
 
        // close unised ends
        unistd::close(pipe_in[pipein]);
        unistd::close(pipe_out[pipeout]);
 
        unistd::write(pipe_in[pipeout], msg.c_str(), msg.size());
        unistd::close(pipe_in[pipeout]);
 
        ssize_t count;
        while ((count = unistd::read(pipe_out[pipein], &buffer, buffer_size)) > 0) {
            result.append(buffer, count);
        }
        unistd::close(pipe_out[pipein]);
        unistd::wait(NULL);
 
    }
    return result;
}
 
int main(int argc, char **argv) {
 
    std::string cmd = "/sbin/md5";
    std::string msg = "hello";
 
    std::cout << execv3(cmd, msg);
    return 0;
}

Out

$ c++ -Wall -O -std=c++11 -o pipe pipe.cpp

$ ./pipe
5d41402abc4b2a76b9719d911017c592

$ echo hello | md5
5d41402abc4b2a76b9719d911017c592

First PagePrevious PageBack to overviewNext PageLast Page