diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2015-08-26 23:01:23 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2015-08-26 23:01:23 -0600 |
commit | 4ab446ed2a12e4f8b599f5912b9d4aabf20e2975 (patch) | |
tree | b810043933c5675788edd32ec61414db9d3dc1eb /src/nslcd_systemd | |
parent | 13bb2e14fcdd260d060b7240357d4a8a80002114 (diff) |
stuff
Diffstat (limited to 'src/nslcd_systemd')
-rw-r--r-- | src/nslcd_systemd/nslcd_systemd.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/nslcd_systemd/nslcd_systemd.go b/src/nslcd_systemd/nslcd_systemd.go new file mode 100644 index 0000000..80e23b2 --- /dev/null +++ b/src/nslcd_systemd/nslcd_systemd.go @@ -0,0 +1,119 @@ +package nslcd_systemd + +import ( + "fmt" + "net" + "nslcd_proto" + "os" + "os/signal" + sd "sd_daemon" + "sd_daemon/logger" + "sync" + "syscall" +) + +type Backend interface { + nslcd_proto.Backend + Reload() +} + +func get_socket() (socket net.Listener, err error) { + socket = nil + err = nil + fds := sd.ListenFds(true) + if fds == nil { + err = fmt.Errorf("failed to aquire sockets from systemd") + return + } + if len(fds) != 1 { + err = fmt.Errorf("wrong number of sockets from systemd: expected %d but got %d", 1, len(fds)) + return + } + socket, err = net.FileListener(fds[0]) + fds[0].Close() + return +} + +func getpeercred(conn *net.UnixConn) (cred *syscall.Ucred, err error) { + cred = nil + file, err := conn.File() + if err != nil { + return + } + defer file.Close() + cred, err = syscall.GetsockoptUcred(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_PEERCRED) + return +} + +func handler(conn *net.UnixConn, backend nslcd_proto.Backend) { + defer conn.Close() + cred, err := getpeercred(conn) + if err != nil { + logger.Debug("connection from unknown client") + } else { + logger.Debug("connection from pid=%v uid=%v gid=%v", + cred.Pid, cred.Uid, cred.Gid) + } + err = nslcd_proto.HandleRequest(backend, conn, conn, *cred) + if err != nil { + logger.Debug("Error while handling request: %v", err) + } +} + +func Main(backend Backend) { + var err error = nil + var socket net.Listener = nil + defer func() { + if socket != nil { + socket.Close() + } + }() + + socket, err = get_socket() + if err != nil { + logger.Err("%s", err.Error()) + sd.Notify(false, "STOPPING=1") + os.Exit(1) + } + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGTERM, syscall.SIGHUP) + + sock := make(chan *net.UnixConn, 1) + go func() { + for { + conn, err := socket.Accept() + if err != nil { + logger.Notice("%s", err.Error()) + } + sock <- conn.(*net.UnixConn) + } + }() + + var wg sync.WaitGroup + sd.Notify(false, "READY=1") +Loop: + for { + select { + case sig := <-sigs: + switch sig { + case syscall.SIGTERM: + sd.Notify(false, "STOPPING=1") + break Loop + case syscall.SIGHUP: + sd.Notify(false, "RELOADING=1") + backend.Reload() + sd.Notify(false, "READY=1") + } + case conn := <-sock: + go func() { + wg.Add(1) + defer wg.Done() + handler(conn, backend) + }() + } + } + wg.Wait() + + os.Exit(0) +} |