diff options
-rw-r--r-- | sd_login/.gitignore | 2 | ||||
-rw-r--r-- | sd_login/Makefile | 2 | ||||
-rw-r--r-- | sd_login/doc.go | 16 | ||||
-rw-r--r-- | sd_login/logind_seat.go | 58 | ||||
-rw-r--r-- | sd_login/logind_session.go | 55 | ||||
-rw-r--r-- | sd_login/logind_user.go | 18 | ||||
-rw-r--r-- | sd_login/machined_machine.go | 19 | ||||
-rw-r--r-- | sd_login/systemd_cgroup.go | 8 | ||||
-rwxr-xr-x | sd_login/systemd_process.go.gen (renamed from sd_login/systemd_pid.go.gen) | 20 |
9 files changed, 107 insertions, 91 deletions
diff --git a/sd_login/.gitignore b/sd_login/.gitignore index 721c03c..e94b335 100644 --- a/sd_login/.gitignore +++ b/sd_login/.gitignore @@ -1 +1 @@ -/systemd_pid.go +/systemd_process.go diff --git a/sd_login/Makefile b/sd_login/Makefile index 98f0746..bed4104 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 += systemd_pid.go +files.src.gen += systemd_process.go files.generate: $(files.src.gen) maintainer-clean: diff --git a/sd_login/doc.go b/sd_login/doc.go index 33c31be..00e7250 100644 --- a/sd_login/doc.go +++ b/sd_login/doc.go @@ -17,14 +17,16 @@ // Package sd_login introspects session and login information from // systemd, logind, and machined. // -// There are 5 basic object types that these three system services manage. +// There are 5 basic object types that these three system services +// manage and are introspected by this package. // // The machine manager maintains a list of "machines": // // 1. machine: A local container or virtual machine // // The host system, and machines hosted on it, may each run their own -// login manager, which keeps track of seats, sessions, and users: +// login manager, which keeps track of "seats", "sessions", and +// "users": // // 2. seat: A set of hardware devices for a workspace; i.e. a screen // and keyboard @@ -36,10 +38,10 @@ // more sessions // // Finally, sessions and users can be used to group together -// processes, which are kept track of by cgroup manager: +// "processes", which are kept track of by cgroup manager: // -// 5. pid: A process may belong to a session, or directly to a user -// if it is not part of a session. This "belonging" is separate -// accounting by the login manager; it is NOT the same as the -// EUID/RUID. +// 5. process: A process may belong to a session, or directly to a +// user if it is not part of a session. This "belonging" is +// separate accounting by the cgroup manager; it is NOT the same +// as the EUID/RUID. package sd_login diff --git a/sd_login/logind_seat.go b/sd_login/logind_seat.go index a62effc..4879950 100644 --- a/sd_login/logind_seat.go +++ b/sd_login/logind_seat.go @@ -21,33 +21,46 @@ import ( "golang.org/x/sys/unix" ) -// A Seat represents a set of hardware devices for a workspace; i.e. a +// A SeatName 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 +// Multiple sessions may be associated with a seat (if +// seat.CanMultiSession()), but only one session may be active on a +// seat at a time. +type SeatName string + +// A SessionNameWithUID is a just a SessionName with a User ID already +// associated with it, so that a separate lookup for GetUser isn't +// necessary. +type SessionNameWithUID struct { + SessionName + User UserID +} + +func (sess SessionNameWithUID) GetUser() (UserID, error) { + return sess.User, nil +} -func (seat Seat) isValid() bool { +func (seat SeatName) isValid() bool { return valid_filename(string(seat)) } // GetSeats returns a list of all currently available local seats. -func GetSeats() ([]Seat, error) { +func GetSeats() ([]SeatName, error) { strs, err := get_files_in_directory("/run/systemd/seats/") if err != nil { return nil, err } - seats := make([]Seat, len(strs)) + seats := make([]SeatName, len(strs)) for i := range strs { - seats[i] = Seat(strs[i]) + seats[i] = SeatName(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) { +func (seat SeatName) GetActive() (sess SessionNameWithUID, err error) { if !seat.isValid() { err = unix.EINVAL return @@ -71,15 +84,15 @@ func (seat Seat) GetActive() (sess AnnotatedSession, err error) { if err != nil { return } - sess.Session = Session(strName) - sess.User = User(intUid) + sess.SessionName = SessionName(strName) + sess.User = UserID(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) { +func (seat SeatName) GetSessions() ([]SessionNameWithUID, error) { if !seat.isValid() { return nil, unix.EINVAL } @@ -102,20 +115,20 @@ func (seat Seat) GetSessions() ([]AnnotatedSession, error) { if len(arySessions) != len(aryUids) { return nil, unix.ENXIO } - ret := make([]AnnotatedSession, len(arySessions)) + ret := make([]SessionNameWithUID, 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) + ret[i].SessionName = SessionName(arySessions[i]) + ret[i].User = UserID(uid) } return ret, nil } -func (seat Seat) can(cap string) (bool, error) { +func (seat SeatName) can(cap string) (bool, error) { if !seat.isValid() { return false, unix.EINVAL } @@ -126,14 +139,21 @@ func (seat Seat) can(cap string) (bool, error) { return parse_boolean(env["CAN_"+cap]) } -func (seat Seat) CanMultiSession() (bool, error) { +// CanMultiSession returns whether this seat is capable of +// multi-session, i.e. login sessions in parallel (with only one being +// active at a time). +func (seat SeatName) CanMultiSession() (bool, error) { return seat.can("MULTI_SESSION") } -func (seat Seat) CanTTY() (bool, error) { +// CanTTY returns whether this seat provides TTY functionality, +// i.e. is useful as a text console. +func (seat SeatName) CanTTY() (bool, error) { return seat.can("TTY") } -func (seat Seat) CanGraphical() (bool, error) { +// CanGraphical returns whether this seat provides graphics +// functionality, i.e. is useful as a graphics display. +func (seat SeatName) CanGraphical() (bool, error) { return seat.can("GRAPHICAL") } diff --git a/sd_login/logind_session.go b/sd_login/logind_session.go index e692426..5c2c5ca 100644 --- a/sd_login/logind_session.go +++ b/sd_login/logind_session.go @@ -14,63 +14,58 @@ package sd_login -type Session string - -type AnnotatedSession struct { - Session - User User -} - -func (sess AnnotatedSession) GetUser() (User, error) { - return sess.User, nil -} +// A SessionName represents a login session. +type SessionName string type SessionState int const ( + // logged in, in background SessionOnline SessionState = iota + + // logged in, in foreground SessionActive + + // nominally logged out, but some processes belonging to it + // are still around. SessionClosing ) -func GetSessions() ([]Session, error) { +func GetSessions() ([]SessionName, error) { strs, err := get_files_in_directory("/run/systemd/sessions/") if err != nil { return nil, err } - sessions := make([]Session, len(strs)) + sessions := make([]SessionName, len(strs)) for i := range strs { - sessions[i] = Session(strs[i]) + sessions[i] = SessionName(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) +func (sess SessionName) IsActive() (bool, error) +func (sess SessionName) IsRemote() (bool, error) +func (sess SessionName) GetState() (SessionState, error) +func (sess SessionName) GetUser() (UserID, error) +func (sess SessionName) GetSeat() (SeatName, error) // PAM -func (sess Session) GetService() (string, error) +func (sess SessionName) GetService() (string, error) // tty, x11, wayland, mir, unspecified -func (sess Session) GetType() (string, error) +func (sess SessionName) GetType() (string, error) // user, greeter, lock-screen -func (sess Session) GetClass() (string, error) +func (sess SessionName) GetClass() (string, error) // GNOME, KDE, systemd-console -func (sess Session) GetDesktop() (string, error) +func (sess SessionName) GetDesktop() (string, error) // X11 DISPLAY -func (sess Session) GetDisplay() (string, error) -func (sess Session) GetRemoteHost() (string, error) +func (sess SessionName) GetDisplay() (string, error) +func (sess SessionName) GetRemoteHost() (string, error) // PAM -func (sess Session) GetRemoteUser() (string, error) -func (sess Session) GetTTY() (string, error) -func (sess Session) GetVT() (uint, error) +func (sess SessionName) GetRemoteUser() (string, error) +func (sess SessionName) GetTTY() (string, error) +func (sess SessionName) GetVT() (uint, error) diff --git a/sd_login/logind_user.go b/sd_login/logind_user.go index 81a5418..8d20d4b 100644 --- a/sd_login/logind_user.go +++ b/sd_login/logind_user.go @@ -18,7 +18,7 @@ import ( "strconv" ) -type User int +type UserID int type UserState int @@ -32,26 +32,26 @@ const ( // GetUsers returns a list of all users who currently have login // sessions. -func GetUsers() ([]User, error) { +func GetUsers() ([]UserID, error) { strs, err := get_files_in_directory("/run/systemd/users/") if err != nil { return nil, err } - var users []User + var users []UserID for _, uid_str := range strs { uid, err := strconv.Atoi(uid_str) if err != nil { continue } - users = append(users, User(uid)) + users = append(users, UserID(uid)) } return users, nil } -func (uid User) IsOnSeat(seat Seat, requireActive bool) bool -func (uid User) GetState() (UserState, error) +func (uid UserID) IsOnSeat(seat SeatName, requireActive bool) bool +func (uid UserID) 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) +func (uid UserID) GetDisplay() (SessionName, error) +func (uid UserID) GetSessions(requireActive bool) ([]SessionName, error) +func (uid UserID) GetSeats(requireActive bool) ([]SeatName, error) diff --git a/sd_login/machined_machine.go b/sd_login/machined_machine.go index d89eaad..f9fb771 100644 --- a/sd_login/machined_machine.go +++ b/sd_login/machined_machine.go @@ -21,12 +21,11 @@ import ( "golang.org/x/sys/unix" ) -// A Machine is a name representing a locally running container or +// A MachineName is a name representing a locally running container or // virtual machine that is registerd with (systemd-)machined. -type Machine string +type MachineName string -// isValid returns whether the Machine name is valid. -func (m Machine) isValid() bool { +func (m MachineName) 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. @@ -59,18 +58,18 @@ func (m Machine) isValid() bool { // GetMachines returns a list of currently running containers/virtual // machines. -func GetMachines() ([]Machine, error) { +func GetMachines() ([]MachineName, error) { strs, err := get_files_in_directory("/run/systemd/machines/") if err != nil { return nil, err } - var machines []Machine + var machines []MachineName for _, str := range strs { - machine := Machine(str) + machine := MachineName(str) if strings.HasPrefix(str, "unit:") || machine.isValid() { continue } - machines = append(machines, Machine(str)) + machines = append(machines, machine) } return machines, nil } @@ -78,7 +77,7 @@ func GetMachines() ([]Machine, error) { // 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) { +func (m MachineName) GetClass() (string, error) { if !m.isValid() { return "", unix.EINVAL } @@ -96,7 +95,7 @@ func (m Machine) GetClass() (string, error) { // GetIfIndices returns the numeric indices of the network interfaces // on the host that are pointing toward this machine. -func (m Machine) GetIfIndices() ([]int, error) { +func (m MachineName) GetIfIndices() ([]int, error) { if !m.isValid() { return nil, unix.EINVAL } diff --git a/sd_login/systemd_cgroup.go b/sd_login/systemd_cgroup.go index 0ceef37..12d5ade 100644 --- a/sd_login/systemd_cgroup.go +++ b/sd_login/systemd_cgroup.go @@ -2,9 +2,9 @@ package sd_login type _Cgroup interface { MustSkipSystemPrefix() _Cgroup - GetSession() Session - GetOwnerUser() User - GetMachine() Machine + GetSession() SessionName + GetOwnerUser() UserID + GetMachine() MachineName GetUserSlice() string GetUserUnit() string @@ -13,4 +13,4 @@ type _Cgroup interface { GetUnit() string } -func (pid PID) getCgroup() (_Cgroup, error) +func (pid ProcessID) getCgroup() (_Cgroup, error) diff --git a/sd_login/systemd_pid.go.gen b/sd_login/systemd_process.go.gen index 8d5e5fb..cadbfc6 100755 --- a/sd_login/systemd_pid.go.gen +++ b/sd_login/systemd_process.go.gen @@ -27,29 +27,29 @@ import ( "golang.org/x/sys/unix" ) -// A PID represents a process. +// A ProcessID represents a process. // -// As a special case, PID(0) refers to the current process. -type PID int +// As a special case, ProcessID(0) refers to the current process. +type ProcessID int -func (pid PID) isValid() bool { +func (pid ProcessID) isValid() bool { return pid >= 0 } -func GetPeer(conn *net.UnixConn) (PID, error) { +func GetPeer(conn *net.UnixConn) (ProcessID, error) { ucred, err := getpeercred(conn) if err != nil { return -1, err } - return PID(ucred.Pid), nil + return ProcessID(ucred.Pid), nil } EOF data=( - 'GetSession Session' - 'GetOwnerUser User' - 'GetMachine Machine' + 'GetSession SessionName' + 'GetOwnerUser UserID' + 'GetMachine MachineName' 'GetUnit string' 'GetUserUnit string' @@ -60,7 +60,7 @@ EOF read Func Type <<<"$item" cat <<EOF -func (pid PID) ${Func}() (v ${Type}, err error) { +func (pid ProcessID) ${Func}() (v ${Type}, err error) { if !pid.isValid() { err = unix.EINVAL return |