// Package cli provides utilities for writing command line utilities that // interact with services. package cli import "os" import "fmt" import "flag" import "os/user" import "strings" import "strconv" import "path/filepath" // Sayf is like Printf, but prints the program name before the message. This is // used for printing messages and errors. func Sayf (format string, values ...any) { Printf(os.Args[0] + ": " + format, values...) } // Printf prints to stderr. func Printf (format string, values ...any) { fmt.Fprintf(flag.CommandLine.Output(), format, values...) } // ServiceUser returns the system user that corresponds to the given service // name. This is not necissarily equivalent Hnakra user, although it is good // practice to have a 1:1 correspondance between them. func ServiceUser (service string) string { return "hn-" + strings.ToLower(service) } // DataDir returns the standard Hnakra data directory. func DataDir () string { return "/var/hnakra" } // ServiceDir returns the standard data directory of a service. func ServiceDir (service string) string { return filepath.Join(DataDir(), "services", ServiceUser(service)) } // NeedRoot halts the program and displays an error if it is not being run as // root. This should be called whenever an operation takes place that requires // root privelages. func NeedRoot() { uid := os.Getuid() if uid != 0 { Sayf("this utility must be run as root") os.Exit(1) } } // MkdirFor makes a directory makes the specified directory (if it doesnt // already exist) and gives ownership of it to the specified uid and gid. func MkdirFor (directory string, uid, gid int) error { err := os.MkdirAll(directory, 0755) if err != nil { return err } err = os.Chmod(directory, 0770) if err != nil { return err } err = os.Chown(directory, uid, gid) if err != nil { return err } return nil } // LookupUID returns the uid and gid of the given username, if it exists. func LookupUID (name string) (uid, gid uint32, err error) { user, err := user.Lookup(name) if err != nil { return 0, 0, err } puid, err := strconv.Atoi(user.Uid) if err != nil { return 0, 0, err } pgid, err := strconv.Atoi(user.Gid) if err != nil { return 0, 0, err } return uint32(puid), uint32(pgid), nil }