summaryrefslogtreecommitdiff
path: root/sd_login/type_monitor.go
diff options
context:
space:
mode:
Diffstat (limited to 'sd_login/type_monitor.go')
-rw-r--r--sd_login/type_monitor.go106
1 files changed, 106 insertions, 0 deletions
diff --git a/sd_login/type_monitor.go b/sd_login/type_monitor.go
new file mode 100644
index 0000000..50f601a
--- /dev/null
+++ b/sd_login/type_monitor.go
@@ -0,0 +1,106 @@
+// Copyright (C) 2016 Luke Shumaker <lukeshu@sbcglobal.net>
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sd_login
+
+import (
+ "git.lukeshu.com/go/libgnulinux/inotify"
+ "golang.org/x/sys/unix"
+)
+
+// Monitor monitors several types of events, so you don't have to do
+// busy-polling.
+//
+// However, Monitor won't actually give you the event that happened,
+// you'll need to read it yourself.
+type Monitor struct {
+ in *inotify.Inotify
+}
+
+type MonitorCategory uint
+
+const (
+ MonitorSeats MonitorCategory = 1 << iota
+ MonitorSessions
+ MonitorUsers
+ MonitorMachines
+
+ MonitorAll = MonitorSeats | MonitorSessions | MonitorUsers | MonitorMachines
+)
+
+func NewMonitor(categories MonitorCategory) (*Monitor, error) {
+ if categories == 0 {
+ return nil, unix.EINVAL
+ }
+
+ in, err := inotify.InotifyInit1(inotify.IN_CLOEXEC)
+ if err != nil {
+ return nil, err
+ }
+
+ if categories&MonitorSeats != 0 {
+ _, err := in.AddWatch("/run/systemd/seats/", inotify.IN_MOVED_TO|inotify.IN_DELETE)
+ if err != nil {
+ in.Close()
+ return nil, err
+ }
+ }
+
+ if categories&MonitorSessions != 0 {
+ _, err := in.AddWatch("/run/systemd/sessions/", inotify.IN_MOVED_TO|inotify.IN_DELETE)
+ if err != nil {
+ in.Close()
+ return nil, err
+ }
+ }
+
+ if categories&MonitorUsers != 0 {
+ _, err := in.AddWatch("/run/systemd/users/", inotify.IN_MOVED_TO|inotify.IN_DELETE)
+ if err != nil {
+ in.Close()
+ return nil, err
+ }
+ }
+
+ if categories&MonitorMachines != 0 {
+ _, err := in.AddWatch("/run/systemd/machines/", inotify.IN_MOVED_TO|inotify.IN_DELETE)
+ if err != nil {
+ in.Close()
+ return nil, err
+ }
+ }
+
+ return &Monitor{in: in}, nil
+}
+
+func (m *Monitor) Close() error {
+ return m.in.Close()
+}
+
+func (m *Monitor) Flush() error {
+ for {
+ ev, err := m.in.ReadNonblock()
+ if err != nil {
+ return err
+ }
+ if ev.Wd < 0 {
+ return nil
+ }
+ }
+}
+
+func (m *Monitor) Wait() error {
+ _, err := m.in.ReadBlock()
+ return err
+}