Here is a simple program, that parses and prints 2 options: -n (w/o associated value) and -t (with numeric value) and an argument after options.

C
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int flags, opt;
  int nsecs, tfnd;

  nsecs = 0;
  tfnd = 0;
  flags = 0;

  while ((opt = getopt(argc, argv, "nt:")) != -1) {
    switch (opt) {
    case 'n':
      flags = 1;
      break;
    case 't':
      // converting string to integer
      nsecs = atoi(optarg);
      tfnd = 1;
      break;
    default: /* '?' */
      exit(EXIT_FAILURE);
    }
  }
  printf("flags=%d; tfnd=%d; nsecs=%d; optind=%d\n", flags, tfnd, nsecs,
         optind);

  if (optind >= argc) {
    fprintf(stderr, "Expected argument after options\n");
    exit(EXIT_FAILURE);
  }

  printf("name argument = %s\n", argv[optind]);

  exit(EXIT_SUCCESS);
}

and the same program in no_std rust

Rust
#![no_std]
#![no_main]

//use libc; // 0.2.186

#[cfg(not(test))]
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
    unsafe { libc::abort() }
}

unsafe extern "C" {
    static mut optarg: *mut libc::c_char;
    static mut optind: i32;
}

#[unsafe(no_mangle)]
extern "C" fn main(argc: i32, argv: *const *mut libc::c_char) {
    let (mut nsecs, mut tfnd, mut flags) = (0, 0, 0);

    loop {
        let opt = unsafe { libc::getopt(argc, argv, c"nt:".as_ptr()) };
        if opt == -1 {
            break;
        }
        match opt as u8 {
            b'n' => {
                flags = 1;
            }
            b't' => {
                nsecs = unsafe { libc::atoi(optarg) };
                tfnd = 1;
            }
            _ => unsafe { libc::exit(libc::EXIT_FAILURE) },
        }
    }
    unsafe {
        libc::printf(
            c"flags=%d; tfnd=%d; nsecs=%d; optind=%d\n".as_ptr(),
            flags,
            tfnd,
            nsecs,
            optind,
        );
    }
    unsafe {
        if optind >= argc {
            libc::printf(c"Expected argument after options\n".as_ptr());
            libc::exit(libc::EXIT_FAILURE)
        }

        libc::printf(c"name argument = %s\n".as_ptr(), *argv.add(optind as usize));
    }

    unsafe { libc::exit(libc::EXIT_SUCCESS) }
}

Important notice: it is not some dismiss of rust, it is just a factual state. MacOS for example pushes you to use libc, since their syscalls ABI is not stable. So there is no way to avoid it