Skip to main content

linuxutils_system/
ipcmk.rs

1use linuxutils_common::man::ManContent;
2
3pub const MAN: ManContent = ManContent::empty();
4
5use clap::Parser;
6use std::{io, process::ExitCode};
7
8/// Create System V IPC resources.
9///
10/// Creates shared memory segments, message queues, or semaphore arrays
11/// using shmget(2), msgget(2), or semget(2) with IPC_PRIVATE.
12#[derive(Parser)]
13#[command(name = "ipcmk", about = "Create System V IPC resources")]
14pub struct Args {
15    /// Create shared memory segment of given size in bytes
16    #[arg(short = 'M', long = "shmem")]
17    shmem: Option<usize>,
18
19    /// Create message queue
20    #[arg(short = 'Q', long)]
21    queue: bool,
22
23    /// Create semaphore array with N elements
24    #[arg(short = 'S', long)]
25    semaphore: Option<i32>,
26
27    /// Permissions in octal (default: 0644)
28    #[arg(short = 'p', long, default_value = "0644")]
29    mode: String,
30}
31
32fn parse_mode(s: &str) -> Result<i32, String> {
33    i32::from_str_radix(s, 8).map_err(|_| format!("invalid mode: {s}"))
34}
35
36pub fn run(args: Args) -> ExitCode {
37    let mode = match parse_mode(&args.mode) {
38        Ok(m) => m,
39        Err(e) => {
40            eprintln!("ipcmk: {e}");
41            return ExitCode::FAILURE;
42        }
43    };
44
45    let flags = libc::IPC_CREAT | libc::IPC_EXCL | mode;
46
47    if let Some(size) = args.shmem {
48        let id = unsafe { libc::shmget(libc::IPC_PRIVATE, size, flags) };
49        if id < 0 {
50            eprintln!("ipcmk: shmget: {}", io::Error::last_os_error());
51            return ExitCode::FAILURE;
52        }
53        println!("Shared memory id: {id}");
54    }
55
56    if args.queue {
57        let id = unsafe { libc::msgget(libc::IPC_PRIVATE, flags) };
58        if id < 0 {
59            eprintln!("ipcmk: msgget: {}", io::Error::last_os_error());
60            return ExitCode::FAILURE;
61        }
62        println!("Message queue id: {id}");
63    }
64
65    if let Some(nsems) = args.semaphore {
66        let id = unsafe { libc::semget(libc::IPC_PRIVATE, nsems, flags) };
67        if id < 0 {
68            eprintln!("ipcmk: semget: {}", io::Error::last_os_error());
69            return ExitCode::FAILURE;
70        }
71        println!("Semaphore id: {id}");
72    }
73
74    if args.shmem.is_none() && !args.queue && args.semaphore.is_none() {
75        eprintln!("ipcmk: specify -M, -Q, or -S. Try 'ipcmk --help'");
76        return ExitCode::FAILURE;
77    }
78
79    ExitCode::SUCCESS
80}