mirror of
https://github.com/gechandesu/pwd.git
synced 2026-02-13 04:21:50 +03:00
138 lines
2.7 KiB
V
138 lines
2.7 KiB
V
@[has_globals]
|
|
module pwd
|
|
|
|
import sync
|
|
|
|
$if windows {
|
|
$compile_error('pwd: MS Windows is not supported')
|
|
}
|
|
|
|
#include <errno.h>
|
|
#include <pwd.h>
|
|
|
|
__global pwd_mutex &sync.Mutex
|
|
|
|
fn init() {
|
|
pwd_mutex = sync.new_mutex()
|
|
}
|
|
|
|
fn cleanup() {
|
|
pwd_mutex.destroy()
|
|
unsafe { free(pwd_mutex) }
|
|
}
|
|
|
|
struct C.passwd {
|
|
pw_name &char
|
|
pw_passwd &char
|
|
pw_uid i32
|
|
pw_gid i32
|
|
pw_gecos &char
|
|
pw_dir &char
|
|
pw_shell &char
|
|
}
|
|
|
|
fn C.getpwuid(i32) &C.passwd
|
|
fn C.getpwnam(&char) &C.passwd
|
|
fn C.setpwent()
|
|
fn C.endpwent()
|
|
fn C.getpwent() &C.passwd
|
|
|
|
pub struct Passwd {
|
|
pub:
|
|
name string // username
|
|
passwd string // user password, usually set to 'x'
|
|
uid int // used ID
|
|
gid int // group ID
|
|
gecos string // user information
|
|
dir string // home directory
|
|
shell string // shell program
|
|
}
|
|
|
|
fn make_passwd(pw &C.passwd) Passwd {
|
|
return unsafe {
|
|
Passwd{
|
|
name: cstring_to_vstring(pw.pw_name)
|
|
passwd: cstring_to_vstring(pw.pw_passwd)
|
|
uid: int(pw.pw_uid)
|
|
gid: int(pw.pw_gid)
|
|
gecos: cstring_to_vstring(pw.pw_gecos)
|
|
dir: cstring_to_vstring(pw.pw_dir)
|
|
shell: cstring_to_vstring(pw.pw_shell)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn make_error(name string, uid int) IError {
|
|
err := C.errno
|
|
if err !in [4, 5, 12, 23, 24, 34] {
|
|
// Error is not EINTR, EIO, ENOMEM, ENFILE, EMFILE or ERANGE
|
|
return EntryNotFoundError{
|
|
name: name
|
|
uid: uid
|
|
}
|
|
}
|
|
return error_with_code(c_error_number_str(err), err)
|
|
}
|
|
|
|
// get_by_uid returns the passwd database entry by user ID.
|
|
// If the entry is not found, the EntryNotFoundError error will be returned.
|
|
pub fn get_by_uid(uid int) !Passwd {
|
|
pwd_mutex.lock()
|
|
defer {
|
|
pwd_mutex.unlock()
|
|
}
|
|
pw := C.getpwuid(uid)
|
|
if isnil(pw) {
|
|
return make_error('', uid)
|
|
}
|
|
return make_passwd(pw)
|
|
}
|
|
|
|
// get_by_uid returns the passwd database entry by user name.
|
|
// If the entry is not found, the EntryNotFoundError error will be returned.
|
|
pub fn get_by_name(name string) !Passwd {
|
|
pwd_mutex.lock()
|
|
defer {
|
|
pwd_mutex.unlock()
|
|
}
|
|
pw := C.getpwnam(&char(name.str))
|
|
if isnil(pw) {
|
|
return make_error(name, -1)
|
|
}
|
|
return make_passwd(pw)
|
|
}
|
|
|
|
// get_all returns all entries from passwd database in arbitrary order.
|
|
pub fn get_all() []Passwd {
|
|
mut pwds := []Passwd{}
|
|
pwd_mutex.lock()
|
|
C.setpwent()
|
|
defer {
|
|
C.endpwent()
|
|
pwd_mutex.unlock()
|
|
}
|
|
for {
|
|
pw := C.getpwent()
|
|
if isnil(pw) {
|
|
break
|
|
}
|
|
pwds << make_passwd(pw)
|
|
}
|
|
return pwds
|
|
}
|
|
|
|
// EntryNotFoundError designates that an entry with the specified UID or name was not found.
|
|
pub struct EntryNotFoundError {
|
|
Error
|
|
name string
|
|
uid int
|
|
}
|
|
|
|
// msg returns the string representation of EntryNotFoundError error.
|
|
pub fn (e EntryNotFoundError) msg() string {
|
|
if e.name != '' {
|
|
return "no passwd entry found by username '${e.name}'"
|
|
}
|
|
return 'no passwd entry found by user ID ${e.uid}'
|
|
}
|