pub(crate) use pwd::module_def;
#[pymodule]
mod pwd {
use crate::{
PyResult, VirtualMachine,
builtins::{PyIntRef, PyUtf8StrRef},
convert::IntoPyException,
exceptions,
types::PyStructSequence,
};
use core::hint::cold_path;
use rustpython_host_env::pwd as host_pwd;
#[cfg(not(target_os = "android"))]
use crate::{PyObjectRef, convert::ToPyObject};
#[pystruct_sequence_data]
struct PasswdData {
pw_name: String,
pw_passwd: String,
pw_uid: u32,
pw_gid: u32,
pw_gecos: String,
pw_dir: String,
pw_shell: String,
}
#[pyattr]
#[pystruct_sequence(name = "struct_passwd", module = "pwd", data = "PasswdData")]
struct PyPasswd;
#[pyclass(with(PyStructSequence))]
impl PyPasswd {}
impl From<host_pwd::Passwd> for PasswdData {
fn from(user: host_pwd::Passwd) -> Self {
Self {
pw_name: user.name,
pw_passwd: user.passwd,
pw_uid: user.uid,
pw_gid: user.gid,
pw_gecos: user.gecos,
pw_dir: user.dir,
pw_shell: user.shell,
}
}
}
#[pyfunction]
fn getpwnam(name: PyUtf8StrRef, vm: &VirtualMachine) -> PyResult<PasswdData> {
if name.as_pystr().contains_nuls() {
cold_path();
return Err(exceptions::nul_char_error(vm));
}
let name = name.as_str();
let user = host_pwd::getpwnam(name);
let user = user.ok_or_else(|| {
vm.new_key_error(
vm.ctx
.new_str(format!("getpwnam(): name not found: {name}"))
.into(),
)
})?;
Ok(PasswdData::from(user))
}
#[pyfunction]
fn getpwuid(uidobj: PyIntRef, vm: &VirtualMachine) -> PyResult<PasswdData> {
let uid_t = libc::uid_t::try_from(uidobj.as_bigint()).ok();
let user = uid_t
.map(host_pwd::getpwuid)
.transpose()
.map_err(|err| err.into_pyexception(vm))?
.flatten();
let user = user.ok_or_else(|| {
vm.new_key_error(
vm.ctx
.new_str(format!("getpwuid(): uid not found: {}", uidobj.as_bigint()))
.into(),
)
})?;
Ok(PasswdData::from(user))
}
#[cfg(not(target_os = "android"))]
#[pyfunction]
fn getpwall(vm: &VirtualMachine) -> Vec<PyObjectRef> {
host_pwd::getpwall()
.into_iter()
.map(PasswdData::from)
.map(|passwd| passwd.to_pyobject(vm))
.collect()
}
}