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 { types[actor.Type()] += 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 }