1

I'm trying to use vala to start an external application using GLib with spawn_command_line_sync(). According to the documentation (http://valadoc.org/#!api=glib-2.0/GLib.Process.spawn_sync) you can pass a string to store the output of the external application.

While this works fine when starting a script which prints a couple of lines, I need to call a program which will print the content of a binary file. (for example "cat /usr/bin/apt-get")

Is there any way how I can receive the output of the external program not in a string, but in a DataStream or something like that ?

I'm planning to write the ouput of the external program to a file, so just calling "cat /usr/bin/apt-get > outputfile" would be an alternative (not as nice), but it doesn't seem to work.

Anyway I would prefer it to get some kind of Output Stream. I would appreciate any help.

Code im using:

using GLib;

static void main(string[] args) {
    string execute = "cat /usr/bin/apt-get";
    string output = "out";

    try {
        GLib.Process.spawn_command_line_sync(execute, out output);
    } catch (SpawnError e) {
        stderr.printf("spawn error!");
        stderr.printf(e.message);
    }

    stdout.printf("Output: %s\n", output);
}

2 Answers 2

2

GLib.Process.spawn_async_with_pipes will let you do just that. It spawns the processes and returns a file descriptor for each of stdout, stderr, and stdin. There's a sample of code in the ValaDoc on how to set up IOChannels to monitor the output.

Sign up to request clarification or add additional context in comments.

Comments

1

Thanks for that, I must have overread spawn_async_with_pipes() returning ints and not strings.

Is there anything wrong with doing it this way ? (besides the buffer size of 1)

using GLib;

static void main(string[] args) {

    string[] argv = {"cat", "/usr/bin/apt-get"};
    string[] envv = Environ.get();
    int child_pid;
    int child_stdin_fd;
    int child_stdout_fd;
    int child_stderr_fd;

    try {
        Process.spawn_async_with_pipes(
            ".",
            argv,
            envv,
            SpawnFlags.SEARCH_PATH,
            null,
            out child_pid,
            out child_stdin_fd,
            out child_stdout_fd,
            out child_stderr_fd);

    } catch (SpawnError e) {
        stderr.printf("spawn error!");
        stderr.printf(e.message);
        return;
    }

    FileStream filestream1 = FileStream.fdopen(child_stdout_fd, "r");
    FileStream filestream2 = FileStream.open("./stdout", "w");

    uint8 buf[1];
    size_t t;
    while ((t = filestream1.read(buf, 1)) != 0) {
        filestream2.write(buf, 1);
    }
}

2 Comments

Nothing wrong, but you should call waitpid or add a ChildWatch to your main loop so you can collect your child's exist status. If not, it becomes a zombie until you exit and it is re-parented by init and reaped.
You might want to consider using GLib.OutputStream.splice (in gio-2.0) instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.