From 265dd14966ae7b83d184d276f6085c12aa18a427 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 16 Apr 2017 10:06:30 -0400 Subject: sd_login: rename files --- sd_login/.gitignore | 2 +- sd_login/Makefile | 2 +- sd_login/cgroup.go | 16 ----- sd_login/logind_seat.go | 139 +++++++++++++++++++++++++++++++++++++++++++ sd_login/logind_session.go | 76 +++++++++++++++++++++++ sd_login/logind_user.go | 57 ++++++++++++++++++ sd_login/machined_machine.go | 122 +++++++++++++++++++++++++++++++++++++ sd_login/monitor.go | 114 +++++++++++++++++++++++++++++++++++ sd_login/systemd_cgroup.go | 16 +++++ sd_login/systemd_pid.go.gen | 76 +++++++++++++++++++++++ sd_login/type_machine.go | 122 ------------------------------------- sd_login/type_monitor.go | 114 ----------------------------------- sd_login/type_pid.go.gen | 76 ----------------------- sd_login/type_seat.go | 139 ------------------------------------------- sd_login/type_session.go | 76 ----------------------- sd_login/type_user.go | 57 ------------------ 16 files changed, 602 insertions(+), 602 deletions(-) delete mode 100644 sd_login/cgroup.go create mode 100644 sd_login/logind_seat.go create mode 100644 sd_login/logind_session.go create mode 100644 sd_login/logind_user.go create mode 100644 sd_login/machined_machine.go create mode 100644 sd_login/monitor.go create mode 100644 sd_login/systemd_cgroup.go create mode 100755 sd_login/systemd_pid.go.gen delete mode 100644 sd_login/type_machine.go delete mode 100644 sd_login/type_monitor.go delete mode 100755 sd_login/type_pid.go.gen delete mode 100644 sd_login/type_seat.go delete mode 100644 sd_login/type_session.go delete mode 100644 sd_login/type_user.go diff --git a/sd_login/.gitignore b/sd_login/.gitignore index 8050442..721c03c 100644 --- a/sd_login/.gitignore +++ b/sd_login/.gitignore @@ -1 +1 @@ -/type_pid.go +/systemd_pid.go diff --git a/sd_login/Makefile b/sd_login/Makefile index daf076d..98f0746 100644 --- a/sd_login/Makefile +++ b/sd_login/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -files.src.gen += type_pid.go +files.src.gen += systemd_pid.go files.generate: $(files.src.gen) maintainer-clean: diff --git a/sd_login/cgroup.go b/sd_login/cgroup.go deleted file mode 100644 index 0ceef37..0000000 --- a/sd_login/cgroup.go +++ /dev/null @@ -1,16 +0,0 @@ -package sd_login - -type _Cgroup interface { - MustSkipSystemPrefix() _Cgroup - GetSession() Session - GetOwnerUser() User - GetMachine() Machine - - GetUserSlice() string - GetUserUnit() string - - GetSlice() string - GetUnit() string -} - -func (pid PID) getCgroup() (_Cgroup, error) diff --git a/sd_login/logind_seat.go b/sd_login/logind_seat.go new file mode 100644 index 0000000..a62effc --- /dev/null +++ b/sd_login/logind_seat.go @@ -0,0 +1,139 @@ +// Copyright (C) 2016-2017 Luke Shumaker +// +// 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 ( + "strconv" + "strings" + + "golang.org/x/sys/unix" +) + +// A Seat represents a set of hardware devices for a workspace; i.e. a +// screen and keyboard. +// +// Multiple sessions may be associated with a seat, but only one +// session may be active on a seat at a time. +type Seat string + +func (seat Seat) isValid() bool { + return valid_filename(string(seat)) +} + +// GetSeats returns a list of all currently available local seats. +func GetSeats() ([]Seat, error) { + strs, err := get_files_in_directory("/run/systemd/seats/") + if err != nil { + return nil, err + } + seats := make([]Seat, len(strs)) + for i := range strs { + seats[i] = Seat(strs[i]) + } + return seats, nil +} + +// GetActive returns which session is currently active on this seat, +// or nil if there is no currently active session. +func (seat Seat) GetActive() (sess AnnotatedSession, err error) { + if !seat.isValid() { + err = unix.EINVAL + return + } + env, err := parse_env_file("/run/systemd/seats/" + string(seat)) + if err != nil { + return + } + + strName, ok := env["ACTIVE"] + if !ok { + err = unix.ENXIO + return + } + strUid, ok := env["ACTIVE_UID"] + if !ok { + err = unix.ENXIO + return + } + intUid, err := strconv.Atoi(strUid) + if err != nil { + return + } + sess.Session = Session(strName) + sess.User = User(intUid) + + return +} + +// GetSessions returns a list of all sessions associated with the +// seat, whether they are active or not. +func (seat Seat) GetSessions() ([]AnnotatedSession, error) { + if !seat.isValid() { + return nil, unix.EINVAL + } + env, err := parse_env_file("/run/systemd/seats/" + string(seat)) + if err != nil { + return nil, err + } + + strSessions, ok := env["SESSIONS"] + if !ok { + return nil, unix.ENXIO + } + strUids, ok := env["UIDS"] + if !ok { + return nil, unix.ENXIO + } + + arySessions := strings.Fields(strSessions) + aryUids := strings.Fields(strUids) + if len(arySessions) != len(aryUids) { + return nil, unix.ENXIO + } + ret := make([]AnnotatedSession, len(arySessions)) + for i := 0; i < len(arySessions); i++ { + uid, err := strconv.Atoi(aryUids[i]) + if err != nil { + return nil, err + } + ret[i].Session = Session(arySessions[i]) + ret[i].User = User(uid) + } + + return ret, nil +} + +func (seat Seat) can(cap string) (bool, error) { + if !seat.isValid() { + return false, unix.EINVAL + } + env, err := parse_env_file("/run/systemd/seats/" + string(seat)) + if err != nil { + return false, err + } + return parse_boolean(env["CAN_"+cap]) +} + +func (seat Seat) CanMultiSession() (bool, error) { + return seat.can("MULTI_SESSION") +} + +func (seat Seat) CanTTY() (bool, error) { + return seat.can("TTY") +} + +func (seat Seat) CanGraphical() (bool, error) { + return seat.can("GRAPHICAL") +} diff --git a/sd_login/logind_session.go b/sd_login/logind_session.go new file mode 100644 index 0000000..e692426 --- /dev/null +++ b/sd_login/logind_session.go @@ -0,0 +1,76 @@ +// Copyright (C) 2016-2017 Luke Shumaker +// +// 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 + +type Session string + +type AnnotatedSession struct { + Session + User User +} + +func (sess AnnotatedSession) GetUser() (User, error) { + return sess.User, nil +} + +type SessionState int + +const ( + SessionOnline SessionState = iota + SessionActive + SessionClosing +) + +func GetSessions() ([]Session, error) { + strs, err := get_files_in_directory("/run/systemd/sessions/") + if err != nil { + return nil, err + } + sessions := make([]Session, len(strs)) + for i := range strs { + sessions[i] = Session(strs[i]) + } + return sessions, nil +} + +func (sess Session) IsActive() bool { + state, err := sess.GetState() + return err == nil && state == SessionActive +} +func (sess Session) IsRemote() bool +func (sess Session) GetState() (SessionState, error) +func (sess Session) GetUser() (User, error) +func (sess Session) GetSeat() (Seat, error) + +// PAM +func (sess Session) GetService() (string, error) + +// tty, x11, wayland, mir, unspecified +func (sess Session) GetType() (string, error) + +// user, greeter, lock-screen +func (sess Session) GetClass() (string, error) + +// GNOME, KDE, systemd-console +func (sess Session) GetDesktop() (string, error) + +// X11 DISPLAY +func (sess Session) GetDisplay() (string, error) +func (sess Session) GetRemoteHost() (string, error) + +// PAM +func (sess Session) GetRemoteUser() (string, error) +func (sess Session) GetTTY() (string, error) +func (sess Session) GetVT() (uint, error) diff --git a/sd_login/logind_user.go b/sd_login/logind_user.go new file mode 100644 index 0000000..81a5418 --- /dev/null +++ b/sd_login/logind_user.go @@ -0,0 +1,57 @@ +// Copyright (C) 2016 Luke Shumaker +// +// 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 ( + "strconv" +) + +type User int + +type UserState int + +const ( + UserOffline UserState = iota + UserLingering + UserOnline + UserActive + UserClosing +) + +// GetUsers returns a list of all users who currently have login +// sessions. +func GetUsers() ([]User, error) { + strs, err := get_files_in_directory("/run/systemd/users/") + if err != nil { + return nil, err + } + var users []User + for _, uid_str := range strs { + uid, err := strconv.Atoi(uid_str) + if err != nil { + continue + } + users = append(users, User(uid)) + } + return users, nil +} + +func (uid User) IsOnSeat(seat Seat, requireActive bool) bool +func (uid User) GetState() (UserState, error) + +// primary session +func (uid User) GetDisplay() (Session, error) +func (uid User) GetSessions(requireActive bool) ([]Session, error) +func (uid User) GetSeats(requireActive bool) ([]Seat, error) diff --git a/sd_login/machined_machine.go b/sd_login/machined_machine.go new file mode 100644 index 0000000..d89eaad --- /dev/null +++ b/sd_login/machined_machine.go @@ -0,0 +1,122 @@ +// Copyright (C) 2016-2017 Luke Shumaker +// +// 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 ( + "strconv" + "strings" + + "golang.org/x/sys/unix" +) + +// A Machine is a name representing a locally running container or +// virtual machine that is registerd with (systemd-)machined. +type Machine string + +// isValid returns whether the Machine name is valid. +func (m Machine) isValid() bool { + if len(m) > host_name_max { + // Note that Linux HOST_NAME_MAX is 64, but DNS allows + // 255, so names from DNS might be invalid. + return false + } + + n_dots := 0 + dot := true + for _, c := range m { + if c == '.' { + if dot { + return false + } + dot = true + n_dots++ + } else { + if !strings.ContainsRune(letters+digits+"-_.", c) { + return false + } + dot = false + } + } + + if dot { // trailing dot or empty + return false + } + + return true +} + +// GetMachines returns a list of currently running containers/virtual +// machines. +func GetMachines() ([]Machine, error) { + strs, err := get_files_in_directory("/run/systemd/machines/") + if err != nil { + return nil, err + } + var machines []Machine + for _, str := range strs { + machine := Machine(str) + if strings.HasPrefix(str, "unit:") || machine.isValid() { + continue + } + machines = append(machines, Machine(str)) + } + return machines, nil +} + +// GetClass returns the class of a locally running machine. The class +// is either "vm" or "container", depending on if the machine is an +// virtual machine or a container. +func (m Machine) GetClass() (string, error) { + if !m.isValid() { + return "", unix.EINVAL + } + + env, err := parse_env_file("/run/systemd/machines/" + string(m)) + if err != nil { + return "", err + } + class, ok := env["CLASS"] + if !ok { + return "", unix.ENXIO // or EIO? + } + return class, nil +} + +// GetIfIndices returns the numeric indices of the network interfaces +// on the host that are pointing toward this machine. +func (m Machine) GetIfIndices() ([]int, error) { + if !m.isValid() { + return nil, unix.EINVAL + } + + env, err := parse_env_file("/run/systemd/machines/" + string(m)) + if err != nil { + return nil, err + } + netif, ok := env["NETIF"] + if !ok { + return nil, unix.ENXIO // or EIO? + } + + var ifindices []int + for _, word := range strings.FieldsFunc(netif, func(c rune) bool { return strings.ContainsRune(whitespace, c) }) { + ifindex, err := strconv.Atoi(word) + if err != nil { + return nil, err + } + ifindices = append(ifindices, ifindex) + } + return ifindices, nil +} diff --git a/sd_login/monitor.go b/sd_login/monitor.go new file mode 100644 index 0000000..2422f06 --- /dev/null +++ b/sd_login/monitor.go @@ -0,0 +1,114 @@ +// Copyright (C) 2016-2017 Luke Shumaker +// +// 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" +) + +// A 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 +} + +// Close closes the monitor. After calling Close, further calls to +// the monitor will fail. +func (m *Monitor) Close() error { + return m.in.Close() +} + +// Flush discards any events that have happened since the last Flush +// or Wait call. +func (m *Monitor) Flush() error { + for { + ev, err := m.in.ReadNonblock() + if err != nil { + return err + } + if ev.Wd < 0 { + return nil + } + } +} + +// Wait blocks until a watched for event has happened. A single call +// to Wait discards only discards first event; if multiple events +// happen at once, multiple calls to Wait will immediately return +// unless Flush is called. +func (m *Monitor) Wait() error { + _, err := m.in.ReadBlock() + return err +} diff --git a/sd_login/systemd_cgroup.go b/sd_login/systemd_cgroup.go new file mode 100644 index 0000000..0ceef37 --- /dev/null +++ b/sd_login/systemd_cgroup.go @@ -0,0 +1,16 @@ +package sd_login + +type _Cgroup interface { + MustSkipSystemPrefix() _Cgroup + GetSession() Session + GetOwnerUser() User + GetMachine() Machine + + GetUserSlice() string + GetUserUnit() string + + GetSlice() string + GetUnit() string +} + +func (pid PID) getCgroup() (_Cgroup, error) diff --git a/sd_login/systemd_pid.go.gen b/sd_login/systemd_pid.go.gen new file mode 100755 index 0000000..8d5e5fb --- /dev/null +++ b/sd_login/systemd_pid.go.gen @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# Copyright (C) 2016-2017 Luke Shumaker +# +# 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. + +{ + printf '//' + printf ' %q' "$0" "$@" + printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' + + cat <= 0 +} + +func GetPeer(conn *net.UnixConn) (PID, error) { + ucred, err := getpeercred(conn) + if err != nil { + return -1, err + } + return PID(ucred.Pid), nil +} + +EOF + + data=( + 'GetSession Session' + 'GetOwnerUser User' + 'GetMachine Machine' + + 'GetUnit string' + 'GetUserUnit string' + 'GetSlice string' + 'GetUserSlice string' + ) + for item in "${data[@]}"; do + read Func Type <<<"$item" + cat < -// -// 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 ( - "strconv" - "strings" - - "golang.org/x/sys/unix" -) - -// A Machine is a name representing a locally running container or -// virtual machine that is registerd with (systemd-)machined. -type Machine string - -// isValid returns whether the Machine name is valid. -func (m Machine) isValid() bool { - if len(m) > host_name_max { - // Note that Linux HOST_NAME_MAX is 64, but DNS allows - // 255, so names from DNS might be invalid. - return false - } - - n_dots := 0 - dot := true - for _, c := range m { - if c == '.' { - if dot { - return false - } - dot = true - n_dots++ - } else { - if !strings.ContainsRune(letters+digits+"-_.", c) { - return false - } - dot = false - } - } - - if dot { // trailing dot or empty - return false - } - - return true -} - -// GetMachines returns a list of currently running containers/virtual -// machines. -func GetMachines() ([]Machine, error) { - strs, err := get_files_in_directory("/run/systemd/machines/") - if err != nil { - return nil, err - } - var machines []Machine - for _, str := range strs { - machine := Machine(str) - if strings.HasPrefix(str, "unit:") || machine.isValid() { - continue - } - machines = append(machines, Machine(str)) - } - return machines, nil -} - -// GetClass returns the class of a locally running machine. The class -// is either "vm" or "container", depending on if the machine is an -// virtual machine or a container. -func (m Machine) GetClass() (string, error) { - if !m.isValid() { - return "", unix.EINVAL - } - - env, err := parse_env_file("/run/systemd/machines/" + string(m)) - if err != nil { - return "", err - } - class, ok := env["CLASS"] - if !ok { - return "", unix.ENXIO // or EIO? - } - return class, nil -} - -// GetIfIndices returns the numeric indices of the network interfaces -// on the host that are pointing toward this machine. -func (m Machine) GetIfIndices() ([]int, error) { - if !m.isValid() { - return nil, unix.EINVAL - } - - env, err := parse_env_file("/run/systemd/machines/" + string(m)) - if err != nil { - return nil, err - } - netif, ok := env["NETIF"] - if !ok { - return nil, unix.ENXIO // or EIO? - } - - var ifindices []int - for _, word := range strings.FieldsFunc(netif, func(c rune) bool { return strings.ContainsRune(whitespace, c) }) { - ifindex, err := strconv.Atoi(word) - if err != nil { - return nil, err - } - ifindices = append(ifindices, ifindex) - } - return ifindices, nil -} diff --git a/sd_login/type_monitor.go b/sd_login/type_monitor.go deleted file mode 100644 index 2422f06..0000000 --- a/sd_login/type_monitor.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (C) 2016-2017 Luke Shumaker -// -// 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" -) - -// A 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 -} - -// Close closes the monitor. After calling Close, further calls to -// the monitor will fail. -func (m *Monitor) Close() error { - return m.in.Close() -} - -// Flush discards any events that have happened since the last Flush -// or Wait call. -func (m *Monitor) Flush() error { - for { - ev, err := m.in.ReadNonblock() - if err != nil { - return err - } - if ev.Wd < 0 { - return nil - } - } -} - -// Wait blocks until a watched for event has happened. A single call -// to Wait discards only discards first event; if multiple events -// happen at once, multiple calls to Wait will immediately return -// unless Flush is called. -func (m *Monitor) Wait() error { - _, err := m.in.ReadBlock() - return err -} diff --git a/sd_login/type_pid.go.gen b/sd_login/type_pid.go.gen deleted file mode 100755 index 8d5e5fb..0000000 --- a/sd_login/type_pid.go.gen +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env bash -# Copyright (C) 2016-2017 Luke Shumaker -# -# 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. - -{ - printf '//' - printf ' %q' "$0" "$@" - printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' - - cat <= 0 -} - -func GetPeer(conn *net.UnixConn) (PID, error) { - ucred, err := getpeercred(conn) - if err != nil { - return -1, err - } - return PID(ucred.Pid), nil -} - -EOF - - data=( - 'GetSession Session' - 'GetOwnerUser User' - 'GetMachine Machine' - - 'GetUnit string' - 'GetUserUnit string' - 'GetSlice string' - 'GetUserSlice string' - ) - for item in "${data[@]}"; do - read Func Type <<<"$item" - cat < -// -// 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 ( - "strconv" - "strings" - - "golang.org/x/sys/unix" -) - -// A Seat represents a set of hardware devices for a workspace; i.e. a -// screen and keyboard. -// -// Multiple sessions may be associated with a seat, but only one -// session may be active on a seat at a time. -type Seat string - -func (seat Seat) isValid() bool { - return valid_filename(string(seat)) -} - -// GetSeats returns a list of all currently available local seats. -func GetSeats() ([]Seat, error) { - strs, err := get_files_in_directory("/run/systemd/seats/") - if err != nil { - return nil, err - } - seats := make([]Seat, len(strs)) - for i := range strs { - seats[i] = Seat(strs[i]) - } - return seats, nil -} - -// GetActive returns which session is currently active on this seat, -// or nil if there is no currently active session. -func (seat Seat) GetActive() (sess AnnotatedSession, err error) { - if !seat.isValid() { - err = unix.EINVAL - return - } - env, err := parse_env_file("/run/systemd/seats/" + string(seat)) - if err != nil { - return - } - - strName, ok := env["ACTIVE"] - if !ok { - err = unix.ENXIO - return - } - strUid, ok := env["ACTIVE_UID"] - if !ok { - err = unix.ENXIO - return - } - intUid, err := strconv.Atoi(strUid) - if err != nil { - return - } - sess.Session = Session(strName) - sess.User = User(intUid) - - return -} - -// GetSessions returns a list of all sessions associated with the -// seat, whether they are active or not. -func (seat Seat) GetSessions() ([]AnnotatedSession, error) { - if !seat.isValid() { - return nil, unix.EINVAL - } - env, err := parse_env_file("/run/systemd/seats/" + string(seat)) - if err != nil { - return nil, err - } - - strSessions, ok := env["SESSIONS"] - if !ok { - return nil, unix.ENXIO - } - strUids, ok := env["UIDS"] - if !ok { - return nil, unix.ENXIO - } - - arySessions := strings.Fields(strSessions) - aryUids := strings.Fields(strUids) - if len(arySessions) != len(aryUids) { - return nil, unix.ENXIO - } - ret := make([]AnnotatedSession, len(arySessions)) - for i := 0; i < len(arySessions); i++ { - uid, err := strconv.Atoi(aryUids[i]) - if err != nil { - return nil, err - } - ret[i].Session = Session(arySessions[i]) - ret[i].User = User(uid) - } - - return ret, nil -} - -func (seat Seat) can(cap string) (bool, error) { - if !seat.isValid() { - return false, unix.EINVAL - } - env, err := parse_env_file("/run/systemd/seats/" + string(seat)) - if err != nil { - return false, err - } - return parse_boolean(env["CAN_"+cap]) -} - -func (seat Seat) CanMultiSession() (bool, error) { - return seat.can("MULTI_SESSION") -} - -func (seat Seat) CanTTY() (bool, error) { - return seat.can("TTY") -} - -func (seat Seat) CanGraphical() (bool, error) { - return seat.can("GRAPHICAL") -} diff --git a/sd_login/type_session.go b/sd_login/type_session.go deleted file mode 100644 index e692426..0000000 --- a/sd_login/type_session.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) 2016-2017 Luke Shumaker -// -// 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 - -type Session string - -type AnnotatedSession struct { - Session - User User -} - -func (sess AnnotatedSession) GetUser() (User, error) { - return sess.User, nil -} - -type SessionState int - -const ( - SessionOnline SessionState = iota - SessionActive - SessionClosing -) - -func GetSessions() ([]Session, error) { - strs, err := get_files_in_directory("/run/systemd/sessions/") - if err != nil { - return nil, err - } - sessions := make([]Session, len(strs)) - for i := range strs { - sessions[i] = Session(strs[i]) - } - return sessions, nil -} - -func (sess Session) IsActive() bool { - state, err := sess.GetState() - return err == nil && state == SessionActive -} -func (sess Session) IsRemote() bool -func (sess Session) GetState() (SessionState, error) -func (sess Session) GetUser() (User, error) -func (sess Session) GetSeat() (Seat, error) - -// PAM -func (sess Session) GetService() (string, error) - -// tty, x11, wayland, mir, unspecified -func (sess Session) GetType() (string, error) - -// user, greeter, lock-screen -func (sess Session) GetClass() (string, error) - -// GNOME, KDE, systemd-console -func (sess Session) GetDesktop() (string, error) - -// X11 DISPLAY -func (sess Session) GetDisplay() (string, error) -func (sess Session) GetRemoteHost() (string, error) - -// PAM -func (sess Session) GetRemoteUser() (string, error) -func (sess Session) GetTTY() (string, error) -func (sess Session) GetVT() (uint, error) diff --git a/sd_login/type_user.go b/sd_login/type_user.go deleted file mode 100644 index 81a5418..0000000 --- a/sd_login/type_user.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2016 Luke Shumaker -// -// 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 ( - "strconv" -) - -type User int - -type UserState int - -const ( - UserOffline UserState = iota - UserLingering - UserOnline - UserActive - UserClosing -) - -// GetUsers returns a list of all users who currently have login -// sessions. -func GetUsers() ([]User, error) { - strs, err := get_files_in_directory("/run/systemd/users/") - if err != nil { - return nil, err - } - var users []User - for _, uid_str := range strs { - uid, err := strconv.Atoi(uid_str) - if err != nil { - continue - } - users = append(users, User(uid)) - } - return users, nil -} - -func (uid User) IsOnSeat(seat Seat, requireActive bool) bool -func (uid User) GetState() (UserState, error) - -// primary session -func (uid User) GetDisplay() (Session, error) -func (uid User) GetSessions(requireActive bool) ([]Session, error) -func (uid User) GetSeats(requireActive bool) ([]Seat, error) -- cgit v1.1-4-g5e80