diff --git a/man/meson.build b/man/meson.build index 8021adedec..c9d511b080 100644 --- a/man/meson.build +++ b/man/meson.build @@ -34,6 +34,7 @@ custom_entities_ent = configure_file( man_pages = [] html_pages = [] source_xml_files = [] +dbus_docs = [] foreach tuple : xsltproc.found() ? manpages : [] stem = tuple[0] section = tuple[1] @@ -90,7 +91,11 @@ foreach tuple : xsltproc.found() ? manpages : [] install_dir : join_paths(docdir, 'html')) html_pages += p3 - source_xml_files += files(tuple[0] + '.xml') + file = files(tuple[0] + '.xml') + source_xml_files += file + if tuple[0].startswith('org.freedesktop.') + dbus_docs += file + endif else message('Skipping @0@.@1@ because @2@ is false'.format(stem, section, condition)) endif @@ -193,6 +198,19 @@ run_target( ############################################################ +if dbus_docs.length() > 0 + custom_target( + 'update-dbus-docs', + output : 'update-dbus-docs', + command : ['python3', + '@0@/tools/update-dbus-docs.py'.format(project_source_root), + '--build-dir=@0@'.format(project_build_root), + '@INPUT@'], + input : dbus_docs) +endif + +############################################################ + if git.found() custom_target( 'update-man-rules', diff --git a/man/org.freedesktop.LogControl1.xml b/man/org.freedesktop.LogControl1.xml new file mode 100644 index 0000000000..125a008347 --- /dev/null +++ b/man/org.freedesktop.LogControl1.xml @@ -0,0 +1,106 @@ + + + + + + + org.freedesktop.LogControl1 + systemd + + + + org.freedesktop.LogControl1 + 5 + + + + org.freedesktop.LogControl1 + D-Bus interface to query and set logging configuration + + + + Introduction + + org.freedesktop.LogControl1 is a generic interface that is intended + to be used by any daemon which should allow setting the log level and target over D-Bus. It is implemented + by various daemons that are part of the + systemd1 suite. + + It is assumed that those settings are global for the whole program, so a fixed object path is + used. The interface should always be available under the path + /org/freedesktop/LogControl1. + + + + Description + + The following interface is exposed: + + +node /org/freedesktop/LogControl1 { + interface org.freedesktop.LogControl1 { + properties: + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + @org.freedesktop.systemd1.Privileged("true") + readwrite s LogLevel = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + @org.freedesktop.systemd1.Privileged("true") + readwrite s LogTarget = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly s SyslogIdentifier = '...'; + }; + interface org.freedesktop.DBus.Peer { ... }; + interface org.freedesktop.DBus.Introspectable { ... }; + interface org.freedesktop.DBus.Properties { ... }; +}; + + + + + + + + + + + + + + + + + + Properties + + LogLevel describes the + syslog3-style + log-level, and should be one of emerg, alert, + crit, err, warning, notice, + info, debug, in order of increasing verbosity. + + LogTarget describes the log target (mechanism). It should be one of + console (log to the console or standard output), + kmsg (log to the kernel ring buffer), + journal (log the the journal natively, see + systemd-journald.service8), + syslog (log using the + syslog3 call). + + + Those two properties are writable, so they may be set by sufficiently privileged users. + + SyslogIdentifier is a read-only property that shows the "syslog identifier". + It is a short string that identifies the program that is the source of log messages that is passed to + the syslog3 call. + + + Note: journalctl option / may + be used to filter log messages by log level, option / + may be used to by the syslog identifier, and filters like _TRANSPORT=syslog, + _TRANSPORT=journal, and _TRANSPORT=kernel may be used to filter + messages by the mechanism through which they reached systemd-journald. + + + diff --git a/man/org.freedesktop.home1.xml b/man/org.freedesktop.home1.xml new file mode 100644 index 0000000000..cb1e3a182e --- /dev/null +++ b/man/org.freedesktop.home1.xml @@ -0,0 +1,369 @@ + + + + + + + org.freedesktop.home1 + systemd + + + + org.freedesktop.home1 + 5 + + + + org.freedesktop.home1 + The D-Bus interface of systemd-homed + + + + Introduction + + + systemd-homed.service8 + is a system service which may be used to to create, remove, change or inspect home areas. This page + describes the D-Bus interface. + + + + + The Manager Object + + The service exposes the following interfaces on the Manager object on the bus: + + +node /org/freedesktop/home1 { + interface org.freedesktop.home1.Manager { + methods: + GetHomeByName(in s user_name, + out u uid, + out s home_state, + out u gid, + out s real_name, + out s home_directory, + out s shell, + out o bus_path); + GetHomeByUID(in u uid, + out s user_name, + out s home_state, + out u gid, + out s real_name, + out s home_directory, + out s shell, + out o bus_path); + GetUserRecordByName(in s user_name, + out s user_record, + out b incomplete, + out o bus_path); + GetUserRecordByUID(in u uid, + out s user_record, + out b incomplete, + out o bus_path); + ListHomes(out a(susussso) home_areas); + ActivateHome(in s user_name, + in s user_record); + DeactivateHome(in s user_name); + RegisterHome(in s home_record); + UnregisterHome(in s user_name); + CreateHome(in s home_record); + RealizeHome(in s user_name, + in s user_record); + RemoveHome(in s user_name); + FixateHome(in s user_name, + in s user_record); + AuthenticateHome(in s user_name, + in s user_record); + UpdateHome(in s user_record); + ResizeHome(in s user_name, + in t size, + in s user_record); + ChangePasswordHome(in s user_name, + in s new_user_record, + in s old_user_record); + LockHome(in s user_name); + UnlockHome(in s user_name, + in s user_record); + AcquireHome(in s user_name, + in s user_record, + in b please_suspend, + out h send_fd); + RefHome(in s user_name, + in b please_suspend, + out h send_fd); + ReleaseHome(in s user_name); + LockAllHomes(); + properties: + readonly a(sso) AutoLogin = [...]; + }; + interface org.freedesktop.DBus.Peer { ... }; + interface org.freedesktop.DBus.Introspectable { ... }; + interface org.freedesktop.DBus.Properties { ... }; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Methods + + ... + + + + Signals + + ... + + + + + The Home Object + + +node /org/freedesktop/home1/home { + interface org.freedesktop.home1.Home { + methods: + Activate(in s user_record); + Deactivate(); + Unregister(); + Realize(in s user_record); + Remove(); + Fixate(in s user_record); + Authenticate(in s user_record); + Update(in s user_record); + Resize(in t size, + in s user_record); + ChangePassword(in s new_user_record, + in s old_user_record); + Lock(); + Unlock(in s user_record); + Acquire(in s user_record, + in b please_suspend, + out h send_fd); + Ref(in b please_suspend, + out h send_fd); + Release(); + properties: + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s UserName = '...'; + readonly u UID = ...; + readonly (suusss) UnixRecord = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly s State = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates") + readonly (sb) UserRecord = ...; + }; + interface org.freedesktop.DBus.Peer { ... }; + interface org.freedesktop.DBus.Introspectable { ... }; + interface org.freedesktop.DBus.Properties { ... }; + interface org.freedesktop.DBus.ObjectManager { ... }; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Versioning + + These D-Bus interfaces follow + the usual interface versioning guidelines. + + diff --git a/man/org.freedesktop.hostname1.xml b/man/org.freedesktop.hostname1.xml index 406a6a369e..d17d9a5521 100644 --- a/man/org.freedesktop.hostname1.xml +++ b/man/org.freedesktop.hostname1.xml @@ -38,11 +38,7 @@ The service exposes the following interfaces on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.hostname1 \ - --object-path /org/freedesktop/hostname1 - + node /org/freedesktop/hostname1 { interface org.freedesktop.hostname1 { methods: @@ -349,6 +345,19 @@ node /org/freedesktop/hostname1 { the usual interface versioning guidelines. + + Examples + + + Introspect <interfacename>org.freedesktop.hostname1</interfacename> on the bus + + $ gdbus introspect --system \ + --dest org.freedesktop.hostname1 \ + --object-path /org/freedesktop/hostname1 + + + + See also diff --git a/man/org.freedesktop.import1.xml b/man/org.freedesktop.import1.xml index 4a425f1ac3..1414cc15d7 100644 --- a/man/org.freedesktop.import1.xml +++ b/man/org.freedesktop.import1.xml @@ -46,11 +46,7 @@ The service exposes the following interfaces on the Manager object on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.import1 \ - --object-path /org/freedesktop/import1 - + node /org/freedesktop/import1 { interface org.freedesktop.import1.Manager { methods: @@ -238,11 +234,7 @@ node /org/freedesktop/import1 { The Transfer Object - -$ gdbus introspect --system \ - --dest org.freedesktop.import1 \ - --object-path /org/freedesktop/import1/transfer/_1 - + node /org/freedesktop/import1/transfer/_1 { interface org.freedesktop.import1.Transfer { methods: @@ -325,6 +317,28 @@ node /org/freedesktop/import1/transfer/_1 { + + Examples + + + Introspect <interfacename>org.freedesktop.import1.Manager</interfacename> on the bus + + $ gdbus introspect --system \ + --dest org.freedesktop.import1 \ + --object-path /org/freedesktop/import1 + + + + + Introspect <interfacename>org.freedesktop.import1.Transfer</interfacename> on the bus + + $ gdbus introspect --system \ + --dest org.freedesktop.import1 \ + --object-path /org/freedesktop/import1/transfer/_1 + + + + Versioning diff --git a/man/org.freedesktop.locale1.xml b/man/org.freedesktop.locale1.xml index f15945e766..3956eaf8a7 100644 --- a/man/org.freedesktop.locale1.xml +++ b/man/org.freedesktop.locale1.xml @@ -34,11 +34,7 @@ The service exposes the following interfaces on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.locale1 \ - --object-path /org/freedesktop/locale1 - + node /org/freedesktop/locale1 { interface org.freedesktop.locale1 { methods: @@ -169,6 +165,20 @@ node /org/freedesktop/locale1 { + + Examples + + + Introspect <interfacename>org.freedesktop.locale1</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.locale1 \ + --object-path /org/freedesktop/locale1 + + + + Versioning diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml index aedf5d7fc3..44ad033752 100644 --- a/man/org.freedesktop.login1.xml +++ b/man/org.freedesktop.login1.xml @@ -38,11 +38,7 @@ The service exposes the following interfaces on the Manager object on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.login1 \ - --object-path /org/freedesktop/login1 - + node /org/freedesktop/login1 { interface org.freedesktop.login1.Manager { methods: @@ -741,10 +737,7 @@ node /org/freedesktop/login1 { Seat Objects - -$ gdbus introspect --system --dest org.freedesktop.login1 \ - --object-path /org/freedesktop/login1/seat/seat0 - + node /org/freedesktop/login1/seat/seat0 { interface org.freedesktop.login1.Seat { methods: @@ -758,8 +751,6 @@ node /org/freedesktop/login1/seat/seat0 { readonly s Id = '...'; readonly (so) ActiveSession = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b CanMultiSession = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly b CanTTY = ...; readonly b CanGraphical = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") @@ -794,8 +785,6 @@ node /org/freedesktop/login1/seat/seat0 { - - @@ -827,7 +816,7 @@ node /org/freedesktop/login1/seat/seat0 { Signals Whenever ActiveSession, Sessions, - CanGraphical, CanMultiSession and CanTTY + CanGraphical, CanTTY, or the idle state changes, PropertyChanged signals are sent out to which clients can subscribe. @@ -840,9 +829,8 @@ node /org/freedesktop/login1/seat/seat0 { ActiveSession encodes the currently active session if there is one. It is a structure consisting of the session id and the object path. - CanMultiSession encodes whether the session is multi-session capable, - CanTTY whether it is suitable for text logins, CanGraphical - whether it is suitable for graphical sessions. + CanTTY encodes whether the session is suitable for text logins, and + CanGraphical whether it is suitable for graphical sessions. The Sessions property is an array of all current sessions of this seat, each encoded in a structure consisting of the ID and the object path. @@ -856,10 +844,7 @@ node /org/freedesktop/login1/seat/seat0 { User Objects - -$ gdbus introspect --system --dest org.freedesktop.login1 \ - --object-path /org/freedesktop/login1/user/_1000 - + node /org/freedesktop/login1/user/_1000 { interface org.freedesktop.login1.User { methods: @@ -1004,11 +989,8 @@ node /org/freedesktop/login1/user/_1000 { Session Objects - -$ gdbus introspect --system --dest org.freedesktop.login1 \ - --object-path /org/freedesktop/login1/session/45 - -node /org/freedesktop/login1/session/45 { + +node /org/freedesktop/login1/session/1 { interface org.freedesktop.login1.Session { methods: Terminate(); @@ -1021,6 +1003,7 @@ node /org/freedesktop/login1/session/45 { in i signal_number); TakeControl(in b force); ReleaseControl(); + SetType(in s type); TakeDevice(in u major, in u minor, out h fd, @@ -1076,7 +1059,6 @@ node /org/freedesktop/login1/session/45 { readonly u Leader = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly u Audit = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s Type = '...'; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s Class = '...'; @@ -1093,6 +1075,100 @@ node /org/freedesktop/login1/session/45 { }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Methods @@ -1109,10 +1185,17 @@ node /org/freedesktop/login1/session/45 { out and replaced. Otherwise, this method fails if there is already a controller. Note that this method is limited to D-Bus users with the effective UID set to the user of the session or root. - ReleaseControl() drops control of a given session. Closing the - D-Bus connection implicitly releases control as well. See TakeControl() for more information. This - method also releases all devices for which the controller requested ownership via TakeDevice(). - + ReleaseControl() drops control of a given session. Closing the D-Bus + connection implicitly releases control as well. See TakeControl() for more + information. This method also releases all devices for which the controller requested ownership via + TakeDevice(). + + SetType() allows the type of the session to be changed dynamically. It can + only be called by session's current controller. If TakeControl() has not been + called, this method will fail. In addition, the session type will be reset to its original value once + control is released, either by calling ReleaseControl() or closing the D-Bus + connection. This should help prevent a session from entering an inconsistent state, for example if the + controller crashes. The only argument type is the new session type. TakeDevice() allows a session controller to get a file descriptor for a specific device. Pass in the major and minor numbers of the character device and @@ -1257,6 +1340,42 @@ node /org/freedesktop/login1/session/45 { + + Examples + + + Introspect <interfacename>org.freedesktop.login1.Manager</interfacename> on the bus + + $ gdbus introspect --system --dest org.freedesktop.login1 \ + --object-path /org/freedesktop/login1 + + + + + Introspect <interfacename>org.freedesktop.login1.Seat</interfacename> on the bus + + $ gdbus introspect --system --dest org.freedesktop.login1 \ + --object-path /org/freedesktop/login1/seat/seat0 + + + + + Introspect <interfacename>org.freedesktop.login1.User</interfacename> on the bus + + $ gdbus introspect --system --dest org.freedesktop.login1 \ + --object-path /org/freedesktop/login1/user/_1000 + + + + + Introspect <interfacename>org.freedesktop.login1.Session</interfacename> on the bus + + $ gdbus introspect --system --dest org.freedesktop.login1 \ + --object-path /org/freedesktop/login1/session/45 + + + + Versioning diff --git a/man/org.freedesktop.machine1.xml b/man/org.freedesktop.machine1.xml index bc9779c521..c18e133e7c 100644 --- a/man/org.freedesktop.machine1.xml +++ b/man/org.freedesktop.machine1.xml @@ -34,11 +34,7 @@ The service exposes the following interfaces on the Manager object on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.machine1 \ - --object-path /org/freedesktop/machine1 - + node /org/freedesktop/machine1 { interface org.freedesktop.machine1.Manager { methods: @@ -435,11 +431,7 @@ node /org/freedesktop/machine1 { Machine Objects - -$ gdbus introspect --system \ - --dest org.freedesktop.machine1 \ - --object-path /org/freedesktop/machine1/machine/rawhide - + node /org/freedesktop/machine1/machine/rawhide { interface org.freedesktop.machine1.Machine { methods: @@ -617,6 +609,30 @@ node /org/freedesktop/machine1/machine/rawhide { + + Examples + + + Introspect <interfacename>org.freedesktop.machine1.Manager</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.machine1 \ + --object-path /org/freedesktop/machine1 + + + + + Introspect <interfacename>org.freedesktop.machine1.Machine</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.machine1 \ + --object-path /org/freedesktop/machine1/machine/rawhide + + + + Versioning diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml index 912f73677c..7a57806ebb 100644 --- a/man/org.freedesktop.resolve1.xml +++ b/man/org.freedesktop.resolve1.xml @@ -46,11 +46,7 @@ The service exposes the following interfaces on the Manager object on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.resolve1 \ - --object-path /org/freedesktop/resolve1 - + node /org/freedesktop/resolve1 { interface org.freedesktop.resolve1.Manager { methods: @@ -145,9 +141,6 @@ node /org/freedesktop/resolve1 { readonly as DNSSECNegativeTrustAnchors = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s DNSStubListener = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - @org.freedesktop.systemd1.Privileged("true") - readwrite s LogLevel = '...'; }; interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; @@ -257,8 +250,6 @@ node /org/freedesktop/resolve1 { - - @@ -551,12 +542,8 @@ node /org/freedesktop/resolve1 { Link Object - -$ gdbus introspect --system \ - --dest org.freedesktop.resolve1 \ - --object-path /org/freedesktop/resolve1/link/_34 - -node /org/freedesktop/resolve1/link/_34 { + +node /org/freedesktop/resolve1/link/_1 { interface org.freedesktop.resolve1.Link { methods: SetDNS(in a(iay) addresses); @@ -790,6 +777,30 @@ node /org/freedesktop/resolve1/link/_34 { + + Examples + + + Introspect <interfacename>org.freedesktop.resolve1.Manager</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.resolve1 \ + --object-path /org/freedesktop/resolve1 + + + + + Introspect <interfacename>org.freedesktop.resolve1.Link</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.resolve1 \ + --object-path /org/freedesktop/resolve1/link/_11 + + + + Versioning diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index da5541be90..741fd3d481 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -57,11 +57,7 @@ The main entry point object is available on the fixed /org/freedesktop/systemd1 object path: - -$ gdbus introspect --system \ - --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1 - + node /org/freedesktop/systemd1 { interface org.freedesktop.systemd1.Manager { methods: @@ -1484,10 +1480,7 @@ node /org/freedesktop/systemd1 { Unit Objects - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice - + node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { interface org.freedesktop.systemd1.Unit { methods: @@ -1674,7 +1667,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; interface org.freedesktop.DBus.Properties { ... }; - interface org.freedesktop.systemd1.Service { ... }; }; @@ -1746,12 +1738,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - - @@ -2139,10 +2127,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { org.freedesktop.systemd1.Service interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice - + node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { interface org.freedesktop.systemd1.Service { methods: @@ -3135,14 +3120,14 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - + + @@ -3746,10 +3731,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { Socket Unit Objects - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket - + node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { interface org.freedesktop.systemd1.Socket { methods: @@ -4777,14 +4759,14 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - + + @@ -5340,10 +5322,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { Target Unit Objects - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/basic_2etarget - + node /org/freedesktop/systemd1/unit/basic_2etarget { interface org.freedesktop.systemd1.Target { }; @@ -5364,11 +5343,8 @@ node /org/freedesktop/systemd1/unit/basic_2etarget { All device unit objects implement the org.freedesktop.systemd1.Device interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/dev_2dfoo_2edevice - -node /org/freedesktop/systemd1/unit/dev_2dfoo_2edevice { + +node /org/freedesktop/systemd1/unit/dev_2dttyS0_2edevice { interface org.freedesktop.systemd1.Device { properties: readonly s SysFSPath = '...'; @@ -5382,14 +5358,14 @@ node /org/freedesktop/systemd1/unit/dev_2dfoo_2edevice { - - + + @@ -5411,10 +5387,7 @@ node /org/freedesktop/systemd1/unit/dev_2dfoo_2edevice { interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/home_2emount - + node /org/freedesktop/systemd1/unit/home_2emount { interface org.freedesktop.systemd1.Mount { methods: @@ -6291,14 +6264,14 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - + + @@ -6773,10 +6746,7 @@ node /org/freedesktop/systemd1/unit/home_2emount { org.freedesktop.systemd1.Automount interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount - + node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount { interface org.freedesktop.systemd1.Automount { properties: @@ -6803,14 +6773,14 @@ node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount - - + + @@ -6841,10 +6811,7 @@ node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer - + node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { interface org.freedesktop.systemd1.Timer { properties: @@ -6901,14 +6868,14 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { - - + + @@ -6980,10 +6947,7 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap - + node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { interface org.freedesktop.systemd1.Swap { methods: @@ -7836,14 +7800,14 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - + + @@ -8306,10 +8270,7 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { Path Unit Objects - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/cups_2epath - + node /org/freedesktop/systemd1/unit/cups_2epath { interface org.freedesktop.systemd1.Path { properties: @@ -8336,14 +8297,14 @@ node /org/freedesktop/systemd1/unit/cups_2epath { - - + + @@ -8382,10 +8343,7 @@ node /org/freedesktop/systemd1/unit/cups_2epath { interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/system_2eslice - + node /org/freedesktop/systemd1/unit/system_2eslice { interface org.freedesktop.systemd1.Slice { methods: @@ -8645,14 +8603,14 @@ node /org/freedesktop/systemd1/unit/system_2eslice { - - + + @@ -8793,10 +8751,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice { interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/unit/session_2d1_2escope - + node /org/freedesktop/systemd1/unit/session_2d1_2escope { interface org.freedesktop.systemd1.Scope { methods: @@ -9097,14 +9052,14 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { - - + + @@ -9293,11 +9248,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { Job objects encapsulate scheduled or running jobs. Each unit can have none or one jobs in the execution queue. Each job is attached to exactly one unit. - -$ gdbus introspect --system --dest org.freedesktop.systemd1 \ - --object-path /org/freedesktop/systemd1/job/1292 - -node /org/freedesktop/systemd1/job/1292 { + +node /org/freedesktop/systemd1/job/666 { interface org.freedesktop.systemd1.Job { methods: Cancel(); @@ -9373,6 +9325,41 @@ node /org/freedesktop/systemd1/job/1292 { + + Examples + + + Introspect <interfacename>org.freedesktop.systemd1.Manager</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.systemd1 \ + --object-path /org/freedesktop/systemd1 + + + + + Introspect a unit on the bus + + +$ busctl introspect org.freedesktop.systemd1 \ + $(busctl call org.freedesktop.systemd1 \ + /org/freedesktop/systemd1 \ + org.freedesktop.systemd1.Manager \ + GetUnit s systemd-resolved.service | cut -d'"' -f2) + + + + + Introspect <interfacename>org.freedesktop.systemd1.Job</interfacename> on the bus + + +$ gdbus introspect --system --dest org.freedesktop.systemd1 \ + --object-path /org/freedesktop/systemd1/job/1292 + + + + Versioning diff --git a/man/org.freedesktop.timedate1.xml b/man/org.freedesktop.timedate1.xml index 3111ebbc42..325c3acfb1 100644 --- a/man/org.freedesktop.timedate1.xml +++ b/man/org.freedesktop.timedate1.xml @@ -34,11 +34,7 @@ The service exposes the following interfaces on the bus: - -$ gdbus introspect --system \ - --dest org.freedesktop.timedate1 \ - --object-path /org/freedesktop/timedate1 - + node /org/freedesktop/timedate1 { interface org.freedesktop.timedate1 { methods: @@ -180,6 +176,20 @@ node /org/freedesktop/timedate1 { + + Examples + + + Introspect <interfacename>org.freedesktop.timedate1</interfacename> on the bus + + +$ gdbus introspect --system \ + --dest org.freedesktop.timedate1 \ + --object-path /org/freedesktop/timedate1 + + + + Versioning diff --git a/man/rules/meson.build b/man/rules/meson.build index 2096222c50..0d05508e7b 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -44,6 +44,8 @@ manpages = [ ['nss-mymachines', '8', ['libnss_mymachines.so.2'], 'ENABLE_NSS_MYMACHINES'], ['nss-resolve', '8', ['libnss_resolve.so.2'], 'ENABLE_NSS_RESOLVE'], ['nss-systemd', '8', ['libnss_systemd.so.2'], 'ENABLE_NSS_SYSTEMD'], + ['org.freedesktop.LogControl1', '5', [], ''], + ['org.freedesktop.home1', '5', [], 'ENABLE_HOMED'], ['org.freedesktop.hostname1', '5', [], 'ENABLE_HOSTNAMED'], ['org.freedesktop.import1', '5', [], 'ENABLE_IMPORTD'], ['org.freedesktop.locale1', '5', [], 'ENABLE_LOCALED'], diff --git a/man/systemd-hostnamed.service.xml b/man/systemd-hostnamed.service.xml index 699316a09a..1aa32a61ce 100644 --- a/man/systemd-hostnamed.service.xml +++ b/man/systemd-hostnamed.service.xml @@ -56,7 +56,9 @@ is a command line client to this service. See - org.freedesktop.hostname11 + org.freedesktop.hostname15 + and + org.freedesktop.LogControl15 for a description of the D-Bus API. diff --git a/man/systemd-importd.service.xml b/man/systemd-importd.service.xml index 355e5b0b98..fa3c3a812f 100644 --- a/man/systemd-importd.service.xml +++ b/man/systemd-importd.service.xml @@ -36,10 +36,11 @@ pull-raw, pull-tar, import-raw, import-tar, export-raw, and export-tar commands. - See the - - importd D-Bus API Documentation for information about the - APIs systemd-importd provides. + See + org.freedesktop.import15 + and + org.freedesktop.LogControl15 + for a description of the D-Bus API. diff --git a/man/systemd-localed.service.xml b/man/systemd-localed.service.xml index e5f6b78d21..49eeeffee6 100644 --- a/man/systemd-localed.service.xml +++ b/man/systemd-localed.service.xml @@ -41,7 +41,9 @@ is a command line client to this service. See - org.freedesktop.locale11 + org.freedesktop.locale15 + and + org.freedesktop.LogControl15 for a description of the D-Bus API. diff --git a/man/systemd-logind.service.xml b/man/systemd-logind.service.xml index 12f9f7a0f6..c602b2e42f 100644 --- a/man/systemd-logind.service.xml +++ b/man/systemd-logind.service.xml @@ -79,7 +79,9 @@ such as users, sessions and seats. See - org.freedesktop.login13 + org.freedesktop.login15 + and + org.freedesktop.LogControl15 for information about the D-Bus APIs systemd-logind provides. For more information on the inhibition logic see the sd-login3 and - org.freedesktop.machine13. + org.freedesktop.machine15. + and + org.freedesktop.LogControl15 A small companion daemon diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml index 2f4efab1ff..6e1ee9f4a5 100644 --- a/man/systemd-resolved.service.xml +++ b/man/systemd-resolved.service.xml @@ -38,6 +38,8 @@ The native, fully-featured API systemd-resolved exposes on the bus, see org.freedesktop.resolve15 + and + org.freedesktop.LogControl15 for details. Usage of this API is generally recommended to clients as it is asynchronous and fully featured (for example, properly returns DNSSEC validation status and interface scope for addresses as necessary for supporting link-local networking). diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml index b722b33115..93cfdf5118 100644 --- a/man/systemd-timedated.service.xml +++ b/man/systemd-timedated.service.xml @@ -55,6 +55,8 @@ See org.freedesktop.timedate15 + and + org.freedesktop.LogControl15 for information about the D-Bus API. diff --git a/man/systemd.xml b/man/systemd.xml index 4e08ff6254..11954a78da 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -281,7 +281,10 @@ systemd.generator7. The D-Bus API of systemd is described in - org.freedesktop.systemd15. + org.freedesktop.systemd15 + and + org.freedesktop.LogControl15. + Systems which invoke systemd in a container or initrd environment should implement the Container Interface or @OUTPUT@'], build_by_default : true) diff --git a/src/core/automount.c b/src/core/automount.c index 0b3f498bfc..54711e2b7f 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -1133,7 +1133,6 @@ const UnitVTable automount_vtable = { .reset_failed = automount_reset_failed, - .bus_vtable = bus_automount_vtable, .bus_set_property = bus_automount_set_property, .shutdown = automount_shutdown, diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index 0e952c8757..404984f664 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -140,6 +140,58 @@ const sd_bus_vtable bus_job_vtable[] = { SD_BUS_VTABLE_END }; +static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Job *j; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = manager_get_job_from_dbus_path(m, path, &j); + if (r < 0) + return 0; + + *found = j; + return 1; +} + +static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + unsigned k = 0; + Iterator i; + Job *j; + + l = new0(char*, hashmap_size(m->jobs)+1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(j, m->jobs, i) { + l[k] = job_dbus_path(j); + if (!l[k]) + return -ENOMEM; + + k++; + } + + assert(hashmap_size(m->jobs) == k); + + *nodes = TAKE_PTR(l); + + return k; +} + +const BusObjectImplementation job_object = { + "/org/freedesktop/systemd1/job", + "org.freedesktop.systemd1.Job", + .fallback_vtables = BUS_FALLBACK_VTABLES({bus_job_vtable, bus_job_find}), + .node_enumerator = bus_job_enumerate, +}; + static int send_new_signal(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h index 380e117fca..a840c6dfe8 100644 --- a/src/core/dbus-job.h +++ b/src/core/dbus-job.h @@ -2,11 +2,12 @@ #pragma once #include "sd-bus.h" -#include "sd-bus-vtable.h" #include "unit.h" +#include "bus-util.h" extern const sd_bus_vtable bus_job_vtable[]; +extern const BusObjectImplementation job_object; int bus_job_method_cancel(sd_bus_message *message, void *job, sd_bus_error *error); int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 30c86ecb14..f21f236025 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -2,7 +2,6 @@ #pragma once #include "sd-bus.h" -#include "sd-bus-vtable.h" #include "unit.h" diff --git a/src/core/dbus.c b/src/core/dbus.c index 17c961edef..76bb91d0ea 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -274,25 +274,6 @@ static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_er } #endif -static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - Manager *m = userdata; - Job *j; - int r; - - assert(bus); - assert(path); - assert(interface); - assert(found); - assert(m); - - r = manager_get_job_from_dbus_path(m, path, &j); - if (r < 0) - return 0; - - *found = j; - return 1; -} - static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) { Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */ int r; @@ -472,32 +453,6 @@ static int bus_kill_context_find(sd_bus *bus, const char *path, const char *inte return 1; } -static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - unsigned k = 0; - Iterator i; - Job *j; - - l = new0(char*, hashmap_size(m->jobs)+1); - if (!l) - return -ENOMEM; - - HASHMAP_FOREACH(j, m->jobs, i) { - l[k] = job_dbus_path(j); - if (!l[k]) - return -ENOMEM; - - k++; - } - - assert(hashmap_size(m->jobs) == k); - - *nodes = TAKE_PTR(l); - - return k; -} - static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; @@ -522,8 +477,147 @@ static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, cha return k; } +static const BusObjectImplementation unit_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Unit", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_unit_vtable, bus_unit_find }), + .node_enumerator = bus_unit_enumerate, +}; + +static const BusObjectImplementation bus_automount_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Automount", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_automount_vtable, bus_unit_interface_find }), +}; + +static const BusObjectImplementation bus_device_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Device", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_device_vtable, bus_unit_interface_find }), +}; + +static const BusObjectImplementation bus_mount_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Mount", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_mount_vtable, bus_unit_interface_find }, + { bus_unit_cgroup_vtable, bus_unit_cgroup_find }, + { bus_cgroup_vtable, bus_cgroup_context_find }, + { bus_exec_vtable, bus_exec_context_find }, + { bus_kill_vtable, bus_kill_context_find }), +}; + +static const BusObjectImplementation bus_path_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Path", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_path_vtable, bus_unit_interface_find }), +}; + +static const BusObjectImplementation bus_scope_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Scope", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_scope_vtable, bus_unit_interface_find }, + { bus_unit_cgroup_vtable, bus_unit_cgroup_find }, + { bus_cgroup_vtable, bus_cgroup_context_find }, + { bus_kill_vtable, bus_kill_context_find }), +}; + +static const BusObjectImplementation bus_service_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Service", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_service_vtable, bus_unit_interface_find }, + { bus_unit_cgroup_vtable, bus_unit_cgroup_find }, + { bus_cgroup_vtable, bus_cgroup_context_find }, + { bus_exec_vtable, bus_exec_context_find }, + { bus_kill_vtable, bus_kill_context_find }), +}; + +static const BusObjectImplementation bus_slice_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Slice", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_slice_vtable, bus_unit_interface_find }, + { bus_unit_cgroup_vtable, bus_unit_cgroup_find }, + { bus_cgroup_vtable, bus_cgroup_context_find }), +}; + +static const BusObjectImplementation bus_socket_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Socket", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_socket_vtable, bus_unit_interface_find }, + { bus_unit_cgroup_vtable, bus_unit_cgroup_find }, + { bus_cgroup_vtable, bus_cgroup_context_find }, + { bus_exec_vtable, bus_exec_context_find }, + { bus_kill_vtable, bus_kill_context_find }), +}; + +static const BusObjectImplementation bus_swap_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Swap", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_swap_vtable, bus_unit_interface_find }, + { bus_unit_cgroup_vtable, bus_unit_cgroup_find }, + { bus_cgroup_vtable, bus_cgroup_context_find }, + { bus_exec_vtable, bus_exec_context_find }, + { bus_kill_vtable, bus_kill_context_find }), +}; + +static const BusObjectImplementation bus_target_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Target", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_target_vtable, bus_unit_interface_find }), +}; + +static const BusObjectImplementation bus_timer_object = { + "/org/freedesktop/systemd1/unit", + "org.freedesktop.systemd1.Timer", + .fallback_vtables = BUS_FALLBACK_VTABLES( + { bus_timer_vtable, bus_unit_interface_find }), +}; + +static const BusObjectImplementation bus_manager_object = { + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + .vtables = BUS_VTABLES(bus_manager_vtable), + .children = BUS_IMPLEMENTATIONS( + &job_object, + &unit_object, + &bus_automount_object, + &bus_device_object, + &bus_mount_object, + &bus_path_object, + &bus_scope_object, + &bus_service_object, + &bus_slice_object, + &bus_socket_object, + &bus_swap_object, + &bus_target_object, + &bus_timer_object), +}; + +static const BusObjectImplementation manager_log_control_object = { + "/org/freedesktop/LogControl1", + "org.freedesktop.LogControl1", + .vtables = BUS_VTABLES(bus_manager_log_control_vtable), +}; + +int bus_manager_introspect_implementations(FILE *out, const char *pattern) { + return bus_introspect_implementations( + out, + pattern, + BUS_IMPLEMENTATIONS(&bus_manager_object, + &manager_log_control_object)); +} + static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { - UnitType t; int r; assert(m); @@ -535,63 +629,11 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { return log_error_errno(r, "Failed to add SELinux access filter: %m"); #endif - r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m); + r = bus_add_implementation(bus, &bus_manager_object, m); if (r < 0) - return log_error_errno(r, "Failed to register Manager vtable: %m"); + return r; - r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/LogControl1", "org.freedesktop.LogControl1", bus_manager_log_control_vtable, m); - if (r < 0) - return log_error_errno(r, "Failed to register service API vtable: %m"); - - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register Job vtable: %m"); - - r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m); - if (r < 0) - return log_error_errno(r, "Failed to add job enumerator: %m"); - - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register Unit vtable: %m"); - - r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m); - if (r < 0) - return log_error_errno(r, "Failed to add job enumerator: %m"); - - for (t = 0; t < _UNIT_TYPE_MAX; t++) { - const char *interface; - - assert_se(interface = unit_dbus_interface_from_type(t)); - - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface); - - if (unit_vtable[t]->cgroup_context_offset > 0) { - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface); - - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface); - } - - if (unit_vtable[t]->exec_context_offset > 0) { - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface); - } - - if (unit_vtable[t]->kill_context_offset > 0) { - r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface); - } - } - - return 0; + return bus_add_implementation(bus, &manager_log_control_object, m); } static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) { diff --git a/src/core/dbus.h b/src/core/dbus.h index d5ba6537ea..812f56ea2a 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -33,3 +33,4 @@ int bus_forward_agent_released(Manager *m, const char *path); uint64_t manager_bus_n_queued_write(Manager *m); void dump_bus_properties(FILE *f); +int bus_manager_introspect_implementations(FILE *out, const char *pattern); diff --git a/src/core/device.c b/src/core/device.c index 8e00fd3df6..a24fea04d0 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1081,8 +1081,6 @@ const UnitVTable device_vtable = { .active_state = device_active_state, .sub_state_to_string = device_sub_state_to_string, - .bus_vtable = bus_device_vtable, - .following = device_following, .following_set = device_following_set, diff --git a/src/core/main.c b/src/core/main.c index 49879d8e37..c9eaf70bd6 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -93,8 +93,11 @@ static enum { ACTION_TEST, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES, + ACTION_BUS_INTROSPECT, } arg_action = ACTION_RUN; +static const char *arg_bus_introspect = NULL; + /* Those variables are initialized to 0 automatically, so we avoid uninitialized memory access. * Real defaults are assigned in reset_arguments() below. */ static char *arg_default_unit; @@ -729,6 +732,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION, ARG_DUMP_CONFIGURATION_ITEMS, ARG_DUMP_BUS_PROPERTIES, + ARG_BUS_INTROSPECT, ARG_DUMP_CORE, ARG_CRASH_CHVT, ARG_CRASH_SHELL, @@ -758,6 +762,7 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, { "dump-bus-properties", no_argument, NULL, ARG_DUMP_BUS_PROPERTIES }, + { "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT }, { "dump-core", optional_argument, NULL, ARG_DUMP_CORE }, { "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT }, { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL }, @@ -885,6 +890,11 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_DUMP_BUS_PROPERTIES; break; + case ARG_BUS_INTROSPECT: + arg_bus_introspect = optarg; + arg_action = ACTION_BUS_INTROSPECT; + break; + case ARG_DUMP_CORE: if (!optarg) arg_dump_core = true; @@ -1033,7 +1043,9 @@ static int help(void) { return log_oom(); printf("%s [OPTIONS...]\n\n" - "Starts up and maintains the system or user services.\n\n" + "%sStarts and monitors system and user services.%s\n\n" + "This program takes no positional arguments.\n\n" + "%sOptions%s:\n" " -h --help Show this help\n" " --version Show version\n" " --test Determine initial transaction, dump it and exit\n" @@ -1042,6 +1054,7 @@ static int help(void) { " --no-pager Do not pipe output into a pager\n" " --dump-configuration-items Dump understood unit configuration items\n" " --dump-bus-properties Dump exposed bus properties\n" + " --bus-introspect=PATH Write XML introspection data\n" " --unit=UNIT Set default unit\n" " --dump-core[=BOOL] Dump core on crash\n" " --crash-vt=NR Change to specified VT on crash\n" @@ -1058,6 +1071,8 @@ static int help(void) { " --default-standard-error= Set default standard error output for services\n" "\nSee the %s for details.\n" , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , ansi_underline(), ansi_normal() , link ); @@ -2611,7 +2626,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES)) + if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES, ACTION_BUS_INTROSPECT)) (void) pager_open(arg_pager_flags); if (arg_action != ACTION_RUN) @@ -2631,6 +2646,10 @@ int main(int argc, char *argv[]) { dump_bus_properties(stdout); retval = EXIT_SUCCESS; goto finish; + } else if (arg_action == ACTION_BUS_INTROSPECT) { + r = bus_manager_introspect_implementations(stdout, arg_bus_introspect); + retval = r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; + goto finish; } assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST)); diff --git a/src/core/mount.c b/src/core/mount.c index 1c4aefd734..97caf3e734 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -2110,7 +2110,6 @@ const UnitVTable mount_vtable = { .control_pid = mount_control_pid, - .bus_vtable = bus_mount_vtable, .bus_set_property = bus_mount_set_property, .bus_commit_properties = bus_mount_commit_properties, diff --git a/src/core/path.c b/src/core/path.c index cb75d778af..c7907ce4bf 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -830,6 +830,5 @@ const UnitVTable path_vtable = { .reset_failed = path_reset_failed, - .bus_vtable = bus_path_vtable, .bus_set_property = bus_path_set_property, }; diff --git a/src/core/scope.c b/src/core/scope.c index e4a536d597..42c51b0865 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -652,7 +652,6 @@ const UnitVTable scope_vtable = { .notify_cgroup_empty = scope_notify_cgroup_empty_event, - .bus_vtable = bus_scope_vtable, .bus_set_property = bus_scope_set_property, .bus_commit_properties = bus_scope_commit_properties, diff --git a/src/core/service.c b/src/core/service.c index d97270598a..b3c4ad73e5 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -4484,7 +4484,6 @@ const UnitVTable service_vtable = { .bus_name_owner_change = service_bus_name_owner_change, - .bus_vtable = bus_service_vtable, .bus_set_property = bus_service_set_property, .bus_commit_properties = bus_service_commit_properties, diff --git a/src/core/slice.c b/src/core/slice.c index 558545d310..38a2805200 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -458,7 +458,6 @@ const UnitVTable slice_vtable = { .active_state = slice_active_state, .sub_state_to_string = slice_sub_state_to_string, - .bus_vtable = bus_slice_vtable, .bus_set_property = bus_slice_set_property, .bus_commit_properties = bus_slice_commit_properties, diff --git a/src/core/socket.c b/src/core/socket.c index 4a0e3a253e..5e8f317bfc 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -3462,7 +3462,6 @@ const UnitVTable socket_vtable = { .control_pid = socket_control_pid, - .bus_vtable = bus_socket_vtable, .bus_set_property = bus_socket_set_property, .bus_commit_properties = bus_socket_commit_properties, diff --git a/src/core/swap.c b/src/core/swap.c index c5945371df..0b42236aca 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -1655,7 +1655,6 @@ const UnitVTable swap_vtable = { .control_pid = swap_control_pid, - .bus_vtable = bus_swap_vtable, .bus_set_property = bus_swap_set_property, .bus_commit_properties = bus_swap_commit_properties, diff --git a/src/core/target.c b/src/core/target.c index 357ca70e09..a1d1cfc38a 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -207,8 +207,6 @@ const UnitVTable target_vtable = { .active_state = target_active_state, .sub_state_to_string = target_sub_state_to_string, - .bus_vtable = bus_target_vtable, - .status_message_formats = { .finished_start_job = { [JOB_DONE] = "Reached target %s.", diff --git a/src/core/timer.c b/src/core/timer.c index 57d979d52d..7f779fb936 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -925,6 +925,5 @@ const UnitVTable timer_vtable = { .time_change = timer_time_change, .timezone_change = timer_timezone_change, - .bus_vtable = bus_timer_vtable, .bus_set_property = bus_timer_set_property, }; diff --git a/src/core/unit.h b/src/core/unit.h index a05fd49e29..a4c342a396 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -600,9 +600,6 @@ typedef struct UnitVTable { * of this type will immediately fail. */ bool (*supported)(void); - /* The bus vtable */ - const sd_bus_vtable *bus_vtable; - /* The strings to print in status messages */ UnitStatusMessageFormats status_message_formats; diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c index 6b4fa58a6f..af2ddce330 100644 --- a/src/home/homed-home-bus.c +++ b/src/home/homed-home-bus.c @@ -712,38 +712,13 @@ int bus_home_method_release( /* We map a uid_t as uint32_t bus property, let's ensure this is safe. */ assert_cc(sizeof(uid_t) == sizeof(uint32_t)); -const sd_bus_vtable home_vtable[] = { - SD_BUS_VTABLE_START(0), - SD_BUS_PROPERTY("UserName", "s", NULL, offsetof(Home, user_name), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Home, uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("UnixRecord", "(suusss)", property_get_unix_record, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), - SD_BUS_PROPERTY("UserRecord", "(sb)", property_get_user_record, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Activate", "s", NULL, bus_home_method_activate, SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Deactivate", NULL, NULL, bus_home_method_deactivate, 0), - SD_BUS_METHOD("Unregister", NULL, NULL, bus_home_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Realize", "s", NULL, bus_home_method_realize, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Remove", NULL, NULL, bus_home_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Fixate", "s", NULL, bus_home_method_fixate, SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Authenticate", "s", NULL, bus_home_method_authenticate, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Update", "s", NULL, bus_home_method_update, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Resize", "ts", NULL, bus_home_method_resize, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("ChangePassword", "ss", NULL, bus_home_method_change_password, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Lock", NULL, NULL, bus_home_method_lock, 0), - SD_BUS_METHOD("Unlock", "s", NULL, bus_home_method_unlock, SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Acquire", "sb", "h", bus_home_method_acquire, SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("Ref", "b", "h", bus_home_method_ref, 0), - SD_BUS_METHOD("Release", NULL, NULL, bus_home_method_release, 0), - SD_BUS_VTABLE_END -}; - int bus_home_path(Home *h, char **ret) { assert(ret); return sd_bus_path_encode("/org/freedesktop/home1/home", h->user_name, ret); } -int bus_home_object_find( +static int bus_home_object_find( sd_bus *bus, const char *path, const char *interface, @@ -772,7 +747,7 @@ int bus_home_object_find( return 1; } -int bus_home_node_enumerator( +static int bus_home_node_enumerator( sd_bus *bus, const char *path, void *userdata, @@ -802,6 +777,107 @@ int bus_home_node_enumerator( return 1; } +const sd_bus_vtable home_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("UserName", "s", + NULL, offsetof(Home, user_name), + SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UID", "u", + NULL, offsetof(Home, uid), + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("UnixRecord", "(suusss)", + property_get_unix_record, 0, + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("State", "s", + property_get_state, 0, + 0), + SD_BUS_PROPERTY("UserRecord", "(sb)", + property_get_user_record, 0, + SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_SENSITIVE), + + SD_BUS_METHOD_WITH_NAMES("Activate", + "s", + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_activate, + SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD("Deactivate", NULL, NULL, bus_home_method_deactivate, 0), + SD_BUS_METHOD("Unregister", NULL, NULL, bus_home_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("Realize", + "s", + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_realize, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + SD_BUS_METHOD("Remove", NULL, NULL, bus_home_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("Fixate", + "s", + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_fixate, + SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("Authenticate", + "s", + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_authenticate, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("Update", + "s", + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_update, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("Resize", + "ts", + SD_BUS_PARAM(size) + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_resize, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("ChangePassword", + "ss", + SD_BUS_PARAM(new_user_record) + SD_BUS_PARAM(old_user_record), + NULL,, + bus_home_method_change_password, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD("Lock", NULL, NULL, bus_home_method_lock, 0), + SD_BUS_METHOD_WITH_NAMES("Unlock", + "s", + SD_BUS_PARAM(user_record), + NULL,, + bus_home_method_unlock, + SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("Acquire", + "sb", + SD_BUS_PARAM(user_record) + SD_BUS_PARAM(please_suspend), + "h", + SD_BUS_PARAM(send_fd), + bus_home_method_acquire, + SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("Ref", + "b", + SD_BUS_PARAM(please_suspend), + "h", + SD_BUS_PARAM(send_fd), + bus_home_method_ref, + 0), + SD_BUS_METHOD("Release", NULL, NULL, bus_home_method_release, 0), + SD_BUS_VTABLE_END +}; + +const BusObjectImplementation home_object = { + "/org/freedesktop/home1/home", + "org.freedesktop.home1.Home", + .fallback_vtables = BUS_FALLBACK_VTABLES({home_vtable, bus_home_object_find}), + .node_enumerator = bus_home_node_enumerator, + .manager = true, +}; + static int on_deferred_change(sd_event_source *s, void *userdata) { _cleanup_free_ char *path = NULL; Home *h = userdata; diff --git a/src/home/homed-home-bus.h b/src/home/homed-home-bus.h index 20516b1205..59b2a970b8 100644 --- a/src/home/homed-home-bus.h +++ b/src/home/homed-home-bus.h @@ -3,6 +3,7 @@ #include "sd-bus.h" +#include "bus-util.h" #include "homed-home.h" int bus_home_client_is_trusted(Home *h, sd_bus_message *message); @@ -25,12 +26,9 @@ int bus_home_method_acquire(sd_bus_message *message, void *userdata, sd_bus_erro int bus_home_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_home_method_release(sd_bus_message *message, void *userdata, sd_bus_error *error); -extern const sd_bus_vtable home_vtable[]; +extern const BusObjectImplementation home_object; int bus_home_path(Home *h, char **ret); -int bus_home_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); -int bus_home_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); - int bus_home_emit_change(Home *h); int bus_home_emit_remove(Home *h); diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c index b239a71887..1b8ec0c738 100644 --- a/src/home/homed-manager-bus.c +++ b/src/home/homed-manager-bus.c @@ -600,44 +600,210 @@ static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus return sd_bus_reply_method_return(message, NULL); } -const sd_bus_vtable manager_vtable[] = { +static const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("AutoLogin", "a(sso)", property_get_auto_login, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_METHOD("GetHomeByName", "s", "usussso", method_get_home_by_name, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetHomeByUID", "u", "ssussso", method_get_home_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetUserRecordByName", "s", "sbo", method_get_user_record_by_name, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("GetUserRecordByUID", "u", "sbo", method_get_user_record_by_uid, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("ListHomes", NULL, "a(susussso)", method_list_homes, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("GetHomeByName", + "s", + SD_BUS_PARAM(user_name), + "usussso", + SD_BUS_PARAM(uid) + SD_BUS_PARAM(home_state) + SD_BUS_PARAM(gid) + SD_BUS_PARAM(real_name) + SD_BUS_PARAM(home_directory) + SD_BUS_PARAM(shell) + SD_BUS_PARAM(bus_path), + method_get_home_by_name, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("GetHomeByUID", + "u", + SD_BUS_PARAM(uid), + "ssussso", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(home_state) + SD_BUS_PARAM(gid) + SD_BUS_PARAM(real_name) + SD_BUS_PARAM(home_directory) + SD_BUS_PARAM(shell) + SD_BUS_PARAM(bus_path), + method_get_home_by_uid, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("GetUserRecordByName", + "s", + SD_BUS_PARAM(user_name), + "sbo", + SD_BUS_PARAM(user_record) + SD_BUS_PARAM(incomplete) + SD_BUS_PARAM(bus_path), + method_get_user_record_by_name, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("GetUserRecordByUID", + "u", + SD_BUS_PARAM(uid), + "sbo", + SD_BUS_PARAM(user_record) + SD_BUS_PARAM(incomplete) + SD_BUS_PARAM(bus_path), + method_get_user_record_by_uid, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("ListHomes", + NULL,, + "a(susussso)", + SD_BUS_PARAM(home_areas), + method_list_homes, + SD_BUS_VTABLE_UNPRIVILEGED), /* The following methods directly execute an operation on a home area, without ref-counting, queueing * or anything, and are accessible through homectl. */ - SD_BUS_METHOD("ActivateHome", "ss", NULL, method_activate_home, SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("DeactivateHome", "s", NULL, method_deactivate_home, 0), - SD_BUS_METHOD("RegisterHome", "s", NULL, method_register_home, SD_BUS_VTABLE_UNPRIVILEGED), /* Add JSON record to homed, but don't create actual $HOME */ - SD_BUS_METHOD("UnregisterHome", "s", NULL, method_unregister_home, SD_BUS_VTABLE_UNPRIVILEGED), /* Remove JSON record from homed, but don't remove actual $HOME */ - SD_BUS_METHOD("CreateHome", "s", NULL, method_create_home, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), /* Add JSON record, and create $HOME for it */ - SD_BUS_METHOD("RealizeHome", "ss", NULL, method_realize_home, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), /* Create $HOME for already registered JSON entry */ - SD_BUS_METHOD("RemoveHome", "s", NULL, method_remove_home, SD_BUS_VTABLE_UNPRIVILEGED), /* Remove JSON record and remove $HOME */ - SD_BUS_METHOD("FixateHome", "ss", NULL, method_fixate_home, SD_BUS_VTABLE_SENSITIVE), /* Investigate $HOME and propagate contained JSON record into our database */ - SD_BUS_METHOD("AuthenticateHome", "ss", NULL, method_authenticate_home, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), /* Just check credentials */ - SD_BUS_METHOD("UpdateHome", "s", NULL, method_update_home, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), /* Update JSON record of existing user */ - SD_BUS_METHOD("ResizeHome", "sts", NULL, method_resize_home, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("ChangePasswordHome", "sss", NULL, method_change_password_home, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("LockHome", "s", NULL, method_lock_home, 0), /* Prepare active home for system suspend: flush out passwords, suspend access */ - SD_BUS_METHOD("UnlockHome", "ss", NULL, method_unlock_home, SD_BUS_VTABLE_SENSITIVE), /* Make $HOME usable after system resume again */ + SD_BUS_METHOD_WITH_NAMES("ActivateHome", + "ss", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(user_record), + NULL,, + method_activate_home, + SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("DeactivateHome", + "s", + SD_BUS_PARAM(user_name), + NULL,, + method_deactivate_home, + 0), - /* The following methods implement ref-counted activation, and are what the PAM module calls (and - * what "homectl with" runs). In contrast to the methods above which fail if an operation is already - * being executed on a home directory, these ones will queue the request, and are thus more - * reliable. Moreover, they are a bit smarter: AcquireHome() will fixate, activate, unlock, or - * authenticate depending on the state of the home, so that the end result is always the same - * (i.e. the home directory is accessible), and we always validate the specified passwords. RefHome() - * will not authenticate, and thus only works if home is already active. */ - SD_BUS_METHOD("AcquireHome", "ssb", "h", method_acquire_home, SD_BUS_VTABLE_SENSITIVE), - SD_BUS_METHOD("RefHome", "sb", "h", method_ref_home, 0), - SD_BUS_METHOD("ReleaseHome", "s", NULL, method_release_home, 0), + /* Add the JSON record to homed, but don't create actual $HOME */ + SD_BUS_METHOD_WITH_NAMES("RegisterHome", + "s", + SD_BUS_PARAM(home_record), + NULL,, + method_register_home, + SD_BUS_VTABLE_UNPRIVILEGED), + + /* Remove the JSON record from homed, but don't remove actual $HOME */ + SD_BUS_METHOD_WITH_NAMES("UnregisterHome", + "s", + SD_BUS_PARAM(user_name), + NULL,, + method_unregister_home, + SD_BUS_VTABLE_UNPRIVILEGED), + + /* Add JSON record, and create $HOME for it */ + SD_BUS_METHOD_WITH_NAMES("CreateHome", + "s", + SD_BUS_PARAM(home_record), + NULL,, + method_create_home, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + /* Create $HOME for already registered JSON entry */ + SD_BUS_METHOD_WITH_NAMES("RealizeHome", + "ss", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(user_record), + NULL,, + method_realize_home, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + /* Remove the JSON record and remove $HOME */ + SD_BUS_METHOD_WITH_NAMES("RemoveHome", + "s", + SD_BUS_PARAM(user_name), + NULL,, + method_remove_home, + SD_BUS_VTABLE_UNPRIVILEGED), + + /* Investigate $HOME and propagate contained JSON record into our database */ + SD_BUS_METHOD_WITH_NAMES("FixateHome", + "ss", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(user_record), + NULL,, + method_fixate_home, + SD_BUS_VTABLE_SENSITIVE), + + /* Just check credentials */ + SD_BUS_METHOD_WITH_NAMES("AuthenticateHome", + "ss", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(user_record), + NULL,, + method_authenticate_home, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + /* Update the JSON record of existing user */ + SD_BUS_METHOD_WITH_NAMES("UpdateHome", + "s", + SD_BUS_PARAM(user_record), + NULL,, + method_update_home, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + SD_BUS_METHOD_WITH_NAMES("ResizeHome", + "sts", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(size) + SD_BUS_PARAM(user_record), + NULL,, + method_resize_home, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + SD_BUS_METHOD_WITH_NAMES("ChangePasswordHome", + "sss", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(new_user_record) + SD_BUS_PARAM(old_user_record), + NULL,, + method_change_password_home, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_SENSITIVE), + + /* Prepare active home for system suspend: flush out passwords, suspend access */ + SD_BUS_METHOD_WITH_NAMES("LockHome", + "s", + SD_BUS_PARAM(user_name), + NULL,, + method_lock_home, + 0), + + /* Make $HOME usable after system resume again */ + SD_BUS_METHOD_WITH_NAMES("UnlockHome", + "ss", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(user_record), + NULL,, + method_unlock_home, + SD_BUS_VTABLE_SENSITIVE), + + /* The following methods implement ref-counted activation, and are what the PAM module and "homectl + * with" use. In contrast to the methods above which fail if an operation is already being executed + * on a home directory, these ones will queue the request, and are thus more reliable. Moreover, + * they are a bit smarter: AcquireHome() will fixate, activate, unlock, or authenticate depending on + * the state of the home area, so that the end result is always the same (i.e. the home directory is + * accessible), and we always validate the specified passwords. RefHome() will not authenticate, and + * thus only works if the home area is already active. */ + SD_BUS_METHOD_WITH_NAMES("AcquireHome", + "ssb", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(user_record) + SD_BUS_PARAM(please_suspend), + "h", + SD_BUS_PARAM(send_fd), + method_acquire_home, + SD_BUS_VTABLE_SENSITIVE), + SD_BUS_METHOD_WITH_NAMES("RefHome", + "sb", + SD_BUS_PARAM(user_name) + SD_BUS_PARAM(please_suspend), + "h", + SD_BUS_PARAM(send_fd), + method_ref_home, + 0), + SD_BUS_METHOD_WITH_NAMES("ReleaseHome", + "s", + SD_BUS_PARAM(user_name), + NULL,, + method_release_home, + 0), /* An operation that acts on all homes that allow it */ SD_BUS_METHOD("LockAllHomes", NULL, NULL, method_lock_all_homes, 0), @@ -645,6 +811,13 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_END }; +const BusObjectImplementation manager_object = { + "/org/freedesktop/home1", + "org.freedesktop.home1.Manager", + .vtables = BUS_VTABLES(manager_vtable), + .children = BUS_IMPLEMENTATIONS(&home_object), +}; + static int on_deferred_auto_login(sd_event_source *s, void *userdata) { Manager *m = userdata; int r; diff --git a/src/home/homed-manager-bus.h b/src/home/homed-manager-bus.h index 40e1cc3d86..93bef9df8e 100644 --- a/src/home/homed-manager-bus.h +++ b/src/home/homed-manager-bus.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include "sd-bus.h" +#include "bus-util.h" -extern const sd_bus_vtable manager_vtable[]; +extern const BusObjectImplementation manager_object; diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 5ce7be4fac..8ea93120d0 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -879,23 +879,7 @@ static int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); - r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/home1", "org.freedesktop.home1.Manager", manager_vtable, m); - if (r < 0) - return log_error_errno(r, "Failed to add manager object vtable: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/home1/home", "org.freedesktop.home1.Home", home_vtable, bus_home_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add image object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/home1/home", bus_home_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add image enumerator: %m"); - - r = sd_bus_add_object_manager(m->bus, NULL, "/org/freedesktop/home1/home"); - if (r < 0) - return log_error_errno(r, "Failed to add object manager: %m"); - - r = bus_log_control_api_register(m->bus); + r = bus_add_implementation(m->bus, &manager_object, m); if (r < 0) return r; diff --git a/src/home/homed.c b/src/home/homed.c index ca43558269..2fd3b65d89 100644 --- a/src/home/homed.c +++ b/src/home/homed.c @@ -3,10 +3,13 @@ #include #include +#include "bus-log-control-api.h" #include "daemon-util.h" #include "homed-manager.h" +#include "homed-manager-bus.h" #include "log.h" #include "main-func.h" +#include "service-util.h" #include "signal-util.h" static int run(int argc, char *argv[]) { @@ -16,10 +19,15 @@ static int run(int argc, char *argv[]) { log_setup_service(); - umask(0022); + r = service_parse_argv("systemd-homed.service", + "A service to create, remove, change or inspect home areas.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; - if (argc != 1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + umask(0022); if (setenv("SYSTEMD_BYPASS_USERDB", "io.systemd.Home", 1) < 0) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set $SYSTEMD_BYPASS_USERDB: %m"); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index ad6577c37e..701041c12a 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -26,6 +26,7 @@ #include "parse-util.h" #include "path-util.h" #include "selinux-util.h" +#include "service-util.h" #include "signal-util.h" #include "strv.h" #include "user-util.h" @@ -739,6 +740,12 @@ static const sd_bus_vtable hostname_vtable[] = { SD_BUS_VTABLE_END, }; +static const BusObjectImplementation manager_object = { + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + .vtables = BUS_VTABLES(hostname_vtable), +}; + static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; @@ -751,9 +758,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { if (r < 0) return log_error_errno(r, "Failed to get system bus connection: %m"); - r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c); + r = bus_add_implementation(bus, &manager_object, c); if (r < 0) - return log_error_errno(r, "Failed to register object: %m"); + return r; r = bus_log_control_api_register(bus); if (r < 0) @@ -780,14 +787,17 @@ static int run(int argc, char *argv[]) { log_setup_service(); + r = service_parse_argv("systemd-hostnamed.service", + "Manage the system hostname and related metadata.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; + umask(0022); mac_selinux_init(); - if (argc != 1) { - log_error("This program takes no arguments."); - return -EINVAL; - } - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = sd_event_default(&event); diff --git a/src/import/importd.c b/src/import/importd.c index 417e686bb9..9408edece1 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -8,6 +8,7 @@ #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-log-control-api.h" +#include "bus-util.h" #include "bus-polkit.h" #include "def.h" #include "fd-util.h" @@ -22,6 +23,7 @@ #include "path-util.h" #include "process-util.h" #include "signal-util.h" +#include "service-util.h" #include "socket-util.h" #include "stat-util.h" #include "string-table.h" @@ -488,11 +490,13 @@ static int transfer_start(Transfer *t) { t->stdin_fd = safe_close(t->stdin_fd); - r = sd_event_add_child(t->manager->event, &t->pid_event_source, t->pid, WEXITED, transfer_on_pid, t); + r = sd_event_add_child(t->manager->event, &t->pid_event_source, + t->pid, WEXITED, transfer_on_pid, t); if (r < 0) return r; - r = sd_event_add_io(t->manager->event, &t->log_event_source, t->log_fd, EPOLLIN, transfer_on_log, t); + r = sd_event_add_io(t->manager->event, &t->log_event_source, + t->log_fd, EPOLLIN, transfer_on_log, t); if (r < 0) return r; @@ -657,7 +661,8 @@ static int manager_new(Manager **ret) { if (r < 0) return r; - r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_on_notify, m); + r = sd_event_add_io(m->event, &m->notify_event_source, + m->notify_fd, EPOLLIN, manager_on_notify, m); if (r < 0) return r; @@ -718,13 +723,15 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_ return -EINVAL; if (!machine_name_is_valid(local)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Local name %s is invalid", local); r = setup_machine_directory(error); if (r < 0) return r; - type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ? TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW; + type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ? + TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW; r = transfer_new(m, &t); if (r < 0) @@ -786,7 +793,8 @@ static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *e return r; if (!machine_name_is_valid(local)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Local name %s is invalid", local); r = setup_machine_directory(error); if (r < 0) @@ -850,7 +858,8 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_ return r; if (!machine_name_is_valid(local)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Local name %s is invalid", local); if (fstat(fd, &st) < 0) return -errno; @@ -858,7 +867,8 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_ if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) return -EINVAL; - type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ? TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW; + type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ? + TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW; r = transfer_new(m, &t); if (r < 0) @@ -922,28 +932,33 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er return r; if (!http_url_is_valid(remote)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "URL %s is invalid", remote); + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "URL %s is invalid", remote); if (isempty(local)) local = NULL; else if (!machine_name_is_valid(local)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Local name %s is invalid", local); if (isempty(verify)) v = IMPORT_VERIFY_SIGNATURE; else v = import_verify_from_string(verify); if (v < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify); + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Unknown verification mode %s", verify); r = setup_machine_directory(error); if (r < 0) return r; - type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW; + type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? + TRANSFER_PULL_TAR : TRANSFER_PULL_RAW; if (manager_find(m, type, remote)) - return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote); + return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, + "Transfer for %s already in progress.", remote); r = transfer_new(m, &t); if (r < 0) @@ -1103,6 +1118,73 @@ static int property_get_progress( static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, transfer_type, TransferType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_verify, import_verify, ImportVerify); +static int transfer_object_find( + sd_bus *bus, + const char *path, + const char *interface, + void *userdata, + void **found, + sd_bus_error *error) { + + Manager *m = userdata; + Transfer *t; + const char *p; + uint32_t id; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + p = startswith(path, "/org/freedesktop/import1/transfer/_"); + if (!p) + return 0; + + r = safe_atou32(p, &id); + if (r < 0 || id == 0) + return 0; + + t = hashmap_get(m->transfers, UINT32_TO_PTR(id)); + if (!t) + return 0; + + *found = t; + return 1; +} + +static int transfer_node_enumerator( + sd_bus *bus, + const char *path, + void *userdata, + char ***nodes, + sd_bus_error *error) { + + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + Transfer *t; + unsigned k = 0; + Iterator i; + + l = new0(char*, hashmap_size(m->transfers) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(t, m->transfers, i) { + + l[k] = strdup(t->object_path); + if (!l[k]) + return -ENOMEM; + + k++; + } + + *nodes = TAKE_PTR(l); + + return 1; +} + static const sd_bus_vtable transfer_vtable[] = { SD_BUS_VTABLE_START(0), @@ -1124,6 +1206,13 @@ static const sd_bus_vtable transfer_vtable[] = { SD_BUS_VTABLE_END, }; +static const BusObjectImplementation transfer_object = { + "/org/freedesktop/import1/transfer", + "org.freedesktop.import1.Transfer", + .fallback_vtables = BUS_FALLBACK_VTABLES({transfer_vtable, transfer_object_find}), + .node_enumerator = transfer_node_enumerator, +}; + static const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), @@ -1230,76 +1319,21 @@ static const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_END, }; -static int transfer_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - Manager *m = userdata; - Transfer *t; - const char *p; - uint32_t id; - int r; - - assert(bus); - assert(path); - assert(interface); - assert(found); - assert(m); - - p = startswith(path, "/org/freedesktop/import1/transfer/_"); - if (!p) - return 0; - - r = safe_atou32(p, &id); - if (r < 0 || id == 0) - return 0; - - t = hashmap_get(m->transfers, UINT32_TO_PTR(id)); - if (!t) - return 0; - - *found = t; - return 1; -} - -static int transfer_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - Transfer *t; - unsigned k = 0; - Iterator i; - - l = new0(char*, hashmap_size(m->transfers) + 1); - if (!l) - return -ENOMEM; - - HASHMAP_FOREACH(t, m->transfers, i) { - - l[k] = strdup(t->object_path); - if (!l[k]) - return -ENOMEM; - - k++; - } - - *nodes = TAKE_PTR(l); - - return 1; -} +static const BusObjectImplementation manager_object = { + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + .vtables = BUS_VTABLES(manager_vtable), + .children = BUS_IMPLEMENTATIONS(&transfer_object), +}; static int manager_add_bus_objects(Manager *m) { int r; assert(m); - r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/import1", "org.freedesktop.import1.Manager", manager_vtable, m); + r = bus_add_implementation(m->bus, &manager_object, m); if (r < 0) - return log_error_errno(r, "Failed to register object: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/import1/transfer", "org.freedesktop.import1.Transfer", transfer_vtable, transfer_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register object: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/import1/transfer", transfer_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add transfer enumerator: %m"); + return r; r = bus_log_control_api_register(m->bus); if (r < 0) @@ -1340,12 +1374,15 @@ static int run(int argc, char *argv[]) { log_setup_service(); - umask(0022); + r = service_parse_argv("systemd-importd.service", + "VM and container image import and export service.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; - if (argc != 1) { - log_error("This program takes no arguments."); - return -EINVAL; - } + umask(0022); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c index 07bd98967d..734abcf3fd 100644 --- a/src/libsystemd/sd-bus/bus-introspect.c +++ b/src/libsystemd/sd-bus/bus-introspect.c @@ -10,6 +10,63 @@ #include "memory-util.h" #include "string-util.h" +#define BUS_INTROSPECT_DOCTYPE \ + "\n" + +#define BUS_INTROSPECT_INTERFACE_PEER \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + +#define BUS_INTROSPECT_INTERFACE_INTROSPECTABLE \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + +#define BUS_INTROSPECT_INTERFACE_PROPERTIES \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + +#define BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + int introspect_begin(struct introspect *i, bool trusted) { assert(i); @@ -40,12 +97,27 @@ int introspect_write_default_interfaces(struct introspect *i, bool object_manage return 0; } +static int set_interface_name(struct introspect *intro, const char *interface_name) { + if (streq_ptr(intro->interface_name, interface_name)) + return 0; + + if (intro->interface_name) + fputs(" \n", intro->f); + + if (interface_name) + fprintf(intro->f, " \n", interface_name); + + return free_and_strdup(&intro->interface_name, interface_name); +} + int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) { char *node; assert(i); assert(prefix); + assert_se(set_interface_name(i, NULL) >= 0); + while ((node = set_steal_first(s))) { const char *e; @@ -115,13 +187,23 @@ static int introspect_write_arguments(struct introspect *i, const char *signatur } } -int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) { +int introspect_write_interface( + struct introspect *i, + const char *interface_name, + const sd_bus_vtable *v) { + const sd_bus_vtable *vtable = v; const char *names = ""; + int r; assert(i); + assert(interface_name); assert(v); + r = set_interface_name(i, interface_name); + if (r < 0) + return r; + for (; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(vtable, v)) { /* Ignore methods, signals and properties that are @@ -178,6 +260,8 @@ int introspect_finish(struct introspect *i, char **ret) { assert(i); + assert_se(set_interface_name(i, NULL) >= 0); + fputs("\n", i->f); r = fflush_and_check(i->f); @@ -196,5 +280,6 @@ void introspect_free(struct introspect *i) { /* Normally introspect_finish() does all the work, this is just a backup for error paths */ safe_fclose(i->f); + free(i->interface_name); free(i->introspection); } diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h index ccbb543d0c..19d39923e5 100644 --- a/src/libsystemd/sd-bus/bus-introspect.h +++ b/src/libsystemd/sd-bus/bus-introspect.h @@ -9,6 +9,7 @@ struct introspect { FILE *f; + char *interface_name; char *introspection; size_t size; bool trusted; @@ -17,6 +18,9 @@ struct introspect { int introspect_begin(struct introspect *i, bool trusted); int introspect_write_default_interfaces(struct introspect *i, bool object_manager); int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix); -int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v); +int introspect_write_interface( + struct introspect *i, + const char *interface_name, + const sd_bus_vtable *v); int introspect_finish(struct introspect *i, char **ret); void introspect_free(struct introspect *i); diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index 913d6eca8a..ad66d634d7 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -827,10 +827,10 @@ static int property_get_all_callbacks_run( if (r < 0) return r; - found_interface = !iface || - streq(iface, "org.freedesktop.DBus.Properties") || - streq(iface, "org.freedesktop.DBus.Peer") || - streq(iface, "org.freedesktop.DBus.Introspectable"); + found_interface = !iface || STR_IN_SET(iface, + "org.freedesktop.DBus.Properties", + "org.freedesktop.DBus.Peer", + "org.freedesktop.DBus.Introspectable"); LIST_FOREACH(vtables, c, first) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -939,7 +939,6 @@ int introspect_path( sd_bus_error *error) { _cleanup_set_free_free_ Set *s = NULL; - const char *previous_interface = NULL; _cleanup_(introspect_free) struct introspect intro = {}; struct node_vtable *c; bool empty; @@ -984,23 +983,11 @@ int introspect_path( if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN) continue; - if (!streq_ptr(previous_interface, c->interface)) { - if (previous_interface) - fputs(" \n", intro.f); - - fprintf(intro.f, " \n", c->interface); - } - - r = introspect_write_interface(&intro, c->vtable); + r = introspect_write_interface(&intro, c->interface, c->vtable); if (r < 0) return r; - - previous_interface = c->interface; } - if (previous_interface) - fputs(" \n", intro.f); - if (empty) { /* Nothing?, let's see if we exist at all, and if not * refuse to do anything */ diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h index d01fd8e6a3..7e1cd3c31e 100644 --- a/src/libsystemd/sd-bus/bus-protocol.h +++ b/src/libsystemd/sd-bus/bus-protocol.h @@ -103,60 +103,3 @@ enum { BUS_START_REPLY_SUCCESS = 1, BUS_START_REPLY_ALREADY_RUNNING = 2, }; - -#define BUS_INTROSPECT_DOCTYPE \ - "\n" - -#define BUS_INTROSPECT_INTERFACE_PEER \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" - -#define BUS_INTROSPECT_INTERFACE_INTROSPECTABLE \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" - -#define BUS_INTROSPECT_INTERFACE_PROPERTIES \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" - -#define BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c index 9c8d1434b1..cbc3158924 100644 --- a/src/libsystemd/sd-bus/test-bus-introspect.c +++ b/src/libsystemd/sd-bus/test-bus-introspect.c @@ -14,11 +14,11 @@ static void test_manual_introspection(const sd_bus_vtable vtable[]) { assert_se(introspect_begin(&intro, false) >= 0); - fprintf(intro.f, " \n"); - assert_se(introspect_write_interface(&intro, vtable) >= 0); - fputs(" \n", intro.f); - + assert_se(introspect_write_interface(&intro, "org.foo", vtable) >= 0); + /* write again to check if output looks OK for a different interface */ + assert_se(introspect_write_interface(&intro, "org.foo.bar", vtable) >= 0); assert_se(introspect_finish(&intro, &s) == 0); + fputs(s, stdout); fputs("\n", stdout); } diff --git a/src/locale/localed.c b/src/locale/localed.c index 7315d93a98..acdf79fa6b 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -25,6 +25,7 @@ #include "missing_capability.h" #include "path-util.h" #include "selinux-util.h" +#include "service-util.h" #include "signal-util.h" #include "string-util.h" #include "strv.h" @@ -709,6 +710,12 @@ static const sd_bus_vtable locale_vtable[] = { SD_BUS_VTABLE_END }; +static const BusObjectImplementation manager_object = { + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + .vtables = BUS_VTABLES(locale_vtable), +}; + static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; @@ -721,9 +728,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { if (r < 0) return log_error_errno(r, "Failed to get system bus connection: %m"); - r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c); + r = bus_add_implementation(bus, &manager_object, c); if (r < 0) - return log_error_errno(r, "Failed to register object: %m"); + return r; r = bus_log_control_api_register(bus); if (r < 0) @@ -754,12 +761,17 @@ static int run(int argc, char *argv[]) { log_setup_service(); + r = service_parse_argv("systemd-localed.service", + "Manage system locale settings and key mappings.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; + umask(0022); mac_selinux_init(); - if (argc != 1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = sd_event_default(&event); diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 136ccf1dd9..47fc53167e 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -3322,7 +3322,7 @@ fail: return r; } -const sd_bus_vtable manager_vtable[] = { +static const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0), @@ -3754,6 +3754,15 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_END }; +const BusObjectImplementation manager_object = { + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + .vtables = BUS_VTABLES(manager_vtable), + .children = BUS_IMPLEMENTATIONS(&seat_object, + &session_object, + &user_object), +}; + static int session_jobs_reply(Session *s, uint32_t jid, const char *unit, const char *result) { assert(s); assert(unit); diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h index 6c73a9654f..6a3ee82f1c 100644 --- a/src/login/logind-dbus.h +++ b/src/login/logind-dbus.h @@ -3,6 +3,7 @@ #include "sd-bus.h" +#include "bus-util.h" #include "logind.h" #include "logind-session.h" #include "logind-user.h" @@ -29,3 +30,5 @@ int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *err int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error); int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error); + +extern const BusObjectImplementation manager_object; diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 7e811e9745..e72f265185 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -291,41 +291,7 @@ static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd return sd_bus_reply_method_return(message, NULL); } -const sd_bus_vtable seat_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("CanMultiSession", "b", property_get_const_true, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0), - SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - - SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_METHOD_WITH_NAMES("ActivateSession", - "s", - SD_BUS_PARAM(session_id), - NULL,, - method_activate_session, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("SwitchTo", - "u", - SD_BUS_PARAM(vtnr), - NULL,, - method_switch_to, - SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_VTABLE_END -}; - -int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { +static int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *e = NULL; sd_bus_message *message; Manager *m = userdata; @@ -373,7 +339,7 @@ char *seat_bus_path(Seat *s) { return strjoin("/org/freedesktop/login1/seat/", t); } -int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { +static int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; sd_bus_message *message; Manager *m = userdata; @@ -478,3 +444,44 @@ int seat_send_changed(Seat *s, const char *properties, ...) { return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l); } + +static const sd_bus_vtable seat_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CanMultiSession", "b", property_get_const_true, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_METHOD_WITH_NAMES("ActivateSession", + "s", + SD_BUS_PARAM(session_id), + NULL,, + method_activate_session, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("SwitchTo", + "u", + SD_BUS_PARAM(vtnr), + NULL,, + method_switch_to, + SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +const BusObjectImplementation seat_object = { + "/org/freedesktop/login1/seat", + "org.freedesktop.login1.Seat", + .fallback_vtables = BUS_FALLBACK_VTABLES({seat_vtable, seat_object_find}), + .node_enumerator = seat_node_enumerator, +}; diff --git a/src/login/logind-seat-dbus.h b/src/login/logind-seat-dbus.h index 2590f64922..5fc857584e 100644 --- a/src/login/logind-seat-dbus.h +++ b/src/login/logind-seat-dbus.h @@ -4,11 +4,10 @@ #include "sd-bus.h" #include "logind-seat.h" +#include "bus-util.h" -extern const sd_bus_vtable seat_vtable[]; +extern const BusObjectImplementation seat_object; -int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); char *seat_bus_path(Seat *s); int seat_send_signal(Seat *s, bool new_seat); diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 9a8dbc87bc..3857f4ab7d 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -581,141 +581,7 @@ static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus return 1; } -const sd_bus_vtable session_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), - BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("State", "s", property_get_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - - SD_BUS_METHOD("Terminate", - NULL, - NULL, - bus_session_method_terminate, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Activate", - NULL, - NULL, - bus_session_method_activate, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Lock", - NULL, - NULL, - bus_session_method_lock, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Unlock", - NULL, - NULL, - bus_session_method_lock, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("SetIdleHint", - "b", - SD_BUS_PARAM(idle), - NULL,, - method_set_idle_hint, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("SetLockedHint", - "b", - SD_BUS_PARAM(locked), - NULL,, - method_set_locked_hint, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("Kill", - "si", - SD_BUS_PARAM(who) - SD_BUS_PARAM(signal_number), - NULL,, - bus_session_method_kill, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("TakeControl", - "b", - SD_BUS_PARAM(force), - NULL,, - method_take_control, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("ReleaseControl", - NULL, - NULL, - method_release_control, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("SetType", - "s", - SD_BUS_PARAM(type), - NULL,, - method_set_type, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("TakeDevice", - "uu", - SD_BUS_PARAM(major) - SD_BUS_PARAM(minor), - "hb", - SD_BUS_PARAM(fd) - SD_BUS_PARAM(inactive), - method_take_device, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("ReleaseDevice", - "uu", - SD_BUS_PARAM(major) - SD_BUS_PARAM(minor), - NULL,, - method_release_device, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("PauseDeviceComplete", - "uu", - SD_BUS_PARAM(major) - SD_BUS_PARAM(minor), - NULL,, - method_pause_device_complete, - SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("SetBrightness", - "ssu", - SD_BUS_PARAM(subsystem) - SD_BUS_PARAM(name) - SD_BUS_PARAM(brightness), - NULL,, - method_set_brightness, - SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_SIGNAL_WITH_NAMES("PauseDevice", - "uus", - SD_BUS_PARAM(major) - SD_BUS_PARAM(minor) - SD_BUS_PARAM(type), - 0), - SD_BUS_SIGNAL_WITH_NAMES("ResumeDevice", - "uuh", - SD_BUS_PARAM(major) - SD_BUS_PARAM(minor) - SD_BUS_PARAM(fd), - 0), - SD_BUS_SIGNAL("Lock", NULL, 0), - SD_BUS_SIGNAL("Unlock", NULL, 0), - - SD_BUS_VTABLE_END -}; - -int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { +static int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *e = NULL; sd_bus_message *message; Manager *m = userdata; @@ -763,7 +629,7 @@ char *session_bus_path(Session *s) { return strjoin("/org/freedesktop/login1/session/", t); } -int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { +static int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; sd_bus_message *message; Manager *m = userdata; @@ -964,3 +830,144 @@ int session_send_create_reply(Session *s, sd_bus_error *error) { (uint32_t) s->vtnr, false); } + +static const sd_bus_vtable session_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("State", "s", property_get_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_METHOD("Terminate", + NULL, + NULL, + bus_session_method_terminate, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Activate", + NULL, + NULL, + bus_session_method_activate, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Lock", + NULL, + NULL, + bus_session_method_lock, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unlock", + NULL, + NULL, + bus_session_method_lock, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("SetIdleHint", + "b", + SD_BUS_PARAM(idle), + NULL,, + method_set_idle_hint, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("SetLockedHint", + "b", + SD_BUS_PARAM(locked), + NULL,, + method_set_locked_hint, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("Kill", + "si", + SD_BUS_PARAM(who) + SD_BUS_PARAM(signal_number), + NULL,, + bus_session_method_kill, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("TakeControl", + "b", + SD_BUS_PARAM(force), + NULL,, + method_take_control, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReleaseControl", + NULL, + NULL, + method_release_control, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("SetType", + "s", + SD_BUS_PARAM(type), + NULL,, + method_set_type, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("TakeDevice", + "uu", + SD_BUS_PARAM(major) + SD_BUS_PARAM(minor), + "hb", + SD_BUS_PARAM(fd) + SD_BUS_PARAM(inactive), + method_take_device, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("ReleaseDevice", + "uu", + SD_BUS_PARAM(major) + SD_BUS_PARAM(minor), + NULL,, + method_release_device, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("PauseDeviceComplete", + "uu", + SD_BUS_PARAM(major) + SD_BUS_PARAM(minor), + NULL,, + method_pause_device_complete, + SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("SetBrightness", + "ssu", + SD_BUS_PARAM(subsystem) + SD_BUS_PARAM(name) + SD_BUS_PARAM(brightness), + NULL,, + method_set_brightness, + SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_SIGNAL_WITH_NAMES("PauseDevice", + "uus", + SD_BUS_PARAM(major) + SD_BUS_PARAM(minor) + SD_BUS_PARAM(type), + 0), + SD_BUS_SIGNAL_WITH_NAMES("ResumeDevice", + "uuh", + SD_BUS_PARAM(major) + SD_BUS_PARAM(minor) + SD_BUS_PARAM(fd), + 0), + SD_BUS_SIGNAL("Lock", NULL, 0), + SD_BUS_SIGNAL("Unlock", NULL, 0), + + SD_BUS_VTABLE_END +}; + +const BusObjectImplementation session_object = { + "/org/freedesktop/login1/session", + "org.freedesktop.login1.Session", + .fallback_vtables = BUS_FALLBACK_VTABLES({session_vtable, session_object_find}), + .node_enumerator = session_node_enumerator, +}; diff --git a/src/login/logind-session-dbus.h b/src/login/logind-session-dbus.h index 9d2315cc60..6df96e06b2 100644 --- a/src/login/logind-session-dbus.h +++ b/src/login/logind-session-dbus.h @@ -5,9 +5,8 @@ #include "logind-session.h" -extern const sd_bus_vtable session_vtable[]; -int session_node_enumerator(sd_bus *bus, const char *path,void *userdata, char ***nodes, sd_bus_error *error); -int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +extern const BusObjectImplementation session_object; + char *session_bus_path(Session *s); int session_send_signal(Session *s, bool new_session); diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index f247567935..63c77cab39 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -258,36 +258,7 @@ int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * return sd_bus_reply_method_return(message, NULL); } -const sd_bus_vtable user_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("UID", "u", property_get_uid, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("GID", "u", property_get_gid, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), - BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), - SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0), - SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0), - - SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("Kill", - "i", - SD_BUS_PARAM(signal_number), - NULL,, - bus_user_method_kill, - SD_BUS_VTABLE_UNPRIVILEGED), - - SD_BUS_VTABLE_END -}; - -int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { +static int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; uid_t uid; User *user; @@ -342,7 +313,7 @@ char *user_bus_path(User *u) { return s; } -int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { +static int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; sd_bus_message *message; Manager *m = userdata; @@ -391,6 +362,42 @@ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** return 1; } +static const sd_bus_vtable user_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("UID", "u", property_get_uid, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("GID", "u", property_get_gid, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), + SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0), + + SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD_WITH_NAMES("Kill", + "i", + SD_BUS_PARAM(signal_number), + NULL,, + bus_user_method_kill, + SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +const BusObjectImplementation user_object = { + "/org/freedesktop/login1/user", + "org.freedesktop.login1.User", + .fallback_vtables = BUS_FALLBACK_VTABLES({user_vtable, user_object_find}), + .node_enumerator = user_node_enumerator, +}; + int user_send_signal(User *u, bool new_user) { _cleanup_free_ char *p = NULL; diff --git a/src/login/logind-user-dbus.h b/src/login/logind-user-dbus.h index acfcb981cf..b3f990c5af 100644 --- a/src/login/logind-user-dbus.h +++ b/src/login/logind-user-dbus.h @@ -5,9 +5,8 @@ #include "logind-user.h" -extern const sd_bus_vtable user_vtable[]; -int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +extern const BusObjectImplementation user_object; + char *user_bus_path(User *s); int user_send_signal(User *u, bool new_user); diff --git a/src/login/logind.c b/src/login/logind.c index 75958189ac..d748e8f4b8 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -27,6 +27,7 @@ #include "parse-util.h" #include "process-util.h" #include "selinux-util.h" +#include "service-util.h" #include "signal-util.h" #include "strv.h" #include "terminal-util.h" @@ -623,33 +624,13 @@ static int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); - r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m); + r = bus_add_implementation(m->bus, &manager_object, m); if (r < 0) - return log_error_errno(r, "Failed to add manager object vtable: %m"); + return r; - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m); + r = bus_log_control_api_register(m->bus); if (r < 0) - return log_error_errno(r, "Failed to add seat object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add seat enumerator: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add session object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add session enumerator: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add user object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add user enumerator: %m"); + return r; r = sd_bus_match_signal_async( m->bus, @@ -707,10 +688,6 @@ static int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to enable subscription: %m"); - r = bus_log_control_api_register(m->bus); - if (r < 0) - return r; - r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to request name: %m"); @@ -1201,12 +1178,15 @@ static int run(int argc, char *argv[]) { log_set_facility(LOG_AUTH); log_setup_service(); - umask(0022); + r = service_parse_argv("systemd-logind.service", + "Manager for user logins and devices and privileged operations.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; - if (argc != 1) { - log_error("This program takes no arguments."); - return -EINVAL; - } + umask(0022); r = mac_selinux_init(); if (r < 0) diff --git a/src/login/logind.h b/src/login/logind.h index 7e4673d27d..d3f5b28078 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -157,8 +157,6 @@ int manager_read_utmp(Manager *m); void manager_connect_utmp(Manager *m); void manager_reconnect_utmp(Manager *m); -extern const sd_bus_vtable manager_vtable[]; - /* gperf lookup function */ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length); diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index 294ef34932..4305f49152 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -354,30 +354,6 @@ int bus_image_method_get_os_release( return bus_reply_pair_array(message, image->os_release); } -const sd_bus_vtable image_vtable[] = { - SD_BUS_VTABLE_START(0), - SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0), - SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0), - SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0), - SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0), - SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0), - SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0), - SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0), - SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0), - SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0), - SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0), - SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetHostname", NULL, "s", bus_image_method_get_hostname, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetMachineID", NULL, "ay", bus_image_method_get_machine_id, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetMachineInfo", NULL, "a{ss}", bus_image_method_get_machine_info, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_VTABLE_END -}; - static int image_flush_cache(sd_event_source *s, void *userdata) { Manager *m = userdata; @@ -388,7 +364,7 @@ static int image_flush_cache(sd_event_source *s, void *userdata) { return 0; } -int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { +static int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *e = NULL; Manager *m = userdata; Image *image = NULL; @@ -462,7 +438,7 @@ char *image_bus_path(const char *name) { return strjoin("/org/freedesktop/machine1/image/", e); } -int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { +static int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_hashmap_free_ Hashmap *images = NULL; _cleanup_strv_free_ char **l = NULL; Image *image; @@ -497,3 +473,34 @@ int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ** return 1; } + +const sd_bus_vtable image_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0), + SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0), + SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0), + SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0), + SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0), + SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0), + SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0), + SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0), + SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0), + SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetHostname", NULL, "s", bus_image_method_get_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineID", NULL, "ay", bus_image_method_get_machine_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineInfo", NULL, "a{ss}", bus_image_method_get_machine_info, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +const BusObjectImplementation image_object = { + "/org/freedesktop/machine1/image", + "org.freedesktop.machine1.Image", + .fallback_vtables = BUS_FALLBACK_VTABLES({image_vtable, image_object_find}), + .node_enumerator = image_node_enumerator, +}; diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h index a918b77d38..43f5f34d20 100644 --- a/src/machine/image-dbus.h +++ b/src/machine/image-dbus.h @@ -1,15 +1,13 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "bus-util.h" #include "machined.h" -extern const sd_bus_vtable image_vtable[]; +extern const BusObjectImplementation image_object; char *image_bus_path(const char *name); -int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); -int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); - int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_rename(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_clone(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index c75467cadf..1d17f220a5 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -1321,7 +1321,99 @@ int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd return sd_bus_reply_method_return(message, "u", (uint32_t) shift); } -const sd_bus_vtable machine_vtable[] = { +static int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Machine *machine; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + if (streq(path, "/org/freedesktop/machine1/machine/self")) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + sd_bus_message *message; + pid_t pid; + + message = sd_bus_get_current_message(bus); + if (!message) + return 0; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + r = manager_get_machine_by_pid(m, pid, &machine); + if (r <= 0) + return 0; + } else { + _cleanup_free_ char *e = NULL; + const char *p; + + p = startswith(path, "/org/freedesktop/machine1/machine/"); + if (!p) + return 0; + + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; + + machine = hashmap_get(m->machines, e); + if (!machine) + return 0; + } + + *found = machine; + return 1; +} + +char *machine_bus_path(Machine *m) { + _cleanup_free_ char *e = NULL; + + assert(m); + + e = bus_label_escape(m->name); + if (!e) + return NULL; + + return strjoin("/org/freedesktop/machine1/machine/", e); +} + +static int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Machine *machine = NULL; + Manager *m = userdata; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + HASHMAP_FOREACH(machine, m->machines, i) { + char *p; + + p = machine_bus_path(machine); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + *nodes = TAKE_PTR(l); + + return 1; +} + +static const sd_bus_vtable machine_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Id", "ay", bus_property_get_id128, offsetof(Machine, id), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1423,97 +1515,12 @@ const sd_bus_vtable machine_vtable[] = { SD_BUS_VTABLE_END }; -int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - Manager *m = userdata; - Machine *machine; - int r; - - assert(bus); - assert(path); - assert(interface); - assert(found); - assert(m); - - if (streq(path, "/org/freedesktop/machine1/machine/self")) { - _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; - sd_bus_message *message; - pid_t pid; - - message = sd_bus_get_current_message(bus); - if (!message) - return 0; - - r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); - if (r < 0) - return r; - - r = sd_bus_creds_get_pid(creds, &pid); - if (r < 0) - return r; - - r = manager_get_machine_by_pid(m, pid, &machine); - if (r <= 0) - return 0; - } else { - _cleanup_free_ char *e = NULL; - const char *p; - - p = startswith(path, "/org/freedesktop/machine1/machine/"); - if (!p) - return 0; - - e = bus_label_unescape(p); - if (!e) - return -ENOMEM; - - machine = hashmap_get(m->machines, e); - if (!machine) - return 0; - } - - *found = machine; - return 1; -} - -char *machine_bus_path(Machine *m) { - _cleanup_free_ char *e = NULL; - - assert(m); - - e = bus_label_escape(m->name); - if (!e) - return NULL; - - return strjoin("/org/freedesktop/machine1/machine/", e); -} - -int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Machine *machine = NULL; - Manager *m = userdata; - Iterator i; - int r; - - assert(bus); - assert(path); - assert(nodes); - - HASHMAP_FOREACH(machine, m->machines, i) { - char *p; - - p = machine_bus_path(machine); - if (!p) - return -ENOMEM; - - r = strv_consume(&l, p); - if (r < 0) - return r; - } - - *nodes = TAKE_PTR(l); - - return 1; -} +const BusObjectImplementation machine_object = { + "/org/freedesktop/machine1/machine", + "org.freedesktop.machine1.Machine", + .fallback_vtables = BUS_FALLBACK_VTABLES({machine_vtable, machine_object_find}), + .node_enumerator = machine_node_enumerator, +}; int machine_send_signal(Machine *m, bool new_machine) { _cleanup_free_ char *p = NULL; diff --git a/src/machine/machine-dbus.h b/src/machine/machine-dbus.h index d9f3c59cea..7080092bcf 100644 --- a/src/machine/machine-dbus.h +++ b/src/machine/machine-dbus.h @@ -3,13 +3,12 @@ #include "sd-bus.h" +#include "bus-util.h" #include "machine.h" -extern const sd_bus_vtable machine_vtable[]; +extern const BusObjectImplementation machine_object; char *machine_bus_path(Machine *s); -int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); -int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 76d5119089..ceb3afadbd 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -1440,6 +1440,14 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_END }; +const BusObjectImplementation manager_object = { + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + .vtables = BUS_VTABLES(manager_vtable), + .children = BUS_IMPLEMENTATIONS( &machine_object, + &image_object ), +}; + int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *path, *result, *unit; Manager *m = userdata; diff --git a/src/machine/machined.c b/src/machine/machined.c index a93bfc42be..f2c8ff26af 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -22,6 +22,7 @@ #include "machined.h" #include "main-func.h" #include "process-util.h" +#include "service-util.h" #include "signal-util.h" #include "special.h" @@ -188,25 +189,9 @@ static int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); - r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m); + r = bus_add_implementation(m->bus, &manager_object, m); if (r < 0) - return log_error_errno(r, "Failed to add manager object vtable: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add machine object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add machine enumerator: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add image object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add image enumerator: %m"); + return r; r = sd_bus_match_signal_async( m->bus, @@ -357,12 +342,15 @@ static int run(int argc, char *argv[]) { log_set_facility(LOG_AUTH); log_setup_service(); - umask(0022); + r = service_parse_argv("systemd-machined.service", + "Manage registrations of local VMs and containers.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; - if (argc != 1) { - log_error("This program takes no arguments."); - return -EINVAL; - } + umask(0022); /* Always create the directories people can create inotify watches in. Note that some applications might check * for the existence of /run/systemd/machines/ to determine whether machined is available, so please always diff --git a/src/machine/machined.h b/src/machine/machined.h index 205d90f83d..0ec3fb9326 100644 --- a/src/machine/machined.h +++ b/src/machine/machined.h @@ -42,7 +42,7 @@ struct Manager { int manager_add_machine(Manager *m, const char *name, Machine **_machine); int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine); -extern const sd_bus_vtable manager_vtable[]; +extern const BusObjectImplementation manager_object; int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 37b9863862..c865d25a38 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -1970,6 +1970,14 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_VTABLE_END, }; +const BusObjectImplementation manager_object = { + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + .vtables = BUS_VTABLES(resolve_vtable), + .children = BUS_IMPLEMENTATIONS(&link_object, + &dnssd_object), +}; + static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { Manager *m = userdata; int b, r; @@ -2004,25 +2012,9 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); - r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m); + r = bus_add_implementation(m->bus, &manager_object, m); if (r < 0) - return log_error_errno(r, "Failed to register object: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register link objects: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to register link enumerator: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", "org.freedesktop.resolve1.DnssdService", dnssd_vtable, dnssd_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to register dnssd objects: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", dnssd_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to register dnssd enumerator: %m"); + return r; r = bus_log_control_api_register(m->bus); if (r < 0) diff --git a/src/resolve/resolved-bus.h b/src/resolve/resolved-bus.h index a499f76ad5..e69171ca70 100644 --- a/src/resolve/resolved-bus.h +++ b/src/resolve/resolved-bus.h @@ -1,8 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "bus-util.h" #include "resolved-manager.h" +extern const BusObjectImplementation manager_object; + int manager_connect_bus(Manager *m); int _manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; #define manager_send_changed(manager, ...) _manager_send_changed(manager, __VA_ARGS__, NULL) diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c index f7dcb3bfa5..84d8d879eb 100644 --- a/src/resolve/resolved-dnssd-bus.c +++ b/src/resolve/resolved-dnssd-bus.c @@ -62,16 +62,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_ return sd_bus_reply_method_return(message, NULL); } -const sd_bus_vtable dnssd_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_METHOD("Unregister", NULL, NULL, bus_dnssd_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_SIGNAL("Conflicted", NULL, 0), - - SD_BUS_VTABLE_END -}; - -int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { +static int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *name = NULL; Manager *m = userdata; DnssdService *service; @@ -95,7 +86,7 @@ int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void return 1; } -int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { +static int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; DnssdService *service; @@ -127,3 +118,19 @@ int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ** return 1; } + +static const sd_bus_vtable dnssd_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_METHOD("Unregister", NULL, NULL, bus_dnssd_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_SIGNAL("Conflicted", NULL, 0), + + SD_BUS_VTABLE_END +}; + +const BusObjectImplementation dnssd_object = { + "/org/freedesktop/resolve1/dnssd", + "org.freedesktop.resolve1.DnssdService", + .fallback_vtables = BUS_FALLBACK_VTABLES({dnssd_vtable, dnssd_object_find}), + .node_enumerator = dnssd_node_enumerator, +}; diff --git a/src/resolve/resolved-dnssd-bus.h b/src/resolve/resolved-dnssd-bus.h index 9ee2ce17ec..8cd75642a7 100644 --- a/src/resolve/resolved-dnssd-bus.h +++ b/src/resolve/resolved-dnssd-bus.h @@ -2,9 +2,8 @@ #include "sd-bus.h" -extern const sd_bus_vtable dnssd_vtable[]; +#include "bus-util.h" -int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); -int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +extern const BusObjectImplementation dnssd_object; int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index d9b6d2c88d..4ba179ce06 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -682,7 +682,82 @@ int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error return sd_bus_reply_method_return(message, NULL); } -const sd_bus_vtable link_vtable[] = { +static int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *e = NULL; + Manager *m = userdata; + Link *link; + int ifindex, r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e); + if (r <= 0) + return 0; + + ifindex = parse_ifindex(e); + if (ifindex < 0) + return 0; + + link = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!link) + return 0; + + *found = link; + return 1; +} + +char *link_bus_path(const Link *link) { + char *p, ifindex[DECIMAL_STR_MAX(link->ifindex)]; + int r; + + assert(link); + + xsprintf(ifindex, "%i", link->ifindex); + + r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p); + if (r < 0) + return NULL; + + return p; +} + +static int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + Link *link; + Iterator i; + unsigned c = 0; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + l = new0(char*, hashmap_size(m->links) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(link, m->links, i) { + char *p; + + p = link_bus_path(link); + if (!p) + return -ENOMEM; + + l[c++] = p; + } + + l[c] = NULL; + *nodes = TAKE_PTR(l); + + return 1; +} + +static const sd_bus_vtable link_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0), @@ -746,77 +821,9 @@ const sd_bus_vtable link_vtable[] = { SD_BUS_VTABLE_END }; -int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - _cleanup_free_ char *e = NULL; - Manager *m = userdata; - Link *link; - int ifindex, r; - - assert(bus); - assert(path); - assert(interface); - assert(found); - assert(m); - - r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e); - if (r <= 0) - return 0; - - ifindex = parse_ifindex(e); - if (ifindex < 0) - return 0; - - link = hashmap_get(m->links, INT_TO_PTR(ifindex)); - if (!link) - return 0; - - *found = link; - return 1; -} - -char *link_bus_path(const Link *link) { - char *p, ifindex[DECIMAL_STR_MAX(link->ifindex)]; - int r; - - assert(link); - - xsprintf(ifindex, "%i", link->ifindex); - - r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p); - if (r < 0) - return NULL; - - return p; -} - -int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - Link *link; - Iterator i; - unsigned c = 0; - - assert(bus); - assert(path); - assert(m); - assert(nodes); - - l = new0(char*, hashmap_size(m->links) + 1); - if (!l) - return -ENOMEM; - - HASHMAP_FOREACH(link, m->links, i) { - char *p; - - p = link_bus_path(link); - if (!p) - return -ENOMEM; - - l[c++] = p; - } - - l[c] = NULL; - *nodes = TAKE_PTR(l); - - return 1; -} +const BusObjectImplementation link_object = { + "/org/freedesktop/resolve1/link", + "org.freedesktop.resolve1.Link", + .fallback_vtables = BUS_FALLBACK_VTABLES({link_vtable, link_object_find}), + .node_enumerator = link_node_enumerator, +}; diff --git a/src/resolve/resolved-link-bus.h b/src/resolve/resolved-link-bus.h index 74068a4777..c249960024 100644 --- a/src/resolve/resolved-link-bus.h +++ b/src/resolve/resolved-link-bus.h @@ -3,13 +3,12 @@ #include "sd-bus.h" +#include "bus-util.h" #include "resolved-link.h" -extern const sd_bus_vtable link_vtable[]; +extern const BusObjectImplementation link_object; -int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); char *link_bus_path(const Link *link); -int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 27848cccae..50989a6b0a 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -7,14 +7,17 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "bus-log-control-api.h" #include "capability-util.h" #include "daemon-util.h" #include "main-func.h" #include "mkdir.h" +#include "resolved-bus.h" #include "resolved-conf.h" #include "resolved-manager.h" #include "resolved-resolv-conf.h" #include "selinux-util.h" +#include "service-util.h" #include "signal-util.h" #include "user-util.h" @@ -25,8 +28,13 @@ static int run(int argc, char *argv[]) { log_setup_service(); - if (argc != 1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + r = service_parse_argv("systemd-resolved.service", + "Provide name resolution with caching using DNS, mDNS, LLMNR.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; umask(0022); diff --git a/src/shared/bus-log-control-api.c b/src/shared/bus-log-control-api.c index ffc52c7774..a1d0d17291 100644 --- a/src/shared/bus-log-control-api.c +++ b/src/shared/bus-log-control-api.c @@ -107,17 +107,8 @@ static const sd_bus_vtable log_control_vtable[] = { SD_BUS_VTABLE_END, }; -int bus_log_control_api_register(sd_bus *bus) { - int r; - - r = sd_bus_add_object_vtable( - bus, - NULL, - "/org/freedesktop/LogControl1", - "org.freedesktop.LogControl1", - log_control_vtable, NULL); - if (r < 0) - return log_error_errno(r, "Failed to register service API object: %m"); - - return 0; -} +const BusObjectImplementation log_control_object = { + "/org/freedesktop/LogControl1", + "org.freedesktop.LogControl1", + .vtables = BUS_VTABLES(log_control_vtable), +}; diff --git a/src/shared/bus-log-control-api.h b/src/shared/bus-log-control-api.h index a6fb2757c5..b1d00b38bc 100644 --- a/src/shared/bus-log-control-api.h +++ b/src/shared/bus-log-control-api.h @@ -2,7 +2,12 @@ #include "sd-bus.h" -int bus_log_control_api_register(sd_bus *bus); +#include "bus-util.h" + +extern const BusObjectImplementation log_control_object; +static inline int bus_log_control_api_register(sd_bus *bus) { + return bus_add_implementation(bus, &log_control_object, NULL); +} int bus_property_get_log_level(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); int bus_property_set_log_level(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 81683e5afe..df701a3bfe 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -16,6 +16,7 @@ #include "alloc-util.h" #include "bus-internal.h" +#include "bus-introspect.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" @@ -1549,3 +1550,171 @@ int bus_message_new_method_call( return sd_bus_message_new_method_call(bus, m, locator->destination, locator->path, locator->interface, member); } + +int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata) { + int r; + + log_debug("Registering bus object implementation for path=%s iface=%s", impl->path, impl->interface); + + for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) { + r = sd_bus_add_object_vtable(bus, NULL, + impl->path, + impl->interface, + *p, + userdata); + if (r < 0) + return log_error_errno(r, "Failed to register bus path %s with interface %s: %m", + impl->path, + impl->interface); + } + + for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) { + r = sd_bus_add_fallback_vtable(bus, NULL, + impl->path, + impl->interface, + p->vtable, + p->object_find, + userdata); + if (r < 0) + return log_error_errno(r, "Failed to register bus path %s with interface %s: %m", + impl->path, + impl->interface); + } + + if (impl->node_enumerator) { + r = sd_bus_add_node_enumerator(bus, NULL, + impl->path, + impl->node_enumerator, + userdata); + if (r < 0) + return log_error_errno(r, "Failed to add node enumerator for %s: %m", + impl->path); + } + + for (size_t i = 0; impl->children && impl->children[i]; i++) { + r = bus_add_implementation(bus, impl->children[i], userdata); + if (r < 0) + return r; + } + + return 0; +} + +static const BusObjectImplementation* find_implementation( + const char *pattern, + const BusObjectImplementation* const* bus_objects) { + + for (size_t i = 0; bus_objects && bus_objects[i]; i++) { + const BusObjectImplementation *impl = bus_objects[i]; + + if (STR_IN_SET(pattern, impl->path, impl->interface)) + return impl; + + impl = find_implementation(pattern, impl->children); + if (impl) + return impl; + } + + return NULL; +} + +static int bus_introspect_implementation( + struct introspect *intro, + const BusObjectImplementation *impl) { + int r; + + for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) { + r = introspect_write_interface(intro, impl->interface, *p); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + } + + for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) { + r = introspect_write_interface(intro, impl->interface, p->vtable); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + } + + return 0; +} + +static void list_paths( + FILE *out, + const BusObjectImplementation* const* bus_objects) { + + for (size_t i = 0; bus_objects[i]; i++) { + fprintf(out, "%s\t%s\n", bus_objects[i]->path, bus_objects[i]->interface); + if (bus_objects[i]->children) + list_paths(out, bus_objects[i]->children); + } +} + +int bus_introspect_implementations( + FILE *out, + const char *pattern, + const BusObjectImplementation* const* bus_objects) { + + const BusObjectImplementation *impl, *main_impl = NULL; + _cleanup_free_ char *s = NULL; + int r; + + if (streq(pattern, "list")) { + list_paths(out, bus_objects); + return 0; + } + + struct introspect intro = {}; + bool is_interface = interface_name_is_valid(pattern); + + impl = find_implementation(pattern, bus_objects); + if (!impl) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "%s %s not found", + is_interface ? "Interface" : "Object path", + pattern); + + /* We use trusted=false here to get all the @org.freedesktop.systemd1.Privileged annotations. */ + r = introspect_begin(&intro, false); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + + r = introspect_write_default_interfaces(&intro, impl->manager); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + + /* Check if there is a non-fallback path that applies to the given interface, also + * print it. This is useful in the case of units: o.fd.systemd1.Service is declared + * as a fallback vtable for o/fd/systemd1/unit, and we also want to print + * o.fd.systemd1.Unit, which is the non-fallback implementation. */ + if (impl->fallback_vtables && is_interface) + main_impl = find_implementation(impl->path, bus_objects); + + if (main_impl) + bus_introspect_implementation(&intro, main_impl); + + if (impl != main_impl) + bus_introspect_implementation(&intro, impl); + + _cleanup_set_free_free_ Set *nodes = NULL; + + for (size_t i = 0; impl->children && impl->children[i]; i++) { + r = set_ensure_allocated(&nodes, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put_strdup(nodes, impl->children[i]->path); + if (r < 0) + return log_oom(); + } + + r = introspect_write_child_nodes(&intro, nodes, impl->path); + if (r < 0) + return r; + + r = introspect_finish(&intro, &s); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + + fputs(s, out); + return 0; +} diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index fd1820ca7e..7678680dae 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -23,11 +23,32 @@ typedef enum BusTransport { } BusTransport; typedef struct BusLocator { - const char *destination; - const char *path; - const char *interface; + const char *destination; + const char *path; + const char *interface; } BusLocator; +typedef struct BusObjectImplementation BusObjectImplementation; + +typedef struct BusObjectVtablePair { + const sd_bus_vtable *vtable; + sd_bus_object_find_t object_find; +} BusObjectVtablePair; + +struct BusObjectImplementation { + const char *path; + const char *interface; + const sd_bus_vtable **vtables; + const BusObjectVtablePair *fallback_vtables; + sd_bus_node_enumerator_t node_enumerator; + bool manager; + const BusObjectImplementation **children; +}; + +#define BUS_VTABLES(...) ((const sd_bus_vtable* []){ __VA_ARGS__, NULL }) +#define BUS_FALLBACK_VTABLES(...) ((const BusObjectVtablePair[]) { __VA_ARGS__, {} }) +#define BUS_IMPLEMENTATIONS(...) ((const BusObjectImplementation* []) { __VA_ARGS__, NULL }) + typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); struct bus_properties_map { @@ -199,3 +220,9 @@ int bus_set_property(sd_bus *bus, const BusLocator *locator, const char *member, int bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const BusLocator *locator, const char *member, sd_bus_message_handler_t callback, void *userdata); int bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const BusLocator *locator, const char *member, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata); int bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const BusLocator *locator, const char *member); + +int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata); +int bus_introspect_implementations( + FILE *out, + const char *pattern, + const BusObjectImplementation* const* bus_objects); diff --git a/src/shared/meson.build b/src/shared/meson.build index 41d214890c..60d6adb068 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -184,6 +184,8 @@ shared_sources = files(''' securebits-util.h serialize.c serialize.h + service-util.c + service-util.h sleep-config.c sleep-config.h socket-netlink.c diff --git a/src/shared/service-util.c b/src/shared/service-util.c new file mode 100644 index 0000000000..c9b684fc05 --- /dev/null +++ b/src/shared/service-util.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "pretty-print.h" +#include "service-util.h" +#include "terminal-util.h" +#include "util.h" + +static int help(const char *program_path, const char *service, const char *description, bool bus_introspect) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man(service, "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "%s%s%s\n\n" + "This program takes no positional arguments.\n\n" + "%sOptions%s:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --bus-introspect=PATH Write D-Bus XML introspection data\n" + "\nSee the %s for details.\n" + , program_path + , ansi_highlight(), description, ansi_normal() + , ansi_underline(), ansi_normal() + , link + ); + + return 0; /* No further action */ +} + +int service_parse_argv( + const char *service, + const char *description, + const BusObjectImplementation* const* bus_objects, + int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_BUS_INTROSPECT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch(c) { + + case 'h': + return help(argv[0], service, description, bus_objects); + + case ARG_VERSION: + return version(); + + case ARG_BUS_INTROSPECT: + return bus_introspect_implementations( + stdout, + optarg, + bus_objects); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unknown option code."); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes no arguments."); + + return 1; /* Further action */ +} diff --git a/src/shared/service-util.h b/src/shared/service-util.h new file mode 100644 index 0000000000..76bff61d58 --- /dev/null +++ b/src/shared/service-util.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "bus-util.h" + +int service_parse_argv( + const char *service, + const char *description, + const BusObjectImplementation* const* bus_objects, + int argc, char *argv[]); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 8e15cd4f06..19e51b063a 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -14,6 +14,7 @@ #include "bus-error.h" #include "bus-log-control-api.h" #include "bus-polkit.h" +#include "bus-util.h" #include "clock-util.h" #include "conf-files.h" #include "def.h" @@ -28,6 +29,7 @@ #include "missing_capability.h" #include "path-util.h" #include "selinux-util.h" +#include "service-util.h" #include "signal-util.h" #include "string-util.h" #include "strv.h" @@ -1085,6 +1087,12 @@ static const sd_bus_vtable timedate_vtable[] = { SD_BUS_VTABLE_END, }; +const BusObjectImplementation manager_object = { + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + .vtables = BUS_VTABLES(timedate_vtable), +}; + static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; @@ -1097,9 +1105,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { if (r < 0) return log_error_errno(r, "Failed to get system bus connection: %m"); - r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c); + r = bus_add_implementation(bus, &manager_object, c); if (r < 0) - return log_error_errno(r, "Failed to register object: %m"); + return r; r = bus_log_control_api_register(bus); if (r < 0) @@ -1126,10 +1134,15 @@ static int run(int argc, char *argv[]) { log_setup_service(); - umask(0022); + r = service_parse_argv("systemd-timedated.service", + "Manage the system clock and timezone and NTP enablement.", + BUS_IMPLEMENTATIONS(&manager_object, + &log_control_object), + argc, argv); + if (r <= 0) + return r; - if (argc != 1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + umask(0022); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); diff --git a/tools/update-dbus-docs.py b/tools/update-dbus-docs.py index 95a22bebfa..f95faaaf22 100755 --- a/tools/update-dbus-docs.py +++ b/tools/update-dbus-docs.py @@ -3,10 +3,10 @@ import collections import sys +import os import shlex import subprocess import io -import pprint from lxml import etree PARSER = etree.XMLParser(no_network=True, @@ -19,23 +19,6 @@ PRINT_ERRORS = True class NoCommand(Exception): pass -def find_command(lines): - acc = [] - for num, line in enumerate(lines): - # skip empty leading line - if num == 0 and not line: - continue - cont = line.endswith('\\') - if cont: - line = line[:-1].rstrip() - acc.append(line if not acc else line.lstrip()) - if not cont: - break - joined = ' '.join(acc) - if not joined.startswith('$ '): - raise NoCommand - return joined[2:], lines[:num+1] + [''], lines[-1] - BORING_INTERFACES = [ 'org.freedesktop.DBus.Peer', 'org.freedesktop.DBus.Introspectable', @@ -183,31 +166,27 @@ def xml_to_text(destination, xml, *, only_interface=None): return file.getvalue(), declarations, interfaces def subst_output(document, programlisting): - try: - cmd, prefix_lines, footer = find_command(programlisting.text.splitlines()) - except NoCommand: + executable = programlisting.get('executable', None) + if executable is None: + # Not our thing return + executable = programlisting.get('executable') + node = programlisting.get('node') + interface = programlisting.get('interface') - only_interface = programlisting.get('interface', None) - - argv = shlex.split(cmd) - argv += ['--xml'] + argv = [f'{build_dir}/{executable}', f'--bus-introspect={interface}'] print(f'COMMAND: {shlex.join(argv)}') - object_idx = argv.index('--object-path') - object_path = argv[object_idx + 1] - try: out = subprocess.check_output(argv, text=True) - except subprocess.CalledProcessError: - print('command failed, ignoring', file=sys.stderr) + except FileNotFoundError: + print(f'{executable} not found, ignoring', file=sys.stderr) return xml = etree.fromstring(out, parser=PARSER) - new_text, declarations, interfaces = xml_to_text(object_path, xml, only_interface=only_interface) - - programlisting.text = '\n'.join(prefix_lines) + '\n' + new_text + footer + new_text, declarations, interfaces = xml_to_text(node, xml, only_interface=interface) + programlisting.text = '\n' + new_text + ' ' if declarations: missing = check_documented(document, declarations) @@ -291,5 +270,14 @@ def process(page): if __name__ == '__main__': pages = sys.argv[1:] + if pages[0].startswith('--build-dir='): + build_dir = pages[0].partition('=')[2] + pages = pages[1:] + else: + build_dir = 'build' + + if not os.path.exists(f'{build_dir}/systemd'): + exit(f"{build_dir}/systemd doesn't exist. Use --build-dir=.") + for page in pages: process(page) diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in index ed573b8f3c..0147b30e0d 100644 --- a/units/systemd-logind.service.in +++ b/units/systemd-logind.service.in @@ -8,7 +8,7 @@ # (at your option) any later version. [Unit] -Description=Login Service +Description=User Login Management Documentation=man:systemd-logind.service(8) man:logind.conf(5) Documentation=https://www.freedesktop.org/wiki/Software/systemd/logind Documentation=https://www.freedesktop.org/wiki/Software/systemd/multiseat