main amadaluzia/webfetch / internal / utils.go
  1package internal
  2
  3import (
  4	"fmt"
  5	"html/template"
  6	"io"
  7	"os"
  8	"path/filepath"
  9)
 10
 11var templateFuncMap = template.FuncMap{
 12	"add":      func(a int, b int) int { return a + b },
 13	"subtract": func(a int, b int) int { return a - b },
 14	"multiply": func(a int, b int) int { return a * b },
 15	"divide":   func(a int, b int) int { return a / b },
 16}
 17
 18// Read /etc/passwd and collect all it's entries..
 19// It returns the collected passwd entries and any errors it encounters.
 20func GetPasswd() (Passwd, error) {
 21	var passwd Passwd
 22	text, err := os.ReadFile("/etc/passwd")
 23	if err != nil {
 24		return nil, fmt.Errorf("failed to read /etc/passwd: %v", err)
 25	}
 26	if err := passwd.UnmarshalText(text); err != nil {
 27		return nil, err
 28	}
 29	return passwd, nil
 30}
 31
 32// Create an OsRelease by reading /etc/os-release.
 33// It returns the resulting OsRelease or any errors it encounters.
 34func GetOsRelease() (OsRelease, error) {
 35	osRelease := make(OsRelease)
 36	text, err := os.ReadFile("/etc/os-release")
 37	if err != nil {
 38		return nil, fmt.Errorf("failed to read /etc/os-release: %v", err)
 39	}
 40	if err := osRelease.UnmarshalText(text); err != nil {
 41		return nil, err
 42	}
 43	return osRelease, nil
 44}
 45
 46// Look up possible environment variables for usernames.
 47// It returns the username given from the first non-empty environment variable, and any errors it encounters.
 48func GetUsername() (string, error) {
 49	userEnvVars := []string{"USER", "USERNAME"}
 50	var ok bool
 51	var val string
 52	for _, envvar := range userEnvVars {
 53		val, ok = os.LookupEnv(envvar)
 54		if ok {
 55			break
 56		}
 57	}
 58	if !ok {
 59		return "", fmt.Errorf("failed to get username")
 60	}
 61	return val, nil
 62}
 63
 64// Using username and passwd, it tries to find the users shell.
 65// It returns the user's shell, and any errors it encounters.
 66func GetShell(username string, passwd Passwd) (string, error) {
 67	pwEnt, err := passwd.Entry(username)
 68	if err != nil {
 69		return "", err
 70	}
 71	return pwEnt.Shell, nil
 72}
 73
 74// Get the systems uptime by reading and parsing /proc/uptime
 75// It returns the resulting uptime, and any errors it encounters.
 76func GetUptime() (Uptime, error) {
 77	var up Uptime
 78	text, err := os.ReadFile("/proc/uptime")
 79	if err != nil {
 80		return up, fmt.Errorf("failed to read /proc/uptime: %v", err)
 81	}
 82	if err := up.UnmarshalText(text); err != nil {
 83		return up, err
 84	}
 85	return up, nil
 86}
 87
 88// Gets the users terminal by looking at given environment variables
 89// It returns the given terminal, and any errors it encounters.
 90func GetTerminal() (string, error) {
 91	termEnvVars := []string{"TERMINAL", "TERM"}
 92	var result string
 93	var ok bool
 94	for _, variable := range termEnvVars {
 95		result, ok = os.LookupEnv(variable)
 96		if ok {
 97			break
 98		}
 99	}
100	if !ok {
101		return "", fmt.Errorf("failed to find terminal")
102	}
103	return result, nil
104}
105
106// Get memory information by reading and parsing /proc/meminfo.
107// It returns the resulting MemoryInfo, and any errors it encounters.
108func GetMemoryInfo() (MemoryInfo, error) {
109	meminfo := make(MemoryInfo)
110	text, err := os.ReadFile("/proc/meminfo")
111	if err != nil {
112		return meminfo, fmt.Errorf("failed to read /proc/meminfo: %v", err)
113	}
114	if err := meminfo.UnmarshalText(text); err != nil {
115		return meminfo, err
116	}
117	return meminfo, nil
118}
119
120// Get information about the desktop environment by looking at the XDG environment variables.
121// "Unknown" will be used in place of any environment variables which are missing.
122// It returns the desktop information.
123func GetDesktopInfo() DesktopInfo {
124	var desktopInfo DesktopInfo
125	currentDesktop, ok := os.LookupEnv("XDG_CURRENT_DESKTOP")
126	if !ok {
127		currentDesktop = "Unknown"
128	}
129	sessionType, ok := os.LookupEnv("XDG_SESSION_TYPE")
130	if !ok {
131		sessionType = "Unknown"
132	}
133	desktopInfo.CurrentDesktop = currentDesktop
134	desktopInfo.SessionType = sessionType
135	return desktopInfo
136}
137
138// Get the system locale by looking at the LANG environment variable.
139// It returns the system locale, or "Unknown" if nothing is found.
140func GetLocale() string {
141	locale, ok := os.LookupEnv("LANG")
142	if !ok {
143		locale = "Unknown"
144	}
145	return locale
146}
147
148// Builds the template found in file using sysinfo, and write it to w.
149// It returns any errors that may have happened.
150func BuildTemplate(w io.Writer, file string, sysinfo SystemInfo) error {
151	name := filepath.Base(file)
152	master, err := template.New(name).Funcs(templateFuncMap).ParseFiles(file)
153	if err != nil {
154		return fmt.Errorf("failed to parse %s: %v", file, err)
155	}
156	if err := master.ExecuteTemplate(w, name, sysinfo); err != nil {
157		return fmt.Errorf("failed to write template to writer: %v", err)
158	}
159	return nil
160}