Przeglądaj źródła

添加依赖包

Minho 8 lat temu
rodzic
commit
e5b6902fe3
43 zmienionych plików z 3254 dodań i 0 usunięć
  1. 27 0
      vendor/github.com/kardianos/osext/LICENSE
  2. 21 0
      vendor/github.com/kardianos/osext/README.md
  3. 33 0
      vendor/github.com/kardianos/osext/osext.go
  4. 9 0
      vendor/github.com/kardianos/osext/osext_go18.go
  5. 22 0
      vendor/github.com/kardianos/osext/osext_plan9.go
  6. 36 0
      vendor/github.com/kardianos/osext/osext_procfs.go
  7. 126 0
      vendor/github.com/kardianos/osext/osext_sysctl.go
  8. 203 0
      vendor/github.com/kardianos/osext/osext_test.go
  9. 36 0
      vendor/github.com/kardianos/osext/osext_windows.go
  10. 0 0
      vendor/github.com/kardianos/service/.gitignore
  11. 16 0
      vendor/github.com/kardianos/service/.travis.yml
  12. 20 0
      vendor/github.com/kardianos/service/LICENSE
  13. 14 0
      vendor/github.com/kardianos/service/README.md
  14. 21 0
      vendor/github.com/kardianos/service/appveyor.yml
  15. 48 0
      vendor/github.com/kardianos/service/console.go
  16. 104 0
      vendor/github.com/kardianos/service/example/logging/main.go
  17. 194 0
      vendor/github.com/kardianos/service/example/runner/runner.go
  18. 18 0
      vendor/github.com/kardianos/service/example/runner/runner.json
  19. 51 0
      vendor/github.com/kardianos/service/example/simple/main.go
  20. 62 0
      vendor/github.com/kardianos/service/example/stopPause/main.go
  21. 15 0
      vendor/github.com/kardianos/service/linux-test-su.sh
  22. 35 0
      vendor/github.com/kardianos/service/linux_test/Makefile
  23. 6 0
      vendor/github.com/kardianos/service/linux_test/README.md
  24. 3 0
      vendor/github.com/kardianos/service/linux_test/systemd/Dockerfile
  25. 3 0
      vendor/github.com/kardianos/service/linux_test/sysv/Dockerfile
  26. 3 0
      vendor/github.com/kardianos/service/linux_test/upstart/Dockerfile
  27. 20 0
      vendor/github.com/kardianos/service/name_test.go
  28. 16 0
      vendor/github.com/kardianos/service/pre_go1.8.go
  29. 362 0
      vendor/github.com/kardianos/service/service.go
  30. 240 0
      vendor/github.com/kardianos/service/service_darwin.go
  31. 15 0
      vendor/github.com/kardianos/service/service_go1.8.go
  32. 75 0
      vendor/github.com/kardianos/service/service_linux.go
  33. 13 0
      vendor/github.com/kardianos/service/service_nosu_test.go
  34. 178 0
      vendor/github.com/kardianos/service/service_su_test.go
  35. 175 0
      vendor/github.com/kardianos/service/service_systemd_linux.go
  36. 252 0
      vendor/github.com/kardianos/service/service_sysv_linux.go
  37. 57 0
      vendor/github.com/kardianos/service/service_test.go
  38. 88 0
      vendor/github.com/kardianos/service/service_unix.go
  39. 181 0
      vendor/github.com/kardianos/service/service_upstart_linux.go
  40. 389 0
      vendor/github.com/kardianos/service/service_windows.go
  41. 14 0
      vendor/github.com/kardianos/service/service_windows_test.go
  42. 23 0
      vendor/github.com/kardianos/service/servicetest_unix_test.go
  43. 30 0
      vendor/github.com/kardianos/service/servicetest_windows_test.go

+ 27 - 0
vendor/github.com/kardianos/osext/LICENSE

@@ -0,0 +1,27 @@
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 21 - 0
vendor/github.com/kardianos/osext/README.md

@@ -0,0 +1,21 @@
+### Extensions to the "os" package.
+
+[![GoDoc](https://godoc.org/github.com/kardianos/osext?status.svg)](https://godoc.org/github.com/kardianos/osext)
+
+## Find the current Executable and ExecutableFolder.
+
+As of go1.8 the Executable function may be found in `os`. The Executable function
+in the std lib `os` package is used if available.
+
+There is sometimes utility in finding the current executable file
+that is running. This can be used for upgrading the current executable
+or finding resources located relative to the executable file. Both
+working directory and the os.Args[0] value are arbitrary and cannot
+be relied on; os.Args[0] can be "faked".
+
+Multi-platform and supports:
+ * Linux
+ * OS X
+ * Windows
+ * Plan 9
+ * BSDs.

+ 33 - 0
vendor/github.com/kardianos/osext/osext.go

@@ -0,0 +1,33 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Extensions to the standard "os" package.
+package osext // import "github.com/kardianos/osext"
+
+import "path/filepath"
+
+var cx, ce = executableClean()
+
+func executableClean() (string, error) {
+	p, err := executable()
+	return filepath.Clean(p), err
+}
+
+// Executable returns an absolute path that can be used to
+// re-invoke the current program.
+// It may not be valid after the current program exits.
+func Executable() (string, error) {
+	return cx, ce
+}
+
+// Returns same path as Executable, returns just the folder
+// path. Excludes the executable name and any trailing slash.
+func ExecutableFolder() (string, error) {
+	p, err := Executable()
+	if err != nil {
+		return "", err
+	}
+
+	return filepath.Dir(p), nil
+}

+ 9 - 0
vendor/github.com/kardianos/osext/osext_go18.go

@@ -0,0 +1,9 @@
+//+build go1.8,!openbsd
+
+package osext
+
+import "os"
+
+func executable() (string, error) {
+	return os.Executable()
+}

+ 22 - 0
vendor/github.com/kardianos/osext/osext_plan9.go

@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//+build !go1.8
+
+package osext
+
+import (
+	"os"
+	"strconv"
+	"syscall"
+)
+
+func executable() (string, error) {
+	f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
+	if err != nil {
+		return "", err
+	}
+	defer f.Close()
+	return syscall.Fd2path(int(f.Fd()))
+}

+ 36 - 0
vendor/github.com/kardianos/osext/osext_procfs.go

@@ -0,0 +1,36 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.8,android !go1.8,linux !go1.8,netbsd !go1.8,solaris !go1.8,dragonfly
+
+package osext
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"runtime"
+	"strings"
+)
+
+func executable() (string, error) {
+	switch runtime.GOOS {
+	case "linux", "android":
+		const deletedTag = " (deleted)"
+		execpath, err := os.Readlink("/proc/self/exe")
+		if err != nil {
+			return execpath, err
+		}
+		execpath = strings.TrimSuffix(execpath, deletedTag)
+		execpath = strings.TrimPrefix(execpath, deletedTag)
+		return execpath, nil
+	case "netbsd":
+		return os.Readlink("/proc/curproc/exe")
+	case "dragonfly":
+		return os.Readlink("/proc/curproc/file")
+	case "solaris":
+		return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
+	}
+	return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
+}

+ 126 - 0
vendor/github.com/kardianos/osext/osext_sysctl.go

@@ -0,0 +1,126 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.8,darwin !go1.8,freebsd openbsd
+
+package osext
+
+import (
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"syscall"
+	"unsafe"
+)
+
+var initCwd, initCwdErr = os.Getwd()
+
+func executable() (string, error) {
+	var mib [4]int32
+	switch runtime.GOOS {
+	case "freebsd":
+		mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
+	case "darwin":
+		mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
+	case "openbsd":
+		mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */}
+	}
+
+	n := uintptr(0)
+	// Get length.
+	_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+	if errNum != 0 {
+		return "", errNum
+	}
+	if n == 0 { // This shouldn't happen.
+		return "", nil
+	}
+	buf := make([]byte, n)
+	_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
+	if errNum != 0 {
+		return "", errNum
+	}
+	if n == 0 { // This shouldn't happen.
+		return "", nil
+	}
+
+	var execPath string
+	switch runtime.GOOS {
+	case "openbsd":
+		// buf now contains **argv, with pointers to each of the C-style
+		// NULL terminated arguments.
+		var args []string
+		argv := uintptr(unsafe.Pointer(&buf[0]))
+	Loop:
+		for {
+			argp := *(**[1 << 20]byte)(unsafe.Pointer(argv))
+			if argp == nil {
+				break
+			}
+			for i := 0; uintptr(i) < n; i++ {
+				// we don't want the full arguments list
+				if string(argp[i]) == " " {
+					break Loop
+				}
+				if argp[i] != 0 {
+					continue
+				}
+				args = append(args, string(argp[:i]))
+				n -= uintptr(i)
+				break
+			}
+			if n < unsafe.Sizeof(argv) {
+				break
+			}
+			argv += unsafe.Sizeof(argv)
+			n -= unsafe.Sizeof(argv)
+		}
+		execPath = args[0]
+		// There is no canonical way to get an executable path on
+		// OpenBSD, so check PATH in case we are called directly
+		if execPath[0] != '/' && execPath[0] != '.' {
+			execIsInPath, err := exec.LookPath(execPath)
+			if err == nil {
+				execPath = execIsInPath
+			}
+		}
+	default:
+		for i, v := range buf {
+			if v == 0 {
+				buf = buf[:i]
+				break
+			}
+		}
+		execPath = string(buf)
+	}
+
+	var err error
+	// execPath will not be empty due to above checks.
+	// Try to get the absolute path if the execPath is not rooted.
+	if execPath[0] != '/' {
+		execPath, err = getAbs(execPath)
+		if err != nil {
+			return execPath, err
+		}
+	}
+	// For darwin KERN_PROCARGS may return the path to a symlink rather than the
+	// actual executable.
+	if runtime.GOOS == "darwin" {
+		if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
+			return execPath, err
+		}
+	}
+	return execPath, nil
+}
+
+func getAbs(execPath string) (string, error) {
+	if initCwdErr != nil {
+		return execPath, initCwdErr
+	}
+	// The execPath may begin with a "../" or a "./" so clean it first.
+	// Join the two paths, trailing and starting slashes undetermined, so use
+	// the generic Join function.
+	return filepath.Join(initCwd, filepath.Clean(execPath)), nil
+}

+ 203 - 0
vendor/github.com/kardianos/osext/osext_test.go

@@ -0,0 +1,203 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin linux freebsd netbsd windows openbsd
+
+package osext
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+const (
+	executableEnvVar = "OSTEST_OUTPUT_EXECUTABLE"
+
+	executableEnvValueMatch  = "match"
+	executableEnvValueDelete = "delete"
+)
+
+func TestPrintExecutable(t *testing.T) {
+	ef, err := Executable()
+	if err != nil {
+		t.Fatalf("Executable failed: %v", err)
+	}
+	t.Log("Executable:", ef)
+}
+func TestPrintExecutableFolder(t *testing.T) {
+	ef, err := ExecutableFolder()
+	if err != nil {
+		t.Fatalf("ExecutableFolder failed: %v", err)
+	}
+	t.Log("Executable Folder:", ef)
+}
+func TestExecutableFolder(t *testing.T) {
+	ef, err := ExecutableFolder()
+	if err != nil {
+		t.Fatalf("ExecutableFolder failed: %v", err)
+	}
+	if ef[len(ef)-1] == filepath.Separator {
+		t.Fatal("ExecutableFolder ends with a trailing slash.")
+	}
+}
+func TestExecutableMatch(t *testing.T) {
+	ep, err := Executable()
+	if err != nil {
+		t.Fatalf("Executable failed: %v", err)
+	}
+
+	// fullpath to be of the form "dir/prog".
+	dir := filepath.Dir(filepath.Dir(ep))
+	fullpath, err := filepath.Rel(dir, ep)
+	if err != nil {
+		t.Fatalf("filepath.Rel: %v", err)
+	}
+	// Make child start with a relative program path.
+	// Alter argv[0] for child to verify getting real path without argv[0].
+	cmd := &exec.Cmd{
+		Dir:  dir,
+		Path: fullpath,
+		Env:  []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueMatch)},
+	}
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("exec(self) failed: %v", err)
+	}
+	outs := string(out)
+	if !filepath.IsAbs(outs) {
+		t.Fatalf("Child returned %q, want an absolute path", out)
+	}
+	if !sameFile(outs, ep) {
+		t.Fatalf("Child returned %q, not the same file as %q", out, ep)
+	}
+}
+
+func TestExecutableDelete(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip()
+	}
+	fpath, err := Executable()
+	if err != nil {
+		t.Fatalf("Executable failed: %v", err)
+	}
+
+	r, w := io.Pipe()
+	stderrBuff := &bytes.Buffer{}
+	stdoutBuff := &bytes.Buffer{}
+	cmd := &exec.Cmd{
+		Path:   fpath,
+		Env:    []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueDelete)},
+		Stdin:  r,
+		Stderr: stderrBuff,
+		Stdout: stdoutBuff,
+	}
+	err = cmd.Start()
+	if err != nil {
+		t.Fatalf("exec(self) start failed: %v", err)
+	}
+
+	tempPath := fpath + "_copy"
+	_ = os.Remove(tempPath)
+
+	err = copyFile(tempPath, fpath)
+	if err != nil {
+		t.Fatalf("copy file failed: %v", err)
+	}
+	err = os.Remove(fpath)
+	if err != nil {
+		t.Fatalf("remove running test file failed: %v", err)
+	}
+	err = os.Rename(tempPath, fpath)
+	if err != nil {
+		t.Fatalf("rename copy to previous name failed: %v", err)
+	}
+
+	w.Write([]byte{0})
+	w.Close()
+
+	err = cmd.Wait()
+	if err != nil {
+		t.Fatalf("exec wait failed: %v", err)
+	}
+
+	childPath := stderrBuff.String()
+	if !filepath.IsAbs(childPath) {
+		t.Fatalf("Child returned %q, want an absolute path", childPath)
+	}
+	if !sameFile(childPath, fpath) {
+		t.Fatalf("Child returned %q, not the same file as %q", childPath, fpath)
+	}
+}
+
+func sameFile(fn1, fn2 string) bool {
+	fi1, err := os.Stat(fn1)
+	if err != nil {
+		return false
+	}
+	fi2, err := os.Stat(fn2)
+	if err != nil {
+		return false
+	}
+	return os.SameFile(fi1, fi2)
+}
+func copyFile(dest, src string) error {
+	df, err := os.Create(dest)
+	if err != nil {
+		return err
+	}
+	defer df.Close()
+
+	sf, err := os.Open(src)
+	if err != nil {
+		return err
+	}
+	defer sf.Close()
+
+	_, err = io.Copy(df, sf)
+	return err
+}
+
+func TestMain(m *testing.M) {
+	env := os.Getenv(executableEnvVar)
+	switch env {
+	case "":
+		os.Exit(m.Run())
+	case executableEnvValueMatch:
+		// First chdir to another path.
+		dir := "/"
+		if runtime.GOOS == "windows" {
+			dir = filepath.VolumeName(".")
+		}
+		os.Chdir(dir)
+		if ep, err := Executable(); err != nil {
+			fmt.Fprint(os.Stderr, "ERROR: ", err)
+		} else {
+			fmt.Fprint(os.Stderr, ep)
+		}
+	case executableEnvValueDelete:
+		bb := make([]byte, 1)
+		var err error
+		n, err := os.Stdin.Read(bb)
+		if err != nil {
+			fmt.Fprint(os.Stderr, "ERROR: ", err)
+			os.Exit(2)
+		}
+		if n != 1 {
+			fmt.Fprint(os.Stderr, "ERROR: n != 1, n == ", n)
+			os.Exit(2)
+		}
+		if ep, err := Executable(); err != nil {
+			fmt.Fprint(os.Stderr, "ERROR: ", err)
+		} else {
+			fmt.Fprint(os.Stderr, ep)
+		}
+	}
+	os.Exit(0)
+}

+ 36 - 0
vendor/github.com/kardianos/osext/osext_windows.go

@@ -0,0 +1,36 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//+build !go1.8
+
+package osext
+
+import (
+	"syscall"
+	"unicode/utf16"
+	"unsafe"
+)
+
+var (
+	kernel                = syscall.MustLoadDLL("kernel32.dll")
+	getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
+)
+
+// GetModuleFileName() with hModule = NULL
+func executable() (exePath string, err error) {
+	return getModuleFileName()
+}
+
+func getModuleFileName() (string, error) {
+	var n uint32
+	b := make([]uint16, syscall.MAX_PATH)
+	size := uint32(len(b))
+
+	r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
+	n = uint32(r0)
+	if n == 0 {
+		return "", e1
+	}
+	return string(utf16.Decode(b[0:n])), nil
+}

+ 0 - 0
vendor/github.com/kardianos/service/.gitignore


+ 16 - 0
vendor/github.com/kardianos/service/.travis.yml

@@ -0,0 +1,16 @@
+language: go
+go_import_path: github.com/kardianos/service
+sudo: required
+
+go:
+  - 1.6
+  - tip
+
+before_install:
+  - go get github.com/mattn/goveralls
+  - go get golang.org/x/tools/cmd/cover
+
+script:
+  - chmod +x linux-test-su.sh
+  - sudo ./linux-test-su.sh $GOPATH `which go`
+  - $GOPATH/bin/goveralls -service=travis-ci

+ 20 - 0
vendor/github.com/kardianos/service/LICENSE

@@ -0,0 +1,20 @@
+Copyright (c) 2015 Daniel Theophanes
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+   1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+
+   2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+
+   3. This notice may not be removed or altered from any source
+   distribution.

+ 14 - 0
vendor/github.com/kardianos/service/README.md

@@ -0,0 +1,14 @@
+# service [![GoDoc](https://godoc.org/github.com/kardianos/service?status.svg)](https://godoc.org/github.com/kardianos/service)
+
+service will install / un-install, start / stop, and run a program as a service (daemon).
+Currently supports Windows XP+, Linux/(systemd | Upstart | SysV), and OSX/Launchd.
+
+Windows controls services by setting up callbacks that is non-trivial. This
+is very different then other systems. This package provides the same API
+despite the substantial differences.
+It also can be used to detect how a program is called, from an interactive
+terminal or from a service manager.
+
+## BUGS
+ * Dependencies field is not implemented for Linux systems and Launchd.
+ * OS X when running as a UserService Interactive will not be accurate.

+ 21 - 0
vendor/github.com/kardianos/service/appveyor.yml

@@ -0,0 +1,21 @@
+version: "{build}"
+
+platform:
+  - x86
+  - x64
+
+clone_folder: c:\gopath\src\github.com\kardianos\service
+
+environment:
+  GOPATH: c:\gopath
+
+install:
+  - go version
+  - go env
+  - go get -v -t ./...
+
+build_script:
+  - go install -v ./...
+
+test_script:
+  - go test -v -tags su ./...

+ 48 - 0
vendor/github.com/kardianos/service/console.go

@@ -0,0 +1,48 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"log"
+	"os"
+)
+
+// ConsoleLogger logs to the std err.
+var ConsoleLogger = consoleLogger{}
+
+type consoleLogger struct {
+	info, warn, err *log.Logger
+}
+
+func init() {
+	ConsoleLogger.info = log.New(os.Stderr, "I: ", log.Ltime)
+	ConsoleLogger.warn = log.New(os.Stderr, "W: ", log.Ltime)
+	ConsoleLogger.err = log.New(os.Stderr, "E: ", log.Ltime)
+}
+
+func (c consoleLogger) Error(v ...interface{}) error {
+	c.err.Print(v...)
+	return nil
+}
+func (c consoleLogger) Warning(v ...interface{}) error {
+	c.warn.Print(v...)
+	return nil
+}
+func (c consoleLogger) Info(v ...interface{}) error {
+	c.info.Print(v...)
+	return nil
+}
+func (c consoleLogger) Errorf(format string, a ...interface{}) error {
+	c.err.Printf(format, a...)
+	return nil
+}
+func (c consoleLogger) Warningf(format string, a ...interface{}) error {
+	c.warn.Printf(format, a...)
+	return nil
+}
+func (c consoleLogger) Infof(format string, a ...interface{}) error {
+	c.info.Printf(format, a...)
+	return nil
+}

+ 104 - 0
vendor/github.com/kardianos/service/example/logging/main.go

@@ -0,0 +1,104 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// Simple service that only works by printing a log message every few seconds.
+package main
+
+import (
+	"flag"
+	"log"
+	"time"
+
+	"github.com/kardianos/service"
+)
+
+var logger service.Logger
+
+// Program structures.
+//  Define Start and Stop methods.
+type program struct {
+	exit chan struct{}
+}
+
+func (p *program) Start(s service.Service) error {
+	if service.Interactive() {
+		logger.Info("Running in terminal.")
+	} else {
+		logger.Info("Running under service manager.")
+	}
+	p.exit = make(chan struct{})
+
+	// Start should not block. Do the actual work async.
+	go p.run()
+	return nil
+}
+func (p *program) run() error {
+	logger.Infof("I'm running %v.", service.Platform())
+	ticker := time.NewTicker(2 * time.Second)
+	for {
+		select {
+		case tm := <-ticker.C:
+			logger.Infof("Still running at %v...", tm)
+		case <-p.exit:
+			ticker.Stop()
+			return nil
+		}
+	}
+}
+func (p *program) Stop(s service.Service) error {
+	// Any work in Stop should be quick, usually a few seconds at most.
+	logger.Info("I'm Stopping!")
+	close(p.exit)
+	return nil
+}
+
+// Service setup.
+//   Define service config.
+//   Create the service.
+//   Setup the logger.
+//   Handle service controls (optional).
+//   Run the service.
+func main() {
+	svcFlag := flag.String("service", "", "Control the system service.")
+	flag.Parse()
+
+	svcConfig := &service.Config{
+		Name:        "GoServiceExampleLogging",
+		DisplayName: "Go Service Example for Logging",
+		Description: "This is an example Go service that outputs log messages.",
+	}
+
+	prg := &program{}
+	s, err := service.New(prg, svcConfig)
+	if err != nil {
+		log.Fatal(err)
+	}
+	errs := make(chan error, 5)
+	logger, err = s.Logger(errs)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	go func() {
+		for {
+			err := <-errs
+			if err != nil {
+				log.Print(err)
+			}
+		}
+	}()
+
+	if len(*svcFlag) != 0 {
+		err := service.Control(s, *svcFlag)
+		if err != nil {
+			log.Printf("Valid actions: %q\n", service.ControlAction)
+			log.Fatal(err)
+		}
+		return
+	}
+	err = s.Run()
+	if err != nil {
+		logger.Error(err)
+	}
+}

+ 194 - 0
vendor/github.com/kardianos/service/example/runner/runner.go

@@ -0,0 +1,194 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// Simple service that only works by printing a log message every few seconds.
+package main
+
+import (
+	"encoding/json"
+	"flag"
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+
+	"github.com/kardianos/osext"
+	"github.com/kardianos/service"
+)
+
+// Config is the runner app config structure.
+type Config struct {
+	Name, DisplayName, Description string
+
+	Dir  string
+	Exec string
+	Args []string
+	Env  []string
+
+	Stderr, Stdout string
+}
+
+var logger service.Logger
+
+type program struct {
+	exit    chan struct{}
+	service service.Service
+
+	*Config
+
+	cmd *exec.Cmd
+}
+
+func (p *program) Start(s service.Service) error {
+	// Look for exec.
+	// Verify home directory.
+	fullExec, err := exec.LookPath(p.Exec)
+	if err != nil {
+		return fmt.Errorf("Failed to find executable %q: %v", p.Exec, err)
+	}
+
+	p.cmd = exec.Command(fullExec, p.Args...)
+	p.cmd.Dir = p.Dir
+	p.cmd.Env = append(os.Environ(), p.Env...)
+
+	go p.run()
+	return nil
+}
+func (p *program) run() {
+	logger.Info("Starting ", p.DisplayName)
+	defer func() {
+		if service.Interactive() {
+			p.Stop(p.service)
+		} else {
+			p.service.Stop()
+		}
+	}()
+
+	if p.Stderr != "" {
+		f, err := os.OpenFile(p.Stderr, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777)
+		if err != nil {
+			logger.Warningf("Failed to open std err %q: %v", p.Stderr, err)
+			return
+		}
+		defer f.Close()
+		p.cmd.Stderr = f
+	}
+	if p.Stdout != "" {
+		f, err := os.OpenFile(p.Stdout, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777)
+		if err != nil {
+			logger.Warningf("Failed to open std out %q: %v", p.Stdout, err)
+			return
+		}
+		defer f.Close()
+		p.cmd.Stdout = f
+	}
+
+	err := p.cmd.Run()
+	if err != nil {
+		logger.Warningf("Error running: %v", err)
+	}
+
+	return
+}
+func (p *program) Stop(s service.Service) error {
+	close(p.exit)
+	logger.Info("Stopping ", p.DisplayName)
+	if p.cmd.ProcessState.Exited() == false {
+		p.cmd.Process.Kill()
+	}
+	if service.Interactive() {
+		os.Exit(0)
+	}
+	return nil
+}
+
+func getConfigPath() (string, error) {
+	fullexecpath, err := osext.Executable()
+	if err != nil {
+		return "", err
+	}
+
+	dir, execname := filepath.Split(fullexecpath)
+	ext := filepath.Ext(execname)
+	name := execname[:len(execname)-len(ext)]
+
+	return filepath.Join(dir, name+".json"), nil
+}
+
+func getConfig(path string) (*Config, error) {
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	conf := &Config{}
+
+	r := json.NewDecoder(f)
+	err = r.Decode(&conf)
+	if err != nil {
+		return nil, err
+	}
+	return conf, nil
+}
+
+func main() {
+	svcFlag := flag.String("service", "", "Control the system service.")
+	flag.Parse()
+
+	configPath, err := getConfigPath()
+	if err != nil {
+		log.Fatal(err)
+	}
+	config, err := getConfig(configPath)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	svcConfig := &service.Config{
+		Name:        config.Name,
+		DisplayName: config.DisplayName,
+		Description: config.Description,
+	}
+
+	prg := &program{
+		exit: make(chan struct{}),
+
+		Config: config,
+	}
+	s, err := service.New(prg, svcConfig)
+	if err != nil {
+		log.Fatal(err)
+	}
+	prg.service = s
+
+	errs := make(chan error, 5)
+	logger, err = s.Logger(errs)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	go func() {
+		for {
+			err := <-errs
+			if err != nil {
+				log.Print(err)
+			}
+		}
+	}()
+
+	if len(*svcFlag) != 0 {
+		err := service.Control(s, *svcFlag)
+		if err != nil {
+			log.Printf("Valid actions: %q\n", service.ControlAction)
+			log.Fatal(err)
+		}
+		return
+	}
+	err = s.Run()
+	if err != nil {
+		logger.Error(err)
+	}
+}

+ 18 - 0
vendor/github.com/kardianos/service/example/runner/runner.json

@@ -0,0 +1,18 @@
+{
+	"Name": "builder",
+	"DisplayName": "Go Builder",
+	"Description": "Run the Go Builder",
+	
+	"Dir": "C:\\dev\\go\\src",
+	"Exec": "C:\\windows\\system32\\cmd.exe",
+	"Args": ["/C","C:\\dev\\go\\src\\all.bat"],
+	"Env": [
+		"PATH=C:\\TDM-GCC-64\\bin;C:\\Program Files (x86)\\Git\\cmd",
+		"GOROOT_BOOTSTRAP=C:\\dev\\go_ready",
+		"HOMEDRIVE=C:",
+		"HOMEPATH=\\Documents and Settings\\Administrator"
+	],
+	
+	"Stderr": "C:\\builder_err.log",
+	"Stdout": "C:\\builder_out.log"
+}

+ 51 - 0
vendor/github.com/kardianos/service/example/simple/main.go

@@ -0,0 +1,51 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// simple does nothing except block while running the service.
+package main
+
+import (
+	"log"
+
+	"github.com/kardianos/service"
+)
+
+var logger service.Logger
+
+type program struct{}
+
+func (p *program) Start(s service.Service) error {
+	// Start should not block. Do the actual work async.
+	go p.run()
+	return nil
+}
+func (p *program) run() {
+	// Do work here
+}
+func (p *program) Stop(s service.Service) error {
+	// Stop should not block. Return with a few seconds.
+	return nil
+}
+
+func main() {
+	svcConfig := &service.Config{
+		Name:        "GoServiceExampleSimple",
+		DisplayName: "Go Service Example",
+		Description: "This is an example Go service.",
+	}
+
+	prg := &program{}
+	s, err := service.New(prg, svcConfig)
+	if err != nil {
+		log.Fatal(err)
+	}
+	logger, err = s.Logger(nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+	err = s.Run()
+	if err != nil {
+		logger.Error(err)
+	}
+}

+ 62 - 0
vendor/github.com/kardianos/service/example/stopPause/main.go

@@ -0,0 +1,62 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// simple does nothing except block while running the service.
+package main
+
+import (
+	"log"
+	"os"
+	"time"
+
+	"github.com/kardianos/service"
+)
+
+var logger service.Logger
+
+type program struct{}
+
+func (p *program) Start(s service.Service) error {
+	// Start should not block. Do the actual work async.
+	go p.run()
+	return nil
+}
+func (p *program) run() {
+	// Do work here
+}
+func (p *program) Stop(s service.Service) error {
+	// Stop should not block. Return with a few seconds.
+	<-time.After(time.Second * 13)
+	return nil
+}
+
+func main() {
+	svcConfig := &service.Config{
+		Name:        "GoServiceExampleStopPause",
+		DisplayName: "Go Service Example: Stop Pause",
+		Description: "This is an example Go service that pauses on stop.",
+	}
+
+	prg := &program{}
+	s, err := service.New(prg, svcConfig)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if len(os.Args) > 1 {
+		err = service.Control(s, os.Args[1])
+		if err != nil {
+			log.Fatal(err)
+		}
+		return
+	}
+
+	logger, err = s.Logger(nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+	err = s.Run()
+	if err != nil {
+		logger.Error(err)
+	}
+}

+ 15 - 0
vendor/github.com/kardianos/service/linux-test-su.sh

@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+# This script is used to run the tests under linux as root
+#
+# Usage:
+#    linux-test-su.sh goPath goBinPath
+#
+# goPath is the standard GOPATH
+# goBinPath is the location of go
+#
+# Typical usage:
+#    sudo ./linux-test-su.sh $GOPATH `which go`
+
+export GOPATH=$1
+export GOROOT=`dirname $(dirname $2)`
+$GOROOT/bin/go test -v -tags su ./...

+ 35 - 0
vendor/github.com/kardianos/service/linux_test/Makefile

@@ -0,0 +1,35 @@
+
+all: sysv systemd upstart clean
+
+test:
+	@go test -c ..
+
+clean:
+	-rm service.test
+
+sysv: test
+	@echo sysv
+	@cp service.test sysv/
+	@docker build -q --tag="service.test.sysv" sysv
+	@-docker run service.test.sysv
+	@-docker rm $(shell docker ps -l -q)
+	@-docker rmi -f service.test.sysv
+	@-rm sysv/service.test
+
+systemd: test
+	@echo systemd
+	@cp service.test systemd/
+	@docker build -q --tag="service.test.systemd" systemd
+	@-docker run --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro service.test.systemd
+	@-docker rm $(shell docker ps -l -q)
+	@-docker rmi -f service.test.systemd
+	@-rm systemd/service.test
+
+upstart: test
+	@echo upstart
+	@cp service.test upstart/
+	@docker build -q --tag="service.test.upstart" upstart
+	@-docker run service.test.upstart
+	@-docker rm $(shell docker ps -l -q)
+	@-docker rmi -f service.test.upstart
+	@-rm upstart/service.test

+ 6 - 0
vendor/github.com/kardianos/service/linux_test/README.md

@@ -0,0 +1,6 @@
+## Docker images to help vet linux configurations.
+
+Although the actual init systems won't run in docker,
+it may still be usefull to attempt to run it in different
+environments.
+

+ 3 - 0
vendor/github.com/kardianos/service/linux_test/systemd/Dockerfile

@@ -0,0 +1,3 @@
+FROM minimum2scp/systemd:latest
+ADD service.test /tmp/
+CMD /tmp/service.test -test.v=true

+ 3 - 0
vendor/github.com/kardianos/service/linux_test/sysv/Dockerfile

@@ -0,0 +1,3 @@
+FROM minimum2scp/baseimage:latest
+ADD service.test /tmp/
+CMD /tmp/service.test -test.v=true

+ 3 - 0
vendor/github.com/kardianos/service/linux_test/upstart/Dockerfile

@@ -0,0 +1,3 @@
+FROM ubuntu:14.04
+ADD service.test /tmp/
+CMD /tmp/service.test -test.v=true

+ 20 - 0
vendor/github.com/kardianos/service/name_test.go

@@ -0,0 +1,20 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestPlatformName(t *testing.T) {
+	got := Platform()
+	t.Logf("Platform is %v", got)
+	wantPrefix := runtime.GOOS + "-"
+	if !strings.HasPrefix(got, wantPrefix) {
+		t.Errorf("Platform() want: /^%s.*$/, got: %s", wantPrefix, got)
+	}
+}

+ 16 - 0
vendor/github.com/kardianos/service/pre_go1.8.go

@@ -0,0 +1,16 @@
+//+build !go1.8
+
+package service
+
+import (
+	"path/filepath"
+
+	"github.com/kardianos/osext"
+)
+
+func (c *Config) execPath() (string, error) {
+	if len(c.Executable) != 0 {
+		return filepath.Abs(c.Executable)
+	}
+	return osext.Executable()
+}

+ 362 - 0
vendor/github.com/kardianos/service/service.go

@@ -0,0 +1,362 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// Package service provides a simple way to create a system service.
+// Currently supports Windows, Linux/(systemd | Upstart | SysV), and OSX/Launchd.
+//
+// Windows controls services by setting up callbacks that is non-trivial. This
+// is very different then other systems. This package provides the same API
+// despite the substantial differences.
+// It also can be used to detect how a program is called, from an interactive
+// terminal or from a service manager.
+//
+// Examples in the example/ folder.
+//
+//	package main
+//
+//	import (
+//		"log"
+//
+//		"github.com/kardianos/service"
+//	)
+//
+//	var logger service.Logger
+//
+//	type program struct{}
+//
+//	func (p *program) Start(s service.Service) error {
+//		// Start should not block. Do the actual work async.
+//		go p.run()
+//		return nil
+//	}
+//	func (p *program) run() {
+//		// Do work here
+//	}
+//	func (p *program) Stop(s service.Service) error {
+//		// Stop should not block. Return with a few seconds.
+//		return nil
+//	}
+//
+//	func main() {
+//		svcConfig := &service.Config{
+//			Name:        "GoServiceTest",
+//			DisplayName: "Go Service Test",
+//			Description: "This is a test Go service.",
+//		}
+//
+//		prg := &program{}
+//		s, err := service.New(prg, svcConfig)
+//		if err != nil {
+//			log.Fatal(err)
+//		}
+//		logger, err = s.Logger(nil)
+//		if err != nil {
+//			log.Fatal(err)
+//		}
+//		err = s.Run()
+//		if err != nil {
+//			logger.Error(err)
+//		}
+//	}
+package service // import "github.com/kardianos/service"
+
+import (
+	"errors"
+	"fmt"
+)
+
+const (
+	optionKeepAlive            = "KeepAlive"
+	optionKeepAliveDefault     = true
+	optionRunAtLoad            = "RunAtLoad"
+	optionRunAtLoadDefault     = false
+	optionUserService          = "UserService"
+	optionUserServiceDefault   = false
+	optionSessionCreate        = "SessionCreate"
+	optionSessionCreateDefault = false
+
+	optionRunWait      = "RunWait"
+	optionReloadSignal = "ReloadSignal"
+	optionPIDFile      = "PIDFile"
+)
+
+// Config provides the setup for a Service. The Name field is required.
+type Config struct {
+	Name        string   // Required name of the service. No spaces suggested.
+	DisplayName string   // Display name, spaces allowed.
+	Description string   // Long description of service.
+	UserName    string   // Run as username.
+	Arguments   []string // Run with arguments.
+
+	// Optional field to specify the executable for service.
+	// If empty the current executable is used.
+	Executable string
+
+	// Array of service dependencies.
+	// Not yet implemented on Linux or OS X.
+	Dependencies []string
+
+	// The following fields are not supported on Windows.
+	WorkingDirectory string // Initial working directory.
+	ChRoot           string
+
+	// System specific options.
+	//  * OS X
+	//    - KeepAlive     bool (true)
+	//    - RunAtLoad     bool (false)
+	//    - UserService   bool (false) - Install as a current user service.
+	//    - SessionCreate bool (false) - Create a full user session.
+	//  * POSIX
+	//    - RunWait      func() (wait for SIGNAL) - Do not install signal but wait for this function to return.
+	//    - ReloadSignal string () [USR1, ...] - Signal to send on reaload.
+	//    - PIDFile     string () [/run/prog.pid] - Location of the PID file.
+	Option KeyValue
+}
+
+var (
+	system         System
+	systemRegistry []System
+)
+
+var (
+	// ErrNameFieldRequired is returned when Conifg.Name is empty.
+	ErrNameFieldRequired = errors.New("Config.Name field is required.")
+	// ErrNoServiceSystemDetected is returned when no system was detected.
+	ErrNoServiceSystemDetected = errors.New("No service system detected.")
+)
+
+// New creates a new service based on a service interface and configuration.
+func New(i Interface, c *Config) (Service, error) {
+	if len(c.Name) == 0 {
+		return nil, ErrNameFieldRequired
+	}
+	if system == nil {
+		return nil, ErrNoServiceSystemDetected
+	}
+	return system.New(i, c)
+}
+
+// KeyValue provides a list of platform specific options. See platform docs for
+// more details.
+type KeyValue map[string]interface{}
+
+// bool returns the value of the given name, assuming the value is a boolean.
+// If the value isn't found or is not of the type, the defaultValue is returned.
+func (kv KeyValue) bool(name string, defaultValue bool) bool {
+	if v, found := kv[name]; found {
+		if castValue, is := v.(bool); is {
+			return castValue
+		}
+	}
+	return defaultValue
+}
+
+// int returns the value of the given name, assuming the value is an int.
+// If the value isn't found or is not of the type, the defaultValue is returned.
+func (kv KeyValue) int(name string, defaultValue int) int {
+	if v, found := kv[name]; found {
+		if castValue, is := v.(int); is {
+			return castValue
+		}
+	}
+	return defaultValue
+}
+
+// string returns the value of the given name, assuming the value is a string.
+// If the value isn't found or is not of the type, the defaultValue is returned.
+func (kv KeyValue) string(name string, defaultValue string) string {
+	if v, found := kv[name]; found {
+		if castValue, is := v.(string); is {
+			return castValue
+		}
+	}
+	return defaultValue
+}
+
+// float64 returns the value of the given name, assuming the value is a float64.
+// If the value isn't found or is not of the type, the defaultValue is returned.
+func (kv KeyValue) float64(name string, defaultValue float64) float64 {
+	if v, found := kv[name]; found {
+		if castValue, is := v.(float64); is {
+			return castValue
+		}
+	}
+	return defaultValue
+}
+
+// funcSingle returns the value of the given name, assuming the value is a float64.
+// If the value isn't found or is not of the type, the defaultValue is returned.
+func (kv KeyValue) funcSingle(name string, defaultValue func()) func() {
+	if v, found := kv[name]; found {
+		if castValue, is := v.(func()); is {
+			return castValue
+		}
+	}
+	return defaultValue
+}
+
+// Platform returns a description of the system service.
+func Platform() string {
+	if system == nil {
+		return ""
+	}
+	return system.String()
+}
+
+// Interactive returns false if running under the OS service manager
+// and true otherwise.
+func Interactive() bool {
+	if system == nil {
+		return true
+	}
+	return system.Interactive()
+}
+
+func newSystem() System {
+	for _, choice := range systemRegistry {
+		if choice.Detect() == false {
+			continue
+		}
+		return choice
+	}
+	return nil
+}
+
+// ChooseSystem chooses a system from the given system services.
+// SystemServices are considered in the order they are suggested.
+// Calling this may change what Interactive and Platform return.
+func ChooseSystem(a ...System) {
+	systemRegistry = a
+	system = newSystem()
+}
+
+// ChosenSystem returns the system that service will use.
+func ChosenSystem() System {
+	return system
+}
+
+// AvailableSystems returns the list of system services considered
+// when choosing the system service.
+func AvailableSystems() []System {
+	return systemRegistry
+}
+
+// System represents the service manager that is available.
+type System interface {
+	// String returns a description of the system.
+	String() string
+
+	// Detect returns true if the system is available to use.
+	Detect() bool
+
+	// Interactive returns false if running under the system service manager
+	// and true otherwise.
+	Interactive() bool
+
+	// New creates a new service for this system.
+	New(i Interface, c *Config) (Service, error)
+}
+
+// Interface represents the service interface for a program. Start runs before
+// the hosting process is granted control and Stop runs when control is returned.
+//
+//   1. OS service manager executes user program.
+//   2. User program sees it is executed from a service manager (IsInteractive is false).
+//   3. User program calls Service.Run() which blocks.
+//   4. Interface.Start() is called and quickly returns.
+//   5. User program runs.
+//   6. OS service manager signals the user program to stop.
+//   7. Interface.Stop() is called and quickly returns.
+//      - For a successful exit, os.Exit should not be called in Interface.Stop().
+//   8. Service.Run returns.
+//   9. User program should quickly exit.
+type Interface interface {
+	// Start provides a place to initiate the service. The service doesn't not
+	// signal a completed start until after this function returns, so the
+	// Start function must not take more then a few seconds at most.
+	Start(s Service) error
+
+	// Stop provides a place to clean up program execution before it is terminated.
+	// It should not take more then a few seconds to execute.
+	// Stop should not call os.Exit directly in the function.
+	Stop(s Service) error
+}
+
+// TODO: Add Configure to Service interface.
+
+// Service represents a service that can be run or controlled.
+type Service interface {
+	// Run should be called shortly after the program entry point.
+	// After Interface.Stop has finished running, Run will stop blocking.
+	// After Run stops blocking, the program must exit shortly after.
+	Run() error
+
+	// Start signals to the OS service manager the given service should start.
+	Start() error
+
+	// Stop signals to the OS service manager the given service should stop.
+	Stop() error
+
+	// Restart signals to the OS service manager the given service should stop then start.
+	Restart() error
+
+	// Install setups up the given service in the OS service manager. This may require
+	// greater rights. Will return an error if it is already installed.
+	Install() error
+
+	// Uninstall removes the given service from the OS service manager. This may require
+	// greater rights. Will return an error if the service is not present.
+	Uninstall() error
+
+	// Opens and returns a system logger. If the user program is running
+	// interactively rather then as a service, the returned logger will write to
+	// os.Stderr. If errs is non-nil errors will be sent on errs as well as
+	// returned from Logger's functions.
+	Logger(errs chan<- error) (Logger, error)
+
+	// SystemLogger opens and returns a system logger. If errs is non-nil errors
+	// will be sent on errs as well as returned from Logger's functions.
+	SystemLogger(errs chan<- error) (Logger, error)
+
+	// String displays the name of the service. The display name if present,
+	// otherwise the name.
+	String() string
+}
+
+// ControlAction list valid string texts to use in Control.
+var ControlAction = [5]string{"start", "stop", "restart", "install", "uninstall"}
+
+// Control issues control functions to the service from a given action string.
+func Control(s Service, action string) error {
+	var err error
+	switch action {
+	case ControlAction[0]:
+		err = s.Start()
+	case ControlAction[1]:
+		err = s.Stop()
+	case ControlAction[2]:
+		err = s.Restart()
+	case ControlAction[3]:
+		err = s.Install()
+	case ControlAction[4]:
+		err = s.Uninstall()
+	default:
+		err = fmt.Errorf("Unknown action %s", action)
+	}
+	if err != nil {
+		return fmt.Errorf("Failed to %s %v: %v", action, s, err)
+	}
+	return nil
+}
+
+// Logger writes to the system log.
+type Logger interface {
+	Error(v ...interface{}) error
+	Warning(v ...interface{}) error
+	Info(v ...interface{}) error
+
+	Errorf(format string, a ...interface{}) error
+	Warningf(format string, a ...interface{}) error
+	Infof(format string, a ...interface{}) error
+}

+ 240 - 0
vendor/github.com/kardianos/service/service_darwin.go

@@ -0,0 +1,240 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"os/signal"
+	"os/user"
+	"path/filepath"
+	"syscall"
+	"text/template"
+	"time"
+)
+
+const maxPathSize = 32 * 1024
+
+const version = "darwin-launchd"
+
+type darwinSystem struct{}
+
+func (darwinSystem) String() string {
+	return version
+}
+func (darwinSystem) Detect() bool {
+	return true
+}
+func (darwinSystem) Interactive() bool {
+	return interactive
+}
+func (darwinSystem) New(i Interface, c *Config) (Service, error) {
+	s := &darwinLaunchdService{
+		i:      i,
+		Config: c,
+
+		userService: c.Option.bool(optionUserService, optionUserServiceDefault),
+	}
+
+	return s, nil
+}
+
+func init() {
+	ChooseSystem(darwinSystem{})
+}
+
+var interactive = false
+
+func init() {
+	var err error
+	interactive, err = isInteractive()
+	if err != nil {
+		panic(err)
+	}
+}
+
+func isInteractive() (bool, error) {
+	// TODO: The PPID of Launchd is 1. The PPid of a service process should match launchd's PID.
+	return os.Getppid() != 1, nil
+}
+
+type darwinLaunchdService struct {
+	i Interface
+	*Config
+
+	userService bool
+}
+
+func (s *darwinLaunchdService) String() string {
+	if len(s.DisplayName) > 0 {
+		return s.DisplayName
+	}
+	return s.Name
+}
+
+func (s *darwinLaunchdService) getHomeDir() (string, error) {
+	u, err := user.Current()
+	if err == nil {
+		return u.HomeDir, nil
+	}
+
+	// alternate methods
+	homeDir := os.Getenv("HOME") // *nix
+	if homeDir == "" {
+		return "", errors.New("User home directory not found.")
+	}
+	return homeDir, nil
+}
+
+func (s *darwinLaunchdService) getServiceFilePath() (string, error) {
+	if s.userService {
+		homeDir, err := s.getHomeDir()
+		if err != nil {
+			return "", err
+		}
+		return homeDir + "/Library/LaunchAgents/" + s.Name + ".plist", nil
+	}
+	return "/Library/LaunchDaemons/" + s.Name + ".plist", nil
+}
+
+func (s *darwinLaunchdService) Install() error {
+	confPath, err := s.getServiceFilePath()
+	if err != nil {
+		return err
+	}
+	_, err = os.Stat(confPath)
+	if err == nil {
+		return fmt.Errorf("Init already exists: %s", confPath)
+	}
+
+	if s.userService {
+		// Ensure that ~/Library/LaunchAgents exists.
+		err = os.MkdirAll(filepath.Dir(confPath), 0700)
+		if err != nil {
+			return err
+		}
+	}
+
+	f, err := os.Create(confPath)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	path, err := s.execPath()
+	if err != nil {
+		return err
+	}
+
+	var to = &struct {
+		*Config
+		Path string
+
+		KeepAlive, RunAtLoad bool
+		SessionCreate        bool
+	}{
+		Config:        s.Config,
+		Path:          path,
+		KeepAlive:     s.Option.bool(optionKeepAlive, optionKeepAliveDefault),
+		RunAtLoad:     s.Option.bool(optionRunAtLoad, optionRunAtLoadDefault),
+		SessionCreate: s.Option.bool(optionSessionCreate, optionSessionCreateDefault),
+	}
+
+	functions := template.FuncMap{
+		"bool": func(v bool) string {
+			if v {
+				return "true"
+			}
+			return "false"
+		},
+	}
+	t := template.Must(template.New("launchdConfig").Funcs(functions).Parse(launchdConfig))
+	return t.Execute(f, to)
+}
+
+func (s *darwinLaunchdService) Uninstall() error {
+	s.Stop()
+
+	confPath, err := s.getServiceFilePath()
+	if err != nil {
+		return err
+	}
+	return os.Remove(confPath)
+}
+
+func (s *darwinLaunchdService) Start() error {
+	confPath, err := s.getServiceFilePath()
+	if err != nil {
+		return err
+	}
+	return run("launchctl", "load", confPath)
+}
+func (s *darwinLaunchdService) Stop() error {
+	confPath, err := s.getServiceFilePath()
+	if err != nil {
+		return err
+	}
+	return run("launchctl", "unload", confPath)
+}
+func (s *darwinLaunchdService) Restart() error {
+	err := s.Stop()
+	if err != nil {
+		return err
+	}
+	time.Sleep(50 * time.Millisecond)
+	return s.Start()
+}
+
+func (s *darwinLaunchdService) Run() error {
+	var err error
+
+	err = s.i.Start(s)
+	if err != nil {
+		return err
+	}
+
+	s.Option.funcSingle(optionRunWait, func() {
+		var sigChan = make(chan os.Signal, 3)
+		signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
+		<-sigChan
+	})()
+
+	return s.i.Stop(s)
+}
+
+func (s *darwinLaunchdService) Logger(errs chan<- error) (Logger, error) {
+	if interactive {
+		return ConsoleLogger, nil
+	}
+	return s.SystemLogger(errs)
+}
+func (s *darwinLaunchdService) SystemLogger(errs chan<- error) (Logger, error) {
+	return newSysLogger(s.Name, errs)
+}
+
+var launchdConfig = `<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
+"http://www.apple.com/DTDs/PropertyList-1.0.dtd" >
+<plist version='1.0'>
+<dict>
+<key>Label</key><string>{{html .Name}}</string>
+<key>ProgramArguments</key>
+<array>
+        <string>{{html .Path}}</string>
+{{range .Config.Arguments}}
+        <string>{{html .}}</string>
+{{end}}
+</array>
+{{if .UserName}}<key>UserName</key><string>{{html .UserName}}</string>{{end}}
+{{if .ChRoot}}<key>RootDirectory</key><string>{{html .ChRoot}}</string>{{end}}
+{{if .WorkingDirectory}}<key>WorkingDirectory</key><string>{{html .WorkingDirectory}}</string>{{end}}
+<key>SessionCreate</key><{{bool .SessionCreate}}/>
+<key>KeepAlive</key><{{bool .KeepAlive}}/>
+<key>RunAtLoad</key><{{bool .RunAtLoad}}/>
+<key>Disabled</key><false/>
+</dict>
+</plist>
+`

+ 15 - 0
vendor/github.com/kardianos/service/service_go1.8.go

@@ -0,0 +1,15 @@
+//+build go1.8
+
+package service
+
+import (
+	"os"
+	"path/filepath"
+)
+
+func (c *Config) execPath() (string, error) {
+	if len(c.Executable) != 0 {
+		return filepath.Abs(c.Executable)
+	}
+	return os.Executable()
+}

+ 75 - 0
vendor/github.com/kardianos/service/service_linux.go

@@ -0,0 +1,75 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"os"
+	"strings"
+)
+
+type linuxSystemService struct {
+	name        string
+	detect      func() bool
+	interactive func() bool
+	new         func(i Interface, c *Config) (Service, error)
+}
+
+func (sc linuxSystemService) String() string {
+	return sc.name
+}
+func (sc linuxSystemService) Detect() bool {
+	return sc.detect()
+}
+func (sc linuxSystemService) Interactive() bool {
+	return sc.interactive()
+}
+func (sc linuxSystemService) New(i Interface, c *Config) (Service, error) {
+	return sc.new(i, c)
+}
+
+func init() {
+	ChooseSystem(linuxSystemService{
+		name:   "linux-systemd",
+		detect: isSystemd,
+		interactive: func() bool {
+			is, _ := isInteractive()
+			return is
+		},
+		new: newSystemdService,
+	},
+		linuxSystemService{
+			name:   "linux-upstart",
+			detect: isUpstart,
+			interactive: func() bool {
+				is, _ := isInteractive()
+				return is
+			},
+			new: newUpstartService,
+		},
+		linuxSystemService{
+			name:   "unix-systemv",
+			detect: func() bool { return true },
+			interactive: func() bool {
+				is, _ := isInteractive()
+				return is
+			},
+			new: newSystemVService,
+		},
+	)
+}
+
+func isInteractive() (bool, error) {
+	// TODO: This is not true for user services.
+	return os.Getppid() != 1, nil
+}
+
+var tf = map[string]interface{}{
+	"cmd": func(s string) string {
+		return `"` + strings.Replace(s, `"`, `\"`, -1) + `"`
+	},
+	"cmdEscape": func(s string) string {
+		return strings.Replace(s, " ", `\x20`, -1)
+	},
+}

+ 13 - 0
vendor/github.com/kardianos/service/service_nosu_test.go

@@ -0,0 +1,13 @@
+// Copyright 2016 Lawrence Woodman <[email protected]>
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// +build !su
+
+package service_test
+
+import "testing"
+
+func TestInstallRunRestartStopRemove(t *testing.T) {
+	t.Skip("skipping test as not running as root/admin (Build tag: su)")
+}

+ 178 - 0
vendor/github.com/kardianos/service/service_su_test.go

@@ -0,0 +1,178 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// This needs to be run as root/admin hence the reason there is a build tag
+// +build su
+
+package service_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"regexp"
+	"testing"
+	"time"
+
+	"github.com/kardianos/service"
+)
+
+const runAsServiceArg = "RunThisAsService"
+
+func TestMain(m *testing.M) {
+	if len(os.Args) == 2 {
+		os.Exit(m.Run())
+	} else if len(os.Args) == 4 && os.Args[2] == runAsServiceArg {
+		reportDir := os.Args[3]
+		writeReport(reportDir, "call")
+		runService()
+		writeReport(reportDir, "finished")
+		os.Exit(0)
+	}
+
+	log.Fatalf("Invalid arguments: %v", os.Args)
+}
+
+func TestInstallRunRestartStopRemove(t *testing.T) {
+	p := &program{}
+	reportDir := mustTempDir(t)
+	defer os.RemoveAll(reportDir)
+
+	s := mustNewRunAsService(t, p, reportDir)
+	_ = s.Uninstall()
+
+	if err := s.Install(); err != nil {
+		t.Fatal("Install", err)
+	}
+	defer s.Uninstall()
+
+	if err := s.Start(); err != nil {
+		t.Fatal("Start", err)
+	}
+	defer s.Stop()
+	checkReport(t, reportDir, "Start()", 1, 0)
+
+	if err := s.Restart(); err != nil {
+		t.Fatal("restart", err)
+	}
+
+	checkReport(t, reportDir, "Restart()", 2, 1)
+	p.numStopped = 0
+	if err := s.Stop(); err != nil {
+		t.Fatal("stop", err)
+	}
+	checkReport(t, reportDir, "Stop()", 2, 2)
+
+	if err := s.Uninstall(); err != nil {
+		t.Fatal("uninstall", err)
+	}
+}
+
+func runService() {
+	p := &program{}
+	sc := &service.Config{
+		Name: "go_service_test",
+	}
+	s, err := service.New(p, sc)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if err = s.Run(); err != nil {
+		log.Fatal(err)
+	}
+}
+
+func mustTempDir(t *testing.T) string {
+	dir, err := ioutil.TempDir("", "servicetest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	return dir
+}
+
+func writeReport(reportDir string, action string) {
+	b := []byte("go_test_service_report")
+	timeStamp := time.Now().UnixNano()
+	err := ioutil.WriteFile(
+		filepath.Join(reportDir, fmt.Sprintf("%d-%s", timeStamp, action)),
+		b,
+		0644,
+	)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+var matchActionRegexp = regexp.MustCompile("^(\\d+-)([a-z]*)$")
+
+func getReport(
+	t *testing.T,
+	reportDir string,
+) (numCalls int, numFinished int) {
+	numCalls = 0
+	numFinished = 0
+	files, err := ioutil.ReadDir(reportDir)
+	if err != nil {
+		t.Fatalf("ReadDir(%s) err: %s", reportDir, err)
+	}
+
+	for _, file := range files {
+		if matchActionRegexp.MatchString(file.Name()) {
+			action := matchActionRegexp.ReplaceAllString(file.Name(), "$2")
+			switch action {
+			case "call":
+				numCalls++
+			case "finished":
+				numFinished++
+			default:
+				t.Fatalf("getReport() found report with incorrect action: %s", action)
+			}
+		}
+	}
+	return
+}
+
+func checkReport(
+	t *testing.T,
+	reportDir string,
+	msgPrefix string,
+	wantNumCalled int,
+	wantNumFinished int,
+) {
+	var numCalled int
+	var numFinished int
+	for i := 0; i < 25; i++ {
+		numCalled, numFinished = getReport(t, reportDir)
+		<-time.After(200 * time.Millisecond)
+		if numCalled == wantNumCalled && numFinished == wantNumFinished {
+			return
+		}
+	}
+	if numCalled != wantNumCalled {
+		t.Fatalf("%s - numCalled: %d, want %d",
+			msgPrefix, numCalled, wantNumCalled)
+	}
+	if numFinished != wantNumFinished {
+		t.Fatalf("%s - numFinished: %d, want %d",
+			msgPrefix, numFinished, wantNumFinished)
+	}
+}
+
+func mustNewRunAsService(
+	t *testing.T,
+	p *program,
+	reportDir string,
+) service.Service {
+	sc := &service.Config{
+		Name:      "go_service_test",
+		Arguments: []string{"-test.v=true", runAsServiceArg, reportDir},
+	}
+	s, err := service.New(p, sc)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return s
+}

+ 175 - 0
vendor/github.com/kardianos/service/service_systemd_linux.go

@@ -0,0 +1,175 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"os/signal"
+	"syscall"
+	"text/template"
+)
+
+func isSystemd() bool {
+	if _, err := os.Stat("/run/systemd/system"); err == nil {
+		return true
+	}
+	return false
+}
+
+type systemd struct {
+	i Interface
+	*Config
+}
+
+func newSystemdService(i Interface, c *Config) (Service, error) {
+	s := &systemd{
+		i:      i,
+		Config: c,
+	}
+
+	return s, nil
+}
+
+func (s *systemd) String() string {
+	if len(s.DisplayName) > 0 {
+		return s.DisplayName
+	}
+	return s.Name
+}
+
+// Systemd services should be supported, but are not currently.
+var errNoUserServiceSystemd = errors.New("User services are not supported on systemd.")
+
+func (s *systemd) configPath() (cp string, err error) {
+	if s.Option.bool(optionUserService, optionUserServiceDefault) {
+		err = errNoUserServiceSystemd
+		return
+	}
+	cp = "/etc/systemd/system/" + s.Config.Name + ".service"
+	return
+}
+func (s *systemd) template() *template.Template {
+	return template.Must(template.New("").Funcs(tf).Parse(systemdScript))
+}
+
+func (s *systemd) Install() error {
+	confPath, err := s.configPath()
+	if err != nil {
+		return err
+	}
+	_, err = os.Stat(confPath)
+	if err == nil {
+		return fmt.Errorf("Init already exists: %s", confPath)
+	}
+
+	f, err := os.Create(confPath)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	path, err := s.execPath()
+	if err != nil {
+		return err
+	}
+
+	var to = &struct {
+		*Config
+		Path         string
+		ReloadSignal string
+		PIDFile      string
+	}{
+		s.Config,
+		path,
+		s.Option.string(optionReloadSignal, ""),
+		s.Option.string(optionPIDFile, ""),
+	}
+
+	err = s.template().Execute(f, to)
+	if err != nil {
+		return err
+	}
+
+	err = run("systemctl", "enable", s.Name+".service")
+	if err != nil {
+		return err
+	}
+	return run("systemctl", "daemon-reload")
+}
+
+func (s *systemd) Uninstall() error {
+	err := run("systemctl", "disable", s.Name+".service")
+	if err != nil {
+		return err
+	}
+	cp, err := s.configPath()
+	if err != nil {
+		return err
+	}
+	if err := os.Remove(cp); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (s *systemd) Logger(errs chan<- error) (Logger, error) {
+	if system.Interactive() {
+		return ConsoleLogger, nil
+	}
+	return s.SystemLogger(errs)
+}
+func (s *systemd) SystemLogger(errs chan<- error) (Logger, error) {
+	return newSysLogger(s.Name, errs)
+}
+
+func (s *systemd) Run() (err error) {
+	err = s.i.Start(s)
+	if err != nil {
+		return err
+	}
+
+	s.Option.funcSingle(optionRunWait, func() {
+		var sigChan = make(chan os.Signal, 3)
+		signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
+		<-sigChan
+	})()
+
+	return s.i.Stop(s)
+}
+
+func (s *systemd) Start() error {
+	return run("systemctl", "start", s.Name+".service")
+}
+
+func (s *systemd) Stop() error {
+	return run("systemctl", "stop", s.Name+".service")
+}
+
+func (s *systemd) Restart() error {
+	return run("systemctl", "restart", s.Name+".service")
+}
+
+const systemdScript = `[Unit]
+Description={{.Description}}
+ConditionFileIsExecutable={{.Path|cmdEscape}}
+
+[Service]
+StartLimitInterval=5
+StartLimitBurst=10
+ExecStart={{.Path|cmdEscape}}{{range .Arguments}} {{.|cmd}}{{end}}
+{{if .ChRoot}}RootDirectory={{.ChRoot|cmd}}{{end}}
+{{if .WorkingDirectory}}WorkingDirectory={{.WorkingDirectory|cmdEscape}}{{end}}
+{{if .UserName}}User={{.UserName}}{{end}}
+{{if .ReloadSignal}}ExecReload=/bin/kill -{{.ReloadSignal}} "$MAINPID"{{end}}
+{{if .PIDFile}}PIDFile={{.PIDFile|cmd}}{{end}}
+Restart=always
+RestartSec=120
+EnvironmentFile=-/etc/sysconfig/{{.Name}}
+
+[Install]
+WantedBy=multi-user.target
+`

+ 252 - 0
vendor/github.com/kardianos/service/service_sysv_linux.go

@@ -0,0 +1,252 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"os/signal"
+	"syscall"
+	"text/template"
+	"time"
+)
+
+type sysv struct {
+	i Interface
+	*Config
+}
+
+func newSystemVService(i Interface, c *Config) (Service, error) {
+	s := &sysv{
+		i:      i,
+		Config: c,
+	}
+
+	return s, nil
+}
+
+func (s *sysv) String() string {
+	if len(s.DisplayName) > 0 {
+		return s.DisplayName
+	}
+	return s.Name
+}
+
+var errNoUserServiceSystemV = errors.New("User services are not supported on SystemV.")
+
+func (s *sysv) configPath() (cp string, err error) {
+	if s.Option.bool(optionUserService, optionUserServiceDefault) {
+		err = errNoUserServiceSystemV
+		return
+	}
+	cp = "/etc/init.d/" + s.Config.Name
+	return
+}
+func (s *sysv) template() *template.Template {
+	return template.Must(template.New("").Funcs(tf).Parse(sysvScript))
+}
+
+func (s *sysv) Install() error {
+	confPath, err := s.configPath()
+	if err != nil {
+		return err
+	}
+	_, err = os.Stat(confPath)
+	if err == nil {
+		return fmt.Errorf("Init already exists: %s", confPath)
+	}
+
+	f, err := os.Create(confPath)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	path, err := s.execPath()
+	if err != nil {
+		return err
+	}
+
+	var to = &struct {
+		*Config
+		Path string
+	}{
+		s.Config,
+		path,
+	}
+
+	err = s.template().Execute(f, to)
+	if err != nil {
+		return err
+	}
+
+	if err = os.Chmod(confPath, 0755); err != nil {
+		return err
+	}
+	for _, i := range [...]string{"2", "3", "4", "5"} {
+		if err = os.Symlink(confPath, "/etc/rc"+i+".d/S50"+s.Name); err != nil {
+			continue
+		}
+	}
+	for _, i := range [...]string{"0", "1", "6"} {
+		if err = os.Symlink(confPath, "/etc/rc"+i+".d/K02"+s.Name); err != nil {
+			continue
+		}
+	}
+
+	return nil
+}
+
+func (s *sysv) Uninstall() error {
+	cp, err := s.configPath()
+	if err != nil {
+		return err
+	}
+	if err := os.Remove(cp); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (s *sysv) Logger(errs chan<- error) (Logger, error) {
+	if system.Interactive() {
+		return ConsoleLogger, nil
+	}
+	return s.SystemLogger(errs)
+}
+func (s *sysv) SystemLogger(errs chan<- error) (Logger, error) {
+	return newSysLogger(s.Name, errs)
+}
+
+func (s *sysv) Run() (err error) {
+	err = s.i.Start(s)
+	if err != nil {
+		return err
+	}
+
+	s.Option.funcSingle(optionRunWait, func() {
+		var sigChan = make(chan os.Signal, 3)
+		signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
+		<-sigChan
+	})()
+
+	return s.i.Stop(s)
+}
+
+func (s *sysv) Start() error {
+	return run("service", s.Name, "start")
+}
+
+func (s *sysv) Stop() error {
+	return run("service", s.Name, "stop")
+}
+
+func (s *sysv) Restart() error {
+	err := s.Stop()
+	if err != nil {
+		return err
+	}
+	time.Sleep(50 * time.Millisecond)
+	return s.Start()
+}
+
+const sysvScript = `#!/bin/sh
+# For RedHat and cousins:
+# chkconfig: - 99 01
+# description: {{.Description}}
+# processname: {{.Path}}
+
+### BEGIN INIT INFO
+# Provides:          {{.Path}}
+# Required-Start:
+# Required-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: {{.DisplayName}}
+# Description:       {{.Description}}
+### END INIT INFO
+
+cmd="{{.Path}}{{range .Arguments}} {{.|cmd}}{{end}}"
+
+name=$(basename $(readlink -f $0))
+pid_file="/var/run/$name.pid"
+stdout_log="/var/log/$name.log"
+stderr_log="/var/log/$name.err"
+
+[ -e /etc/sysconfig/$name ] && . /etc/sysconfig/$name
+
+get_pid() {
+    cat "$pid_file"
+}
+
+is_running() {
+    [ -f "$pid_file" ] && ps $(get_pid) > /dev/null 2>&1
+}
+
+case "$1" in
+    start)
+        if is_running; then
+            echo "Already started"
+        else
+            echo "Starting $name"
+            {{if .WorkingDirectory}}cd '{{.WorkingDirectory}}'{{end}}
+            $cmd >> "$stdout_log" 2>> "$stderr_log" &
+            echo $! > "$pid_file"
+            if ! is_running; then
+                echo "Unable to start, see $stdout_log and $stderr_log"
+                exit 1
+            fi
+        fi
+    ;;
+    stop)
+        if is_running; then
+            echo -n "Stopping $name.."
+            kill $(get_pid)
+            for i in {1..10}
+            do
+                if ! is_running; then
+                    break
+                fi
+                echo -n "."
+                sleep 1
+            done
+            echo
+            if is_running; then
+                echo "Not stopped; may still be shutting down or shutdown may have failed"
+                exit 1
+            else
+                echo "Stopped"
+                if [ -f "$pid_file" ]; then
+                    rm "$pid_file"
+                fi
+            fi
+        else
+            echo "Not running"
+        fi
+    ;;
+    restart)
+        $0 stop
+        if is_running; then
+            echo "Unable to stop, will not attempt to start"
+            exit 1
+        fi
+        $0 start
+    ;;
+    status)
+        if is_running; then
+            echo "Running"
+        else
+            echo "Stopped"
+            exit 1
+        fi
+    ;;
+    *)
+    echo "Usage: $0 {start|stop|restart|status}"
+    exit 1
+    ;;
+esac
+exit 0
+`

+ 57 - 0
vendor/github.com/kardianos/service/service_test.go

@@ -0,0 +1,57 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service_test
+
+import (
+	"testing"
+	"time"
+
+	"github.com/kardianos/service"
+)
+
+func TestRunInterrupt(t *testing.T) {
+	p := &program{}
+	sc := &service.Config{
+		Name: "go_service_test",
+	}
+	s, err := service.New(p, sc)
+	if err != nil {
+		t.Fatalf("New err: %s", err)
+	}
+
+	go func() {
+		<-time.After(1 * time.Second)
+		interruptProcess(t)
+	}()
+
+	go func() {
+		for i := 0; i < 25 && p.numStopped == 0; i++ {
+			<-time.After(200 * time.Millisecond)
+		}
+		if p.numStopped == 0 {
+			t.Fatal("Run() hasn't been stopped")
+		}
+	}()
+
+	if err = s.Run(); err != nil {
+		t.Fatalf("Run() err: %s", err)
+	}
+}
+
+type program struct {
+	numStopped int
+}
+
+func (p *program) Start(s service.Service) error {
+	go p.run()
+	return nil
+}
+func (p *program) run() {
+	// Do work here
+}
+func (p *program) Stop(s service.Service) error {
+	p.numStopped++
+	return nil
+}

+ 88 - 0
vendor/github.com/kardianos/service/service_unix.go

@@ -0,0 +1,88 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// +build linux darwin
+
+package service
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log/syslog"
+	"os/exec"
+)
+
+func newSysLogger(name string, errs chan<- error) (Logger, error) {
+	w, err := syslog.New(syslog.LOG_INFO, name)
+	if err != nil {
+		return nil, err
+	}
+	return sysLogger{w, errs}, nil
+}
+
+type sysLogger struct {
+	*syslog.Writer
+	errs chan<- error
+}
+
+func (s sysLogger) send(err error) error {
+	if err != nil && s.errs != nil {
+		s.errs <- err
+	}
+	return err
+}
+
+func (s sysLogger) Error(v ...interface{}) error {
+	return s.send(s.Writer.Err(fmt.Sprint(v...)))
+}
+func (s sysLogger) Warning(v ...interface{}) error {
+	return s.send(s.Writer.Warning(fmt.Sprint(v...)))
+}
+func (s sysLogger) Info(v ...interface{}) error {
+	return s.send(s.Writer.Info(fmt.Sprint(v...)))
+}
+func (s sysLogger) Errorf(format string, a ...interface{}) error {
+	return s.send(s.Writer.Err(fmt.Sprintf(format, a...)))
+}
+func (s sysLogger) Warningf(format string, a ...interface{}) error {
+	return s.send(s.Writer.Warning(fmt.Sprintf(format, a...)))
+}
+func (s sysLogger) Infof(format string, a ...interface{}) error {
+	return s.send(s.Writer.Info(fmt.Sprintf(format, a...)))
+}
+
+func run(command string, arguments ...string) error {
+	cmd := exec.Command(command, arguments...)
+
+	// Connect pipe to read Stderr
+	stderr, err := cmd.StderrPipe()
+
+	if err != nil {
+		// Failed to connect pipe
+		return fmt.Errorf("%q failed to connect stderr pipe: %v", command, err)
+	}
+
+	// Do not use cmd.Run()
+	if err := cmd.Start(); err != nil {
+		// Problem while copying stdin, stdout, or stderr
+		return fmt.Errorf("%q failed: %v", command, err)
+	}
+
+	// Zero exit status
+	// Darwin: launchctl can fail with a zero exit status,
+	// so check for emtpy stderr
+	if command == "launchctl" {
+		slurp, _ := ioutil.ReadAll(stderr)
+		if len(slurp) > 0 {
+			return fmt.Errorf("%q failed with stderr: %s", command, slurp)
+		}
+	}
+
+	if err := cmd.Wait(); err != nil {
+		// Command didn't exit with a zero exit status.
+		return fmt.Errorf("%q failed: %v", command, err)
+	}
+
+	return nil
+}

+ 181 - 0
vendor/github.com/kardianos/service/service_upstart_linux.go

@@ -0,0 +1,181 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"os/exec"
+	"os/signal"
+	"strings"
+	"text/template"
+	"time"
+)
+
+func isUpstart() bool {
+	if _, err := os.Stat("/sbin/upstart-udev-bridge"); err == nil {
+		return true
+	}
+	if _, err := os.Stat("/sbin/init"); err == nil {
+		if out, err := exec.Command("/sbin/init", "--version").Output(); err == nil {
+			if strings.Contains(string(out), "init (upstart") {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+type upstart struct {
+	i Interface
+	*Config
+}
+
+func newUpstartService(i Interface, c *Config) (Service, error) {
+	s := &upstart{
+		i:      i,
+		Config: c,
+	}
+
+	return s, nil
+}
+
+func (s *upstart) String() string {
+	if len(s.DisplayName) > 0 {
+		return s.DisplayName
+	}
+	return s.Name
+}
+
+// Upstart has some support for user services in graphical sessions.
+// Due to the mix of actual support for user services over versions, just don't bother.
+// Upstart will be replaced by systemd in most cases anyway.
+var errNoUserServiceUpstart = errors.New("User services are not supported on Upstart.")
+
+func (s *upstart) configPath() (cp string, err error) {
+	if s.Option.bool(optionUserService, optionUserServiceDefault) {
+		err = errNoUserServiceUpstart
+		return
+	}
+	cp = "/etc/init/" + s.Config.Name + ".conf"
+	return
+}
+func (s *upstart) template() *template.Template {
+	return template.Must(template.New("").Funcs(tf).Parse(upstartScript))
+}
+
+func (s *upstart) Install() error {
+	confPath, err := s.configPath()
+	if err != nil {
+		return err
+	}
+	_, err = os.Stat(confPath)
+	if err == nil {
+		return fmt.Errorf("Init already exists: %s", confPath)
+	}
+
+	f, err := os.Create(confPath)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	path, err := s.execPath()
+	if err != nil {
+		return err
+	}
+
+	var to = &struct {
+		*Config
+		Path string
+	}{
+		s.Config,
+		path,
+	}
+
+	return s.template().Execute(f, to)
+}
+
+func (s *upstart) Uninstall() error {
+	cp, err := s.configPath()
+	if err != nil {
+		return err
+	}
+	if err := os.Remove(cp); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (s *upstart) Logger(errs chan<- error) (Logger, error) {
+	if system.Interactive() {
+		return ConsoleLogger, nil
+	}
+	return s.SystemLogger(errs)
+}
+func (s *upstart) SystemLogger(errs chan<- error) (Logger, error) {
+	return newSysLogger(s.Name, errs)
+}
+
+func (s *upstart) Run() (err error) {
+	err = s.i.Start(s)
+	if err != nil {
+		return err
+	}
+
+	s.Option.funcSingle(optionRunWait, func() {
+		var sigChan = make(chan os.Signal, 3)
+		signal.Notify(sigChan, os.Interrupt, os.Kill)
+		<-sigChan
+	})()
+
+	return s.i.Stop(s)
+}
+
+func (s *upstart) Start() error {
+	return run("initctl", "start", s.Name)
+}
+
+func (s *upstart) Stop() error {
+	return run("initctl", "stop", s.Name)
+}
+
+func (s *upstart) Restart() error {
+	err := s.Stop()
+	if err != nil {
+		return err
+	}
+	time.Sleep(50 * time.Millisecond)
+	return s.Start()
+}
+
+// The upstart script should stop with an INT or the Go runtime will terminate
+// the program before the Stop handler can run.
+const upstartScript = `# {{.Description}}
+
+ {{if .DisplayName}}description    "{{.DisplayName}}"{{end}}
+
+kill signal INT
+{{if .ChRoot}}chroot {{.ChRoot}}{{end}}
+{{if .WorkingDirectory}}chdir {{.WorkingDirectory}}{{end}}
+start on filesystem or runlevel [2345]
+stop on runlevel [!2345]
+
+{{if .UserName}}setuid {{.UserName}}{{end}}
+
+respawn
+respawn limit 10 5
+umask 022
+
+console none
+
+pre-start script
+    test -x {{.Path}} || { stop; exit 0; }
+end script
+
+# Start
+exec {{.Path}}{{range .Arguments}} {{.|cmd}}{{end}}
+`

+ 389 - 0
vendor/github.com/kardianos/service/service_windows.go

@@ -0,0 +1,389 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"fmt"
+	"os"
+	"os/signal"
+	"strconv"
+	"sync"
+	"time"
+
+	"golang.org/x/sys/windows/registry"
+	"golang.org/x/sys/windows/svc"
+	"golang.org/x/sys/windows/svc/eventlog"
+	"golang.org/x/sys/windows/svc/mgr"
+)
+
+const version = "windows-service"
+
+type windowsService struct {
+	i Interface
+	*Config
+
+	errSync      sync.Mutex
+	stopStartErr error
+}
+
+// WindowsLogger allows using windows specific logging methods.
+type WindowsLogger struct {
+	ev   *eventlog.Log
+	errs chan<- error
+}
+
+type windowsSystem struct{}
+
+func (windowsSystem) String() string {
+	return version
+}
+func (windowsSystem) Detect() bool {
+	return true
+}
+func (windowsSystem) Interactive() bool {
+	return interactive
+}
+func (windowsSystem) New(i Interface, c *Config) (Service, error) {
+	ws := &windowsService{
+		i:      i,
+		Config: c,
+	}
+	return ws, nil
+}
+
+func init() {
+	ChooseSystem(windowsSystem{})
+}
+
+func (l WindowsLogger) send(err error) error {
+	if err == nil {
+		return nil
+	}
+	if l.errs != nil {
+		l.errs <- err
+	}
+	return err
+}
+
+// Error logs an error message.
+func (l WindowsLogger) Error(v ...interface{}) error {
+	return l.send(l.ev.Error(3, fmt.Sprint(v...)))
+}
+
+// Warning logs an warning message.
+func (l WindowsLogger) Warning(v ...interface{}) error {
+	return l.send(l.ev.Warning(2, fmt.Sprint(v...)))
+}
+
+// Info logs an info message.
+func (l WindowsLogger) Info(v ...interface{}) error {
+	return l.send(l.ev.Info(1, fmt.Sprint(v...)))
+}
+
+// Errorf logs an error message.
+func (l WindowsLogger) Errorf(format string, a ...interface{}) error {
+	return l.send(l.ev.Error(3, fmt.Sprintf(format, a...)))
+}
+
+// Warningf logs an warning message.
+func (l WindowsLogger) Warningf(format string, a ...interface{}) error {
+	return l.send(l.ev.Warning(2, fmt.Sprintf(format, a...)))
+}
+
+// Infof logs an info message.
+func (l WindowsLogger) Infof(format string, a ...interface{}) error {
+	return l.send(l.ev.Info(1, fmt.Sprintf(format, a...)))
+}
+
+// NError logs an error message and an event ID.
+func (l WindowsLogger) NError(eventID uint32, v ...interface{}) error {
+	return l.send(l.ev.Error(eventID, fmt.Sprint(v...)))
+}
+
+// NWarning logs an warning message and an event ID.
+func (l WindowsLogger) NWarning(eventID uint32, v ...interface{}) error {
+	return l.send(l.ev.Warning(eventID, fmt.Sprint(v...)))
+}
+
+// NInfo logs an info message and an event ID.
+func (l WindowsLogger) NInfo(eventID uint32, v ...interface{}) error {
+	return l.send(l.ev.Info(eventID, fmt.Sprint(v...)))
+}
+
+// NErrorf logs an error message and an event ID.
+func (l WindowsLogger) NErrorf(eventID uint32, format string, a ...interface{}) error {
+	return l.send(l.ev.Error(eventID, fmt.Sprintf(format, a...)))
+}
+
+// NWarningf logs an warning message and an event ID.
+func (l WindowsLogger) NWarningf(eventID uint32, format string, a ...interface{}) error {
+	return l.send(l.ev.Warning(eventID, fmt.Sprintf(format, a...)))
+}
+
+// NInfof logs an info message and an event ID.
+func (l WindowsLogger) NInfof(eventID uint32, format string, a ...interface{}) error {
+	return l.send(l.ev.Info(eventID, fmt.Sprintf(format, a...)))
+}
+
+var interactive = false
+
+func init() {
+	var err error
+	interactive, err = svc.IsAnInteractiveSession()
+	if err != nil {
+		panic(err)
+	}
+}
+
+func (ws *windowsService) String() string {
+	if len(ws.DisplayName) > 0 {
+		return ws.DisplayName
+	}
+	return ws.Name
+}
+
+func (ws *windowsService) setError(err error) {
+	ws.errSync.Lock()
+	defer ws.errSync.Unlock()
+	ws.stopStartErr = err
+}
+func (ws *windowsService) getError() error {
+	ws.errSync.Lock()
+	defer ws.errSync.Unlock()
+	return ws.stopStartErr
+}
+
+func (ws *windowsService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
+	const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
+	changes <- svc.Status{State: svc.StartPending}
+
+	if err := ws.i.Start(ws); err != nil {
+		ws.setError(err)
+		return true, 1
+	}
+
+	changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
+loop:
+	for {
+		c := <-r
+		switch c.Cmd {
+		case svc.Interrogate:
+			changes <- c.CurrentStatus
+		case svc.Stop, svc.Shutdown:
+			changes <- svc.Status{State: svc.StopPending}
+			if err := ws.i.Stop(ws); err != nil {
+				ws.setError(err)
+				return true, 2
+			}
+			break loop
+		default:
+			continue loop
+		}
+	}
+
+	return false, 0
+}
+
+func (ws *windowsService) Install() error {
+	exepath, err := ws.execPath()
+	if err != nil {
+		return err
+	}
+
+	m, err := mgr.Connect()
+	if err != nil {
+		return err
+	}
+	defer m.Disconnect()
+	s, err := m.OpenService(ws.Name)
+	if err == nil {
+		s.Close()
+		return fmt.Errorf("service %s already exists", ws.Name)
+	}
+	s, err = m.CreateService(ws.Name, exepath, mgr.Config{
+		DisplayName:      ws.DisplayName,
+		Description:      ws.Description,
+		StartType:        mgr.StartAutomatic,
+		ServiceStartName: ws.UserName,
+		Password:         ws.Option.string("Password", ""),
+		Dependencies:     ws.Dependencies,
+	}, ws.Arguments...)
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+	err = eventlog.InstallAsEventCreate(ws.Name, eventlog.Error|eventlog.Warning|eventlog.Info)
+	if err != nil {
+		s.Delete()
+		return fmt.Errorf("InstallAsEventCreate() failed: %s", err)
+	}
+	return nil
+}
+
+func (ws *windowsService) Uninstall() error {
+	m, err := mgr.Connect()
+	if err != nil {
+		return err
+	}
+	defer m.Disconnect()
+	s, err := m.OpenService(ws.Name)
+	if err != nil {
+		return fmt.Errorf("service %s is not installed", ws.Name)
+	}
+	defer s.Close()
+	err = s.Delete()
+	if err != nil {
+		return err
+	}
+	err = eventlog.Remove(ws.Name)
+	if err != nil {
+		return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
+	}
+	return nil
+}
+
+func (ws *windowsService) Run() error {
+	ws.setError(nil)
+	if !interactive {
+		// Return error messages from start and stop routines
+		// that get executed in the Execute method.
+		// Guarded with a mutex as it may run a different thread
+		// (callback from windows).
+		runErr := svc.Run(ws.Name, ws)
+		startStopErr := ws.getError()
+		if startStopErr != nil {
+			return startStopErr
+		}
+		if runErr != nil {
+			return runErr
+		}
+		return nil
+	}
+	err := ws.i.Start(ws)
+	if err != nil {
+		return err
+	}
+
+	sigChan := make(chan os.Signal)
+
+	signal.Notify(sigChan, os.Interrupt, os.Kill)
+
+	<-sigChan
+
+	return ws.i.Stop(ws)
+}
+
+func (ws *windowsService) Start() error {
+	m, err := mgr.Connect()
+	if err != nil {
+		return err
+	}
+	defer m.Disconnect()
+
+	s, err := m.OpenService(ws.Name)
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+	return s.Start()
+}
+
+func (ws *windowsService) Stop() error {
+	m, err := mgr.Connect()
+	if err != nil {
+		return err
+	}
+	defer m.Disconnect()
+
+	s, err := m.OpenService(ws.Name)
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	return ws.stopWait(s)
+}
+
+func (ws *windowsService) Restart() error {
+	m, err := mgr.Connect()
+	if err != nil {
+		return err
+	}
+	defer m.Disconnect()
+
+	s, err := m.OpenService(ws.Name)
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	err = ws.stopWait(s)
+	if err != nil {
+		return err
+	}
+
+	return s.Start()
+}
+
+func (ws *windowsService) stopWait(s *mgr.Service) error {
+	// First stop the service. Then wait for the service to
+	// actually stop before starting it.
+	status, err := s.Control(svc.Stop)
+	if err != nil {
+		return err
+	}
+
+	timeDuration := time.Millisecond * 50
+
+	timeout := time.After(getStopTimeout() + (timeDuration * 2))
+	tick := time.NewTicker(timeDuration)
+	defer tick.Stop()
+
+	for status.State != svc.Stopped {
+		select {
+		case <-tick.C:
+			status, err = s.Query()
+			if err != nil {
+				return err
+			}
+		case <-timeout:
+			break
+		}
+	}
+	return nil
+}
+
+// getStopTimeout fetches the time before windows will kill the service.
+func getStopTimeout() time.Duration {
+	// For default and paths see https://support.microsoft.com/en-us/kb/146092
+	defaultTimeout := time.Millisecond * 20000
+	key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control`, registry.READ)
+	if err != nil {
+		return defaultTimeout
+	}
+	sv, _, err := key.GetStringValue("WaitToKillServiceTimeout")
+	if err != nil {
+		return defaultTimeout
+	}
+	v, err := strconv.Atoi(sv)
+	if err != nil {
+		return defaultTimeout
+	}
+	return time.Millisecond * time.Duration(v)
+}
+
+func (ws *windowsService) Logger(errs chan<- error) (Logger, error) {
+	if interactive {
+		return ConsoleLogger, nil
+	}
+	return ws.SystemLogger(errs)
+}
+func (ws *windowsService) SystemLogger(errs chan<- error) (Logger, error) {
+	el, err := eventlog.Open(ws.Name)
+	if err != nil {
+		return nil, err
+	}
+	return WindowsLogger{el, errs}, nil
+}

+ 14 - 0
vendor/github.com/kardianos/service/service_windows_test.go

@@ -0,0 +1,14 @@
+// Copyright 2015 Daniel Theophanes.
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service
+
+import (
+	"testing"
+)
+
+func TestTimeout(t *testing.T) {
+	stopSpan := getStopTimeout()
+	t.Log("Max Stop Duration", stopSpan)
+}

+ 23 - 0
vendor/github.com/kardianos/service/servicetest_unix_test.go

@@ -0,0 +1,23 @@
+// Copyright 2016 Lawrence Woodman <[email protected]>
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package service_test
+
+import (
+	"os"
+	"testing"
+)
+
+func interruptProcess(t *testing.T) {
+	pid := os.Getpid()
+	p, err := os.FindProcess(pid)
+	if err != nil {
+		t.Fatalf("FindProcess: %s", err)
+	}
+	if err := p.Signal(os.Interrupt); err != nil {
+		t.Fatalf("Signal: %s", err)
+	}
+}

+ 30 - 0
vendor/github.com/kardianos/service/servicetest_windows_test.go

@@ -0,0 +1,30 @@
+// Copyright 2016 Lawrence Woodman <[email protected]>
+// Use of this source code is governed by a zlib-style
+// license that can be found in the LICENSE file.
+
+package service_test
+
+import (
+	"os"
+	"syscall"
+	"testing"
+)
+
+func interruptProcess(t *testing.T) {
+	dll, err := syscall.LoadDLL("kernel32.dll")
+	if err != nil {
+		t.Fatalf("LoadDLL(\"kernel32.dll\") err: %s", err)
+	}
+	p, err := dll.FindProc("GenerateConsoleCtrlEvent")
+	if err != nil {
+		t.Fatalf("FindProc(\"GenerateConsoleCtrlEvent\") err: %s", err)
+	}
+	// Send the CTRL_BREAK_EVENT to a console process group that shares
+	// the console associated with the calling process.
+	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683155(v=vs.85).aspx
+	pid := os.Getpid()
+	r1, _, err := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid))
+	if r1 == 0 {
+		t.Fatalf("Call(CTRL_BREAK_EVENT, %d) err: %s", pid, err)
+	}
+}