chiark / gitweb /
machine: make sure unpriviliged "machinectl status" can show the machine's OS version
[elogind.git] / src / core / dbus-timer.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 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 "unit.h"
23 #include "timer.h"
24 #include "dbus-unit.h"
25 #include "dbus-timer.h"
26 #include "bus-util.h"
27
28 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
29
30 static int property_get_monotonic_timers(
31                 sd_bus *bus,
32                 const char *path,
33                 const char *interface,
34                 const char *property,
35                 sd_bus_message *reply,
36                 void *userdata,
37                 sd_bus_error *error) {
38
39         Timer *t = userdata;
40         TimerValue *v;
41         int r;
42
43         assert(bus);
44         assert(reply);
45         assert(t);
46
47         r = sd_bus_message_open_container(reply, 'a', "(stt)");
48         if (r < 0)
49                 return r;
50
51         LIST_FOREACH(value, v, t->values) {
52                 _cleanup_free_ char *buf = NULL;
53                 const char *s;
54                 size_t l;
55
56                 if (v->base == TIMER_CALENDAR)
57                         continue;
58
59                 s = timer_base_to_string(v->base);
60                 assert(endswith(s, "Sec"));
61
62                 /* s/Sec/USec/ */
63                 l = strlen(s);
64                 buf = new(char, l+2);
65                 if (!buf)
66                         return -ENOMEM;
67
68                 memcpy(buf, s, l-3);
69                 memcpy(buf+l-3, "USec", 5);
70
71                 r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
72                 if (r < 0)
73                         return r;
74         }
75
76         return sd_bus_message_close_container(reply);
77 }
78
79 static int property_get_calendar_timers(
80                 sd_bus *bus,
81                 const char *path,
82                 const char *interface,
83                 const char *property,
84                 sd_bus_message *reply,
85                 void *userdata,
86                 sd_bus_error *error) {
87
88         Timer *t = userdata;
89         TimerValue *v;
90         int r;
91
92         assert(bus);
93         assert(reply);
94         assert(t);
95
96         r = sd_bus_message_open_container(reply, 'a', "(sst)");
97         if (r < 0)
98                 return r;
99
100         LIST_FOREACH(value, v, t->values) {
101                 _cleanup_free_ char *buf = NULL;
102
103                 if (v->base != TIMER_CALENDAR)
104                         continue;
105
106                 r = calendar_spec_to_string(v->calendar_spec, &buf);
107                 if (r < 0)
108                         return r;
109
110                 r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
111                 if (r < 0)
112                         return r;
113         }
114
115         return sd_bus_message_close_container(reply);
116 }
117
118 static int property_get_unit(
119                 sd_bus *bus,
120                 const char *path,
121                 const char *interface,
122                 const char *property,
123                 sd_bus_message *reply,
124                 void *userdata,
125                 sd_bus_error *error) {
126
127         Unit *u = userdata, *trigger;
128
129         assert(bus);
130         assert(reply);
131         assert(u);
132
133         trigger = UNIT_TRIGGER(u);
134
135         return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
136 }
137
138 static int property_get_next_elapse_monotonic(
139                 sd_bus *bus,
140                 const char *path,
141                 const char *interface,
142                 const char *property,
143                 sd_bus_message *reply,
144                 void *userdata,
145                 sd_bus_error *error) {
146
147         Timer *t = userdata;
148         usec_t x;
149
150         assert(bus);
151         assert(reply);
152         assert(t);
153
154         if (t->next_elapse_monotonic_or_boottime <= 0)
155                 x = 0;
156         else if (t->wake_system) {
157                 usec_t a, b;
158
159                 a = now(CLOCK_MONOTONIC);
160                 b = now(CLOCK_BOOTTIME);
161
162                 if (t->next_elapse_monotonic_or_boottime + a > b)
163                         x = t->next_elapse_monotonic_or_boottime + a - b;
164                 else
165                         x = 0;
166         } else
167                 x = t->next_elapse_monotonic_or_boottime;
168
169         return sd_bus_message_append(reply, "t", x);
170 }
171
172 const sd_bus_vtable bus_timer_vtable[] = {
173         SD_BUS_VTABLE_START(0),
174         SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
175         SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
176         SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
177         SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
178         SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
179         BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
180         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
181         SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
182         SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
183         SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
184         SD_BUS_VTABLE_END
185 };