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}