A CLI tool to edit dinit service files with ease
1package main
2
3import (
4 "fmt"
5 "os"
6 "path"
7 "slices"
8 "syscall"
9)
10
11func getServiceDirs() (serviceDirs []string) {
12 if os.Getuid() == 0 {
13 serviceDirs = []string{"/etc/dinit.d", "/run/dinit.d", "/usr/local/lib/dinit.d", "/lib/dinit.d"}
14 } else {
15 if xdg_home, ok := os.LookupEnv("XDG_CONFIG_HOME"); ok {
16 serviceDirs = append(serviceDirs, path.Join(xdg_home, "dinit.d"))
17 }
18 if home, ok := os.LookupEnv("HOME"); ok {
19 serviceDirs = append(serviceDirs, path.Join(home, ".config/dinit.d"))
20 }
21 serviceDirs = slices.Concat(serviceDirs, []string{"/etc/dinit.d/user", "/usr/lib/dinit.d/user", "/usr/local/lib/dinit.d/user"})
22 }
23 return
24}
25
26type Service struct {
27 Name string
28 Path string
29}
30
31func main() {
32 dirs := getServiceDirs()
33 services := []Service{}
34 for _, dir := range dirs {
35 entries, err := os.ReadDir(dir)
36 if err != nil {
37 // missing dir is ok
38 if !os.IsNotExist(err) {
39 fmt.Println(err)
40 }
41 } else {
42 for _, entry := range entries {
43 if entry.Type().IsRegular() {
44 name := entry.Name()
45 path := path.Join(dir, name)
46 services = append(services, Service{
47 Name: name,
48 Path: path,
49 })
50 }
51 }
52 }
53 }
54
55 if len(os.Args) < 2 {
56 listAll(services)
57 } else {
58 edit(services, os.Args[1])
59 }
60}
61
62func listAll(services []Service) {
63 longest := 0
64 for _, srv := range services {
65 longest = max(longest, len(srv.Name))
66 }
67 for _, srv := range services {
68 fmt.Fprintf(os.Stdout, "%-*s%s\n", longest+4, srv.Name, srv.Path)
69 }
70}
71
72func edit(services []Service, name string) {
73 i := slices.IndexFunc(services, func(srv Service) bool { return srv.Name == name })
74 if i < 0 {
75 fmt.Println("service not found:", name)
76 os.Exit(1)
77 } else {
78 if editor_sh, ok := os.LookupEnv("EDITOR"); ok {
79 err := syscall.Exec("/bin/sh", []string{"sh", "-c", editor_sh + " " + services[i].Path}, os.Environ())
80 if err != nil {
81 fmt.Println(err)
82 os.Exit(1)
83 }
84 }
85 }
86}