chiark / gitweb /
manager: print warning on console before reboot
[elogind.git] / src / console / consoled-manager.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
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 <libudev.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "consoled.h"
27 #include "grdev.h"
28 #include "idev.h"
29 #include "log.h"
30 #include "sd-bus.h"
31 #include "sd-daemon.h"
32 #include "sd-event.h"
33 #include "sd-login.h"
34 #include "sysview.h"
35 #include "unifont.h"
36 #include "util.h"
37
38 int manager_new(Manager **out) {
39         _cleanup_(manager_freep) Manager *m = NULL;
40         int r;
41
42         assert(out);
43
44         m = new0(Manager, 1);
45         if (!m)
46                 return -ENOMEM;
47
48         r = sd_event_default(&m->event);
49         if (r < 0)
50                 return r;
51
52         r = sd_event_set_watchdog(m->event, true);
53         if (r < 0)
54                 return r;
55
56         r = sigprocmask_many(SIG_BLOCK, SIGTERM, SIGQUIT, SIGINT, SIGWINCH, SIGCHLD, -1);
57         if (r < 0)
58                 return r;
59
60         r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
61         if (r < 0)
62                 return r;
63
64         r = sd_event_add_signal(m->event, NULL, SIGQUIT, NULL, NULL);
65         if (r < 0)
66                 return r;
67
68         r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
69         if (r < 0)
70                 return r;
71
72         r = sd_bus_open_system(&m->sysbus);
73         if (r < 0)
74                 return r;
75
76         r = sd_bus_attach_event(m->sysbus, m->event, SD_EVENT_PRIORITY_NORMAL);
77         if (r < 0)
78                 return r;
79
80         r = unifont_new(&m->uf);
81         if (r < 0)
82                 return r;
83
84         r = sysview_context_new(&m->sysview,
85                                 SYSVIEW_CONTEXT_SCAN_LOGIND |
86                                 SYSVIEW_CONTEXT_SCAN_EVDEV |
87                                 SYSVIEW_CONTEXT_SCAN_DRM,
88                                 m->event,
89                                 m->sysbus,
90                                 NULL);
91         if (r < 0)
92                 return r;
93
94         r = grdev_context_new(&m->grdev, m->event, m->sysbus);
95         if (r < 0)
96                 return r;
97
98         r = idev_context_new(&m->idev, m->event, m->sysbus);
99         if (r < 0)
100                 return r;
101
102         *out = m;
103         m = NULL;
104         return 0;
105 }
106
107 Manager *manager_free(Manager *m) {
108         if (!m)
109                 return NULL;
110
111         assert(!m->workspace_list);
112
113         m->idev = idev_context_unref(m->idev);
114         m->grdev = grdev_context_unref(m->grdev);
115         m->sysview = sysview_context_free(m->sysview);
116         m->uf = unifont_unref(m->uf);
117         m->sysbus = sd_bus_unref(m->sysbus);
118         m->event = sd_event_unref(m->event);
119         free(m);
120
121         return NULL;
122 }
123
124 static int manager_sysview_session_filter(Manager *m, sysview_event *event) {
125         const char *sid = event->session_filter.id;
126         _cleanup_free_ char *desktop = NULL;
127         int r;
128
129         assert(sid);
130
131         r = sd_session_get_desktop(sid, &desktop);
132         if (r < 0)
133                 return 0;
134
135         return streq(desktop, "SYSTEMD-CONSOLE");
136 }
137
138 static int manager_sysview_session_add(Manager *m, sysview_event *event) {
139         sysview_session *session = event->session_add.session;
140         Session *s;
141         int r;
142
143         r = sysview_session_take_control(session);
144         if (r < 0) {
145                 log_error("Cannot request session control on '%s': %s",
146                           sysview_session_get_name(session), strerror(-r));
147                 return r;
148         }
149
150         r = session_new(&s, m, session);
151         if (r < 0) {
152                 log_error("Cannot create session on '%s': %s",
153                           sysview_session_get_name(session), strerror(-r));
154                 sysview_session_release_control(session);
155                 return r;
156         }
157
158         sysview_session_set_userdata(session, s);
159
160         return 0;
161 }
162
163 static int manager_sysview_session_remove(Manager *m, sysview_event *event) {
164         sysview_session *session = event->session_remove.session;
165         Session *s;
166
167         s = sysview_session_get_userdata(session);
168         if (!s)
169                 return 0;
170
171         session_free(s);
172
173         return 0;
174 }
175
176 static int manager_sysview_session_attach(Manager *m, sysview_event *event) {
177         sysview_session *session = event->session_attach.session;
178         sysview_device *device = event->session_attach.device;
179         Session *s;
180
181         s = sysview_session_get_userdata(session);
182         if (!s)
183                 return 0;
184
185         session_add_device(s, device);
186
187         return 0;
188 }
189
190 static int manager_sysview_session_detach(Manager *m, sysview_event *event) {
191         sysview_session *session = event->session_detach.session;
192         sysview_device *device = event->session_detach.device;
193         Session *s;
194
195         s = sysview_session_get_userdata(session);
196         if (!s)
197                 return 0;
198
199         session_remove_device(s, device);
200
201         return 0;
202 }
203
204 static int manager_sysview_session_refresh(Manager *m, sysview_event *event) {
205         sysview_session *session = event->session_refresh.session;
206         sysview_device *device = event->session_refresh.device;
207         struct udev_device *ud = event->session_refresh.ud;
208         Session *s;
209
210         s = sysview_session_get_userdata(session);
211         if (!s)
212                 return 0;
213
214         session_refresh_device(s, device, ud);
215
216         return 0;
217 }
218
219 static int manager_sysview_session_control(Manager *m, sysview_event *event) {
220         sysview_session *session = event->session_control.session;
221         int error = event->session_control.error;
222         Session *s;
223
224         s = sysview_session_get_userdata(session);
225         if (!s)
226                 return 0;
227
228         if (error < 0) {
229                 log_error("Cannot take session control on '%s': %s",
230                           sysview_session_get_name(session), strerror(-error));
231                 session_free(s);
232                 sysview_session_set_userdata(session, NULL);
233                 return -error;
234         }
235
236         return 0;
237 }
238
239 static int manager_sysview_fn(sysview_context *sysview, void *userdata, sysview_event *event) {
240         Manager *m = userdata;
241         int r;
242
243         assert(m);
244
245         switch (event->type) {
246         case SYSVIEW_EVENT_SESSION_FILTER:
247                 r = manager_sysview_session_filter(m, event);
248                 break;
249         case SYSVIEW_EVENT_SESSION_ADD:
250                 r = manager_sysview_session_add(m, event);
251                 break;
252         case SYSVIEW_EVENT_SESSION_REMOVE:
253                 r = manager_sysview_session_remove(m, event);
254                 break;
255         case SYSVIEW_EVENT_SESSION_ATTACH:
256                 r = manager_sysview_session_attach(m, event);
257                 break;
258         case SYSVIEW_EVENT_SESSION_DETACH:
259                 r = manager_sysview_session_detach(m, event);
260                 break;
261         case SYSVIEW_EVENT_SESSION_REFRESH:
262                 r = manager_sysview_session_refresh(m, event);
263                 break;
264         case SYSVIEW_EVENT_SESSION_CONTROL:
265                 r = manager_sysview_session_control(m, event);
266                 break;
267         default:
268                 r = 0;
269                 break;
270         }
271
272         return r;
273 }
274
275 int manager_run(Manager *m) {
276         int r;
277
278         assert(m);
279
280         r = sysview_context_start(m->sysview, manager_sysview_fn, m);
281         if (r < 0)
282                 return r;
283
284         r = sd_event_loop(m->event);
285
286         sysview_context_stop(m->sysview);
287         return r;
288 }