camfish/util.go

124 lines
2.4 KiB
Go

package camfish
import "fmt"
import "log"
import "time"
import "iter"
import "errors"
import "strconv"
import "syscall"
import "os/user"
import "strings"
import "context"
import "sync/atomic"
import "unicode/utf8"
func defaul[T comparable](value, def T) T {
var zero T
if value == zero { return def }
return value
}
func panicWrap(f func() error) (err error) {
defer func () {
if pan := recover(); pan != nil {
if panErr, ok := pan.(error); ok {
err = panErr
} else {
err = errors.New(fmt.Sprint(pan))
}
}
} ()
err = f()
return
}
func panicWrapCtx(ctx context.Context, f func(context.Context) error) (err error) {
defer func () {
if pan := recover(); pan != nil {
if panErr, ok := pan.(error); ok {
err = panErr
} else {
err = errors.New(fmt.Sprint(pan))
}
}
} ()
err = f(ctx)
return
}
type atomicDuration atomic.Int64
type atomicInt64Ptr = *atomic.Int64
func (duration* atomicDuration) Load() time.Duration {
return time.Duration((*atomic.Int64)(duration).Load())
}
func (duration *atomicDuration) Store(newDuration time.Duration) {
(*atomic.Int64)(duration).Store(int64(newDuration))
}
func logActors (actors iter.Seq[Actor]) {
output := "actors: "
x := utf8.RuneCountInString(output)
first := true
line := func () {
if output == "" { return }
if first {
first = false
log.Println("(i)", output)
} else {
log.Println(" ", output)
}
output = ""
x = 0
}
types := make(map[string] int)
for actor := range actors {
typ := actor.Type()
if named, ok := actor.(Named); ok {
typ = fmt.Sprintf("%s/%s", typ, named.Name())
}
types[typ] += 1
}
for typ, count := range types {
if count > 1 {
typ += fmt.Sprintf("(%d)", count)
}
typ += ", "
x += 2
typeLen := utf8.RuneCountInString(typ)
if x + typeLen >= 60 {
line()
}
output += typ
x += typeLen
}
if output != "" {
output = strings.TrimSuffix(output, ", ")
}
line()
}
func dropPrivelege (usr, group string) error {
if group != "" {
groupInfo, err := user.LookupGroup(group)
if err != nil { return err }
gid, err := strconv.Atoi(groupInfo.Gid)
if err != nil { return err }
err = syscall.Setgid(gid)
if err != nil { return err }
}
if usr != "" {
usrInfo, err := user.Lookup(usr)
if err != nil { return err }
uid, err := strconv.Atoi(usrInfo.Uid)
if err != nil { return err }
err = syscall.Setuid(uid)
if err != nil { return err }
}
return nil
}