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