mirror of
https://github.com/gechandesu/pwd.git
synced 2026-02-13 04:21:50 +03:00
init
This commit is contained in:
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.v]
|
||||
indent_style = tab
|
||||
8
.gitattributes
vendored
Normal file
8
.gitattributes
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
* text=auto eol=lf
|
||||
*.bat eol=crlf
|
||||
|
||||
*.v linguist-language=V
|
||||
*.vv linguist-language=V
|
||||
*.vsh linguist-language=V
|
||||
v.mod linguist-language=V
|
||||
.vdocignore linguist-language=ignore
|
||||
48
.github/workflows/docs.yaml
vendored
Normal file
48
.github/workflows/docs.yaml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: Docs
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup V
|
||||
run: |
|
||||
wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
|
||||
unzip -q /tmp/v.zip -d /tmp
|
||||
echo /tmp/v >> "$GITHUB_PATH"
|
||||
|
||||
- name: Build docs
|
||||
run: |
|
||||
v doc -f html -m .
|
||||
pushd _docs
|
||||
ln -vs ${{ github.event.repository.name }}.html index.html
|
||||
ls -alFh
|
||||
popd
|
||||
|
||||
- name: Upload static files as artifact
|
||||
id: deployment
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: _docs/
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
24
.github/workflows/test.yaml
vendored
Normal file
24
.github/workflows/test.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup V
|
||||
run: |
|
||||
wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
|
||||
unzip -q /tmp/v.zip -d /tmp
|
||||
echo /tmp/v >> "$GITHUB_PATH"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
v -stats test .
|
||||
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Binaries for programs and plugins
|
||||
main
|
||||
pwd
|
||||
*.exe
|
||||
*.exe~
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Ignore binary output folders
|
||||
bin/
|
||||
|
||||
# Ignore common editor/system specific metadata
|
||||
.DS_Store
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
|
||||
# ENV
|
||||
.env
|
||||
|
||||
# vweb and database
|
||||
*.db
|
||||
*.js
|
||||
8
README.md
Normal file
8
README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Access to the UNIX Password Database
|
||||
|
||||
`pwd` module provides thread-safe access to the UNIX user account and password
|
||||
database.
|
||||
|
||||
See [passwd(5)](https://man7.org/linux/man-pages/man5/passwd.5.html),
|
||||
[getpwent(3)](https://man7.org/linux/man-pages/man3/getpwent.3.html) and
|
||||
[getpwnam(3)](https://man7.org/linux/man-pages/man3/getpwnam.3.html) for info.
|
||||
22
UNLICENSE
Normal file
22
UNLICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of relinquishment in
|
||||
perpetuity of all present and future rights to this software under copyright
|
||||
law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
137
pwd.c.v
Normal file
137
pwd.c.v
Normal file
@@ -0,0 +1,137 @@
|
||||
@[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}'
|
||||
}
|
||||
17
pwd_test.v
Normal file
17
pwd_test.v
Normal file
@@ -0,0 +1,17 @@
|
||||
// vtest build: !windows
|
||||
import pwd
|
||||
|
||||
fn test_get_by_uid() {
|
||||
pw := pwd.get_by_uid(0)!
|
||||
assert pw.name == 'root'
|
||||
}
|
||||
|
||||
fn test_get_by_name() {
|
||||
pw := pwd.get_by_name('root')!
|
||||
assert pw.uid == 0
|
||||
}
|
||||
|
||||
fn test_get_all() {
|
||||
pws := pwd.get_all()
|
||||
assert pws.len > 0
|
||||
}
|
||||
Reference in New Issue
Block a user