1

Is there a way to make a system call in Zig, other than using a cImport? right now I've got it to work with something like that:

const c = @cImport({
    @cInclude("stdlib.h");
});

// ...

const result: c_int = c.system(cmd);

While this works fine, I'd like to do it "the zig way", without having to import stuff from C.

sigod
  • 3,514
  • 2
  • 21
  • 44
  • 1
    `system` is a not a system call, it is a function. You can to call a syscall _or_ you want to call a C function? System calls are implemented by pushing _specific_ data to _specific_ registers and then calling _specific_ assembly to trigger interrupt, see `man syscall`. It would be much simpler to re-use a C wrapper for that. – KamilCuk Aug 08 '23 at 11:28
  • ah, okay, thanks for the clarification. Then I guess my question is, is there an equivalent of the system-function in zig, that I can use to execute a command? – softMachina Aug 08 '23 at 11:46
  • 1
    Note that `system` isn't really "idiomatic" in C either. It's OK for throwaway scripts, but for "serious" programs you'd use your platforms process API (i.e. `fork/exec`, `CreateProcess`, ... or a suitable abstraction thereof). – Cubic Aug 09 '23 at 07:13

1 Answers1

3

The alternative to using C's system() function is to use ChildProcess in Zig:

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.debug.assert(gpa.deinit() == .ok);
    const allocator = gpa.allocator();

    const result = try std.ChildProcess.exec(.{
        .allocator = allocator,
        .argv = &[_][]const u8{ "date" },
    });
    defer {
        allocator.free(result.stdout);
        allocator.free(result.stderr);
    }

    std.log.info("stdout: {s}", .{ result.stdout });
    std.log.info("stderr: {s}", .{ result.stderr });
}

This prints:

$ zig build run
info: stdout: Tue, Aug  8, 2023  1:45:02 PM

info: stderr:
sigod
  • 3,514
  • 2
  • 21
  • 44