User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cpp:pipe [2019-05-28 15:26]
cpp:pipe [2020-02-15 00:57] (current)
Line 1: Line 1:
 +
 +=====Unix execute command with redirect std input/​output to pipes.=====
 +
 +"Yet another"​ variant of classic algorithm. =)
 +
 +<code c++ pipe.cpp>​
 +/*
 + * pipe.cpp
 + *
 + * Copyright 2004-2019 Oleg Borodin ​ <​borodin@unix7.org>​
 + *
 + * 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;
 +}
 +</​code>​
 +
 +===Out===
 +
 +<​file>​
 +$ c++ -Wall -O -std=c++11 -o pipe pipe.cpp
 +
 +$ ./pipe
 +5d41402abc4b2a76b9719d911017c592
 +
 +$ echo hello | md5
 +5d41402abc4b2a76b9719d911017c592
 +
 +</​file>​
 +
 +----
 +[<>]