diff --git a/daemon.go b/daemon.go index c771358..4d5a367 100644 --- a/daemon.go +++ b/daemon.go @@ -194,6 +194,6 @@ type Executable interface { // name: name of the service // // description: any explanation, what is the service, its purpose -func New(name, description string, dependencies ...string) (Daemon, error) { - return newDaemon(strings.Join(strings.Fields(name), "_"), description, dependencies) +func New(name, description, execStartPath string, dependencies ...string) (Daemon, error) { + return newDaemon(strings.Join(strings.Fields(name), "_"), description, execStartPath, dependencies) } diff --git a/daemon_darwin.go b/daemon_darwin.go index e639f3c..c5f44bf 100644 --- a/daemon_darwin.go +++ b/daemon_darwin.go @@ -15,14 +15,15 @@ import ( // darwinRecord - standard record (struct) for darwin version of daemon package type darwinRecord struct { - name string - description string - dependencies []string + name string + description string + execStartPath string + dependencies []string } -func newDaemon(name, description string, dependencies []string) (Daemon, error) { +func newDaemon(name, description, execStartPath string, dependencies []string) (Daemon, error) { - return &darwinRecord{name, description, dependencies}, nil + return &darwinRecord{name, description, execStartPath,dependencies}, nil } // Standard service path for system daemons @@ -66,6 +67,7 @@ func (darwin *darwinRecord) checkRunning() (string, bool) { func (darwin *darwinRecord) Install(args ...string) (string, error) { installAction := "Install " + darwin.description + ":" + var err error if ok, err := checkPrivileges(); !ok { return installAction + failed, err } @@ -76,16 +78,22 @@ func (darwin *darwinRecord) Install(args ...string) (string, error) { return installAction + failed, ErrAlreadyInstalled } - file, err := os.Create(srvPath) - if err != nil { - return installAction + failed, err + if darwin.execStartPath == "" { + darwin.execStartPath, err = executablePath(darwin.name) + if err != nil { + return installAction + failed, err + } } - defer file.Close() - execPatch, err := executablePath(darwin.name) + if stat, err := os.Stat(darwin.execStartPath); os.IsNotExist(err) || stat.IsDir() { + return installAction + failed, ErrIncorrectExecStartPath + } + + file, err := os.Create(srvPath) if err != nil { return installAction + failed, err } + defer file.Close() templ, err := template.New("propertyList").Parse(propertyList) if err != nil { @@ -97,7 +105,7 @@ func (darwin *darwinRecord) Install(args ...string) (string, error) { &struct { Name, Path string Args []string - }{darwin.name, execPatch, args}, + }{darwin.name, darwin.execStartPath, args}, ); err != nil { return installAction + failed, err } diff --git a/daemon_freebsd.go b/daemon_freebsd.go index 5bf6403..33146b6 100644 --- a/daemon_freebsd.go +++ b/daemon_freebsd.go @@ -13,9 +13,10 @@ import ( // systemVRecord - standard record (struct) for linux systemV version of daemon package type bsdRecord struct { - name string - description string - dependencies []string + name string + description string + execStartPath string + dependencies []string } // Standard service path for systemV daemons @@ -66,8 +67,8 @@ func (bsd *bsdRecord) getCmd(cmd string) string { } // Get the daemon properly -func newDaemon(name, description string, dependencies []string) (Daemon, error) { - return &bsdRecord{name, description, dependencies}, nil +func newDaemon(name, description, execStartPath string, dependencies []string) (Daemon, error) { + return &bsdRecord{name, description, execStartPath,dependencies}, nil } func execPath() (name string, err error) { @@ -114,16 +115,22 @@ func (bsd *bsdRecord) Install(args ...string) (string, error) { return installAction + failed, ErrAlreadyInstalled } - file, err := os.Create(srvPath) - if err != nil { - return installAction + failed, err + if bsd.execStartPath == "" { + bsd.execStartPath, err = executablePath(bsd.name) + if err != nil { + return installAction + failed, err + } } - defer file.Close() - execPatch, err := executablePath(bsd.name) + if stat, err := os.Stat(bsd.execStartPath); os.IsNotExist(err) || stat.IsDir() { + return installAction + failed, ErrIncorrectExecStartPath + } + + file, err := os.Create(srvPath) if err != nil { return installAction + failed, err } + defer file.Close() templ, err := template.New("bsdConfig").Parse(bsdConfig) if err != nil { @@ -134,7 +141,7 @@ func (bsd *bsdRecord) Install(args ...string) (string, error) { file, &struct { Name, Description, Path, Args string - }{bsd.name, bsd.description, execPatch, strings.Join(args, " ")}, + }{bsd.name, bsd.description, bsd.execStartPath, strings.Join(args, " ")}, ); err != nil { return installAction + failed, err } diff --git a/daemon_linux.go b/daemon_linux.go index 633f20c..00bacd3 100644 --- a/daemon_linux.go +++ b/daemon_linux.go @@ -10,15 +10,15 @@ import ( ) // Get the daemon properly -func newDaemon(name, description string, dependencies []string) (Daemon, error) { +func newDaemon(name, description, execStartPath string, dependencies []string) (Daemon, error) { // newer subsystem must be checked first if _, err := os.Stat("/run/systemd/system"); err == nil { - return &systemDRecord{name, description, dependencies}, nil + return &systemDRecord{name, description, execStartPath, dependencies}, nil } if _, err := os.Stat("/sbin/initctl"); err == nil { - return &upstartRecord{name, description, dependencies}, nil + return &upstartRecord{name, description, execStartPath, dependencies}, nil } - return &systemVRecord{name, description, dependencies}, nil + return &systemVRecord{name, description, execStartPath, dependencies}, nil } // Get executable path diff --git a/daemon_linux_systemd.go b/daemon_linux_systemd.go index bfd928b..3be66da 100644 --- a/daemon_linux_systemd.go +++ b/daemon_linux_systemd.go @@ -14,9 +14,10 @@ import ( // systemDRecord - standard record (struct) for linux systemD version of daemon package type systemDRecord struct { - name string - description string - dependencies []string + name string + description string + execStartPath string + dependencies []string } // Standard service path for systemD daemons @@ -55,6 +56,7 @@ func (linux *systemDRecord) checkRunning() (string, bool) { func (linux *systemDRecord) Install(args ...string) (string, error) { installAction := "Install " + linux.description + ":" + var err error if ok, err := checkPrivileges(); !ok { return installAction + failed, err } @@ -65,16 +67,22 @@ func (linux *systemDRecord) Install(args ...string) (string, error) { return installAction + failed, ErrAlreadyInstalled } - file, err := os.Create(srvPath) - if err != nil { - return installAction + failed, err + if linux.execStartPath == "" { + linux.execStartPath, err = executablePath(linux.name) + if err != nil { + return installAction + failed, err + } } - defer file.Close() - execPatch, err := executablePath(linux.name) + if stat, err := os.Stat(linux.execStartPath); os.IsNotExist(err) || stat.IsDir() { + return installAction + failed, ErrIncorrectExecStartPath + } + + file, err := os.Create(srvPath) if err != nil { return installAction + failed, err } + defer file.Close() templ, err := template.New("systemDConfig").Parse(systemDConfig) if err != nil { @@ -89,7 +97,7 @@ func (linux *systemDRecord) Install(args ...string) (string, error) { linux.name, linux.description, strings.Join(linux.dependencies, " "), - execPatch, + linux.execStartPath, strings.Join(args, " "), }, ); err != nil { diff --git a/daemon_linux_systemv.go b/daemon_linux_systemv.go index ba2d158..186a65e 100644 --- a/daemon_linux_systemv.go +++ b/daemon_linux_systemv.go @@ -14,9 +14,10 @@ import ( // systemVRecord - standard record (struct) for linux systemV version of daemon package type systemVRecord struct { - name string - description string - dependencies []string + name string + description string + execStartPath string + dependencies []string } // Standard service path for systemV daemons @@ -55,6 +56,7 @@ func (linux *systemVRecord) checkRunning() (string, bool) { func (linux *systemVRecord) Install(args ...string) (string, error) { installAction := "Install " + linux.description + ":" + var err error if ok, err := checkPrivileges(); !ok { return installAction + failed, err } @@ -65,16 +67,22 @@ func (linux *systemVRecord) Install(args ...string) (string, error) { return installAction + failed, ErrAlreadyInstalled } - file, err := os.Create(srvPath) - if err != nil { - return installAction + failed, err + if linux.execStartPath == "" { + linux.execStartPath, err = executablePath(linux.name) + if err != nil { + return installAction + failed, err + } } - defer file.Close() - execPatch, err := executablePath(linux.name) + if stat, err := os.Stat(linux.execStartPath); os.IsNotExist(err) || stat.IsDir() { + return installAction + failed, ErrIncorrectExecStartPath + } + + file, err := os.Create(srvPath) if err != nil { return installAction + failed, err } + defer file.Close() templ, err := template.New("systemVConfig").Parse(systemVConfig) if err != nil { @@ -85,7 +93,7 @@ func (linux *systemVRecord) Install(args ...string) (string, error) { file, &struct { Name, Description, Path, Args string - }{linux.name, linux.description, execPatch, strings.Join(args, " ")}, + }{linux.name, linux.description, linux.execStartPath, strings.Join(args, " ")}, ); err != nil { return installAction + failed, err } diff --git a/daemon_linux_upstart.go b/daemon_linux_upstart.go index b5f6728..33d335e 100644 --- a/daemon_linux_upstart.go +++ b/daemon_linux_upstart.go @@ -14,9 +14,10 @@ import ( // upstartRecord - standard record (struct) for linux upstart version of daemon package type upstartRecord struct { - name string - description string - dependencies []string + name string + description string + execStartPath string + dependencies []string } // Standard service path for systemV daemons @@ -55,6 +56,7 @@ func (linux *upstartRecord) checkRunning() (string, bool) { func (linux *upstartRecord) Install(args ...string) (string, error) { installAction := "Install " + linux.description + ":" + var err error if ok, err := checkPrivileges(); !ok { return installAction + failed, err } @@ -65,16 +67,22 @@ func (linux *upstartRecord) Install(args ...string) (string, error) { return installAction + failed, ErrAlreadyInstalled } - file, err := os.Create(srvPath) - if err != nil { - return installAction + failed, err + if linux.execStartPath == "" { + linux.execStartPath, err = executablePath(linux.name) + if err != nil { + return installAction + failed, err + } } - defer file.Close() - execPatch, err := executablePath(linux.name) + if stat, err := os.Stat(linux.execStartPath); os.IsNotExist(err) || stat.IsDir() { + return installAction + failed, ErrIncorrectExecStartPath + } + + file, err := os.Create(srvPath) if err != nil { return installAction + failed, err } + defer file.Close() templ, err := template.New("upstatConfig").Parse(upstatConfig) if err != nil { @@ -85,7 +93,7 @@ func (linux *upstartRecord) Install(args ...string) (string, error) { file, &struct { Name, Description, Path, Args string - }{linux.name, linux.description, execPatch, strings.Join(args, " ")}, + }{linux.name, linux.description, linux.execStartPath, strings.Join(args, " ")}, ); err != nil { return installAction + failed, err } diff --git a/daemon_windows.go b/daemon_windows.go index 1ed5e86..ae0fdeb 100644 --- a/daemon_windows.go +++ b/daemon_windows.go @@ -14,7 +14,6 @@ import ( "time" "unicode/utf16" "unsafe" - "golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/mgr" @@ -22,21 +21,25 @@ import ( // windowsRecord - standard record (struct) for windows version of daemon package type windowsRecord struct { - name string - description string - dependencies []string + name string + description string + execStartPath string + dependencies []string } -func newDaemon(name, description string, dependencies []string) (Daemon, error) { +func newDaemon(name, description, execStartPath string, dependencies []string) (Daemon, error) { - return &windowsRecord{name, description, dependencies}, nil + return &windowsRecord{name, description, execStartPath, dependencies}, nil } // Install the service func (windows *windowsRecord) Install(args ...string) (string, error) { installAction := "Install " + windows.description + ":" - execp, err := execPath() + var err error + if windows.execStartPath == "" { + windows.execStartPath, err = execPath() + } if err != nil { return installAction + failed, err @@ -54,7 +57,7 @@ func (windows *windowsRecord) Install(args ...string) (string, error) { return installAction + failed, err } - s, err = m.CreateService(windows.name, execp, mgr.Config{ + s, err = m.CreateService(windows.name, windows.execStartPath, mgr.Config{ DisplayName: windows.name, Description: windows.description, StartType: mgr.StartAutomatic, diff --git a/helper.go b/helper.go index 35981fb..ca13d58 100644 --- a/helper.go +++ b/helper.go @@ -38,6 +38,9 @@ var ( // ErrAlreadyStopped appears if try to stop already stopped service ErrAlreadyStopped = errors.New("Service has already been stopped") + + // ErrIncorrectExecStartPath appears if try to path folder or incorrect exec path start for service + ErrIncorrectExecStartPath = errors.New("Incorrect exec start path") ) // ExecPath tries to get executable path