func ReadDirNoExit(dirname string) ([]os.FileInfo, []error, error) {
	if dirname == "" {
		dirname = "."
	}
	f, err := os.Open(dirname)
	if err != nil {
		return nil, nil, err
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	list := make([]os.FileInfo, 0, len(names))
	errs := make([]error, 0, len(names))
	for _, filename := range names {
		fip, lerr := os.Lstat(dirname + "/" + filename)
		if os.IsNotExist(lerr) {
			continue
		}
		list = append(list, fip)
		errs = append(errs, lerr)
	}
	return list, errs, nil
}
borrowed from ioutil.ReadDir
ReadDir reads the directory named by dirname and returns
a list of directory entries, minus those with lstat errors
package util
import (
	"fmt"
	"os"
	"reflect"
	"regexp"
)
func CompileRegexps(regexpStrings []string) ([]*regexp.Regexp, error) {
	regexps := []*regexp.Regexp{}
	for _, regexpStr := range regexpStrings {
		r, err := regexp.Compile(regexpStr)
		if err != nil {
			return []*regexp.Regexp{}, err
		}
		regexps = append(regexps, r)
	}
	return regexps, nil
}
func UsingSystemdInitSystem() bool {
	if _, err := os.Stat("/run/systemd/system"); err == nil {
		return true
	}
	return false
}
func AllPtrFieldsNil(obj interface{}) bool {
	v := reflect.ValueOf(obj)
	if !v.IsValid() {
		panic(fmt.Sprintf("reflect.ValueOf() produced a non-valid Value for %#v", obj))
	}
	if v.Kind() == reflect.Ptr {
		if v.IsNil() {
			return true
		}
		v = v.Elem()
	}
	for i := 0; i < v.NumField(); i++ {
		if v.Field(i).Kind() == reflect.Ptr && !v.Field(i).IsNil() {
			return false
		}
	}
	return true
}
func FileExists(filename string) (bool, error) {
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}
	return true, nil
}