libc_system/
lib.rs

1//! # libc-system
2//!
3//! **libc-system** provides a single cross‑platform function, [`system`], to execute a shell
4//! command and return its exit code.
5//!
6//! ## Overview
7//!
8//! - On **non‑Windows** systems, it calls the C library’s `system()` function. The command is
9//!   passed as a narrow (UTF‑8) null‑terminated C string.
10//! - On **Windows**, it calls the C runtime’s `_wsystem()` function. The command is converted from
11//!   UTF‑8 to a wide (UTF‑16) string to properly handle non‑ASCII characters.
12//!
13//! This crate lets you execute shell commands without having to worry about platform-specific
14//! differences.
15//!
16//! ## Example
17//!
18//! ```rust
19//! use libc_system::system;
20//!
21//! let exit_code = system("echo Hello, World!");
22//! println!("Exit code: {}", exit_code);
23//! ```
24//!
25//! ## Platform-specific details
26//!
27//! - **Windows:** Uses `_wsystem` from the C runtime. The command is converted into a wide
28//!   (UTF‑16) string.
29//! - **Others:** Uses `system` from libc. The command is converted into a narrow, null‑terminated
30//!   string.
31
32#[cfg(not(windows))]
33pub fn system(command: &str) -> i32 {
34    extern "C" {
35        pub fn system(s: *const std::ffi::c_char) -> std::ffi::c_int;
36    }
37
38    let c_command = match std::ffi::CString::new(command) {
39        Ok(s) => s,
40        Err(_) => return -1,
41    };
42
43    unsafe { system(c_command.as_ptr()) }
44}
45
46#[cfg(windows)]
47pub fn system(command: &str) -> i32 {
48    use std::os::windows::ffi::OsStrExt;
49
50    extern "C" {
51        pub fn _wsystem(command: *const std::ffi::c_ushort) -> std::ffi::c_int;
52    }
53
54    if command.find("\0").is_some() {
55        return -1;
56    }
57
58    let wide: Vec<u16> = std::ffi::OsStr::new(command)
59        .encode_wide()
60        .chain(std::iter::once(0))
61        .collect();
62    unsafe { _wsystem(wide.as_ptr()) }
63}