Mercurial > crates > nonstick
comparison libpam-sys/src/lib.rs @ 136:efbc235f01d3
Separate libpam-sys-helpers from libpam-sys.
This separates the parts of libpam-sys that don't need linking against libpam
from the parts that do need to link against libpam.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Thu, 03 Jul 2025 14:28:04 -0400 |
| parents | libpam-sys/src/ffi.rs@6c1e1bdb4164 |
| children | 88627c057709 |
comparison
equal
deleted
inserted
replaced
| 135:b52594841480 | 136:efbc235f01d3 |
|---|---|
| 1 #![doc = include_str!("../README.md")] | 1 //! `libpam-sys` provides low-level access to `libpam`. |
| 2 //! | 2 //! |
| 3 //! ## PAM implementation | 3 //! Everything in here is directly as exported from the `libpam` library or |
| 4 //! its header files, with limited exceptions: | |
| 4 //! | 5 //! |
| 5 #![doc = concat!("This documentation was built for the **", env!("LIBPAMSYS_IMPL"), "** implementation.")] | 6 //! - The [`pam_impl`] submodule (and the [`pam_impl_name!`] macro) contains |
| 6 | 7 //! tools for detecting the current PAM library. |
| 7 mod constants; | 8 //! - [`AppData`] is an opaque pointer newtype. |
| 8 mod ffi; | 9 //! - [`ConversationCallback`] and [`CleanupCallback`] are aliases for |
| 9 pub mod helpers; | 10 //! what are otherwise anonymous function types. |
| 10 pub mod pam_impl; | 11 //! |
| 12 #![doc = concat!("This documentation was built for the **", pam_impl_name!(), "** implementation.")] | |
| 13 //! | |
| 14 //! You can override this **at build time** by setting the `LIBPAMSYS_IMPL` | |
| 15 //! environment variable to one of the values of the [`pam_impl::PamImpl`] enum. | |
| 16 //! | |
| 17 //! For more information about configuration, see [the README](https://crates.io/crate/libpam-sys). | |
| 18 #![allow(non_camel_case_types)] | |
| 19 #![allow(unused_imports)] | |
| 11 | 20 |
| 12 #[doc(inline)] | 21 #[doc(inline)] |
| 13 pub use crate::{constants::*, ffi::*, pam_impl::*}; | 22 pub use libpam_sys_helpers::constants::*; |
| 23 #[doc(inline)] | |
| 24 pub use libpam_sys_helpers::{pam_impl, pam_impl_name}; | |
| 25 use num_enum::{IntoPrimitive, TryFromPrimitive}; | |
| 26 use std::ffi::{c_char, c_int, c_uint, c_void}; | |
| 27 use std::fmt; | |
| 28 use std::marker::{PhantomData, PhantomPinned}; | |
| 29 | |
| 30 /// A marker struct to make whatever it's in `!Sync`, `!Send`, and `!Unpin`. | |
| 31 #[derive(Default, PartialOrd, PartialEq, Ord, Eq)] | |
| 32 #[repr(C)] | |
| 33 struct ExtremelyUnsafe { | |
| 34 _value: (), | |
| 35 _marker: PhantomData<(PhantomPinned, *mut c_void)>, | |
| 36 } | |
| 37 | |
| 38 impl fmt::Debug for ExtremelyUnsafe { | |
| 39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 40 write!(f, "ExtremelyUnsafe({self:p})") | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 /// An opaque structure that PAM uses to communicate. | |
| 45 /// | |
| 46 /// This is only ever returned in pointer form and cannot be constructed. | |
| 47 #[repr(C)] | |
| 48 pub struct pam_handle(ExtremelyUnsafe); | |
| 49 | |
| 50 impl fmt::Debug for pam_handle { | |
| 51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 52 write!(f, "pam_handle({self:p}") | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 /// An opaque structure that is passed through PAM in a conversation. | |
| 57 #[repr(C)] | |
| 58 pub struct AppData(ExtremelyUnsafe); | |
| 59 | |
| 60 impl fmt::Debug for AppData { | |
| 61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 62 write!(f, "AppData({self:p}") | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 /// Just an alias for the type of [`pam_conv::conv`]. | |
| 67 /// | |
| 68 /// For important details about the format of `messages`, | |
| 69 /// see [`libpam_sys_helpers::memory::PtrPtrVec`]. | |
| 70 /// | |
| 71 /// ```no_run | |
| 72 /// # use libpam_sys::{ConversationCallback, pam_conv}; | |
| 73 /// fn convo() -> ConversationCallback { | |
| 74 /// // ... | |
| 75 /// # unimplemented!() | |
| 76 /// } | |
| 77 /// let conv = pam_conv{conv: convo(), appdata_ptr: std::ptr::null_mut()}; | |
| 78 /// ``` | |
| 79 pub type ConversationCallback = unsafe extern "C" fn( | |
| 80 num_msg: c_int, | |
| 81 msg: *const *const pam_message, | |
| 82 resp: *mut *mut pam_response, | |
| 83 appdata: *mut AppData, | |
| 84 ) -> c_int; | |
| 85 | |
| 86 /// Alias for the callback to [`pam_set_data`]. | |
| 87 /// | |
| 88 /// ```no_run | |
| 89 /// # use std::ffi::CString; | |
| 90 /// use libpam_sys::{CleanupCallback, pam_set_data}; | |
| 91 /// # use libpam_sys::pam_handle; | |
| 92 /// # let handle: *mut pam_handle = std::ptr::null_mut(); | |
| 93 /// # let mut my_data = 100; | |
| 94 /// # let data_ptr = &mut my_data as *mut i32; | |
| 95 /// fn cleanup() -> CleanupCallback { | |
| 96 /// // ... | |
| 97 /// # unimplemented!() | |
| 98 /// } | |
| 99 /// let name = CString::new("name").unwrap(); | |
| 100 /// unsafe { | |
| 101 /// pam_set_data(handle, name.as_ptr().cast_mut(), data_ptr.cast(), cleanup()); | |
| 102 /// } | |
| 103 /// ``` | |
| 104 pub type CleanupCallback = | |
| 105 unsafe extern "C" fn(pamh: *mut pam_handle, data: *mut c_void, pam_end_status: c_int); | |
| 106 | |
| 107 /// Used by PAM to communicate between the module and the application. | |
| 108 #[repr(C)] | |
| 109 pub struct pam_conv { | |
| 110 pub conv: unsafe extern "C" fn( | |
| 111 num_msg: c_int, | |
| 112 msg: *const *const pam_message, | |
| 113 resp: *mut *mut pam_response, | |
| 114 appdata: *mut AppData, | |
| 115 ) -> c_int, | |
| 116 pub appdata_ptr: *mut AppData, | |
| 117 } | |
| 118 | |
| 119 /// A message sent into a PAM conversation. | |
| 120 #[repr(C)] | |
| 121 pub struct pam_message { | |
| 122 pub msg_style: c_int, | |
| 123 pub msg: *const c_char, | |
| 124 } | |
| 125 | |
| 126 /// A response returned from a PAM conversation. | |
| 127 #[repr(C)] | |
| 128 pub struct pam_response { | |
| 129 pub resp: *mut c_char, | |
| 130 /// Completely unused. | |
| 131 pub resp_retcode: c_int, | |
| 132 } | |
| 133 | |
| 134 /// Definition of the PAM_XAUTHDATA item. Compatible with `xcb_auth_info_t`. | |
| 135 #[cfg(pam_impl = "LinuxPam")] | |
| 136 #[repr(C)] | |
| 137 pub struct pam_xauth_data { | |
| 138 pub namelen: c_int, | |
| 139 pub name: *mut c_char, | |
| 140 pub datalen: c_int, | |
| 141 pub data: *mut c_char, | |
| 142 } | |
| 143 | |
| 144 #[cfg(pam_impl = "LinuxPam")] | |
| 145 #[derive(Debug)] | |
| 146 #[repr(C)] | |
| 147 pub struct pam_modutil_privs { | |
| 148 pub grplist: *mut libc::gid_t, | |
| 149 pub number_of_groups: c_int, | |
| 150 pub allocated: c_int, | |
| 151 pub old_gid: libc::gid_t, | |
| 152 pub old_uid: libc::uid_t, | |
| 153 pub is_dropped: c_int, | |
| 154 } | |
| 155 | |
| 156 #[cfg(pam_impl = "OpenPam")] | |
| 157 pub type pam_func_t = unsafe extern "C" fn( | |
| 158 handle: *mut pam_handle, | |
| 159 flags: c_int, | |
| 160 argc: c_int, | |
| 161 argv: *const *const c_char, | |
| 162 ) -> c_int; | |
| 163 | |
| 164 #[cfg(pam_impl = "OpenPam")] | |
| 165 #[derive(Debug)] | |
| 166 #[repr(C)] | |
| 167 pub struct pam_module { | |
| 168 pub path: *mut c_char, | |
| 169 pub func: [pam_func_t; 6], | |
| 170 pub dlh: *mut c_void, | |
| 171 } | |
| 172 | |
| 173 #[cfg(pam_impl = "OpenPam")] | |
| 174 #[derive(Debug)] | |
| 175 #[repr(C)] | |
| 176 pub struct pam_repository { | |
| 177 pub typ: *mut c_char, | |
| 178 pub scope: *mut c_void, | |
| 179 pub scope_len: usize, | |
| 180 } | |
| 181 | |
| 182 // These are the functions specified in X/SSO. Everybody exports them. | |
| 183 #[link(name = "pam")] | |
| 184 extern "C" { | |
| 185 /// Account validation. | |
| 186 pub fn pam_acct_mgmt(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 187 | |
| 188 /// Authenticate a user. | |
| 189 pub fn pam_authenticate(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 190 | |
| 191 // Nobody implements pam_authenticate_secondary. | |
| 192 | |
| 193 /// Manage authentication tokens. | |
| 194 pub fn pam_chauthtok(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 195 | |
| 196 /// Close an opened user session. | |
| 197 pub fn pam_close_session(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 198 | |
| 199 /// Ends the PAM transaction. | |
| 200 pub fn pam_end(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 201 | |
| 202 /// Gets module-specific data. PAM still owns the data. | |
| 203 pub fn pam_get_data( | |
| 204 pamh: *mut pam_handle, | |
| 205 module_data_name: *const c_char, | |
| 206 data: *mut *const c_void, | |
| 207 ) -> c_int; | |
| 208 | |
| 209 /// Gets an environment variable. You own the return value. | |
| 210 pub fn pam_getenv(pamh: *const pam_handle, name: *const c_char) -> *mut c_char; | |
| 211 | |
| 212 /// Gets all the environment variables. You own everything it points to. | |
| 213 pub fn pam_getenvlist(pamh: *const pam_handle) -> *mut *mut c_char; | |
| 214 | |
| 215 /// Get information about the transaction. | |
| 216 /// | |
| 217 /// The item is owned by PAM. | |
| 218 pub fn pam_get_item( | |
| 219 pamh: *const pam_handle, | |
| 220 item_type: c_int, | |
| 221 item: *mut *const c_void, | |
| 222 ) -> c_int; | |
| 223 | |
| 224 // Nobody implements pam_get_mapped_authtok. | |
| 225 // Nobody implements pam_get_mapped_username. | |
| 226 | |
| 227 /// Get the username. PAM owns it. | |
| 228 pub fn pam_get_user( | |
| 229 pamh: *mut pam_handle, | |
| 230 user: *mut *const c_char, | |
| 231 prompt: *const c_char, | |
| 232 ) -> c_int; | |
| 233 | |
| 234 /// Opens a user session. | |
| 235 pub fn pam_open_session(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 236 | |
| 237 /// Sets the value of an environment variable. `namevalue` is copied. | |
| 238 pub fn pam_putenv(pamh: *mut pam_handle, namevalue: *const c_char) -> c_int; | |
| 239 | |
| 240 /// Update or delete user credentials. | |
| 241 pub fn pam_setcred(pamh: *mut pam_handle, flags: c_int) -> c_int; | |
| 242 | |
| 243 /// Set module-specific data. PAM will call `cleanup` when completed. | |
| 244 pub fn pam_set_data( | |
| 245 pamh: *mut pam_handle, | |
| 246 module_data_name: *const c_char, | |
| 247 data: *mut c_void, | |
| 248 cleanup: unsafe extern "C" fn( | |
| 249 pamh: *mut pam_handle, | |
| 250 data: *mut c_void, | |
| 251 pam_end_status: c_int, | |
| 252 ), | |
| 253 ) -> c_int; | |
| 254 | |
| 255 /// Set information about the transaction. The `item` is copied. | |
| 256 pub fn pam_set_item(pamh: *mut pam_handle, item_type: c_int, item: *const c_void) -> c_int; | |
| 257 | |
| 258 // Nobody implements pam_set_mapped_authtok. | |
| 259 // Nobody implements pam_set_mapped_username. | |
| 260 | |
| 261 // The pam_sm_whatever functions are prototypes for the functions that | |
| 262 // a PAM module should implement, not symbols provided by PAM. | |
| 263 | |
| 264 // Nobody implements pam_authenticate_secondary. | |
| 265 | |
| 266 /// Starts a PAM transaction. The `conv` may or may not be copied. | |
| 267 pub fn pam_start( | |
| 268 service: *const c_char, | |
| 269 user: *const c_char, | |
| 270 pam_conv: *mut pam_conv, | |
| 271 pamh: *mut *mut pam_handle, | |
| 272 ) -> c_int; | |
| 273 | |
| 274 /// Gets a statically-allocated error string. | |
| 275 /// | |
| 276 /// All implementations of PAM known to this library (Linux-PAM, OpenPAM, | |
| 277 /// and Sun) ignore `pamh` and will accept a null pointer. | |
| 278 pub fn pam_strerror(pamh: *const pam_handle, error_number: c_int) -> *mut c_char; | |
| 279 } | |
| 280 | |
| 281 #[cfg(any(pam_impl = "LinuxPam", pam_impl = "OpenPam"))] | |
| 282 extern "C" { | |
| 283 /// Gets `PAM_AUTHTOK`, or asks the user if that is unset. | |
| 284 pub fn pam_get_authtok( | |
| 285 pamh: *mut pam_handle, | |
| 286 item: c_int, | |
| 287 authtok: *mut *const c_char, | |
| 288 prompt: *const c_char, | |
| 289 ) -> c_int; | |
| 290 | |
| 291 pub fn pam_prompt( | |
| 292 pamh: *const pam_handle, | |
| 293 style: c_int, | |
| 294 response: *mut *mut c_char, | |
| 295 fmt: *const c_char, | |
| 296 ... | |
| 297 ) -> c_int; | |
| 298 | |
| 299 } | |
| 300 | |
| 301 #[cfg(pam_impl = "LinuxPam")] | |
| 302 extern "C" { | |
| 303 pub fn pam_fail_delay(pamh: *mut pam_handle, musec_delay: c_uint) -> c_int; | |
| 304 | |
| 305 /// Start a PAM transaction based on configuration in the given directory. | |
| 306 pub fn pam_start_confdir( | |
| 307 service_name: *const c_char, | |
| 308 user: *const c_char, | |
| 309 pam_conversation: *mut pam_conv, | |
| 310 confdir: *const c_char, | |
| 311 pamh: *mut *mut pam_handle, | |
| 312 ) -> c_int; | |
| 313 | |
| 314 // We don't export the v-variants of the formatting functions. | |
| 315 | |
| 316 pub fn pam_syslog(pamh: *const pam_handle, priority: c_int, fmt: *const c_char, ...); | |
| 317 | |
| 318 pub fn pam_get_authtok_noverify( | |
| 319 pamh: *const pam_handle, | |
| 320 authtok: *mut *const c_char, | |
| 321 prompt: *const c_char, | |
| 322 ) -> c_int; | |
| 323 | |
| 324 pub fn pam_get_authtok_verify( | |
| 325 pamh: *const pam_handle, | |
| 326 authtok: *mut *const c_char, | |
| 327 prompt: *const c_char, | |
| 328 ) -> c_int; | |
| 329 | |
| 330 // pam_modutil also lives in libpam for Linux. | |
| 331 | |
| 332 pub fn pam_modutil_check_user_in_passwd( | |
| 333 pamh: *mut pam_handle, | |
| 334 user_name: *const c_char, | |
| 335 file_name: *const c_char, | |
| 336 ) -> c_int; | |
| 337 | |
| 338 pub fn pam_modutil_getpwnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::passwd; | |
| 339 | |
| 340 pub fn pam_modutil_getpwuid(pamh: *mut pam_handle, uid: libc::uid_t) -> *mut libc::passwd; | |
| 341 | |
| 342 pub fn pam_modutil_getgrnam(pamh: *mut pam_handle, group: *const c_char) -> *mut libc::group; | |
| 343 | |
| 344 pub fn pam_modutil_getgrgid(pamh: *mut pam_handle, gid: libc::gid_t) -> *mut libc::group; | |
| 345 | |
| 346 pub fn pam_modutil_getspnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::spwd; | |
| 347 | |
| 348 pub fn pam_modutil_user_in_group_nam_nam( | |
| 349 pamh: *mut pam_handle, | |
| 350 user: *const c_char, | |
| 351 group: *const c_char, | |
| 352 ) -> c_int; | |
| 353 pub fn pam_modutil_user_in_group_nam_gid( | |
| 354 pamh: *mut pam_handle, | |
| 355 user: *const c_char, | |
| 356 group: libc::gid_t, | |
| 357 ) -> c_int; | |
| 358 | |
| 359 pub fn pam_modutil_user_in_group_uid_nam( | |
| 360 pamh: *mut pam_handle, | |
| 361 user: libc::uid_t, | |
| 362 group: *const c_char, | |
| 363 ) -> c_int; | |
| 364 | |
| 365 pub fn pam_modutil_user_in_group_uid_gid( | |
| 366 pamh: *mut pam_handle, | |
| 367 user: libc::uid_t, | |
| 368 group: libc::gid_t, | |
| 369 ) -> c_int; | |
| 370 | |
| 371 pub fn pam_modutil_getlogin(pamh: *mut pam_handle) -> *const c_char; | |
| 372 | |
| 373 pub fn pam_modutil_read(fd: c_int, buffer: *mut c_char, count: c_int) -> c_int; | |
| 374 | |
| 375 pub fn pam_modutil_write(fd: c_int, buffer: *const c_char, count: c_int) -> c_int; | |
| 376 | |
| 377 pub fn pam_modutil_audit_write( | |
| 378 pamh: *mut pam_handle, | |
| 379 typ: c_int, | |
| 380 message: *const c_char, | |
| 381 retval: c_int, | |
| 382 ) -> c_int; | |
| 383 | |
| 384 pub fn pam_modutil_drop_priv( | |
| 385 pamh: *mut pam_handle, | |
| 386 p: *mut pam_modutil_privs, | |
| 387 pw: *const libc::passwd, | |
| 388 ) -> c_int; | |
| 389 | |
| 390 pub fn pam_modutil_regain_priv(pamh: *mut pam_handle, p: *mut pam_modutil_privs) -> c_int; | |
| 391 | |
| 392 pub fn pam_modutil_sanitize_helper_fds( | |
| 393 pamh: *mut pam_handle, | |
| 394 redirect_stdin: pam_modutil_redirect_fd, | |
| 395 redirect_stdout: pam_modutil_redirect_fd, | |
| 396 redirect_stderr: pam_modutil_redirect_fd, | |
| 397 ) -> c_int; | |
| 398 | |
| 399 pub fn pam_modutil_search_key( | |
| 400 pamh: *mut pam_handle, | |
| 401 file_name: *const c_char, | |
| 402 key: *const c_char, | |
| 403 ) -> *mut c_char; | |
| 404 } | |
| 405 | |
| 406 #[cfg(pam_impl = "OpenPam")] | |
| 407 extern "C" { | |
| 408 pub fn openpam_borrow_cred(pamh: *mut pam_handle, passwd: *const libc::passwd) -> c_int; | |
| 409 | |
| 410 pub fn openpam_subst( | |
| 411 pamh: *const pam_handle, | |
| 412 buf: *mut c_char, | |
| 413 _bufsize: *mut usize, | |
| 414 _template: *const c_char, | |
| 415 ) -> c_int; | |
| 416 | |
| 417 pub fn openpam_free_data(pamh: *mut pam_handle, data: *mut c_void, status: c_int); | |
| 418 | |
| 419 pub fn openpam_free_envlist(_envlist: *mut *mut c_char); | |
| 420 | |
| 421 pub fn openpam_get_option(_pamh: *mut pam_handle, _option: *const c_char) -> *const c_char; | |
| 422 | |
| 423 pub fn openpam_restore_cred(pamh: *mut pam_handle) -> c_int; | |
| 424 | |
| 425 pub fn openpam_set_option( | |
| 426 _pamh: *mut pam_handle, | |
| 427 _option: *const c_char, | |
| 428 _value: *const c_char, | |
| 429 ) -> c_int; | |
| 430 | |
| 431 pub fn pam_error(pamh: *const pam_handle, _fmt: *const c_char, ...) -> c_int; | |
| 432 | |
| 433 pub fn pam_info(_pamh: *const pam_handle, _fmt: *const c_char, ...) -> c_int; | |
| 434 | |
| 435 pub fn openpam_readline( | |
| 436 _f: *mut libc::FILE, | |
| 437 _lineno: *mut c_int, | |
| 438 _lenp: *mut usize, | |
| 439 ) -> *mut c_char; | |
| 440 | |
| 441 pub fn openpam_readlinev( | |
| 442 _f: *mut libc::FILE, | |
| 443 _lineno: *mut c_int, | |
| 444 _lenp: *mut c_int, | |
| 445 ) -> *mut *mut c_char; | |
| 446 | |
| 447 pub fn openpam_readword( | |
| 448 _f: *mut libc::FILE, | |
| 449 _lineno: *mut c_int, | |
| 450 _lenp: *mut usize, | |
| 451 ) -> *mut c_char; | |
| 452 | |
| 453 pub fn openpam_straddch( | |
| 454 _str: *mut *mut c_char, | |
| 455 _sizep: *mut usize, | |
| 456 _lenp: *mut usize, | |
| 457 ch: c_int, | |
| 458 ) -> c_int; | |
| 459 | |
| 460 pub fn openpam_set_feature(_feature: c_int, _onoff: c_int) -> c_int; | |
| 461 | |
| 462 pub fn openpam_get_feature(_feature: c_int, _onoff: *mut c_int) -> c_int; | |
| 463 | |
| 464 pub fn _openpam_log(_level: c_int, _func: *const c_char, _fmt: *const c_char, ...); | |
| 465 | |
| 466 /// A premade conversation function that talks to the TTY. | |
| 467 /// | |
| 468 /// ```no_run | |
| 469 /// # use std::ffi::CString; | |
| 470 /// # use std::ptr; | |
| 471 /// use libpam_sys::*; | |
| 472 /// # let service = CString::new("whatever").unwrap(); | |
| 473 /// # let user = CString::new("whatever").unwrap(); | |
| 474 /// let mut handle: *mut pam_handle = ptr::null_mut(); | |
| 475 /// let mut conv = pam_conv{ | |
| 476 /// conv: openpam_ttyconv, | |
| 477 /// appdata_ptr: ptr::null_mut(), | |
| 478 /// }; | |
| 479 /// let result = unsafe { pam_start( | |
| 480 /// service.as_ptr(), user.as_ptr(), &mut conv, &mut handle | |
| 481 /// ) }; | |
| 482 /// ``` | |
| 483 pub fn openpam_ttyconv( | |
| 484 n: c_int, | |
| 485 _msg: *const *const pam_message, | |
| 486 _resp: *mut *mut pam_response, | |
| 487 _data: *mut AppData, | |
| 488 ) -> c_int; | |
| 489 | |
| 490 pub static mut openpam_ttyconv_timeout: c_int; | |
| 491 | |
| 492 /// A null conversation function. | |
| 493 /// | |
| 494 /// ```no_run | |
| 495 /// # use std::ffi::CString; | |
| 496 /// # use std::ptr; | |
| 497 /// use libpam_sys::*; | |
| 498 /// # let service = CString::new("whatever").unwrap(); | |
| 499 /// # let user = CString::new("whatever").unwrap(); | |
| 500 /// let mut handle: *mut pam_handle = ptr::null_mut(); | |
| 501 /// let mut conv = pam_conv{ | |
| 502 /// conv: openpam_nullconv, | |
| 503 /// appdata_ptr: ptr::null_mut(), | |
| 504 /// }; | |
| 505 /// let result = unsafe { pam_start( | |
| 506 /// service.as_ptr(), user.as_ptr(), &mut conv, &mut handle | |
| 507 /// ) }; | |
| 508 /// ``` | |
| 509 pub fn openpam_nullconv( | |
| 510 n: c_int, | |
| 511 _msg: *const *const pam_message, | |
| 512 _resp: *mut *mut pam_response, | |
| 513 _data: *mut AppData, | |
| 514 ) -> c_int; | |
| 515 } |
