(Feat): Initial Commit
This commit is contained in:
133
src/session/scan.go
Normal file
133
src/session/scan.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// session — environment scanning from xsessions, wayland-sessions,
|
||||
// and custom script directories. Includes desktop entry parser.
|
||||
//
|
||||
// Mirrors vendor/src/post_login/mod.rs:get_envs and parse_desktop_entry.
|
||||
package session
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DesktopEntry struct {
|
||||
Name string
|
||||
Exec string
|
||||
Hidden bool
|
||||
NoDisplay bool
|
||||
}
|
||||
|
||||
func parseDesktopEntry(path string) (*DesktopEntry, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open %s: %w", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
e := &DesktopEntry{}
|
||||
inSection := false
|
||||
sc := bufio.NewScanner(f)
|
||||
for sc.Scan() {
|
||||
line := strings.TrimSpace(sc.Text())
|
||||
if line == "" || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
if line[0] == '[' && line[len(line)-1] == ']' {
|
||||
inSection = line == "[Desktop Entry]"
|
||||
continue
|
||||
}
|
||||
if !inSection {
|
||||
continue
|
||||
}
|
||||
eq := strings.IndexByte(line, '=')
|
||||
if eq < 0 {
|
||||
continue
|
||||
}
|
||||
k, v := line[:eq], line[eq+1:]
|
||||
switch k {
|
||||
case "Name":
|
||||
e.Name = v
|
||||
case "Exec":
|
||||
e.Exec = v
|
||||
case "Hidden":
|
||||
e.Hidden = strings.EqualFold(v, "true")
|
||||
case "NoDisplay":
|
||||
e.NoDisplay = strings.EqualFold(v, "true")
|
||||
}
|
||||
}
|
||||
if sc.Err() != nil {
|
||||
return nil, sc.Err()
|
||||
}
|
||||
if e.Exec == "" {
|
||||
return nil, fmt.Errorf("no Exec in %s", path)
|
||||
}
|
||||
if e.Name == "" {
|
||||
e.Name = e.Exec
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func ScanEnvs(xSessions, wlSessions, xScripts, wlScripts string, includeTTY bool) []PostLoginEnv {
|
||||
var envs []PostLoginEnv
|
||||
|
||||
scanDesktopDir(xSessions, "x11", &envs)
|
||||
scanDesktopDir(wlSessions, "wayland", &envs)
|
||||
scanScriptDir(xScripts, "x11", &envs)
|
||||
scanScriptDir(wlScripts, "wayland", &envs)
|
||||
|
||||
if len(envs) == 0 || includeTTY {
|
||||
envs = append(envs, PostLoginEnv{Kind: "tty", Title: "TTYSHELL"})
|
||||
}
|
||||
return envs
|
||||
}
|
||||
|
||||
func scanDesktopDir(dir, kind string, envs *[]PostLoginEnv) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, e := range entries {
|
||||
if e.IsDir() || filepath.Ext(e.Name()) != ".desktop" {
|
||||
continue
|
||||
}
|
||||
path := filepath.Join(dir, e.Name())
|
||||
de, err := parseDesktopEntry(path)
|
||||
if err != nil || de.Hidden || de.NoDisplay {
|
||||
continue
|
||||
}
|
||||
*envs = append(*envs, PostLoginEnv{
|
||||
Kind: kind,
|
||||
Title: de.Name,
|
||||
XinitrcPath: de.Exec,
|
||||
ScriptPath: de.Exec,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func scanScriptDir(dir, kind string, envs *[]PostLoginEnv) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, e := range entries {
|
||||
if e.IsDir() {
|
||||
continue
|
||||
}
|
||||
info, err := e.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if info.Mode()&0111 == 0 {
|
||||
continue
|
||||
}
|
||||
path := filepath.Join(dir, e.Name())
|
||||
*envs = append(*envs, PostLoginEnv{
|
||||
Kind: kind,
|
||||
Title: e.Name(),
|
||||
XinitrcPath: path,
|
||||
ScriptPath: path,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user