From 58861a7cbcd8f745ec0cc99e7dced13da07eff68 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 18 Jan 2017 22:24:27 -0500 Subject: initial commit --- systemd-timesyncd-wrap.go | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 systemd-timesyncd-wrap.go (limited to 'systemd-timesyncd-wrap.go') diff --git a/systemd-timesyncd-wrap.go b/systemd-timesyncd-wrap.go new file mode 100644 index 0000000..3d5971b --- /dev/null +++ b/systemd-timesyncd-wrap.go @@ -0,0 +1,98 @@ +package main + +import ( + "net" + "os" + "strings" + "sync" + "syscall" +) + +func socketUnixgram(name string) (*net.UnixConn, error) { + fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0) + if err != nil { + return nil, err + } + conn, err := net.FileConn(os.NewFile(uintptr(fd), name)) + if err != nil { + return nil, err + } + unixConn := conn.(*net.UnixConn) + return unixConn, nil +} + +func sendmsg(dat, oob []byte, sockname string) error { + writer, err := socketUnixgram(sockname) + if err != nil { + return err + } + _, _, err = writer.WriteMsgUnix(dat, oob, &net.UnixAddr{Net: "unixgram", Name: sockname}) + return err +} + +func main() { + sync_sockname := "/run/timesyncd/time-sync.sock" + fake_sockname := "/run/timesyncd/notify.sock" + real_sockname := os.Getenv("NOTIFY_SOCKET") + + fake_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: fake_sockname}) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + + os.Setenv("NOTIFY_SOCKET", fake_sockname) + proc, err := os.StartProcess(os.Args[1], os.Args[1:], &os.ProcAttr{}) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + synced := false + var dat [4096]byte + oob := make([]byte, syscall.CmsgSpace(syscall.SizeofUcred)+syscall.CmsgSpace(8*768)) + for { + n, oobn, flags, _, err := fake_sock.ReadMsgUnix(dat[:], oob[:]) + if err != nil { + break + } + if flags&syscall.MSG_TRUNC != 0 { + continue + } + if !synced { + for _, line := range strings.Split(string(dat[:n]), "\n") { + if strings.HasPrefix(line, "STATUS=Synchronized") { + _ = sendmsg([]byte(line), nil, sync_sockname) + synced = true + break + } + } + } + _ = sendmsg(dat[:n], oob[:oobn], real_sockname) + } + wg.Done() + }() + + state, err := proc.Wait() + _ = fake_sock.Close() + wg.Wait() + + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + status := state.Sys().(syscall.WaitStatus) + if status.Exited() { + os.Exit(status.ExitStatus()) + } + if status.Signaled() { + self, _ := os.FindProcess(os.Getpid()) + self.Signal(status.Signal()) + } +} -- cgit v1.2.3