LCOV - code coverage report
Current view: top level - login - logind-seat-dbus.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 210 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2011 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <errno.h>
      23             : #include <string.h>
      24             : 
      25             : #include "util.h"
      26             : #include "bus-util.h"
      27             : #include "strv.h"
      28             : #include "bus-common-errors.h"
      29             : #include "bus-label.h"
      30             : #include "logind.h"
      31             : #include "logind-seat.h"
      32             : 
      33           0 : static int property_get_active_session(
      34             :                 sd_bus *bus,
      35             :                 const char *path,
      36             :                 const char *interface,
      37             :                 const char *property,
      38             :                 sd_bus_message *reply,
      39             :                 void *userdata,
      40             :                 sd_bus_error *error) {
      41             : 
      42           0 :         _cleanup_free_ char *p = NULL;
      43           0 :         Seat *s = userdata;
      44             : 
      45           0 :         assert(bus);
      46           0 :         assert(reply);
      47           0 :         assert(s);
      48             : 
      49           0 :         p = s->active ? session_bus_path(s->active) : strdup("/");
      50           0 :         if (!p)
      51           0 :                 return -ENOMEM;
      52             : 
      53           0 :         return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
      54             : }
      55             : 
      56           0 : static int property_get_can_multi_session(
      57             :                 sd_bus *bus,
      58             :                 const char *path,
      59             :                 const char *interface,
      60             :                 const char *property,
      61             :                 sd_bus_message *reply,
      62             :                 void *userdata,
      63             :                 sd_bus_error *error) {
      64             : 
      65           0 :         Seat *s = userdata;
      66             : 
      67           0 :         assert(bus);
      68           0 :         assert(reply);
      69           0 :         assert(s);
      70             : 
      71           0 :         return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
      72             : }
      73             : 
      74           0 : static int property_get_can_tty(
      75             :                 sd_bus *bus,
      76             :                 const char *path,
      77             :                 const char *interface,
      78             :                 const char *property,
      79             :                 sd_bus_message *reply,
      80             :                 void *userdata,
      81             :                 sd_bus_error *error) {
      82             : 
      83           0 :         Seat *s = userdata;
      84             : 
      85           0 :         assert(bus);
      86           0 :         assert(reply);
      87           0 :         assert(s);
      88             : 
      89           0 :         return sd_bus_message_append(reply, "b", seat_can_tty(s));
      90             : }
      91             : 
      92           0 : static int property_get_can_graphical(
      93             :                 sd_bus *bus,
      94             :                 const char *path,
      95             :                 const char *interface,
      96             :                 const char *property,
      97             :                 sd_bus_message *reply,
      98             :                 void *userdata,
      99             :                 sd_bus_error *error) {
     100             : 
     101           0 :         Seat *s = userdata;
     102             : 
     103           0 :         assert(bus);
     104           0 :         assert(reply);
     105           0 :         assert(s);
     106             : 
     107           0 :         return sd_bus_message_append(reply, "b", seat_can_graphical(s));
     108             : }
     109             : 
     110           0 : static int property_get_sessions(
     111             :                 sd_bus *bus,
     112             :                 const char *path,
     113             :                 const char *interface,
     114             :                 const char *property,
     115             :                 sd_bus_message *reply,
     116             :                 void *userdata,
     117             :                 sd_bus_error *error) {
     118             : 
     119           0 :         Seat *s = userdata;
     120             :         Session *session;
     121             :         int r;
     122             : 
     123           0 :         assert(bus);
     124           0 :         assert(reply);
     125           0 :         assert(s);
     126             : 
     127           0 :         r = sd_bus_message_open_container(reply, 'a', "(so)");
     128           0 :         if (r < 0)
     129           0 :                 return r;
     130             : 
     131           0 :         LIST_FOREACH(sessions_by_seat, session, s->sessions) {
     132           0 :                 _cleanup_free_ char *p = NULL;
     133             : 
     134           0 :                 p = session_bus_path(session);
     135           0 :                 if (!p)
     136           0 :                         return -ENOMEM;
     137             : 
     138           0 :                 r = sd_bus_message_append(reply, "(so)", session->id, p);
     139           0 :                 if (r < 0)
     140           0 :                         return r;
     141             : 
     142             :         }
     143             : 
     144           0 :         r = sd_bus_message_close_container(reply);
     145           0 :         if (r < 0)
     146           0 :                 return r;
     147             : 
     148           0 :         return 1;
     149             : }
     150             : 
     151           0 : static int property_get_idle_hint(
     152             :                 sd_bus *bus,
     153             :                 const char *path,
     154             :                 const char *interface,
     155             :                 const char *property,
     156             :                 sd_bus_message *reply,
     157             :                 void *userdata,
     158             :                 sd_bus_error *error) {
     159             : 
     160           0 :         Seat *s = userdata;
     161             : 
     162           0 :         assert(bus);
     163           0 :         assert(reply);
     164           0 :         assert(s);
     165             : 
     166           0 :         return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
     167             : }
     168             : 
     169           0 : static int property_get_idle_since_hint(
     170             :                 sd_bus *bus,
     171             :                 const char *path,
     172             :                 const char *interface,
     173             :                 const char *property,
     174             :                 sd_bus_message *reply,
     175             :                 void *userdata,
     176             :                 sd_bus_error *error) {
     177             : 
     178           0 :         Seat *s = userdata;
     179             :         dual_timestamp t;
     180             :         uint64_t u;
     181             :         int r;
     182             : 
     183           0 :         assert(bus);
     184           0 :         assert(reply);
     185           0 :         assert(s);
     186             : 
     187           0 :         r = seat_get_idle_hint(s, &t);
     188           0 :         if (r < 0)
     189           0 :                 return r;
     190             : 
     191           0 :         u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
     192             : 
     193           0 :         return sd_bus_message_append(reply, "t", u);
     194             : }
     195             : 
     196           0 : int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     197           0 :         Seat *s = userdata;
     198             :         int r;
     199             : 
     200           0 :         assert(message);
     201           0 :         assert(s);
     202             : 
     203           0 :         r = bus_verify_polkit_async(
     204             :                         message,
     205             :                         CAP_KILL,
     206             :                         "org.freedesktop.login1.manage",
     207             :                         false,
     208             :                         UID_INVALID,
     209           0 :                         &s->manager->polkit_registry,
     210             :                         error);
     211           0 :         if (r < 0)
     212           0 :                 return r;
     213           0 :         if (r == 0)
     214           0 :                 return 1; /* Will call us back */
     215             : 
     216           0 :         r = seat_stop_sessions(s, true);
     217           0 :         if (r < 0)
     218           0 :                 return r;
     219             : 
     220           0 :         return sd_bus_reply_method_return(message, NULL);
     221             : }
     222             : 
     223           0 : static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     224           0 :         Seat *s = userdata;
     225             :         const char *name;
     226             :         Session *session;
     227             :         int r;
     228             : 
     229           0 :         assert(message);
     230           0 :         assert(s);
     231             : 
     232           0 :         r = sd_bus_message_read(message, "s", &name);
     233           0 :         if (r < 0)
     234           0 :                 return r;
     235             : 
     236           0 :         session = hashmap_get(s->manager->sessions, name);
     237           0 :         if (!session)
     238           0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
     239             : 
     240           0 :         if (session->seat != s)
     241           0 :                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
     242             : 
     243           0 :         r = session_activate(session);
     244           0 :         if (r < 0)
     245           0 :                 return r;
     246             : 
     247           0 :         return sd_bus_reply_method_return(message, NULL);
     248             : }
     249             : 
     250           0 : static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     251           0 :         Seat *s = userdata;
     252             :         unsigned int to;
     253             :         int r;
     254             : 
     255           0 :         assert(message);
     256           0 :         assert(s);
     257             : 
     258           0 :         r = sd_bus_message_read(message, "u", &to);
     259           0 :         if (r < 0)
     260           0 :                 return r;
     261             : 
     262           0 :         if (to <= 0)
     263           0 :                 return -EINVAL;
     264             : 
     265           0 :         r = seat_switch_to(s, to);
     266           0 :         if (r < 0)
     267           0 :                 return r;
     268             : 
     269           0 :         return sd_bus_reply_method_return(message, NULL);
     270             : }
     271             : 
     272           0 : static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     273           0 :         Seat *s = userdata;
     274             :         int r;
     275             : 
     276           0 :         assert(message);
     277           0 :         assert(s);
     278             : 
     279           0 :         r = seat_switch_to_next(s);
     280           0 :         if (r < 0)
     281           0 :                 return r;
     282             : 
     283           0 :         return sd_bus_reply_method_return(message, NULL);
     284             : }
     285             : 
     286           0 : static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     287           0 :         Seat *s = userdata;
     288             :         int r;
     289             : 
     290           0 :         assert(message);
     291           0 :         assert(s);
     292             : 
     293           0 :         r = seat_switch_to_previous(s);
     294           0 :         if (r < 0)
     295           0 :                 return r;
     296             : 
     297           0 :         return sd_bus_reply_method_return(message, NULL);
     298             : }
     299             : 
     300             : const sd_bus_vtable seat_vtable[] = {
     301             :         SD_BUS_VTABLE_START(0),
     302             : 
     303             :         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST),
     304             :         SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     305             :         SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     306             :         SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     307             :         SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     308             :         SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     309             :         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     310             :         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     311             :         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     312             : 
     313             :         SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
     314             :         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
     315             :         SD_BUS_METHOD("SwitchTo", "u", NULL, method_switch_to, SD_BUS_VTABLE_UNPRIVILEGED),
     316             :         SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED),
     317             :         SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED),
     318             : 
     319             :         SD_BUS_VTABLE_END
     320             : };
     321             : 
     322           0 : int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
     323           0 :         Manager *m = userdata;
     324             :         Seat *seat;
     325             :         int r;
     326             : 
     327           0 :         assert(bus);
     328           0 :         assert(path);
     329           0 :         assert(interface);
     330           0 :         assert(found);
     331           0 :         assert(m);
     332             : 
     333           0 :         if (streq(path, "/org/freedesktop/login1/seat/self")) {
     334           0 :                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
     335             :                 sd_bus_message *message;
     336             :                 Session *session;
     337             :                 const char *name;
     338             : 
     339           0 :                 message = sd_bus_get_current_message(bus);
     340           0 :                 if (!message)
     341           0 :                         return 0;
     342             : 
     343           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
     344           0 :                 if (r < 0)
     345           0 :                         return r;
     346             : 
     347           0 :                 r = sd_bus_creds_get_session(creds, &name);
     348           0 :                 if (r < 0)
     349           0 :                         return r;
     350             : 
     351           0 :                 session = hashmap_get(m->sessions, name);
     352           0 :                 if (!session)
     353           0 :                         return 0;
     354             : 
     355           0 :                 seat = session->seat;
     356             :         } else {
     357           0 :                 _cleanup_free_ char *e = NULL;
     358             :                 const char *p;
     359             : 
     360           0 :                 p = startswith(path, "/org/freedesktop/login1/seat/");
     361           0 :                 if (!p)
     362           0 :                         return 0;
     363             : 
     364           0 :                 e = bus_label_unescape(p);
     365           0 :                 if (!e)
     366           0 :                         return -ENOMEM;
     367             : 
     368           0 :                 seat = hashmap_get(m->seats, e);
     369             :         }
     370             : 
     371           0 :         if (!seat)
     372           0 :                 return 0;
     373             : 
     374           0 :         *found = seat;
     375           0 :         return 1;
     376             : }
     377             : 
     378           0 : char *seat_bus_path(Seat *s) {
     379           0 :         _cleanup_free_ char *t = NULL;
     380             : 
     381           0 :         assert(s);
     382             : 
     383           0 :         t = bus_label_escape(s->id);
     384           0 :         if (!t)
     385           0 :                 return NULL;
     386             : 
     387           0 :         return strappend("/org/freedesktop/login1/seat/", t);
     388             : }
     389             : 
     390           0 : int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
     391           0 :         _cleanup_strv_free_ char **l = NULL;
     392             :         sd_bus_message *message;
     393           0 :         Manager *m = userdata;
     394             :         Seat *seat;
     395             :         Iterator i;
     396             :         int r;
     397             : 
     398           0 :         assert(bus);
     399           0 :         assert(path);
     400           0 :         assert(nodes);
     401             : 
     402           0 :         HASHMAP_FOREACH(seat, m->seats, i) {
     403             :                 char *p;
     404             : 
     405           0 :                 p = seat_bus_path(seat);
     406           0 :                 if (!p)
     407           0 :                         return -ENOMEM;
     408             : 
     409           0 :                 r = strv_consume(&l, p);
     410           0 :                 if (r < 0)
     411           0 :                         return r;
     412             :         }
     413             : 
     414           0 :         message = sd_bus_get_current_message(bus);
     415           0 :         if (message) {
     416           0 :                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
     417             :                 const char *name;
     418             :                 Session *session;
     419             : 
     420           0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
     421           0 :                 if (r >= 0) {
     422           0 :                         r = sd_bus_creds_get_session(creds, &name);
     423           0 :                         if (r >= 0) {
     424           0 :                                 session = hashmap_get(m->sessions, name);
     425           0 :                                 if (session && session->seat) {
     426           0 :                                         r = strv_extend(&l, "/org/freedesktop/login1/seat/self");
     427           0 :                                         if (r < 0)
     428           0 :                                                 return r;
     429             :                                 }
     430             :                         }
     431             :                 }
     432             :         }
     433             : 
     434           0 :         *nodes = l;
     435           0 :         l = NULL;
     436             : 
     437           0 :         return 1;
     438             : }
     439             : 
     440           0 : int seat_send_signal(Seat *s, bool new_seat) {
     441           0 :         _cleanup_free_ char *p = NULL;
     442             : 
     443           0 :         assert(s);
     444             : 
     445           0 :         p = seat_bus_path(s);
     446           0 :         if (!p)
     447           0 :                 return -ENOMEM;
     448             : 
     449           0 :         return sd_bus_emit_signal(
     450           0 :                         s->manager->bus,
     451             :                         "/org/freedesktop/login1",
     452             :                         "org.freedesktop.login1.Manager",
     453             :                         new_seat ? "SeatNew" : "SeatRemoved",
     454             :                         "so", s->id, p);
     455             : }
     456             : 
     457           0 : int seat_send_changed(Seat *s, const char *properties, ...) {
     458           0 :         _cleanup_free_ char *p = NULL;
     459             :         char **l;
     460             : 
     461           0 :         assert(s);
     462             : 
     463           0 :         if (!s->started)
     464           0 :                 return 0;
     465             : 
     466           0 :         p = seat_bus_path(s);
     467           0 :         if (!p)
     468           0 :                 return -ENOMEM;
     469             : 
     470           0 :         l = strv_from_stdarg_alloca(properties);
     471             : 
     472           0 :         return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
     473             : }

Generated by: LCOV version 1.11