Вопрос

I'm developing a cross platform project currently. On windows i had a class that ran a process/script (using a commandline), waited for it to end, and read everything from it's stdout/stderr to a buffer. I then printed the output to a custom 'console'. Note: This was not a redirection of child stdout to parent stdout, just a pipe from child stdout to parent.

I'm new to OSX/unix-like api's but i can understand the canonical way of doing something like this is forking and piping stdouts together. However, i dont want to redirect it to stdout and i would like to capture the output.. It should work pretty much like this (pseudocode, resemblance with unix functions purely coincidental):

class program
{
    string name, cmdline;
    string output;
    program(char * name, char * cmdline)
        : name(name), cmdline(cmdline) {};

    int run()
    {
        // run program - spawn it as a new process
        int pid = exec(name, cmdline);
        // wait for it to finish
        wait(pid);
        char buf[size];
        int n;
        // read output of program's stdout
        // keep appending data until there's nothing left to read
        while (read(pid, buf, size, &n))
            output.append(buf, n);
        // return exit code of process
        return getexitcode(pid);
    }

    const string & getOutput() { return output;  }
};

How would i go about doing this on OSX?

E:

Okay so i studied the relevant api's and it seems that some kind of fork/exec combo is unavoidable. Problem at hand is that my process is very large and forking it really seems like a bad idea (i see that some unix implementations can't do it if the parent process takes up 50%+ of the system ram).

Can't i avoid this scheme in any way? I see that vfork() might be a possible contender, so maybe i could try to mimic the popen() function using vfork. But then again, most man pages state that vfork might very well just be fork()

Это было полезно?

Решение

You have a library call to do just that: popen. It will provide you with a return value of a file descriptor, and you can read that descriptor till eof. It's part of stdio, so you can do that on OSX, but other systems as well. Just remember to pclose() the descriptor.

 #include <stdio.h>

     FILE *     popen(const char *command, const char *mode);

     int    pclose(FILE *stream);

if you want to keep output with absolutely no redirection, the only thing we can think of is using something like "tee" - a command which splits the output to a file but maintains its own stdout. It's fairly easy to implement that in code as well, but it might not be necessary in this case.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top