list Windows user services

This commit is contained in:
AJ ONeal 2019-08-02 14:53:43 -06:00
parent cc0176e058
commit f03a0755af
2 changed files with 124 additions and 0 deletions

View File

@ -51,6 +51,10 @@ func Stop(conf *service.Service) error {
return stop(conf)
}
func List(conf *service.Service) ([]string, []string, []error) {
return list(conf)
}
// IsPrivileged returns true if we suspect that the current user (or process) will be able
// to write to system folders, bind to privileged ports, and otherwise
// successfully run a system service.
@ -67,6 +71,16 @@ func WhereIs(exe string) (string, error) {
return filepath.Abs(filepath.ToSlash(exepath))
}
type ManageError struct {
Name string
Hint string
Parent error
}
func (e *ManageError) Error() string {
return e.Name + ": " + e.Hint + ": " + e.Parent.Error()
}
type ErrDaemonize struct {
DaemonArgs []string
error string

View File

@ -130,6 +130,38 @@ func stop(conf *service.Service) error {
return runner.Stop(conf)
}
func list(c *service.Service) ([]string, []string, []error) {
var errs []error
regs, err := listRegistry(c)
if nil != err {
errs = append(errs, err)
}
cfgs, errors := listConfigs(c)
if 0 != len(errors) {
errs = append(errs, errors...)
}
managed := []string{}
for i := range cfgs {
managed = append(managed, cfgs[i].Name)
}
others := []string{}
for i := range regs {
reg := regs[i]
for j := range cfgs {
cfg := cfgs[j]
if reg != cfg.Title {
others = append(others, reg)
}
}
}
return managed, others, errs
}
func getRunnerArgs(c *service.Service) []string {
self := os.Args[0]
debug := ""
@ -154,6 +186,84 @@ func getRunnerArgs(c *service.Service) []string {
}
}
type winConf struct {
Filename string `json:"-"`
Name string `json:"name"`
Title string `json:"title"`
}
func listConfigs(c *service.Service) ([]winConf, []error) {
var errs []error
smdir := `\opt\serviceman`
if !c.System {
smdir = filepath.Join(c.Home, ".local", smdir)
}
confpath := filepath.Join(smdir, `etc`)
infos, err := ioutil.ReadDir(confpath)
if nil != err {
if os.IsNotExist(err) {
return nil, nil
}
errs = append(errs, &ManageError{
Name: confpath,
Hint: "Read directory",
Parent: err,
})
return nil, errs
}
// TODO report active status
srvs := []winConf{}
for i := range infos {
filename := strings.ToLower(infos[i].Name())
if len(filename) <= srvLen || !strings.HasSuffix(srvExt, filename) {
continue
}
name := filename[:len(filename)-srvLen]
b, err := ioutil.ReadFile(filepath.Join(confpath, filename))
if nil != err {
errs = append(errs, &ManageError{
Name: name,
Hint: "Read file",
Parent: err,
})
continue
}
cfg := &winConf{Filename: filename}
err = json.Unmarshal(b, cfg)
if nil != err {
errs = append(errs, &ManageError{
Name: name,
Hint: "Parse JSON",
Parent: err,
})
continue
}
srvs = append(srvs)
}
return srvs, nil
}
func listRegistry(c *service.Service) ([]string, error) {
autorunKey := `SOFTWARE\Microsoft\Windows\CurrentVersion\Run`
k, _, err := registry.CreateKey(
registry.CURRENT_USER,
autorunKey,
registry.QUERY_VALUE,
)
if err != nil {
log.Fatal(err)
}
defer k.Close()
return k.ReadValueNames(-1)
}
// copies self to install path and returns config path
func installServiceman(c *service.Service) ([]string, error) {
// TODO check version and upgrade or dismiss