main amadaluzia/webfetch / internal / passwd.go
 1package internal
 2
 3import (
 4	"bufio"
 5	"bytes"
 6	"fmt"
 7	"slices"
 8	"strconv"
 9)
10
11// PasswdEntry holds information about the user, such as their username, home directory, or shell.
12type PasswdEntry struct {
13	Username string
14	Password string
15	UID      int
16	GID      int
17	GECOS    string
18	Home     string
19	Shell    string
20}
21
22// A list of passwd entries, mirroring what you would find in /etc/passwd.
23type Passwd []PasswdEntry
24
25func (passwd *PasswdEntry) UnmarshalText(text []byte) error {
26	line := bytes.Split(text, []byte{':'})
27	passwd.Username = string(line[0])
28	passwd.Password = string(line[1])
29	uid, err := strconv.Atoi(string(line[2]))
30	if err != nil {
31		return fmt.Errorf("failed to convert UID to int: %v", err)
32	}
33	gid, err := strconv.Atoi(string(line[3]))
34	if err != nil {
35		return fmt.Errorf("failed to convert GID to int: %v", err)
36	}
37	passwd.UID = uid
38	passwd.GID = gid
39	passwd.GECOS = string(line[4])
40	passwd.Home = string(line[5])
41	passwd.Shell = string(line[6])
42	return nil
43}
44
45func (passwd *Passwd) UnmarshalText(text []byte) error {
46	var b bytes.Buffer
47	if _, err := b.Write(text); err != nil {
48		return fmt.Errorf("failed to write passwd file to buffer: %v", err)
49	}
50	scanner := bufio.NewScanner(&b)
51	line := 1
52	for scanner.Scan() {
53		var entry PasswdEntry
54		if err := entry.UnmarshalText(scanner.Bytes()); err != nil {
55			return fmt.Errorf("failed to parse passwd file, line %d: %v", line, err)
56		}
57		*passwd = append(*passwd, entry)
58		line++
59	}
60	return nil
61}
62
63// Get an entry from a list of passwd entries.
64func (passwd Passwd) Entry(user string) (PasswdEntry, error) {
65	if len(passwd) == 0 {
66		return PasswdEntry{}, fmt.Errorf("passwd has no entries")
67	}
68	i := slices.IndexFunc(passwd, func(pwent PasswdEntry) bool {
69		return pwent.Username == user
70	})
71	if i == -1 {
72		return PasswdEntry{}, fmt.Errorf("failed to find user %s", user)
73	}
74	return passwd[i], nil
75}