chiark / gitweb /
treewide: simplify log_*_errno(r,...) immediately followed by "return r"
[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                 return log_error_errno(r, "Cannot request session control on '%s': %m",
146                                        sysview_session_get_name(session));
147
148         r = session_new(&s, m, session);
149         if (r < 0) {
150                 log_error_errno(r, "Cannot create session on '%s': %m",
151                                 sysview_session_get_name(session));
152                 sysview_session_release_control(session);
153                 return r;
154         }
155
156         sysview_session_set_userdata(session, s);
157
158         return 0;
159 }
160
161 static int manager_sysview_session_remove(Manager *m, sysview_event *event) {
162         sysview_session *session = event->session_remove.session;
163         Session *s;
164
165         s = sysview_session_get_userdata(session);
166         if (!s)
167                 return 0;
168
169         session_free(s);
170
171         return 0;
172 }
173
174 static int manager_sysview_session_attach(Manager *m, sysview_event *event) {
175         sysview_session *session = event->session_attach.session;
176         sysview_device *device = event->session_attach.device;
177         Session *s;
178
179         s = sysview_session_get_userdata(session);
180         if (!s)
181                 return 0;
182
183         session_add_device(s, device);
184
185         return 0;
186 }
187
188 static int manager_sysview_session_detach(Manager *m, sysview_event *event) {
189         sysview_session *session = event->session_detach.session;
190         sysview_device *device = event->session_detach.device;
191         Session *s;
192
193         s = sysview_session_get_userdata(session);
194         if (!s)
195                 return 0;
196
197         session_remove_device(s, device);
198
199         return 0;
200 }
201
202 static int manager_sysview_session_refresh(Manager *m, sysview_event *event) {
203         sysview_session *session = event->session_refresh.session;
204         sysview_device *device = event->session_refresh.device;
205         struct udev_device *ud = event->session_refresh.ud;
206         Session *s;
207
208         s = sysview_session_get_userdata(session);
209         if (!s)
210                 return 0;
211
212         session_refresh_device(s, device, ud);
213
214         return 0;
215 }
216
217 static int manager_sysview_session_control(Manager *m, sysview_event *event) {
218         sysview_session *session = event->session_control.session;
219         int error = event->session_control.error;
220         Session *s;
221
222         s = sysview_session_get_userdata(session);
223         if (!s)
224                 return 0;
225
226         if (error < 0) {
227                 log_error_errno(error, "Cannot take session control on '%s': %m",
228                                 sysview_session_get_name(session));
229                 session_free(s);
230                 sysview_session_set_userdata(session, NULL);
231                 return -error;
232         }
233
234         return 0;
235 }
236
237 static int manager_sysview_fn(sysview_context *sysview, void *userdata, sysview_event *event) {
238         Manager *m = userdata;
239         int r;
240
241         assert(m);
242
243         switch (event->type) {
244         case SYSVIEW_EVENT_SESSION_FILTER:
245                 r = manager_sysview_session_filter(m, event);
246                 break;
247         case SYSVIEW_EVENT_SESSION_ADD:
248                 r = manager_sysview_session_add(m, event);
249                 break;
250         case SYSVIEW_EVENT_SESSION_REMOVE:
251                 r = manager_sysview_session_remove(m, event);
252                 break;
253         case SYSVIEW_EVENT_SESSION_ATTACH:
254                 r = manager_sysview_session_attach(m, event);
255                 break;
256         case SYSVIEW_EVENT_SESSION_DETACH:
257                 r = manager_sysview_session_detach(m, event);
258                 break;
259         case SYSVIEW_EVENT_SESSION_REFRESH:
260                 r = manager_sysview_session_refresh(m, event);
261                 break;
262         case SYSVIEW_EVENT_SESSION_CONTROL:
263                 r = manager_sysview_session_control(m, event);
264                 break;
265         default:
266                 r = 0;
267                 break;
268         }
269
270         return r;
271 }
272
273 int manager_run(Manager *m) {
274         int r;
275
276         assert(m);
277
278         r = sysview_context_start(m->sysview, manager_sysview_fn, m);
279         if (r < 0)
280                 return r;
281
282         r = sd_event_loop(m->event);
283
284         sysview_context_stop(m->sysview);
285         return r;
286 }