use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_void};
use libntirpc_sys::*;
const HELLO_PROG: rpcprog_t = 0x3000_0001;
const HELLO_VERS: rpcvers_t = 1;
const HELLO_PROC: rpcproc_t = 1;
unsafe extern "C" fn wrap_string(xdrs: *mut XDR, arg: *mut c_void) -> bool {
unsafe { xdr_wrapstring(xdrs, arg as *mut *mut c_char) }
}
unsafe extern "C" fn svc_req_alloc(xprt: *mut SVCXPRT, xdrs: *mut XDR) -> *mut svc_req {
unsafe {
let req = libc::calloc(1, std::mem::size_of::<svc_req>()) as *mut svc_req;
(*req).rq_xprt = xprt;
(*req).rq_xdrs = xdrs;
req
}
}
unsafe extern "C" fn svc_req_free(req: *mut svc_req, _stat: xprt_stat) {
unsafe { libc::free(req as *mut c_void) }
}
fn main() {
let name = std::env::args()
.nth(1)
.unwrap_or_else(|| "world".to_string());
let host = std::env::args()
.nth(2)
.unwrap_or_else(|| "127.0.0.1".to_string());
let name_c = CString::new(name).unwrap();
let host_c = CString::new(host).unwrap();
let nettype = c"udp";
unsafe {
let mut params: svc_init_params = std::mem::zeroed();
params.flags = (SVC_INIT_EPOLL | SVC_INIT_NOREG_XPRTS) as u_long;
params.max_events = 16;
params.alloc_cb = Some(svc_req_alloc);
params.free_cb = Some(svc_req_free);
svc_init(&mut params);
let mut name_ptr: *mut c_char = name_c.as_ptr() as *mut c_char;
let mut result: *mut c_char = std::ptr::null_mut();
let stat = rpc_call(
host_c.as_ptr(),
HELLO_PROG,
HELLO_VERS,
HELLO_PROC,
Some(wrap_string),
&mut name_ptr as *mut *mut c_char as *const c_void,
Some(wrap_string),
&mut result as *mut *mut c_char as *mut c_void,
nettype.as_ptr(),
);
if stat != clnt_stat_RPC_SUCCESS {
eprintln!("RPC call failed with status {stat}");
std::process::exit(1);
}
let reply = CStr::from_ptr(result);
println!("{}", reply.to_string_lossy());
libc::free(result as *mut c_void);
}
}