Provide Stdin input to External Command

Hello,
I am trying to call another binary/command from zig and provide stdin for it.
This is the shell command I am trying to reproduce:

echo hello | grep o

The following code works, if I remove the .wait and term part.
But I want the exit code to check if everything worked.
Any ideas or help is appreciated.

const std = @import("std");
const print = std.debug.print;
const Child = std.process.Child;
const ArrayList = std.ArrayList;

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    const argv = [_][]const u8{ "grep", "o" };
    var child = Child.init(&argv, allocator);
    child.stdin_behavior = .Pipe;
    child.stdout_behavior = .Pipe;
    child.stderr_behavior = .Pipe;
    var stdout = ArrayList(u8).init(allocator);
    var stderr = ArrayList(u8).init(allocator);
    defer {
        stdout.deinit();
        stderr.deinit();
    }
    try child.spawn();
    if (child.stdin) |stdin| {
        const writer = stdin.writer();
        try writer.writeAll("hello");
        stdin.close();
    }
    try child.collectOutput(&stdout, &stderr, 1024);
    const term = try child.wait();

    try std.testing.expectEqual(term.Exited, 0);
    try std.testing.expectEqualStrings("hello\n", stdout.items);
    try std.testing.expectEqualStrings("", stderr.items);
}

You need to set child.stdin to null after closing it, otherwise child.wait() will attempt to close it again.

3 Likes

Thank you, it worked.