pax_global_header00006660000000000000000000000064127663546720014534gustar00rootroot0000000000000052 comment=c25dac49e50cbbcbef8c81b089f56156f4067729 svcutils-1.0.10/000077500000000000000000000000001276635467200134675ustar00rootroot00000000000000svcutils-1.0.10/README.md000066400000000000000000000031471276635467200147530ustar00rootroot00000000000000# Utilities for writing services in Go [![GoDoc](https://godoc.org/gopkg.in/hlandau/svcutils.v1?status.svg)](https://godoc.org/gopkg.in/hlandau/svcutils.v1) The following packages are contained in this repository: * chroot, a package for chrooting and then determining whether absolute paths can be addressed within that chroot and, if so, converting them appropriately; * exepath, a package for determining the absolute path of the executable as invoked, but without resolving symlinks, which can be useful in some circumstances; * passwd, a package for determining user and group information on \*NIX systems beyond that available in `os/user`; * pidfile, a package for creating and locking PID files on \*NIX; * setuid, a package for changing UID and GID on \*NIX systems, including workarounds for the unfortunate absurdities underlying Linux's implementation of setuid (which means that `syscall.Setuid` does not work on Linux); * systemd, a package for detecting whether systemd is in use and sending status messages to it, in a way that works in a chroot; * caps, a package for detecting and dropping capabilities on Linux; * dupfd, a package for duplicating file descriptors to a target file descriptor number, which irons out some differences between different \*NIX platforms. ## Licence © 2015—2016 Hugo Landau [Licenced under the licence with SHA256 hash `fd80a26fbb3f644af1fa994134446702932968519797227e07a1368dea80f0bc`, a copy of which can be found here.](https://github.com/hlandau/rilts/blob/master/licences/COPYING.MIT) svcutils-1.0.10/caps/000077500000000000000000000000001276635467200144155ustar00rootroot00000000000000svcutils-1.0.10/caps/caps-linuxc.go000066400000000000000000000017001276635467200171700ustar00rootroot00000000000000// +build linux,cgo package caps import "syscall" /* #cgo LDFLAGS: -lcap #include #include static int hasanycap(void) { cap_t c, zc; int hasCap; zc = cap_init(); if (!zc) { return -errno; } if (cap_clear(zc) < 0) { cap_free(zc); return -errno; } c = cap_get_proc(); if (!c) { cap_free(c); cap_free(zc); return -errno; } hasCap = !!cap_compare(c, zc); cap_free(c); cap_free(zc); return hasCap; } static int dropcaps(void) { int ec; cap_t c; c = cap_init(); if (!c) { cap_free(c); return errno; } if (cap_clear(c) < 0) { cap_free(c); return errno; } if (cap_set_proc(c)) { cap_free(c); return errno; } cap_free(c); return 0; } */ import "C" const supported = true func haveAny() bool { return C.hasanycap() != 0 } func drop() error { eno := C.dropcaps() if eno != 0 { return syscall.Errno(eno) } return nil } svcutils-1.0.10/caps/caps-other.go000066400000000000000000000002151276635467200170070ustar00rootroot00000000000000// +build !linux linux,!cgo package caps const supported = false func haveAny() bool { return false } func drop() error { return nil } svcutils-1.0.10/caps/docs.go000066400000000000000000000007601276635467200156770ustar00rootroot00000000000000// Package caps provides functions for controlling capabilities on Linux. On // other OSes, the functions are no-ops. package caps // This constant will be true iff the target platform supports capabilities. const Supported = supported // Returns true iff there are any capabilities available to the program. // Returns false on non-Linux OSes. func HaveAny() bool { return haveAny() } // Attempt to drop all capabilities. Does nothing on non-Linux OSes. func Drop() error { return drop() } svcutils-1.0.10/caps/linuxperms.txt000066400000000000000000000024671276635467200173750ustar00rootroot00000000000000PROCESS STATE Root Directory ; ok Current Directory ; ok Real User ID ; ok Effective User ID ; ok Saved Set User ID ; ok Real Group ID ; ok Effective Group ID ; ok Saved Set Group ID ; ok Extra Group IDs ; ok FS User ID ; managed automatically FS Group ID ; managed automatically Permitted Capabilities Inheritable Capabilities Effective Capabilities Capability Bounding Set ; ok Securebits ; ok NoNewPrivs ; ok Umask ; ok Session ID (setsid) ; ok Resource Limits ; ok Maximum Core File Size Maximum File Descriptors Maximum Stack Size Maximum Processes with Real User ID Maximum File Size Creatable Maximum Virtual Memory Size Maximum Data Size Seccomp ; not used CAPABILITIES OF INTEREST CAP_SYS_CHROOT CAP_NET_BIND_SERVICE CAP_SETPCAP CAP_SETUID CAP_SETGID CAP_SYS_RESOURCE DAEMONIZATION PRELUDE umask(0); // (fork) // setup stdin/stdout/stderr fds setsid(); chdir("/"); PRIVILEGE DESCENT chdir("/"); set_rlimits(); set_securebits(); set_capability_bounding_set(); chroot(chrootDir); setresgid(gid,gid,gid); setgroups(groups); setresuid(uid,uid,uid); chdir("/"); verify_no_capabilities(); prctl(PR_SET_NO_NEW_PRIVS, 1); svcutils-1.0.10/chroot/000077500000000000000000000000001276635467200147655ustar00rootroot00000000000000svcutils-1.0.10/chroot/chroot-nunix.go000066400000000000000000000002531276635467200177510ustar00rootroot00000000000000// +build windows plan9 package chroot func getAnchor() string { return "" } func rel(path string) (chrootRelativePath string, canAddress bool) { return path, true } svcutils-1.0.10/chroot/chroot-unix.go000066400000000000000000000015771276635467200176050ustar00rootroot00000000000000// +build !windows,!plan9 package chroot import ( "fmt" "path/filepath" "strings" "syscall" ) var anchor = "/" func getAnchor() string { return anchor } func rel(path string) (chrootRelativePath string, canAddress bool) { p, err := filepath.Rel(Anchor(), path) if err != nil || p == "" { return "", false } if p == ".." || strings.HasPrefix(p, "../") { return "", false } if p == "." { return "/", true } return "/" + p, true } // Chroots into a directory. The package keeps track of the resultant chroot // path, even after multiple successive chroot operations. The anchor is // updated if the operation is successful. func Chroot(path string) error { if !filepath.IsAbs(path) { return fmt.Errorf("chroot path must be absolute: %v", path) } err := syscall.Chroot(path) if err != nil { return err } anchor = filepath.Join(anchor, path[1:]) return nil } svcutils-1.0.10/chroot/chroot.go000066400000000000000000000016661276635467200166230ustar00rootroot00000000000000// Package chroot provides functions to determine whether paths are inside a // chroot and to make them relative to that chroot if so. // // In order for this package to work, you must chroot via the Chroot function // provided via this package. // // All functions except Chroot are available on Windows but act as identity // functions. package chroot // Returns the "chroot anchor", the path under which the process has been // chrooted. If the process has not been chrooted, this is "/". This can be // used to obtain chroot-relative paths necessary to access files after // chrooting. See Rel. func Anchor() string { return getAnchor() } // path should be an absolute path. If, given the current Anchor, it can // be accessed, returns the path which should be used to open the file given // the current chroot and returns true. Otherwise returns false. func Rel(path string) (chrootRelativePath string, canAddress bool) { return rel(path) } svcutils-1.0.10/dupfd/000077500000000000000000000000001276635467200145715ustar00rootroot00000000000000svcutils-1.0.10/dupfd/doc.go000066400000000000000000000006531276635467200156710ustar00rootroot00000000000000// Package dupfd makes the Dup2 system call uniformly available on *NIX // platforms. // // The call is not available on Solaris, but an alternate mechanism is // available to obtain the same effect. The call has been replaced with // dup3 on Linux, and dup2 is not available in the legacy-free arm64 // port of Linux. // // This package provides a uniform Dup2 function for all of these platforms. // *NIX only. package dupfd svcutils-1.0.10/dupfd/dupfd-linux.go000066400000000000000000000003161276635467200173570ustar00rootroot00000000000000// +build linux package dupfd import "syscall" // Always use dup3 on Linux because dup2 is not available on arm64. func dup2(sourceFD, targetFD int) error { return syscall.Dup3(sourceFD, targetFD, 0) } svcutils-1.0.10/dupfd/dupfd-solaris.go000066400000000000000000000004311276635467200176720ustar00rootroot00000000000000// +build solaris package dupfd import "syscall" func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err syscall.Errno) const f_dup2fd = 0x09 func dup2(sourceFD, targetFD int) error { _, err := fcntl1(uintptr(sourceFD), f_dup2fd, uintptr(targetFD)) return err } svcutils-1.0.10/dupfd/dupfd-unix.go000066400000000000000000000002411276635467200172000ustar00rootroot00000000000000// +build !windows,!solaris,!plan9,!linux package dupfd import "syscall" func dup2(sourceFD, targetFD int) error { return syscall.Dup2(sourceFD, targetFD) } svcutils-1.0.10/dupfd/dupfd-windows.go000066400000000000000000000000471276635467200177130ustar00rootroot00000000000000// +build windows plan9 package dupfd svcutils-1.0.10/dupfd/dupfd.go000066400000000000000000000002501276635467200162170ustar00rootroot00000000000000// +build !windows,!plan9 package dupfd // Duplicates an FD to a target FD. See dup2(2). func Dup2(sourceFD, targetFD int) error { return dup2(sourceFD, targetFD) } svcutils-1.0.10/dupfd/syscall_solaris_amd64.s000066400000000000000000000001241276635467200211530ustar00rootroot00000000000000#include "textflag.h" TEXT ·fcntl1(SB),NOSPLIT,$0 JMP runtime·syscall_fcntl(SB) svcutils-1.0.10/exepath/000077500000000000000000000000001276635467200151255ustar00rootroot00000000000000svcutils-1.0.10/exepath/exepath.go000066400000000000000000000045561276635467200171240ustar00rootroot00000000000000// Package exepath provides information on the path used to invoke the running // program. // // Relativity // // This package is distinct from other packages providing similar functionality // because the path it provides is not realpath'd. That is, if a binary was // executed via a symlink, the path expressed is still expressed in terms of // that symlink. This is useful if you wish to use relative paths. // // For example: // // /here/foo/ // bin: symlink to /somewhere/else/bin // data.txt // // /somewhere/else/bin // foo // // /here/foo$ ./bin/foo // // Here Abs in this package will specify /here/foo/bin/foo, meaning that // Join(Dir(Abs), "..") leads to /here/foo, not /somewhere/else, allowing // easy access to data.txt. package exepath // import "gopkg.in/hlandau/svcutils.v1/exepath" import ( "os" "os/exec" "path/filepath" "strings" ) // Absolute path to EXE which was invoked. This is set at init()-time. // // This path is not realpath'd — see package documentation. var Abs string func getRawPath() string { // "github.com/kardianos/osext".Executable looks nice, but may return the // realpath of the path because this is how the kernel returns it as // /proc/self/exe. This causes problems with layouts like // // some-work-directory/ // bin/ -> symlink to $GOPATH/bin // src/ -> symlink to $GOPATH/src // etc/ // ... configuration files ... // // where bin/foo is executed from some-work-directory and expects to find files in etc/. // Since -fork reexecutes with the exepath.Abs path, this prevents paths like // $BIN/../etc/foo.conf from working (where $BIN is the dir of the executable path). // // Okay, maybe this is a byzantine configuration. But still, this breaks my existing // configuration, so I'm sticking with os.Args[0] for now, as -fork should be as seamless // as possible to relying applications. return os.Args[0] } func init() { rawPath := getRawPath() // If there are no separators in rawPath, we've presumably been invoked from the path // and should qualify the path accordingly. idx := strings.IndexFunc(rawPath, func(r rune) bool { return r == '/' || r == filepath.Separator }) if idx < 0 { abs, err := exec.LookPath(rawPath) if err != nil { return } Abs = abs } else { abs, err := filepath.Abs(rawPath) if err != nil { return } Abs = abs } initProgramName() } svcutils-1.0.10/exepath/programname.go000066400000000000000000000007631276635467200177720ustar00rootroot00000000000000package exepath import "path/filepath" import "strings" // By default, contains the lowercase basename of Abs with any file extension stripped. // // This can be changed by any configuration code which knows better. It may be // used e.g. as the application name for syslog. var ProgramName string // Used to track what set the program name. var ProgramNameSetter = "default" func initProgramName() { b := filepath.Base(Abs) ProgramName = strings.ToLower(b[0 : len(b)-len(filepath.Ext(b))]) } svcutils-1.0.10/passwd/000077500000000000000000000000001276635467200147705ustar00rootroot00000000000000svcutils-1.0.10/passwd/doc.go000066400000000000000000000001571276635467200160670ustar00rootroot00000000000000// Package passwd provides the resolution of user and group names and // membership. *NIX only. package passwd svcutils-1.0.10/passwd/passwd-c.go000066400000000000000000000026511276635467200170440ustar00rootroot00000000000000// +build cgo,!windows package passwd import ( "fmt" "unsafe" ) /* #include "pwnam.h" #include #include #include */ import "C" func getGIDForUID(uid string) (int, error) { var x C.gid_t n, err := ParseUID(uid) if err != nil { return 0, err } uidn := C.uid_t(n) if C.de_gid_for_uid(uidn, &x) < 0 { return 0, fmt.Errorf("cannot get GID for UID: %d", n) } return int(x), nil } //export de_gid_cb func de_gid_cb(p C.uintptr_t, gid C.gid_t) { f := *(*func(C.gid_t))(unsafe.Pointer(uintptr(p))) f(gid) } func parseUserName(username string) (int, error) { var x C.uid_t cusername := C.CString(username) defer C.free(unsafe.Pointer(cusername)) if C.de_username_to_uid(cusername, &x) < 0 { return 0, fmt.Errorf("cannot convert username to uid: %s", username) } return int(x), nil } func parseGroupName(groupname string) (int, error) { var x C.gid_t cgroupname := C.CString(groupname) defer C.free(unsafe.Pointer(cgroupname)) if C.de_groupname_to_gid(cgroupname, &x) < 0 { return 0, fmt.Errorf("cannot convert group name to gid: %s", groupname) } return int(x), nil } func getExtraGIDs(gid int) (gids []int, err error) { gidn := C.gid_t(gid) f := func(gid C.gid_t) { gids = append(gids, int(gid)) } if C.de_get_extra_gids(gidn, C.uintptr_t(uintptr(unsafe.Pointer(&f)))) < 0 { return nil, fmt.Errorf("cannot retrieve additional groups list for GID %d", gid) } return } svcutils-1.0.10/passwd/passwd-nc.go000066400000000000000000000011321276635467200172130ustar00rootroot00000000000000// +build !cgo,!windows package passwd import "fmt" var errNoCgo = fmt.Errorf("because this binary was built without cgo, UIDs/GIDs must be specified numerically and not as names") func parseUserName(username string) (int, error) { return 0, errNoCgo } func parseGroupName(groupname string) (int, error) { return 0, errNoCgo } func getGIDForUID(uid string) (int, error) { n, err := ParseUID(uid) if err != nil { return 0, err } // XXX: assume GID is same as UID return n, nil } func getExtraGIDs(gid int) (gids []int, err error) { // XXX: use empty extra GIDs list return nil, nil } svcutils-1.0.10/passwd/passwd.go000066400000000000000000000017151276635467200166240ustar00rootroot00000000000000// +build !windows package passwd import "strconv" // Parse a UID string. The string should either be a username or a decimal user // ID. Returns the user ID or an error. func ParseUID(uid string) (int, error) { n, err := strconv.ParseUint(uid, 10, 31) if err != nil { return parseUserName(uid) } return int(n), nil } // Parse a GID string. The string should either be a group name or a decimal group // ID. Returns the group ID or an error. func ParseGID(gid string) (int, error) { n, err := strconv.ParseUint(gid, 10, 31) if err != nil { return parseGroupName(gid) } return int(n), nil } // Given a UID string (a username or decimal user ID string), find the primary // GID for the given UID and return it. func GetGIDForUID(uid string) (int, error) { return getGIDForUID(uid) } // Given a group ID, returns an array of the supplementary group IDs that group // implies. func GetExtraGIDs(gid int) (gids []int, err error) { return getExtraGIDs(gid) } svcutils-1.0.10/passwd/passwd_windows.go000066400000000000000000000000421276635467200203660ustar00rootroot00000000000000// +build windows package passwd svcutils-1.0.10/passwd/pwnam.h000066400000000000000000000050731276635467200162700ustar00rootroot00000000000000#pragma once // This needs to be >=200112L or _SC_GETPW_R_SIZE_MAX etc. do not // manifest on Darwin. #ifndef _POSIX_C_SOURCE # define _POSIX_C_SOURCE 200112L #endif #include #include #include #include #include #include #include void de_gid_cb(uintptr_t ptr, gid_t gid); static int de_username_to_uid(const char *name, uid_t *uid) { struct passwd p, *pp = NULL; size_t buflen = 1024; char *buf = NULL; int ec; long sz; sz = sysconf(_SC_GETPW_R_SIZE_MAX); if (sz > buflen && sz != SIZE_MAX) buflen = sz; again: buf = realloc(buf, buflen); if (!buf) return -1; ec = getpwnam_r(name, &p, buf, buflen, &pp); if (ec == ERANGE) { buflen *= 2; goto again; } if (ec != 0 || !pp) { free(buf); return -1; } *uid = p.pw_uid; free(buf); return 0; } static int de_groupname_to_gid(const char *name, gid_t *gid) { struct group p, *pp = NULL; size_t buflen = 1024; char *buf = NULL; int ec; long sz; sz = sysconf(_SC_GETGR_R_SIZE_MAX); if (sz > buflen && sz != SIZE_MAX) buflen = sz; again: buf = realloc(buf, buflen); if (!buf) return -1; ec = getgrnam_r(name, &p, buf, buflen, &pp); if (ec == ERANGE) { buflen *= 2; goto again; } if (ec != 0 || !pp) { free(buf); return -1; } *gid = p.gr_gid; free(buf); return 0; } static int de_get_extra_gids(gid_t gid, uintptr_t p) { struct group g, *pg = NULL; size_t buflen = 1024; char *buf = NULL; int ec; long sz; char **name; gid_t agid; sz = sysconf(_SC_GETGR_R_SIZE_MAX); if (sz > buflen && sz != SIZE_MAX) buflen = sz; again: buf = realloc(buf, buflen); if (!buf) return -1; ec = getgrgid_r(gid, &g, buf, buflen, &pg); if (ec == ERANGE) { buflen *= 2; goto again; } if (ec != 0 || !pg) { free(buf); return -1; } for (name=g.gr_mem; *name; ++name) { ec = de_groupname_to_gid(*name, &agid); if (ec < 0) { free(buf); return -1; } de_gid_cb(p, agid); } free(buf); return 0; } static int de_gid_for_uid(uid_t uid, gid_t *gid) { struct passwd p, *pp = NULL; size_t buflen = 1024; char *buf = NULL; int ec; long sz; sz = sysconf(_SC_GETGR_R_SIZE_MAX); if (sz > buflen && sz != SIZE_MAX) buflen = sz; again: buf = realloc(buf, buflen); if (!buf) return -1; ec = getpwuid_r(uid, &p, buf, buflen, &pp); if (ec == ERANGE) { buflen *= 2; goto again; } if (ec != 0 || !pp) { free(buf); return -1; } *gid = p.pw_gid; free(buf); return 0; } svcutils-1.0.10/pidfile/000077500000000000000000000000001276635467200151035ustar00rootroot00000000000000svcutils-1.0.10/pidfile/docs.go000066400000000000000000000001441276635467200163610ustar00rootroot00000000000000// Package pidfile provides functions for the creation and locking of PID // files. package pidfile svcutils-1.0.10/pidfile/pidfile.go000066400000000000000000000041201276635467200170430ustar00rootroot00000000000000// +build !windows,!plan9 package pidfile import ( "fmt" "io" "os" "sync" "syscall" ) var ( pidFile *os.File pidFileName string ) type pidfile struct { once sync.Once f *os.File path string } func (p *pidfile) Close() error { p.once.Do(func() { // Try and remove file, don't care if it fails. os.Remove(p.path) p.f.Close() p.f = nil }) return nil } // Opens and locks a file and writes the current PID to it. The file is kept open // until you close the returned interface, at which point it is deleted. It may also // be deleted if the program exits without closing the returned interface. func Open(path string) (io.Closer, error) { return OpenWith(path, fmt.Sprintf("%d\n", os.Getpid())) } // Opens and locks a file and writes body to it. The file is kept open until // you close the returned interface, at which point it is deleted. It may also // be deleted if the program exits without closing the returned interface. func OpenWith(path, body string) (io.Closer, error) { f, err := open(path) if err != nil { return nil, err } _, err = f.WriteString(body) if err != nil { f.Close() return nil, err } return &pidfile{ f: f, path: path, }, nil } func open(path string) (*os.File, error) { var f *os.File var err error for { f, err = os.OpenFile(path, syscall.O_RDWR|syscall.O_CREAT|syscall.O_EXCL, 0644) if err != nil { if !os.IsExist(err) { return nil, err } f, err = os.OpenFile(path, syscall.O_RDWR, 0644) if err != nil { if os.IsNotExist(err) { continue } return nil, err } } err = syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &syscall.Flock_t{ Type: syscall.F_WRLCK, }) if err != nil { f.Close() return nil, err } st1 := syscall.Stat_t{} err = syscall.Fstat(int(f.Fd()), &st1) // ffs if err != nil { f.Close() return nil, err } st2 := syscall.Stat_t{} err = syscall.Stat(path, &st2) if err != nil { f.Close() if os.IsNotExist(err) { continue } return nil, err } if st1.Ino != st2.Ino { f.Close() continue } break } return f, nil } svcutils-1.0.10/pidfile/pidfile_other.go000066400000000000000000000000201276635467200202370ustar00rootroot00000000000000package pidfile svcutils-1.0.10/setuid/000077500000000000000000000000001276635467200147645ustar00rootroot00000000000000svcutils-1.0.10/setuid/docs.go000066400000000000000000000020501276635467200162400ustar00rootroot00000000000000// Package setuid provides functions to change the current UID and GID on *nix // systems. // // These functions are only available on *NIX platforms. On systems without // setres[ug]id, but only setre[ug]id, etc., setres[ug]id calls are translated // to such calls. // // Linux Support // // Linux support is somewhat harder than it seems. The syscall package provides // Setuid, etc., but on Linux, these functions are a trap: // // Linux has a faulty, non-compliant implementation of setuid(2) which only // changes the UID of the current thread, not the whole process. Amazingly, // even the manual page lies and claims that it affects the process. // // glibc's setuid syscall wrapper dispatches setuid calls to all threads. Ergo, // the manual page for setuid(3) but not setuid(2) is accurate. // // The same also applies to setgid, setresuid, setresgid, etc. Though oddly // enough not setgroups. // // Therefore setuid, setgid, setresuid and setresgid are dispatched through // cgo, hence this package rather than using the syscall package. package setuid svcutils-1.0.10/setuid/setuid-linuxc.go000066400000000000000000000024011276635467200201050ustar00rootroot00000000000000// +build cgo,linux package setuid import "syscall" /* #define _GNU_SOURCE #include #include // These differ to the libc prototypes because they return // 0 on success but errno on failure rather than -1. static int csetuid(uid_t uid) { int ec = setuid(uid); return (ec < 0) ? errno : 0; } static int csetgid(gid_t gid) { int ec = setgid(gid); return (ec < 0) ? errno : 0; } static int csetresuid(uid_t ruid, uid_t euid, uid_t suid) { int ec = setresuid(ruid, euid, suid); return (ec < 0) ? errno : 0; } static int csetresgid(gid_t rgid, gid_t egid, gid_t sgid) { int ec = setresgid(rgid, egid, sgid); return (ec < 0) ? errno : 0; } */ import "C" func setuid(uid int) error { eno := C.csetuid(C.uid_t(uid)) if eno != 0 { return syscall.Errno(eno) } return nil } func setgid(gid int) error { eno := C.csetgid(C.gid_t(gid)) if eno != 0 { return syscall.Errno(eno) } return nil } func setresgid(rgid, egid, sgid int) error { eno := C.csetresgid(C.gid_t(rgid), C.gid_t(egid), C.gid_t(sgid)) if eno != 0 { return syscall.Errno(eno) } return nil } func setresuid(ruid, euid, suid int) error { eno := C.csetresuid(C.uid_t(ruid), C.uid_t(euid), C.uid_t(suid)) if eno != 0 { return syscall.Errno(eno) } return nil } svcutils-1.0.10/setuid/setuid-linuxnc.go000066400000000000000000000006111276635467200202640ustar00rootroot00000000000000// +build linux,!cgo package setuid import "fmt" var errNoSetuid = fmt.Errorf("set*id calls are not supported on Linux when built with cgo disabled") func setuid(uid int) error { return errNoSetuid } func setgid(gid int) error { return errNoSetuid } func setresgid(rgid, egid, sgid int) error { return errNoSetuid } func setresuid(ruid, euid, suid int) error { return errNoSetuid } svcutils-1.0.10/setuid/setuid-unix.go000066400000000000000000000012001276635467200175620ustar00rootroot00000000000000// +build !windows,!plan9 package setuid import "syscall" // Setuid calls the *NIX setuid() function. func Setuid(uid int) error { return setuid(uid) } // Setgid calls the *NIX setgid() function. func Setgid(gid int) error { return setgid(gid) } // Setgroups calls the *NIX setgroups() function. func Setgroups(gids []int) error { return syscall.Setgroups(gids) } // Setresgid calls the *NIX setresgid() function. func Setresgid(rgid, egid, sgid int) error { return setresgid(rgid, egid, sgid) } // Setresuid calls the *NIX setresuid() function. func Setresuid(ruid, euid, suid int) error { return setresuid(ruid, euid, suid) } svcutils-1.0.10/setuid/setuid-unixnos.go000066400000000000000000000007641276635467200203200ustar00rootroot00000000000000// +build darwin freebsd openbsd netbsd solaris dragonfly package setuid import "syscall" func setuid(uid int) error { return syscall.Setuid(uid) } func setgid(gid int) error { return syscall.Setgid(gid) } // darwin doesn't seem to have saved GIDs, so use setregid func setresgid(rgid, egid, sgid int) error { return syscall.Setregid(rgid, egid) } // darwin doesn't seem to have saved UIDs, so use setreuid func setresuid(ruid, euid, suid int) error { return syscall.Setreuid(ruid, euid) } svcutils-1.0.10/setuid/setuid-unixs.go000066400000000000000000000006511276635467200177560ustar00rootroot00000000000000// +build !linux,!windows,!darwin,!freebsd,!openbsd,!netbsd,!solaris,!plan9,!dragonfly package setuid import "syscall" func setuid(uid int) error { return syscall.Setuid(uid) } func setgid(gid int) error { return syscall.Setgid(gid) } func setresgid(rgid, egid, sgid int) error { return syscall.Setresgid(rgid, egid, sgid) } func setresuid(ruid, euid, suid int) error { return syscall.Setresuid(ruid, euid, suid) } svcutils-1.0.10/setuid/setuid-windows.go000066400000000000000000000000421276635467200202740ustar00rootroot00000000000000// +build windows package setuid svcutils-1.0.10/svcutils.go000066400000000000000000000002171276635467200156720ustar00rootroot00000000000000// Package svcutils provides various utilities related to writing services in // Go. package svcutils // import "gopkg.in/hlandau/svcutils.v1" svcutils-1.0.10/systemd/000077500000000000000000000000001276635467200151575ustar00rootroot00000000000000svcutils-1.0.10/systemd/docs.go000066400000000000000000000005271276635467200164420ustar00rootroot00000000000000// Package systemd provides functions for detecting and working with the // systemd service manager. // // It is based on other packages such as github.com/coreos/go-systemd/util, // but that package has become more complicated and dependent on cgo, so // a small amount of its more pertinent functionality is duplicated here. package systemd svcutils-1.0.10/systemd/isrunning.go000066400000000000000000000016461276635467200175310ustar00rootroot00000000000000package systemd // import "gopkg.in/hlandau/svcutils.v1/systemd" import "os" // IsRunningSystemd checks whether the host was booted with systemd as its init // system. This functions similar to systemd's `sd_booted(3)`: internally, it // checks whether /run/systemd/system/ exists and is a directory. // http://www.freedesktop.org/software/systemd/man/sd_booted.html func IsRunning() bool { fi, err := os.Lstat("/run/systemd/system") if err != nil { return false } return fi.IsDir() } // Deprecated. Use IsRunning() instead. func IsRunningSystemd() bool { return IsRunning() } // Technically this is 'is running under systemd with the notify service type'. // The purpose of this is to allow a daemon to determine whether it should // behave in a systemd-like way, though, so that's fine. func IsRunningUnder() bool { return IsRunning() && os.Getenv("NOTIFY_SOCKET") != "" } // © 2015 CoreOS, Inc. Apache 2.0 License svcutils-1.0.10/systemd/sdnotify.go000066400000000000000000000025771276635467200173600ustar00rootroot00000000000000// +build !windows,!plan9 package systemd import ( "errors" "net" "os" "sync" ) // Error returned if no systemd notify protocol socket can be found. // // This is an indication that the service is not running under systemd or // Type=notify is not set in the systemd unit file. var ErrNoSocket = errors.New("No socket") // sdNotifySocket var sdNotifyMutex sync.Mutex var sdNotifySocket *net.UnixConn var sdNotifyInited bool // Send sends a message to the init daemon. It is common to ignore the error. // // This function differs from that in github.com/coreos/go-systemd/daemon in // that that code closes the socket after each call, and so won't work in a // chroot. This function keeps the socket open; so long as it is called at // least once before chrooting, it can continue to be used. // // May return ErrNoSocket. func NotifySend(state string) error { sdNotifyMutex.Lock() defer sdNotifyMutex.Unlock() if !sdNotifyInited { sdNotifyInited = true socketAddr := &net.UnixAddr{ Name: os.Getenv("NOTIFY_SOCKET"), Net: "unixgram", } if socketAddr.Name == "" { return ErrNoSocket } conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr) if err != nil { return err } sdNotifySocket = conn } if sdNotifySocket == nil { return ErrNoSocket } _, err := sdNotifySocket.Write([]byte(state)) return err } // © 2015 CoreOS, Inc. Apache 2.0 License