diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-11-01 14:46:15 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-11-01 14:46:15 -0400 |
commit | c7eea383aeaf6748daf994e9e28e4d0c25350736 (patch) | |
tree | a0979cbd4e6be06385fd0340e050147fdacd6e35 /src/util/fd.go |
initial commit
Diffstat (limited to 'src/util/fd.go')
-rw-r--r-- | src/util/fd.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/util/fd.go b/src/util/fd.go new file mode 100644 index 0000000..17c64cd --- /dev/null +++ b/src/util/fd.go @@ -0,0 +1,101 @@ +// Copyright 2015-2016 Luke Shumaker + +package util + +import ( + "net" + "os" + "strings" + "fmt" + "sync" + "strconv" + + sd "lukeshu.com/git/go/libsystemd/sd_daemon" +) + +var fdsLock sync.Mutex +var fds = map[int]*os.File{} +var sdFds = map[string]int{} + +func init() { + fds[0] = os.Stdin + fds[1] = os.Stdout + fds[2] = os.Stderr + fromSd := sd.ListenFds(true) + if fromSd == nil { + return + } + for i, file := range fromSd { + fds[i+3] = file + sdFds[file.Name()] = i+3 + } +} + +func FdNameToNum(name string) int { + switch name { + case "stdin": + return 0 + case "stdout": + return 1 + case "stderr": + return 2 + case "systemd": + if len(sdFds) == 0 { + return -1 + } + return 3 + default: + if n, err := strconv.Atoi(name); err == nil { + if n >= 0 { + return n + } + } else if strings.HasPrefix(name, "systemd:") { + name = strings.TrimPrefix(name, "systemd") + n, ok := sdFds[name] + if ok { + return n + } else if n, err := strconv.Atoi(name); err == nil && n < len(sdFds) { + return n+3 + } + } + return -1 + } +} + +func FdFile(fd int) *os.File { + fdsLock.Lock() + defer fdsLock.Unlock() + file, ok := fds[fd] + if ok { + return file + } + file = os.NewFile(uintptr(fd), fmt.Sprintf("/dev/fd/%d", fd)) + fds[fd] = file + return file +} + +func StreamListener(stype, saddr string) (net.Listener, error) { + switch stype { + case "fd": + return net.FileListener(FdFile(FdNameToNum(saddr))) + default: /* case "tcp", "tcp4", "tcp6", "unix", "unixpacket": */ + return net.Listen(stype, saddr) + } +} + +func PacketListener(stype, saddr string) (net.PacketConn, error) { + switch stype { + case "fd": + return net.FilePacketConn(FdFile(FdNameToNum(saddr))) + default: /* case "udp", "udp4", "udp6", "ip", "ip4", "ip6", "unixgram": */ + return net.ListenPacket(stype, saddr) + } +} + +// For completeless, I might want to implement methods for each of +// these: +// - FIFO +// - Special +// - Netlink +// - MessageQueue +// - USBFunction |