Merge lp:~ubuntu-branches/ubuntu/precise/plymouth/precise-201311300306 into lp:ubuntu/precise/plymouth
- Precise (12.04)
- precise-201311300306
- Merge into precise
Status: | Needs review |
---|---|
Proposed branch: | lp:~ubuntu-branches/ubuntu/precise/plymouth/precise-201311300306 |
Merge into: | lp:ubuntu/precise/plymouth |
Diff against target: |
8207 lines (+8060/-28) (has conflicts) 11 files modified
.pc.moved/tty1-after-boot.patch/src/main.c (+1/-7) .pc/applied-patches (+23/-0) .pc/debug-fixes.patch/src/main.c (+1992/-0) .pc/initramfsless-boot.patch/src/main.c (+2003/-0) .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src/main.c (+1986/-0) .pc/upstream-terminal-no-ISTRIP.patch/src/main.c (+1986/-0) debian/changelog (+13/-0) debian/patches/initramfsless-boot.patch (+54/-0) debian/patches/misc-changes.patch (+0/-14) debian/patches/series (+1/-0) src/main.c (+1/-7) Conflict adding files to .pc. Created directory. Conflict because .pc is not versioned, but has versioned children. Versioned directory. Conflict adding file .pc. Moved existing file to .pc.moved. Conflict adding files to .pc/debug-fixes.patch. Created directory. Conflict because .pc/debug-fixes.patch is not versioned, but has versioned children. Versioned directory. Conflict adding files to .pc/debug-fixes.patch/src. Created directory. Conflict because .pc/debug-fixes.patch/src is not versioned, but has versioned children. Versioned directory. Conflict adding files to .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch. Created directory. Conflict because .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch is not versioned, but has versioned children. Versioned directory. Conflict adding files to .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src. Created directory. Conflict because .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src is not versioned, but has versioned children. Versioned directory. Conflict adding files to .pc/upstream-terminal-no-ISTRIP.patch. Created directory. Conflict because .pc/upstream-terminal-no-ISTRIP.patch is not versioned, but has versioned children. Versioned directory. Conflict adding files to .pc/upstream-terminal-no-ISTRIP.patch/src. Created directory. Conflict because .pc/upstream-terminal-no-ISTRIP.patch/src is not versioned, but has versioned children. Versioned directory. |
To merge this branch: | bzr merge lp:~ubuntu-branches/ubuntu/precise/plymouth/precise-201311300306 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+197278@code.launchpad.net |
Commit message
Description of the change
The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/precise/plymouth reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/precise/plymouth/precise-201311300306. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.
If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https:/
(this is an automatically generated message)
Unmerged revisions
- 1425. By Steve Langasek
-
* debian/
patches/ initramfsless- boot.patch: clean up our failure path when
/dev/pts isn't available yet:
- don't free a buffer that we might use again later
- once we've created the session object, keep it around, instead of
freeing it again and leaving a dangling reference to it in the loop
exit handler list.
it's not clear if this was working before, but it definitely hits an
assert now. LP: #981314. - 1424. By Steve Langasek
-
split initramfsless boot support out into a separate patch
- 1423. By Colin Watson
-
releasing version 0.8.2-2ubuntu30
- 1422. By Colin Watson
-
merge lp:~jamesodhunt/ubuntu/precise/plymouth/bug-553745, with added quilt fixing
- 1421. By Colin Watson
-
add lots of .pc files to try to stop the importer thinking it needs to overwrite this branch
- 1420. By Steve Langasek
-
merge fix for bug #979824
- 1419. By Steve Langasek
-
releasing version 0.8.2-2ubuntu29
- 1418. By Steve Langasek
-
debian/
plymouth- theme-{ k,}ubuntu- text.{triggers, postinst} : regenerate
our theme when /etc/lsb-release changes. LP: #957380. - 1417. By Steve Langasek
-
debian/
patches/ tty1-after- boot.patch: Switch back to tty1 on exit if
started with vt.handoff. Closes LP: #913731. - 1416. By Steve Langasek
-
the new file is named ubuntu_logo.png, not ubuntu-logo.png.
Preview Diff
1 | === added directory '.pc' |
2 | === renamed directory '.pc' => '.pc.moved' |
3 | === modified file '.pc.moved/tty1-after-boot.patch/src/main.c' |
4 | --- .pc/tty1-after-boot.patch/src/main.c 2012-04-13 15:11:36 +0000 |
5 | +++ .pc.moved/tty1-after-boot.patch/src/main.c 2013-11-30 04:03:08 +0000 |
6 | @@ -1478,6 +1478,7 @@ |
7 | session = ply_terminal_session_new (NULL); |
8 | |
9 | ply_terminal_session_attach_to_event_loop (session, state->loop); |
10 | + state->session = session; |
11 | } |
12 | else |
13 | { |
14 | @@ -1492,12 +1493,6 @@ |
15 | (should_be_redirected? on_session_finished: NULL), |
16 | -1, state)) |
17 | { |
18 | - ply_save_errno (); |
19 | - ply_terminal_session_free (session); |
20 | - ply_buffer_free (state->boot_buffer); |
21 | - state->boot_buffer = NULL; |
22 | - ply_restore_errno (); |
23 | - |
24 | state->is_redirected = false; |
25 | state->is_attached = false; |
26 | return false; |
27 | @@ -1505,7 +1500,6 @@ |
28 | |
29 | state->is_redirected = should_be_redirected; |
30 | state->is_attached = true; |
31 | - state->session = session; |
32 | |
33 | return true; |
34 | } |
35 | |
36 | === added file '.pc/applied-patches' |
37 | --- .pc/applied-patches 1970-01-01 00:00:00 +0000 |
38 | +++ .pc/applied-patches 2013-11-30 04:03:08 +0000 |
39 | @@ -0,0 +1,23 @@ |
40 | +ubuntu_details.patch |
41 | +details_removeSeparator.patch |
42 | +misc-changes.patch |
43 | +initramfsless-boot.patch |
44 | +vga16fb-renderer.patch |
45 | +lbm-nouveau.patch |
46 | +nouveau-framebuffer.patch |
47 | +ubuntu-logo.patch |
48 | +ubuntu-text.patch |
49 | +kubuntu-text.patch |
50 | +gcc45-arith-workaround.patch |
51 | +debug-fixes.patch |
52 | +upstart-bridge.patch |
53 | +avoid-sigpipe.patch |
54 | +upstream-event-loop-reference.patch |
55 | +upstream-event-loop-number.patch |
56 | +upstream-terminal-force-newline.patch |
57 | +upstream-terminal-OPOST.patch |
58 | +upstream-terminal-no-ISTRIP.patch |
59 | +main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch |
60 | +tty1-after-boot.patch |
61 | +invalid-event-source-workaround.patch |
62 | +autoreconf.patch |
63 | |
64 | === added directory '.pc/debug-fixes.patch' |
65 | === added directory '.pc/debug-fixes.patch/src' |
66 | === added file '.pc/debug-fixes.patch/src/main.c' |
67 | --- .pc/debug-fixes.patch/src/main.c 1970-01-01 00:00:00 +0000 |
68 | +++ .pc/debug-fixes.patch/src/main.c 2013-11-30 04:03:08 +0000 |
69 | @@ -0,0 +1,1992 @@ |
70 | +/* main.c - boot messages monitor |
71 | + * |
72 | + * Copyright (C) 2007 Red Hat, Inc |
73 | + * |
74 | + * This file is free software; you can redistribute it and/or modify |
75 | + * it under the terms of the GNU General Public License as published |
76 | + * by the Free Software Foundation; either version 2 of the License, |
77 | + * or (at your option) any later version. |
78 | + * |
79 | + * This file is distributed in the hope that it will be useful, but |
80 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
81 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
82 | + * General Public License for more details. |
83 | + * |
84 | + * You should have received a copy of the GNU General Public License |
85 | + * along with this; see the file COPYING. If not, write to the Free |
86 | + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
87 | + * 02111-1307, USA. |
88 | + * |
89 | + * Written by: Ray Strode <rstrode@redhat.com> |
90 | + */ |
91 | +#include "config.h" |
92 | + |
93 | +#include <sys/stat.h> |
94 | +#include <sys/types.h> |
95 | +#include <limits.h> |
96 | +#include <dirent.h> |
97 | +#include <fcntl.h> |
98 | +#include <stdlib.h> |
99 | +#include <stdio.h> |
100 | +#include <sysexits.h> |
101 | +#include <sys/ioctl.h> |
102 | +#include <unistd.h> |
103 | +#include <wchar.h> |
104 | +#include <paths.h> |
105 | +#include <assert.h> |
106 | + |
107 | +#include <linux/kd.h> |
108 | +#include <linux/vt.h> |
109 | + |
110 | +#include "ply-buffer.h" |
111 | +#include "ply-command-parser.h" |
112 | +#include "ply-boot-server.h" |
113 | +#include "ply-boot-splash.h" |
114 | +#include "ply-event-loop.h" |
115 | +#include "ply-list.h" |
116 | +#include "ply-logger.h" |
117 | +#include "ply-terminal-session.h" |
118 | +#include "ply-trigger.h" |
119 | +#include "ply-utils.h" |
120 | +#include "ply-progress.h" |
121 | + |
122 | +#ifndef PLY_MAX_COMMAND_LINE_SIZE |
123 | +#define PLY_MAX_COMMAND_LINE_SIZE 512 |
124 | +#endif |
125 | + |
126 | +#define BOOT_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/boot-duration" |
127 | +#define SHUTDOWN_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/shutdown-duration" |
128 | + |
129 | +typedef enum { |
130 | + PLY_MODE_BOOT, |
131 | + PLY_MODE_SHUTDOWN |
132 | +} ply_mode_t; |
133 | + |
134 | +typedef struct |
135 | +{ |
136 | + const char *keys; |
137 | + ply_trigger_t *trigger; |
138 | +} ply_keystroke_watch_t; |
139 | + |
140 | +typedef struct |
141 | +{ |
142 | + enum {PLY_ENTRY_TRIGGER_TYPE_PASSWORD, |
143 | + PLY_ENTRY_TRIGGER_TYPE_QUESTION} |
144 | + type; |
145 | + const char *prompt; |
146 | + ply_trigger_t *trigger; |
147 | +} ply_entry_trigger_t; |
148 | + |
149 | +typedef struct |
150 | +{ |
151 | + ply_event_loop_t *loop; |
152 | + ply_boot_server_t *boot_server; |
153 | + ply_list_t *pixel_displays; |
154 | + ply_list_t *text_displays; |
155 | + ply_keyboard_t *keyboard; |
156 | + ply_boot_splash_t *boot_splash; |
157 | + ply_terminal_session_t *session; |
158 | + ply_buffer_t *boot_buffer; |
159 | + ply_progress_t *progress; |
160 | + ply_list_t *keystroke_triggers; |
161 | + ply_list_t *entry_triggers; |
162 | + ply_buffer_t *entry_buffer; |
163 | + ply_command_parser_t *command_parser; |
164 | + ply_mode_t mode; |
165 | + ply_renderer_t *renderer; |
166 | + ply_terminal_t *terminal; |
167 | + |
168 | + ply_trigger_t *deactivate_trigger; |
169 | + ply_trigger_t *quit_trigger; |
170 | + |
171 | + char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; |
172 | + uint32_t no_boot_log : 1; |
173 | + uint32_t showing_details : 1; |
174 | + uint32_t system_initialized : 1; |
175 | + uint32_t is_redirected : 1; |
176 | + uint32_t is_attached : 1; |
177 | + uint32_t should_be_attached : 1; |
178 | + uint32_t should_retain_splash : 1; |
179 | + uint32_t is_inactive : 1; |
180 | + |
181 | + char *kernel_console_tty; |
182 | + char *override_splash_path; |
183 | + char *system_default_splash_path; |
184 | + char *distribution_default_splash_path; |
185 | + const char *default_tty; |
186 | + |
187 | + int number_of_errors; |
188 | + ply_list_t *pending_messages; |
189 | +} state_t; |
190 | + |
191 | +static ply_boot_splash_t *start_boot_splash (state_t *state, |
192 | + const char *theme_path); |
193 | + |
194 | +static void add_display_and_keyboard_for_terminal (state_t *state, |
195 | + const char *tty_name); |
196 | + |
197 | +static void add_default_displays_and_keyboard (state_t *state); |
198 | + |
199 | +static bool attach_to_running_session (state_t *state); |
200 | +static void on_escape_pressed (state_t *state); |
201 | +static void dump_details_and_quit_splash (state_t *state); |
202 | +static void update_display (state_t *state); |
203 | + |
204 | +static void on_error_message (ply_buffer_t *debug_buffer, |
205 | + const void *bytes, |
206 | + size_t number_of_bytes); |
207 | +static ply_buffer_t *debug_buffer; |
208 | +static char *debug_buffer_path = NULL; |
209 | +static char *pid_file = NULL; |
210 | +static void check_for_consoles (state_t *state, |
211 | + const char *default_tty, |
212 | + bool should_add_displays); |
213 | +static void toggle_between_splash_and_details (state_t *state); |
214 | + |
215 | +static void |
216 | +on_session_output (state_t *state, |
217 | + const char *output, |
218 | + size_t size) |
219 | +{ |
220 | + ply_buffer_append_bytes (state->boot_buffer, output, size); |
221 | + if (state->boot_splash != NULL) |
222 | + ply_boot_splash_update_output (state->boot_splash, |
223 | + output, size); |
224 | +} |
225 | + |
226 | +static void |
227 | +on_session_finished (state_t *state) |
228 | +{ |
229 | + ply_trace ("got hang up on terminal session fd"); |
230 | +} |
231 | + |
232 | +static void |
233 | +on_update (state_t *state, |
234 | + const char *status) |
235 | +{ |
236 | + ply_trace ("updating status to '%s'", status); |
237 | + if (strncmp (status, "fsck:", 5)) |
238 | + ply_progress_status_update (state->progress, |
239 | + status); |
240 | + if (state->boot_splash != NULL) |
241 | + ply_boot_splash_update_status (state->boot_splash, |
242 | + status); |
243 | +} |
244 | + |
245 | +static void |
246 | +flush_pending_messages (state_t *state) |
247 | +{ |
248 | + ply_list_node_t *node = ply_list_get_first_node (state->pending_messages); |
249 | + while (node != NULL) |
250 | + { |
251 | + ply_list_node_t *next_node; |
252 | + char *message = ply_list_node_get_data (node); |
253 | + |
254 | + ply_trace ("displaying queued message"); |
255 | + |
256 | + ply_boot_splash_display_message (state->boot_splash, message); |
257 | + next_node = ply_list_get_next_node (state->pending_messages, node); |
258 | + ply_list_remove_node (state->pending_messages, node); |
259 | + free(message); |
260 | + node = next_node; |
261 | + } |
262 | +} |
263 | + |
264 | +static void |
265 | +show_detailed_splash (state_t *state) |
266 | +{ |
267 | + if (state->boot_splash != NULL) |
268 | + return; |
269 | + |
270 | + ply_trace ("Showing detailed splash screen"); |
271 | + state->boot_splash = start_boot_splash (state, |
272 | + PLYMOUTH_THEME_PATH "details/details.plymouth"); |
273 | + |
274 | + if (state->boot_splash == NULL) |
275 | + { |
276 | + ply_trace ("Could not start detailed splash screen, exiting"); |
277 | + exit (1); |
278 | + } |
279 | +} |
280 | + |
281 | +static void |
282 | +find_override_splash (state_t *state) |
283 | +{ |
284 | + char *splash_string; |
285 | + |
286 | + if (state->override_splash_path != NULL) |
287 | + return; |
288 | + |
289 | + splash_string = strstr (state->kernel_command_line, "plymouth:splash="); |
290 | + |
291 | + if (splash_string != NULL) |
292 | + { |
293 | + char *end; |
294 | + splash_string = strdup (splash_string + strlen ("plymouth:splash=")); |
295 | + |
296 | + end = strstr (splash_string, " "); |
297 | + |
298 | + if (end != NULL) |
299 | + *end = '\0'; |
300 | + |
301 | + ply_trace ("Splash is configured to be '%s'", splash_string); |
302 | + |
303 | + asprintf (&state->override_splash_path, |
304 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
305 | + splash_string, splash_string); |
306 | + } |
307 | +} |
308 | + |
309 | +static void |
310 | +find_system_default_splash (state_t *state) |
311 | +{ |
312 | + ply_key_file_t *key_file; |
313 | + char *splash_string; |
314 | + |
315 | + if (state->system_default_splash_path != NULL) |
316 | + return; |
317 | + |
318 | + ply_trace ("Trying to load " PLYMOUTH_CONF_DIR "plymouthd.conf"); |
319 | + key_file = ply_key_file_new (PLYMOUTH_CONF_DIR "plymouthd.conf"); |
320 | + |
321 | + if (!ply_key_file_load (key_file)) |
322 | + { |
323 | + ply_trace ("failed to load " PLYMOUTH_CONF_DIR "plymouthd.conf"); |
324 | + ply_key_file_free (key_file); |
325 | + return; |
326 | + } |
327 | + |
328 | + splash_string = ply_key_file_get_value (key_file, "Daemon", "Theme"); |
329 | + |
330 | + ply_trace ("System default splash is configured to be '%s'", splash_string); |
331 | + |
332 | + asprintf (&state->system_default_splash_path, |
333 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
334 | + splash_string, splash_string); |
335 | + free (splash_string); |
336 | +} |
337 | + |
338 | +static void |
339 | +find_distribution_default_splash (state_t *state) |
340 | +{ |
341 | + ply_key_file_t *key_file; |
342 | + char *splash_string; |
343 | + |
344 | + if (state->distribution_default_splash_path != NULL) |
345 | + return; |
346 | + |
347 | + ply_trace ("Trying to load " PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
348 | + key_file = ply_key_file_new (PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
349 | + |
350 | + if (!ply_key_file_load (key_file)) |
351 | + { |
352 | + ply_trace ("failed to load " PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
353 | + ply_key_file_free (key_file); |
354 | + return; |
355 | + } |
356 | + |
357 | + splash_string = ply_key_file_get_value (key_file, "Daemon", "Theme"); |
358 | + |
359 | + ply_trace ("Distribution default splash is configured to be '%s'", splash_string); |
360 | + |
361 | + asprintf (&state->distribution_default_splash_path, |
362 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
363 | + splash_string, splash_string); |
364 | + free (splash_string); |
365 | +} |
366 | + |
367 | +static void |
368 | +show_default_splash (state_t *state) |
369 | +{ |
370 | + if (state->boot_splash != NULL) |
371 | + return; |
372 | + |
373 | + ply_trace ("Showing splash screen"); |
374 | + find_override_splash (state); |
375 | + if (state->override_splash_path != NULL) |
376 | + { |
377 | + ply_trace ("Trying override splash at '%s'", state->override_splash_path); |
378 | + state->boot_splash = start_boot_splash (state, |
379 | + state->override_splash_path); |
380 | + } |
381 | + |
382 | + find_system_default_splash (state); |
383 | + if (state->boot_splash == NULL && |
384 | + state->system_default_splash_path != NULL) |
385 | + { |
386 | + ply_trace ("Trying system default splash"); |
387 | + state->boot_splash = start_boot_splash (state, |
388 | + state->system_default_splash_path); |
389 | + } |
390 | + |
391 | + find_distribution_default_splash (state); |
392 | + if (state->boot_splash == NULL && |
393 | + state->distribution_default_splash_path != NULL) |
394 | + { |
395 | + ply_trace ("Trying distribution default splash"); |
396 | + state->boot_splash = start_boot_splash (state, |
397 | + state->distribution_default_splash_path); |
398 | + } |
399 | + |
400 | + if (state->boot_splash == NULL) |
401 | + { |
402 | + ply_trace ("Trying old scheme for default splash"); |
403 | + state->boot_splash = start_boot_splash (state, |
404 | + PLYMOUTH_THEME_PATH "default.plymouth"); |
405 | + } |
406 | + |
407 | + if (state->boot_splash == NULL) |
408 | + { |
409 | + ply_trace ("Could not start default splash screen," |
410 | + "showing text splash screen"); |
411 | + state->boot_splash = start_boot_splash (state, |
412 | + PLYMOUTH_THEME_PATH "text.plymouth"); |
413 | + } |
414 | + |
415 | + if (state->boot_splash == NULL) |
416 | + { |
417 | + if (errno != ENOENT) |
418 | + ply_error ("could not start boot splash: %m"); |
419 | + show_detailed_splash (state); |
420 | + } |
421 | +} |
422 | + |
423 | +static void |
424 | +on_ask_for_password (state_t *state, |
425 | + const char *prompt, |
426 | + ply_trigger_t *answer) |
427 | +{ |
428 | + ply_entry_trigger_t *entry_trigger; |
429 | + |
430 | + /* No splash, client will have to get password |
431 | + */ |
432 | + if (state->boot_splash == NULL) |
433 | + { |
434 | + ply_trace ("no splash loaded, replying immediately with no password"); |
435 | + ply_trigger_pull (answer, NULL); |
436 | + return; |
437 | + } |
438 | + |
439 | + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); |
440 | + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_PASSWORD; |
441 | + entry_trigger->prompt = prompt; |
442 | + entry_trigger->trigger = answer; |
443 | + ply_trace ("queuing password request with boot splash"); |
444 | + ply_list_append_data (state->entry_triggers, entry_trigger); |
445 | + update_display (state); |
446 | +} |
447 | + |
448 | +static void |
449 | +on_ask_question (state_t *state, |
450 | + const char *prompt, |
451 | + ply_trigger_t *answer) |
452 | +{ |
453 | + ply_entry_trigger_t *entry_trigger; |
454 | + |
455 | + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); |
456 | + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_QUESTION; |
457 | + entry_trigger->prompt = prompt; |
458 | + entry_trigger->trigger = answer; |
459 | + ply_trace ("queuing question with boot splash"); |
460 | + ply_list_append_data (state->entry_triggers, entry_trigger); |
461 | + update_display (state); |
462 | +} |
463 | + |
464 | +static void |
465 | +on_display_message (state_t *state, |
466 | + const char *message) |
467 | +{ |
468 | + ply_trace ("displaying message %s", message); |
469 | + if (state->boot_splash != NULL) |
470 | + ply_boot_splash_display_message (state->boot_splash, message); |
471 | + else |
472 | + ply_list_append_data (state->pending_messages, strdup(message)); |
473 | +} |
474 | + |
475 | +static void |
476 | +on_watch_for_keystroke (state_t *state, |
477 | + const char *keys, |
478 | + ply_trigger_t *trigger) |
479 | +{ |
480 | + ply_keystroke_watch_t *keystroke_trigger = |
481 | + calloc (1, sizeof (ply_keystroke_watch_t)); |
482 | + ply_trace ("watching for keystroke"); |
483 | + keystroke_trigger->keys = keys; |
484 | + keystroke_trigger->trigger = trigger; |
485 | + ply_list_append_data (state->keystroke_triggers, keystroke_trigger); |
486 | +} |
487 | + |
488 | +static void |
489 | +on_ignore_keystroke (state_t *state, |
490 | + const char *keys) |
491 | +{ |
492 | + ply_list_node_t *node; |
493 | + |
494 | + ply_trace ("ignoring for keystroke"); |
495 | + |
496 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
497 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
498 | + { |
499 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
500 | + if ((!keystroke_trigger->keys && !keys) || |
501 | + (keystroke_trigger->keys && keys && strcmp(keystroke_trigger->keys, keys)==0)) |
502 | + { |
503 | + ply_trigger_pull (keystroke_trigger->trigger, NULL); |
504 | + ply_list_remove_node (state->keystroke_triggers, node); |
505 | + return; |
506 | + } |
507 | + } |
508 | +} |
509 | + |
510 | +static void |
511 | +on_progress_pause (state_t *state) |
512 | +{ |
513 | + ply_trace ("pausing progress"); |
514 | + ply_progress_pause (state->progress); |
515 | +} |
516 | + |
517 | +static void |
518 | +on_progress_unpause (state_t *state) |
519 | +{ |
520 | + ply_trace ("unpausing progress"); |
521 | + ply_progress_unpause (state->progress); |
522 | +} |
523 | + |
524 | +static void |
525 | +on_newroot (state_t *state, |
526 | + const char *root_dir) |
527 | +{ |
528 | + if (state->mode != PLY_MODE_BOOT) |
529 | + { |
530 | + ply_trace ("new root is only supported in boot mode "); |
531 | + return; |
532 | + } |
533 | + |
534 | + ply_trace ("new root mounted at \"%s\", switching to it", root_dir); |
535 | + chdir(root_dir); |
536 | + chroot("."); |
537 | + chdir("/"); |
538 | + ply_progress_load_cache (state->progress, BOOT_DURATION_FILE); |
539 | + if (state->boot_splash != NULL) |
540 | + ply_boot_splash_root_mounted (state->boot_splash); |
541 | +} |
542 | + |
543 | +static const char * |
544 | +get_cache_file_for_mode (ply_mode_t mode) |
545 | +{ |
546 | + const char *filename; |
547 | + |
548 | + switch ((int)mode) |
549 | + { |
550 | + case PLY_MODE_BOOT: |
551 | + filename = BOOT_DURATION_FILE; |
552 | + break; |
553 | + case PLY_MODE_SHUTDOWN: |
554 | + filename = SHUTDOWN_DURATION_FILE; |
555 | + break; |
556 | + default: |
557 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
558 | + abort (); |
559 | + break; |
560 | + } |
561 | + |
562 | + ply_trace ("returning cache file '%s'", filename); |
563 | + return filename; |
564 | +} |
565 | + |
566 | +static const char * |
567 | +get_log_file_for_mode (ply_mode_t mode) |
568 | +{ |
569 | + const char *filename; |
570 | + |
571 | + switch ((int)mode) |
572 | + { |
573 | + case PLY_MODE_BOOT: |
574 | + filename = PLYMOUTH_LOG_DIRECTORY "/boot.log"; |
575 | + break; |
576 | + case PLY_MODE_SHUTDOWN: |
577 | + filename = _PATH_DEVNULL; |
578 | + break; |
579 | + default: |
580 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
581 | + abort (); |
582 | + break; |
583 | + } |
584 | + |
585 | + ply_trace ("returning log file '%s'", filename); |
586 | + return filename; |
587 | +} |
588 | + |
589 | +static const char * |
590 | +get_log_spool_file_for_mode (ply_mode_t mode) |
591 | +{ |
592 | + const char *filename; |
593 | + |
594 | + switch ((int)mode) |
595 | + { |
596 | + case PLY_MODE_BOOT: |
597 | + filename = PLYMOUTH_SPOOL_DIRECTORY "/boot.log"; |
598 | + break; |
599 | + case PLY_MODE_SHUTDOWN: |
600 | + filename = NULL; |
601 | + break; |
602 | + default: |
603 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
604 | + abort (); |
605 | + break; |
606 | + } |
607 | + |
608 | + ply_trace ("returning spool file '%s'", filename); |
609 | + return filename; |
610 | +} |
611 | + |
612 | +static void |
613 | +spool_error (state_t *state) |
614 | +{ |
615 | + const char *logfile; |
616 | + const char *logspool; |
617 | + |
618 | + ply_trace ("spooling error for viewer"); |
619 | + |
620 | + logfile = get_log_file_for_mode (state->mode); |
621 | + logspool = get_log_spool_file_for_mode (state->mode); |
622 | + |
623 | + if (logfile != NULL && logspool != NULL) |
624 | + { |
625 | + unlink (logspool); |
626 | + |
627 | + ply_create_file_link (logfile, logspool); |
628 | + } |
629 | +} |
630 | + |
631 | +static void |
632 | +prepare_logging (state_t *state) |
633 | +{ |
634 | + const char *logfile; |
635 | + |
636 | + if (!state->system_initialized) |
637 | + { |
638 | + ply_trace ("not preparing logging yet, system not initialized"); |
639 | + return; |
640 | + } |
641 | + |
642 | + if (state->session == NULL) |
643 | + { |
644 | + ply_trace ("not preparing logging, no session"); |
645 | + return; |
646 | + } |
647 | + |
648 | + logfile = get_log_file_for_mode (state->mode); |
649 | + if (logfile != NULL) |
650 | + { |
651 | + ply_trace ("opening log '%s'", logfile); |
652 | + ply_terminal_session_open_log (state->session, logfile); |
653 | + |
654 | + if (state->number_of_errors > 0) |
655 | + spool_error (state); |
656 | + } |
657 | +} |
658 | + |
659 | +static void |
660 | +on_system_initialized (state_t *state) |
661 | +{ |
662 | + ply_trace ("system now initialized, opening log"); |
663 | + state->system_initialized = true; |
664 | + |
665 | + prepare_logging (state); |
666 | +} |
667 | + |
668 | +static void |
669 | +on_error (state_t *state) |
670 | +{ |
671 | + ply_trace ("encountered error during boot up"); |
672 | + |
673 | + if (state->system_initialized && state->number_of_errors == 0) |
674 | + spool_error (state); |
675 | + else |
676 | + ply_trace ("not spooling because number of errors %d", state->number_of_errors); |
677 | + |
678 | + state->number_of_errors++; |
679 | +} |
680 | + |
681 | +static bool |
682 | +plymouth_should_ignore_show_splash_calls (state_t *state) |
683 | +{ |
684 | + ply_trace ("checking if plymouth should be running"); |
685 | + if (state->mode != PLY_MODE_BOOT || ply_string_has_prefix (state->kernel_command_line, "plymouth:force-splash") || strstr (state->kernel_command_line, " plymouth:force-splash") != NULL) |
686 | + return false; |
687 | + |
688 | + return ply_string_has_prefix (state->kernel_command_line, "init=") || strstr (state->kernel_command_line, " init=") != NULL; |
689 | +} |
690 | + |
691 | +static bool |
692 | +plymouth_should_show_default_splash (state_t *state) |
693 | +{ |
694 | + ply_trace ("checking if plymouth should show default splash"); |
695 | + |
696 | + const char const *strings[] = { |
697 | + " single ", " single\n", "^single ", |
698 | + " 1 ", " 1\n", "^1 ", |
699 | + " s ", " s\n", "^s ", |
700 | + " S ", " S\n", "^S ", |
701 | + " -s ", " -s\n", "^-s ", |
702 | + NULL |
703 | + }; |
704 | + int i; |
705 | + |
706 | + if (state->kernel_console_tty != NULL) |
707 | + return false; |
708 | + |
709 | + for (i = 0; strings[i] != NULL; i++) |
710 | + { |
711 | + int cmp; |
712 | + if (strings[i][0] == '^') |
713 | + cmp = strncmp(state->kernel_command_line, strings[i]+1, |
714 | + strlen(strings[i]+1)) == 0; |
715 | + else |
716 | + cmp = strstr (state->kernel_command_line, strings[i]) != NULL; |
717 | + |
718 | + if (cmp) |
719 | + { |
720 | + ply_trace ("kernel command line has option \"%s\"", strings[i]); |
721 | + return false; |
722 | + } |
723 | + } |
724 | + |
725 | + return strstr (state->kernel_command_line, "rhgb") != NULL || (strstr (state->kernel_command_line, "splash") != NULL && strstr(state->kernel_command_line, "splash=verbose") == NULL); |
726 | +} |
727 | + |
728 | +static void |
729 | +remove_displays_and_keyboard (state_t *state) |
730 | +{ |
731 | + ply_list_node_t *node; |
732 | + ply_trace ("removing displays and keyboard"); |
733 | + |
734 | + node = ply_list_get_first_node (state->pixel_displays); |
735 | + while (node != NULL) |
736 | + { |
737 | + ply_list_node_t *next_node; |
738 | + ply_pixel_display_t *display; |
739 | + |
740 | + ply_trace ("removing pixel display"); |
741 | + next_node = ply_list_get_next_node (state->pixel_displays, node); |
742 | + display = ply_list_node_get_data (node); |
743 | + ply_pixel_display_free (display); |
744 | + |
745 | + ply_list_remove_node (state->pixel_displays, node); |
746 | + |
747 | + node = next_node; |
748 | + } |
749 | + |
750 | + node = ply_list_get_first_node (state->text_displays); |
751 | + while (node != NULL) |
752 | + { |
753 | + ply_list_node_t *next_node; |
754 | + ply_text_display_t *display; |
755 | + |
756 | + ply_trace ("removing text display"); |
757 | + next_node = ply_list_get_next_node (state->text_displays, node); |
758 | + display = ply_list_node_get_data (node); |
759 | + ply_text_display_free (display); |
760 | + |
761 | + ply_list_remove_node (state->text_displays, node); |
762 | + |
763 | + node = next_node; |
764 | + } |
765 | + |
766 | + if (state->keyboard != NULL) |
767 | + { |
768 | + ply_trace ("removing keyboard"); |
769 | + ply_keyboard_stop_watching_for_input (state->keyboard); |
770 | + ply_keyboard_free (state->keyboard); |
771 | + state->keyboard = NULL; |
772 | + } |
773 | +} |
774 | + |
775 | +static void |
776 | +on_show_splash (state_t *state) |
777 | +{ |
778 | + bool has_display; |
779 | + |
780 | + if (state->is_inactive) |
781 | + { |
782 | + ply_trace ("show splash called while inactive"); |
783 | + return; |
784 | + } |
785 | + |
786 | + if (plymouth_should_ignore_show_splash_calls (state)) |
787 | + { |
788 | + ply_trace ("show splash called while ignoring show splash calls"); |
789 | + dump_details_and_quit_splash (state); |
790 | + return; |
791 | + } |
792 | + |
793 | + check_for_consoles (state, state->default_tty, true); |
794 | + |
795 | + has_display = ply_list_get_length (state->pixel_displays) > 0 || |
796 | + ply_list_get_length (state->text_displays) > 0; |
797 | + |
798 | + if (!state->is_attached && state->should_be_attached && has_display) |
799 | + attach_to_running_session (state); |
800 | + |
801 | + if (!has_display && state->is_attached) |
802 | + { |
803 | + ply_trace ("no open seats, detaching session"); |
804 | + ply_terminal_session_detach (state->session); |
805 | + state->is_redirected = false; |
806 | + state->is_attached = false; |
807 | + } |
808 | + |
809 | + if (plymouth_should_show_default_splash (state)) |
810 | + { |
811 | + show_default_splash (state); |
812 | + state->showing_details = false; |
813 | + } |
814 | + else |
815 | + { |
816 | + show_detailed_splash (state); |
817 | + state->showing_details = true; |
818 | + } |
819 | + flush_pending_messages (state); |
820 | +} |
821 | + |
822 | +static void |
823 | +quit_splash (state_t *state) |
824 | +{ |
825 | + ply_trace ("quiting splash"); |
826 | + if (state->boot_splash != NULL) |
827 | + { |
828 | + ply_trace ("freeing splash"); |
829 | + ply_boot_splash_free (state->boot_splash); |
830 | + state->boot_splash = NULL; |
831 | + } |
832 | + |
833 | + ply_trace ("removing displays and keyboard"); |
834 | + remove_displays_and_keyboard (state); |
835 | + |
836 | + if (state->renderer != NULL) |
837 | + { |
838 | + ply_renderer_close (state->renderer); |
839 | + ply_renderer_free (state->renderer); |
840 | + state->renderer = NULL; |
841 | + } |
842 | + |
843 | + if (state->terminal != NULL) |
844 | + { |
845 | + if (!state->should_retain_splash) |
846 | + { |
847 | + ply_trace ("Not retaining splash, so deallocating VT"); |
848 | + ply_terminal_deactivate_vt (state->terminal); |
849 | + } |
850 | + ply_terminal_close (state->terminal); |
851 | + ply_terminal_free (state->terminal); |
852 | + state->terminal = NULL; |
853 | + } |
854 | + |
855 | + if (state->session != NULL) |
856 | + { |
857 | + ply_trace ("detaching session"); |
858 | + ply_terminal_session_detach (state->session); |
859 | + state->is_redirected = false; |
860 | + state->is_attached = false; |
861 | + } |
862 | +} |
863 | + |
864 | +static void |
865 | +dump_details_and_quit_splash (state_t *state) |
866 | +{ |
867 | + state->showing_details = false; |
868 | + toggle_between_splash_and_details (state); |
869 | + |
870 | + if (state->renderer != NULL) |
871 | + ply_renderer_deactivate (state->renderer); |
872 | + if (state->boot_splash != NULL) |
873 | + ply_boot_splash_hide (state->boot_splash); |
874 | + |
875 | + quit_splash (state); |
876 | +} |
877 | + |
878 | +static void |
879 | +on_hide_splash (state_t *state) |
880 | +{ |
881 | + if (state->is_inactive) |
882 | + return; |
883 | + |
884 | + if (state->boot_splash == NULL) |
885 | + return; |
886 | + |
887 | + ply_trace ("hiding boot splash"); |
888 | + dump_details_and_quit_splash (state); |
889 | +} |
890 | + |
891 | +#ifdef PLY_ENABLE_GDM_TRANSITION |
892 | +static void |
893 | +tell_gdm_to_transition (void) |
894 | +{ |
895 | + int fd; |
896 | + |
897 | + fd = creat ("/var/spool/gdm/force-display-on-active-vt", 0644); |
898 | + close (fd); |
899 | +} |
900 | +#endif |
901 | + |
902 | +static void |
903 | +quit_program (state_t *state) |
904 | +{ |
905 | + ply_trace ("exiting event loop"); |
906 | + ply_event_loop_exit (state->loop, 0); |
907 | + |
908 | + if (pid_file != NULL) |
909 | + { |
910 | + unlink (pid_file); |
911 | + free (pid_file); |
912 | + pid_file = NULL; |
913 | + } |
914 | + |
915 | +#ifdef PLY_ENABLE_GDM_TRANSITION |
916 | + if (state->should_retain_splash) |
917 | + { |
918 | + tell_gdm_to_transition (); |
919 | + } |
920 | +#endif |
921 | + |
922 | + if (state->deactivate_trigger != NULL) |
923 | + { |
924 | + ply_trigger_pull (state->deactivate_trigger, NULL); |
925 | + state->deactivate_trigger = NULL; |
926 | + } |
927 | + if (state->quit_trigger != NULL) |
928 | + { |
929 | + ply_trigger_pull (state->quit_trigger, NULL); |
930 | + state->quit_trigger = NULL; |
931 | + } |
932 | +} |
933 | + |
934 | +static void |
935 | +deactivate_splash (state_t *state) |
936 | +{ |
937 | + assert (!state->is_inactive); |
938 | + |
939 | + if (state->renderer != NULL) |
940 | + { |
941 | + ply_trace ("deactivating renderer"); |
942 | + ply_renderer_deactivate (state->renderer); |
943 | + } |
944 | + |
945 | + if (state->keyboard != NULL) |
946 | + { |
947 | + ply_trace ("deactivating keyboard"); |
948 | + ply_keyboard_stop_watching_for_input (state->keyboard); |
949 | + } |
950 | + |
951 | + if ((state->session != NULL) && state->is_attached) |
952 | + { |
953 | + ply_trace ("deactivating terminal session"); |
954 | + ply_terminal_session_detach (state->session); |
955 | + state->is_redirected = false; |
956 | + state->is_attached = false; |
957 | + } |
958 | + |
959 | + if (state->terminal != NULL) |
960 | + { |
961 | + ply_trace ("deactivating terminal"); |
962 | + ply_terminal_stop_watching_for_vt_changes (state->terminal); |
963 | + ply_terminal_set_buffered_input (state->terminal); |
964 | + ply_terminal_ignore_mode_changes (state->terminal, true); |
965 | + } |
966 | + |
967 | + state->is_inactive = true; |
968 | + |
969 | + ply_trigger_pull (state->deactivate_trigger, NULL); |
970 | + state->deactivate_trigger = NULL; |
971 | +} |
972 | + |
973 | +static void |
974 | +on_boot_splash_idle (state_t *state) |
975 | +{ |
976 | + ply_trace ("boot splash idle"); |
977 | + |
978 | + /* In the case where we've received both a deactivate command and a |
979 | + * quit command, the quit command takes precedence. |
980 | + */ |
981 | + if (state->quit_trigger != NULL) |
982 | + { |
983 | + if (!state->should_retain_splash) |
984 | + { |
985 | + ply_trace ("hiding splash"); |
986 | + if (state->renderer != NULL) |
987 | + ply_renderer_deactivate (state->renderer); |
988 | + if (state->boot_splash != NULL) |
989 | + ply_boot_splash_hide (state->boot_splash); |
990 | + } |
991 | + |
992 | + ply_trace ("quitting splash"); |
993 | + quit_splash (state); |
994 | + ply_trace ("quitting program"); |
995 | + quit_program (state); |
996 | + } |
997 | + else if (state->deactivate_trigger != NULL) |
998 | + { |
999 | + ply_trace ("deactivating splash"); |
1000 | + deactivate_splash (state); |
1001 | + } |
1002 | +} |
1003 | + |
1004 | + |
1005 | +static void |
1006 | +on_deactivate (state_t *state, |
1007 | + ply_trigger_t *deactivate_trigger) |
1008 | +{ |
1009 | + if ((state->deactivate_trigger != NULL) || state->is_inactive) |
1010 | + { |
1011 | + ply_trigger_add_handler (state->deactivate_trigger, |
1012 | + (ply_trigger_handler_t) |
1013 | + ply_trigger_pull, |
1014 | + deactivate_trigger); |
1015 | + return; |
1016 | + } |
1017 | + |
1018 | + state->deactivate_trigger = deactivate_trigger; |
1019 | + |
1020 | + ply_trace ("deactivating"); |
1021 | + if (state->boot_splash != NULL) |
1022 | + { |
1023 | + ply_boot_splash_become_idle (state->boot_splash, |
1024 | + (ply_boot_splash_on_idle_handler_t) |
1025 | + on_boot_splash_idle, |
1026 | + state); |
1027 | + } |
1028 | + else |
1029 | + { |
1030 | + ply_trace ("deactivating splash"); |
1031 | + deactivate_splash (state); |
1032 | + } |
1033 | +} |
1034 | + |
1035 | +static void |
1036 | +on_reactivate (state_t *state) |
1037 | +{ |
1038 | + if (!state->is_inactive) |
1039 | + return; |
1040 | + |
1041 | + if (state->terminal != NULL) |
1042 | + { |
1043 | + ply_terminal_watch_for_vt_changes (state->terminal); |
1044 | + ply_terminal_set_unbuffered_input (state->terminal); |
1045 | + ply_terminal_ignore_mode_changes (state->terminal, false); |
1046 | + } |
1047 | + |
1048 | + if ((state->session != NULL) && state->should_be_attached) |
1049 | + { |
1050 | + ply_trace ("reactivating terminal session"); |
1051 | + attach_to_running_session (state); |
1052 | + } |
1053 | + |
1054 | + if (state->keyboard != NULL) |
1055 | + { |
1056 | + ply_trace ("activating keyboard"); |
1057 | + ply_keyboard_watch_for_input (state->keyboard); |
1058 | + } |
1059 | + |
1060 | + if (state->renderer != NULL) |
1061 | + { |
1062 | + ply_trace ("activating renderer"); |
1063 | + ply_renderer_activate (state->renderer); |
1064 | + } |
1065 | + |
1066 | + state->is_inactive = false; |
1067 | + |
1068 | + update_display (state); |
1069 | +} |
1070 | + |
1071 | +static void |
1072 | +on_quit (state_t *state, |
1073 | + bool retain_splash, |
1074 | + ply_trigger_t *quit_trigger) |
1075 | +{ |
1076 | + if (state->quit_trigger != NULL) |
1077 | + { |
1078 | + ply_trigger_add_handler (state->quit_trigger, |
1079 | + (ply_trigger_handler_t) |
1080 | + ply_trigger_pull, |
1081 | + quit_trigger); |
1082 | + return; |
1083 | + } |
1084 | + |
1085 | + state->quit_trigger = quit_trigger; |
1086 | + state->should_retain_splash = retain_splash; |
1087 | + |
1088 | + ply_trace ("time to quit, closing log"); |
1089 | + if (state->session != NULL) |
1090 | + ply_terminal_session_close_log (state->session); |
1091 | + ply_trace ("unloading splash"); |
1092 | + |
1093 | + if (state->is_inactive && !retain_splash) |
1094 | + { |
1095 | + /* We've been deactivated and X failed to start |
1096 | + */ |
1097 | + dump_details_and_quit_splash (state); |
1098 | + quit_program (state); |
1099 | + } |
1100 | + else if (state->boot_splash != NULL) |
1101 | + { |
1102 | + ply_boot_splash_become_idle (state->boot_splash, |
1103 | + (ply_boot_splash_on_idle_handler_t) |
1104 | + on_boot_splash_idle, |
1105 | + state); |
1106 | + } |
1107 | + else |
1108 | + quit_program (state); |
1109 | +} |
1110 | + |
1111 | +static bool |
1112 | +on_has_active_vt (state_t *state) |
1113 | +{ |
1114 | + if (state->terminal != NULL) |
1115 | + return ply_terminal_is_active (state->terminal); |
1116 | + else |
1117 | + return false; |
1118 | +} |
1119 | + |
1120 | +static ply_boot_server_t * |
1121 | +start_boot_server (state_t *state) |
1122 | +{ |
1123 | + ply_boot_server_t *server; |
1124 | + |
1125 | + server = ply_boot_server_new ((ply_boot_server_update_handler_t) on_update, |
1126 | + (ply_boot_server_ask_for_password_handler_t) on_ask_for_password, |
1127 | + (ply_boot_server_ask_question_handler_t) on_ask_question, |
1128 | + (ply_boot_server_display_message_handler_t) on_display_message, |
1129 | + (ply_boot_server_watch_for_keystroke_handler_t) on_watch_for_keystroke, |
1130 | + (ply_boot_server_ignore_keystroke_handler_t) on_ignore_keystroke, |
1131 | + (ply_boot_server_progress_pause_handler_t) on_progress_pause, |
1132 | + (ply_boot_server_progress_unpause_handler_t) on_progress_unpause, |
1133 | + (ply_boot_server_show_splash_handler_t) on_show_splash, |
1134 | + (ply_boot_server_hide_splash_handler_t) on_hide_splash, |
1135 | + (ply_boot_server_newroot_handler_t) on_newroot, |
1136 | + (ply_boot_server_system_initialized_handler_t) on_system_initialized, |
1137 | + (ply_boot_server_error_handler_t) on_error, |
1138 | + (ply_boot_server_deactivate_handler_t) on_deactivate, |
1139 | + (ply_boot_server_reactivate_handler_t) on_reactivate, |
1140 | + (ply_boot_server_quit_handler_t) on_quit, |
1141 | + (ply_boot_server_has_active_vt_handler_t) on_has_active_vt, |
1142 | + state); |
1143 | + |
1144 | + if (!ply_boot_server_listen (server)) |
1145 | + { |
1146 | + ply_save_errno (); |
1147 | + ply_boot_server_free (server); |
1148 | + ply_restore_errno (); |
1149 | + return NULL; |
1150 | + } |
1151 | + |
1152 | + ply_boot_server_attach_to_event_loop (server, state->loop); |
1153 | + |
1154 | + return server; |
1155 | +} |
1156 | + |
1157 | + |
1158 | +static void |
1159 | +update_display (state_t *state) |
1160 | +{ |
1161 | + if (!state->boot_splash) return; |
1162 | + |
1163 | + ply_list_node_t *node; |
1164 | + node = ply_list_get_first_node (state->entry_triggers); |
1165 | + if (node) |
1166 | + { |
1167 | + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); |
1168 | + if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) |
1169 | + { |
1170 | + int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), |
1171 | + ply_buffer_get_size (state->entry_buffer)); |
1172 | + bullets = MAX(0, bullets); |
1173 | + ply_boot_splash_display_password (state->boot_splash, |
1174 | + entry_trigger->prompt, |
1175 | + bullets); |
1176 | + } |
1177 | + else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) |
1178 | + { |
1179 | + ply_boot_splash_display_question (state->boot_splash, |
1180 | + entry_trigger->prompt, |
1181 | + ply_buffer_get_bytes (state->entry_buffer)); |
1182 | + } |
1183 | + else { |
1184 | + ply_trace("unkown entry type"); |
1185 | + } |
1186 | + } |
1187 | + else |
1188 | + { |
1189 | + ply_boot_splash_display_normal (state->boot_splash); |
1190 | + } |
1191 | + |
1192 | +} |
1193 | + |
1194 | +static void |
1195 | +toggle_between_splash_and_details (state_t *state) |
1196 | +{ |
1197 | + ply_trace ("toggling between splash and details"); |
1198 | + if (state->boot_splash != NULL) |
1199 | + { |
1200 | + ply_trace ("hiding and freeing current splash"); |
1201 | + ply_boot_splash_hide (state->boot_splash); |
1202 | + ply_boot_splash_free (state->boot_splash); |
1203 | + state->boot_splash = NULL; |
1204 | + } |
1205 | + |
1206 | + if (!state->showing_details) |
1207 | + { |
1208 | + show_detailed_splash (state); |
1209 | + state->showing_details = true; |
1210 | + } |
1211 | + else |
1212 | + { |
1213 | + show_default_splash (state); |
1214 | + state->showing_details = false; |
1215 | + } |
1216 | + update_display (state); |
1217 | +} |
1218 | + |
1219 | +static void |
1220 | +on_escape_pressed (state_t *state) |
1221 | +{ |
1222 | + ply_trace ("escape key pressed"); |
1223 | + toggle_between_splash_and_details (state); |
1224 | +} |
1225 | + |
1226 | +static void |
1227 | +on_keyboard_input (state_t *state, |
1228 | + const char *keyboard_input, |
1229 | + size_t character_size) |
1230 | +{ |
1231 | + ply_list_node_t *node; |
1232 | + node = ply_list_get_first_node (state->entry_triggers); |
1233 | + if (node) |
1234 | + { /* \x3 (ETX) is Ctrl+C and \x4 (EOT) is Ctrl+D */ |
1235 | + if (character_size == 1 && ( keyboard_input[0] == '\x3' || keyboard_input[0] == '\x4' )) |
1236 | + { |
1237 | + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); |
1238 | + ply_trigger_pull (entry_trigger->trigger, "\x3"); |
1239 | + ply_buffer_clear (state->entry_buffer); |
1240 | + ply_list_remove_node (state->entry_triggers, node); |
1241 | + free (entry_trigger); |
1242 | + } |
1243 | + else |
1244 | + { |
1245 | + ply_buffer_append_bytes (state->entry_buffer, keyboard_input, character_size); |
1246 | + } |
1247 | + update_display (state); |
1248 | + } |
1249 | + else |
1250 | + { |
1251 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
1252 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
1253 | + { |
1254 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
1255 | + if (!keystroke_trigger->keys || strstr(keystroke_trigger->keys, keyboard_input)) /* assume strstr works on utf8 arrays */ |
1256 | + { |
1257 | + ply_trigger_pull (keystroke_trigger->trigger, keyboard_input); |
1258 | + ply_list_remove_node (state->keystroke_triggers, node); |
1259 | + free(keystroke_trigger); |
1260 | + return; |
1261 | + } |
1262 | + } |
1263 | + return; |
1264 | + } |
1265 | +} |
1266 | + |
1267 | +static void |
1268 | +on_backspace (state_t *state) |
1269 | +{ |
1270 | + ssize_t bytes_to_remove; |
1271 | + ssize_t previous_character_size; |
1272 | + const char *bytes; |
1273 | + size_t size; |
1274 | + ply_list_node_t *node = ply_list_get_first_node (state->entry_triggers); |
1275 | + if (!node) return; |
1276 | + |
1277 | + bytes = ply_buffer_get_bytes (state->entry_buffer); |
1278 | + size = ply_buffer_get_size (state->entry_buffer); |
1279 | + |
1280 | + bytes_to_remove = MIN(size, PLY_UTF8_CHARACTER_SIZE_MAX); |
1281 | + while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < bytes_to_remove) |
1282 | + { |
1283 | + if (previous_character_size > 0) |
1284 | + bytes_to_remove -= previous_character_size; |
1285 | + else |
1286 | + bytes_to_remove--; |
1287 | + } |
1288 | + |
1289 | + ply_buffer_remove_bytes_at_end (state->entry_buffer, bytes_to_remove); |
1290 | + update_display (state); |
1291 | +} |
1292 | + |
1293 | +static void |
1294 | +on_enter (state_t *state, |
1295 | + const char *line) |
1296 | +{ |
1297 | + ply_list_node_t *node; |
1298 | + node = ply_list_get_first_node (state->entry_triggers); |
1299 | + if (node) |
1300 | + { |
1301 | + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); |
1302 | + const char* reply_text = ply_buffer_get_bytes (state->entry_buffer); |
1303 | + ply_trigger_pull (entry_trigger->trigger, reply_text); |
1304 | + ply_buffer_clear (state->entry_buffer); |
1305 | + ply_list_remove_node (state->entry_triggers, node); |
1306 | + free (entry_trigger); |
1307 | + update_display (state); |
1308 | + } |
1309 | + else |
1310 | + { |
1311 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
1312 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
1313 | + { |
1314 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
1315 | + if (!keystroke_trigger->keys || strstr(keystroke_trigger->keys, "\n")) /* assume strstr works on utf8 arrays */ |
1316 | + { |
1317 | + ply_trigger_pull (keystroke_trigger->trigger, line); |
1318 | + ply_list_remove_node (state->keystroke_triggers, node); |
1319 | + free(keystroke_trigger); |
1320 | + return; |
1321 | + } |
1322 | + } |
1323 | + return; |
1324 | + } |
1325 | +} |
1326 | + |
1327 | +static void |
1328 | +set_keyboard (state_t *state, |
1329 | + ply_keyboard_t *keyboard) |
1330 | +{ |
1331 | + state->keyboard = keyboard; |
1332 | + |
1333 | + ply_keyboard_add_escape_handler (keyboard, (ply_keyboard_escape_handler_t) |
1334 | + on_escape_pressed, state); |
1335 | + ply_trace ("listening for keystrokes"); |
1336 | + ply_keyboard_add_input_handler (keyboard, |
1337 | + (ply_keyboard_input_handler_t) |
1338 | + on_keyboard_input, state); |
1339 | + ply_trace ("listening for backspace"); |
1340 | + ply_keyboard_add_backspace_handler (keyboard, |
1341 | + (ply_keyboard_backspace_handler_t) |
1342 | + on_backspace, state); |
1343 | + ply_trace ("listening for enter"); |
1344 | + ply_keyboard_add_enter_handler (keyboard, |
1345 | + (ply_keyboard_enter_handler_t) |
1346 | + on_enter, state); |
1347 | +} |
1348 | +static void |
1349 | +add_display_and_keyboard_for_terminal (state_t *state, |
1350 | + const char *tty_name) |
1351 | +{ |
1352 | + ply_text_display_t *display; |
1353 | + ply_keyboard_t *keyboard; |
1354 | + |
1355 | + ply_trace ("adding display and keyboard for %s", tty_name); |
1356 | + |
1357 | + state->terminal = ply_terminal_new (tty_name); |
1358 | + |
1359 | + // urgh |
1360 | + if (!ply_terminal_open (state->terminal)) |
1361 | + return; |
1362 | + |
1363 | + keyboard = ply_keyboard_new_for_terminal (state->terminal); |
1364 | + display = ply_text_display_new (state->terminal); |
1365 | + |
1366 | + ply_list_append_data (state->text_displays, display); |
1367 | + state->keyboard = keyboard; |
1368 | + set_keyboard (state, keyboard); |
1369 | +} |
1370 | + |
1371 | +static void |
1372 | +add_pixel_displays_from_renderer (state_t *state, |
1373 | + ply_renderer_t *renderer) |
1374 | +{ |
1375 | + ply_list_t *heads; |
1376 | + ply_list_node_t *node; |
1377 | + |
1378 | + heads = ply_renderer_get_heads (renderer); |
1379 | + |
1380 | + ply_trace ("Adding displays for %d heads", |
1381 | + ply_list_get_length (heads)); |
1382 | + |
1383 | + node = ply_list_get_first_node (heads); |
1384 | + while (node != NULL) |
1385 | + { |
1386 | + ply_list_node_t *next_node; |
1387 | + ply_renderer_head_t *head; |
1388 | + ply_pixel_display_t *display; |
1389 | + |
1390 | + head = ply_list_node_get_data (node); |
1391 | + next_node = ply_list_get_next_node (heads, node); |
1392 | + |
1393 | + display = ply_pixel_display_new (renderer, head); |
1394 | + |
1395 | + ply_list_append_data (state->pixel_displays, display); |
1396 | + |
1397 | + node = next_node; |
1398 | + } |
1399 | + |
1400 | +} |
1401 | + |
1402 | +static void |
1403 | +add_default_displays_and_keyboard (state_t *state) |
1404 | +{ |
1405 | + ply_renderer_t *renderer; |
1406 | + ply_keyboard_t *keyboard; |
1407 | + ply_terminal_t *terminal; |
1408 | + ply_text_display_t *text_display; |
1409 | + |
1410 | + ply_trace ("adding default displays and keyboard"); |
1411 | + |
1412 | + terminal = ply_terminal_new (state->default_tty); |
1413 | + |
1414 | + renderer = ply_renderer_new (NULL, terminal); |
1415 | + |
1416 | + if (!ply_renderer_open (renderer)) |
1417 | + { |
1418 | + ply_trace ("could not open renderer /dev/fb"); |
1419 | + ply_renderer_free (renderer); |
1420 | + ply_terminal_free (terminal); |
1421 | + |
1422 | + add_display_and_keyboard_for_terminal (state, state->default_tty); |
1423 | + return; |
1424 | + } |
1425 | + |
1426 | + state->terminal = terminal; |
1427 | + |
1428 | + keyboard = ply_keyboard_new_for_renderer (renderer); |
1429 | + set_keyboard (state, keyboard); |
1430 | + |
1431 | + add_pixel_displays_from_renderer (state, renderer); |
1432 | + |
1433 | + text_display = ply_text_display_new (state->terminal); |
1434 | + ply_list_append_data (state->text_displays, text_display); |
1435 | + |
1436 | + state->renderer = renderer; |
1437 | +} |
1438 | + |
1439 | +static void |
1440 | +add_displays_and_keyboard_to_boot_splash (state_t *state, |
1441 | + ply_boot_splash_t *splash) |
1442 | +{ |
1443 | + ply_list_node_t *node; |
1444 | + |
1445 | + ply_trace ("setting keyboard on boot splash"); |
1446 | + if (state->keyboard != NULL) |
1447 | + ply_boot_splash_set_keyboard (splash, state->keyboard); |
1448 | + |
1449 | + node = ply_list_get_first_node (state->pixel_displays); |
1450 | + while (node != NULL) |
1451 | + { |
1452 | + ply_pixel_display_t *display; |
1453 | + ply_list_node_t *next_node; |
1454 | + |
1455 | + display = ply_list_node_get_data (node); |
1456 | + next_node = ply_list_get_next_node (state->pixel_displays, node); |
1457 | + ply_trace ("adding pixel display on boot splash"); |
1458 | + ply_boot_splash_add_pixel_display (splash, display); |
1459 | + |
1460 | + node = next_node; |
1461 | + } |
1462 | + |
1463 | + node = ply_list_get_first_node (state->text_displays); |
1464 | + while (node != NULL) |
1465 | + { |
1466 | + ply_text_display_t *display; |
1467 | + ply_list_node_t *next_node; |
1468 | + |
1469 | + display = ply_list_node_get_data (node); |
1470 | + next_node = ply_list_get_next_node (state->text_displays, node); |
1471 | + |
1472 | + ply_trace ("adding text display on boot splash"); |
1473 | + ply_boot_splash_add_text_display (splash, display); |
1474 | + |
1475 | + node = next_node; |
1476 | + } |
1477 | +} |
1478 | + |
1479 | +static ply_boot_splash_t * |
1480 | +start_boot_splash (state_t *state, |
1481 | + const char *theme_path) |
1482 | +{ |
1483 | + ply_boot_splash_t *splash; |
1484 | + ply_boot_splash_mode_t splash_mode; |
1485 | + |
1486 | + ply_trace ("Loading boot splash theme '%s'", |
1487 | + theme_path); |
1488 | + |
1489 | + splash = ply_boot_splash_new (theme_path, |
1490 | + PLYMOUTH_PLUGIN_PATH, |
1491 | + state->boot_buffer, |
1492 | + state->terminal); |
1493 | + |
1494 | + if (!ply_boot_splash_load (splash)) |
1495 | + { |
1496 | + ply_save_errno (); |
1497 | + ply_boot_splash_free (splash); |
1498 | + ply_restore_errno (); |
1499 | + return NULL; |
1500 | + } |
1501 | + |
1502 | + ply_trace ("attaching plugin to event loop"); |
1503 | + ply_boot_splash_attach_to_event_loop (splash, state->loop); |
1504 | + |
1505 | + ply_trace ("attaching progress to plugin"); |
1506 | + ply_boot_splash_attach_progress (splash, state->progress); |
1507 | + |
1508 | + add_displays_and_keyboard_to_boot_splash (state, splash); |
1509 | + |
1510 | + ply_trace ("showing plugin"); |
1511 | + if (state->mode == PLY_MODE_SHUTDOWN) |
1512 | + splash_mode = PLY_BOOT_SPLASH_MODE_SHUTDOWN; |
1513 | + else |
1514 | + splash_mode = PLY_BOOT_SPLASH_MODE_BOOT_UP; |
1515 | + |
1516 | + if (!ply_boot_splash_show (splash, splash_mode)) |
1517 | + { |
1518 | + ply_save_errno (); |
1519 | + ply_boot_splash_unset_keyboard (splash); |
1520 | + ply_boot_splash_free (splash); |
1521 | + ply_restore_errno (); |
1522 | + return NULL; |
1523 | + } |
1524 | + |
1525 | + ply_keyboard_watch_for_input (state->keyboard); |
1526 | + |
1527 | + update_display (state); |
1528 | + return splash; |
1529 | +} |
1530 | + |
1531 | +static bool |
1532 | +attach_to_running_session (state_t *state) |
1533 | +{ |
1534 | + ply_terminal_session_t *session; |
1535 | + ply_terminal_session_flags_t flags; |
1536 | + bool should_be_redirected; |
1537 | + |
1538 | + flags = 0; |
1539 | + |
1540 | + should_be_redirected = !state->no_boot_log; |
1541 | + |
1542 | + if (should_be_redirected) |
1543 | + flags |= PLY_TERMINAL_SESSION_FLAGS_REDIRECT_CONSOLE; |
1544 | + |
1545 | + if (state->session == NULL) |
1546 | + { |
1547 | + ply_trace ("creating new terminal session"); |
1548 | + session = ply_terminal_session_new (NULL); |
1549 | + |
1550 | + ply_terminal_session_attach_to_event_loop (session, state->loop); |
1551 | + state->session = session; |
1552 | + } |
1553 | + else |
1554 | + { |
1555 | + session = state->session; |
1556 | + ply_trace ("session already created"); |
1557 | + } |
1558 | + |
1559 | + if (!ply_terminal_session_attach (session, flags, |
1560 | + (ply_terminal_session_output_handler_t) |
1561 | + on_session_output, |
1562 | + (ply_terminal_session_done_handler_t) |
1563 | + (should_be_redirected? on_session_finished: NULL), |
1564 | + -1, state)) |
1565 | + { |
1566 | + state->is_redirected = false; |
1567 | + state->is_attached = false; |
1568 | + return false; |
1569 | + } |
1570 | + |
1571 | + state->is_redirected = should_be_redirected; |
1572 | + state->is_attached = true; |
1573 | + |
1574 | + return true; |
1575 | +} |
1576 | + |
1577 | +static bool |
1578 | +get_kernel_command_line (state_t *state) |
1579 | +{ |
1580 | + int fd; |
1581 | + |
1582 | + ply_trace ("opening /proc/cmdline"); |
1583 | + fd = open ("proc/cmdline", O_RDONLY); |
1584 | + |
1585 | + if (fd < 0) |
1586 | + { |
1587 | + ply_trace ("couldn't open it: %m"); |
1588 | + return false; |
1589 | + } |
1590 | + |
1591 | + ply_trace ("reading kernel command line"); |
1592 | + if (read (fd, state->kernel_command_line, sizeof (state->kernel_command_line)) < 0) |
1593 | + { |
1594 | + ply_trace ("couldn't read it: %m"); |
1595 | + return false; |
1596 | + } |
1597 | + |
1598 | + ply_trace ("Kernel command line is: '%s'", state->kernel_command_line); |
1599 | + close (fd); |
1600 | + return true; |
1601 | +} |
1602 | + |
1603 | +static void |
1604 | +check_verbosity (state_t *state) |
1605 | +{ |
1606 | + char *path; |
1607 | + |
1608 | + ply_trace ("checking if tracing should be enabled"); |
1609 | + |
1610 | + path = NULL; |
1611 | + if ((strstr (state->kernel_command_line, " plymouth:debug ") != NULL) |
1612 | + || (strstr (state->kernel_command_line, "plymouth:debug ") != NULL) |
1613 | + || (strstr (state->kernel_command_line, " plymouth:debug") != NULL) |
1614 | + || (path = strstr (state->kernel_command_line, " plymouth:debug=file:")) != NULL) |
1615 | + { |
1616 | +#ifdef LOG_TO_DEBUG_FILE |
1617 | + int fd; |
1618 | +#endif |
1619 | + |
1620 | + ply_trace ("tracing should be enabled!"); |
1621 | + if (!ply_is_tracing ()) |
1622 | + ply_toggle_tracing (); |
1623 | + |
1624 | + if (path != NULL && debug_buffer_path == NULL) |
1625 | + { |
1626 | + char *end; |
1627 | + |
1628 | + path += strlen (" plymouth:debug=file:"); |
1629 | + debug_buffer_path = strdup (path); |
1630 | + end = strstr (debug_buffer_path, " "); |
1631 | + |
1632 | + if (end != NULL) |
1633 | + *end = '\0'; |
1634 | + |
1635 | + debug_buffer_path = path; |
1636 | + } |
1637 | + |
1638 | + if (debug_buffer == NULL) |
1639 | + debug_buffer = ply_buffer_new (); |
1640 | + |
1641 | +#ifdef LOG_TO_DEBUG_FILE |
1642 | + fd = open ("/dev/console", O_RDWR); |
1643 | + ply_logger_set_output_fd (ply_logger_get_error_default (), fd); |
1644 | +#endif |
1645 | + } |
1646 | + else |
1647 | + ply_trace ("tracing shouldn't be enabled!"); |
1648 | + |
1649 | + if (debug_buffer != NULL) |
1650 | + { |
1651 | + if (debug_buffer_path == NULL) |
1652 | + debug_buffer_path = strdup (PLYMOUTH_LOG_DIRECTORY "/plymouth-debug.log"); |
1653 | + |
1654 | + ply_logger_add_filter (ply_logger_get_error_default (), |
1655 | + (ply_logger_filter_handler_t) |
1656 | + on_error_message, |
1657 | + debug_buffer); |
1658 | + |
1659 | + } |
1660 | +} |
1661 | + |
1662 | +static void |
1663 | +check_logging (state_t *state) |
1664 | +{ |
1665 | + ply_trace ("checking if console messages should be redirected and logged"); |
1666 | + |
1667 | + if ((strstr (state->kernel_command_line, " plymouth:nolog ") != NULL) |
1668 | + || (strstr (state->kernel_command_line, "plymouth:nolog ") != NULL) |
1669 | + || (strstr (state->kernel_command_line, " plymouth:nolog") != NULL)) |
1670 | + { |
1671 | + ply_trace ("logging won't be enabled!"); |
1672 | + state->no_boot_log = true; |
1673 | + } |
1674 | + else |
1675 | + { |
1676 | + ply_trace ("logging will be enabled!"); |
1677 | + state->no_boot_log = false; |
1678 | + } |
1679 | +} |
1680 | + |
1681 | +static void |
1682 | +check_for_consoles (state_t *state, |
1683 | + const char *default_tty, |
1684 | + bool should_add_displays) |
1685 | +{ |
1686 | + char *console_key; |
1687 | + char *remaining_command_line; |
1688 | + |
1689 | + ply_trace ("checking for consoles%s", |
1690 | + should_add_displays? " and adding displays": ""); |
1691 | + |
1692 | + remaining_command_line = state->kernel_command_line; |
1693 | + while ((console_key = strstr (remaining_command_line, " console=")) != NULL) |
1694 | + { |
1695 | + char *end; |
1696 | + ply_trace ("serial console found!"); |
1697 | + |
1698 | + free (state->kernel_console_tty); |
1699 | + state->kernel_console_tty = strdup (console_key + strlen (" console=")); |
1700 | + |
1701 | + remaining_command_line = console_key + strlen (" console="); |
1702 | + |
1703 | + end = strpbrk (state->kernel_console_tty, " \n\t\v,"); |
1704 | + |
1705 | + if (end != NULL) |
1706 | + { |
1707 | + *end = '\0'; |
1708 | + remaining_command_line += end - state->kernel_console_tty; |
1709 | + } |
1710 | + |
1711 | + if (strcmp (state->kernel_console_tty, "tty0") == 0 || strcmp (state->kernel_console_tty, "/dev/tty0") == 0) |
1712 | + { |
1713 | + free (state->kernel_console_tty); |
1714 | + state->kernel_console_tty = strdup (default_tty); |
1715 | + } |
1716 | + |
1717 | + if (should_add_displays) |
1718 | + add_display_and_keyboard_for_terminal (state, state->kernel_console_tty); |
1719 | + } |
1720 | + |
1721 | + ply_trace ("There are currently %d text displays", |
1722 | + ply_list_get_length (state->text_displays)); |
1723 | + if (should_add_displays && ply_list_get_length (state->text_displays) == 0) |
1724 | + add_default_displays_and_keyboard (state); |
1725 | +} |
1726 | + |
1727 | +static bool |
1728 | +redirect_standard_io_to_device (const char *device) |
1729 | +{ |
1730 | + int fd; |
1731 | + char *file; |
1732 | + |
1733 | + ply_trace ("redirecting stdio to %s", device); |
1734 | + |
1735 | + if (strncmp (device, "/dev/", strlen ("/dev/")) == 0) |
1736 | + file = strdup (device); |
1737 | + else |
1738 | + asprintf (&file, "/dev/%s", device); |
1739 | + |
1740 | + fd = open (file, O_RDWR | O_APPEND); |
1741 | + |
1742 | + free (file); |
1743 | + |
1744 | + if (fd < 0) |
1745 | + return false; |
1746 | + |
1747 | + dup2 (fd, STDIN_FILENO); |
1748 | + dup2 (fd, STDOUT_FILENO); |
1749 | + dup2 (fd, STDERR_FILENO); |
1750 | + |
1751 | + close (fd); |
1752 | + |
1753 | + return true; |
1754 | +} |
1755 | + |
1756 | +static bool |
1757 | +initialize_environment (state_t *state) |
1758 | +{ |
1759 | + ply_trace ("initializing minimal work environment"); |
1760 | + |
1761 | + if (!get_kernel_command_line (state)) |
1762 | + return false; |
1763 | + |
1764 | + check_verbosity (state); |
1765 | + check_logging (state); |
1766 | + |
1767 | + state->keystroke_triggers = ply_list_new (); |
1768 | + state->entry_triggers = ply_list_new (); |
1769 | + state->entry_buffer = ply_buffer_new(); |
1770 | + state->pixel_displays = ply_list_new (); |
1771 | + state->text_displays = ply_list_new (); |
1772 | + state->pending_messages = ply_list_new (); |
1773 | + state->keyboard = NULL; |
1774 | + |
1775 | + if (!state->default_tty) |
1776 | + { |
1777 | + if (state->mode == PLY_MODE_SHUTDOWN) |
1778 | + { |
1779 | + state->default_tty = SHUTDOWN_TTY; |
1780 | + } |
1781 | + else |
1782 | + state->default_tty = BOOT_TTY; |
1783 | + } |
1784 | + |
1785 | + check_for_consoles (state, state->default_tty, false); |
1786 | + |
1787 | + if (state->kernel_console_tty != NULL) |
1788 | + redirect_standard_io_to_device (state->kernel_console_tty); |
1789 | + else |
1790 | + redirect_standard_io_to_device (state->default_tty); |
1791 | + |
1792 | + ply_trace ("initialized minimal work environment"); |
1793 | + return true; |
1794 | +} |
1795 | + |
1796 | +static void |
1797 | +on_error_message (ply_buffer_t *debug_buffer, |
1798 | + const void *bytes, |
1799 | + size_t number_of_bytes) |
1800 | +{ |
1801 | + ply_buffer_append_bytes (debug_buffer, bytes, number_of_bytes); |
1802 | +} |
1803 | + |
1804 | +static void |
1805 | +dump_debug_buffer_to_file (void) |
1806 | +{ |
1807 | + int fd; |
1808 | + const char *bytes; |
1809 | + size_t size; |
1810 | + |
1811 | + fd = open (debug_buffer_path, |
1812 | + O_WRONLY | O_CREAT | O_TRUNC, 0600); |
1813 | + |
1814 | + if (fd < 0) |
1815 | + return; |
1816 | + |
1817 | + size = ply_buffer_get_size (debug_buffer); |
1818 | + bytes = ply_buffer_get_bytes (debug_buffer); |
1819 | + ply_write (fd, bytes, size); |
1820 | + close (fd); |
1821 | +} |
1822 | + |
1823 | + #include <termios.h> |
1824 | + #include <unistd.h> |
1825 | +static void |
1826 | +on_crash (int signum) |
1827 | +{ |
1828 | + struct termios term_attributes; |
1829 | + int fd; |
1830 | + |
1831 | + fd = open ("/dev/tty1", O_RDWR | O_NOCTTY); |
1832 | + if (fd < 0) fd = open ("/dev/hvc0", O_RDWR | O_NOCTTY); |
1833 | + |
1834 | + ioctl (fd, KDSETMODE, KD_TEXT); |
1835 | + |
1836 | + tcgetattr (fd, &term_attributes); |
1837 | + |
1838 | + term_attributes.c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON; |
1839 | + term_attributes.c_oflag |= OPOST; |
1840 | + term_attributes.c_lflag |= ECHO | ICANON | ISIG | IEXTEN; |
1841 | + |
1842 | + tcsetattr (fd, TCSAFLUSH, &term_attributes); |
1843 | + |
1844 | + close (fd); |
1845 | + |
1846 | + if (debug_buffer != NULL) |
1847 | + { |
1848 | + dump_debug_buffer_to_file (); |
1849 | + pause (); |
1850 | + } |
1851 | + |
1852 | + if (pid_file != NULL) |
1853 | + { |
1854 | + unlink (pid_file); |
1855 | + free (pid_file); |
1856 | + pid_file = NULL; |
1857 | + } |
1858 | + |
1859 | + signal (signum, SIG_DFL); |
1860 | + raise(signum); |
1861 | +} |
1862 | + |
1863 | +int |
1864 | +main (int argc, |
1865 | + char **argv) |
1866 | +{ |
1867 | + state_t state = { 0 }; |
1868 | + int exit_code; |
1869 | + bool should_help = false; |
1870 | + bool no_daemon = false; |
1871 | + bool debug = false; |
1872 | + bool attach_to_session; |
1873 | + ply_daemon_handle_t *daemon_handle; |
1874 | + char *mode_string = NULL; |
1875 | + char *tty = NULL; |
1876 | + |
1877 | + state.command_parser = ply_command_parser_new ("plymouthd", "Boot splash control server"); |
1878 | + |
1879 | + state.loop = ply_event_loop_get_default (); |
1880 | + |
1881 | + ply_command_parser_add_options (state.command_parser, |
1882 | + "help", "This help message", PLY_COMMAND_OPTION_TYPE_FLAG, |
1883 | + "attach-to-session", "Redirect console messages from screen to log", PLY_COMMAND_OPTION_TYPE_FLAG, |
1884 | + "no-daemon", "Do not daemonize", PLY_COMMAND_OPTION_TYPE_FLAG, |
1885 | + "debug", "Output debugging information", PLY_COMMAND_OPTION_TYPE_FLAG, |
1886 | + "debug-file", "File to output debugging information to", PLY_COMMAND_OPTION_TYPE_STRING, |
1887 | + "mode", "Mode is one of: boot, shutdown", PLY_COMMAND_OPTION_TYPE_STRING, |
1888 | + "pid-file", "Write the pid of the daemon to a file", PLY_COMMAND_OPTION_TYPE_STRING, |
1889 | + "tty", "TTY to use instead of default", PLY_COMMAND_OPTION_TYPE_STRING, |
1890 | + NULL); |
1891 | + |
1892 | + if (!ply_command_parser_parse_arguments (state.command_parser, state.loop, argv, argc)) |
1893 | + { |
1894 | + char *help_string; |
1895 | + |
1896 | + help_string = ply_command_parser_get_help_string (state.command_parser); |
1897 | + |
1898 | + ply_error ("%s", help_string); |
1899 | + |
1900 | + free (help_string); |
1901 | + return EX_USAGE; |
1902 | + } |
1903 | + |
1904 | + ply_command_parser_get_options (state.command_parser, |
1905 | + "help", &should_help, |
1906 | + "attach-to-session", &attach_to_session, |
1907 | + "mode", &mode_string, |
1908 | + "no-daemon", &no_daemon, |
1909 | + "debug", &debug, |
1910 | + "debug-file", &debug_buffer_path, |
1911 | + "pid-file", &pid_file, |
1912 | + "tty", &tty, |
1913 | + NULL); |
1914 | + |
1915 | + if (should_help) |
1916 | + { |
1917 | + char *help_string; |
1918 | + |
1919 | + help_string = ply_command_parser_get_help_string (state.command_parser); |
1920 | + |
1921 | + if (argc < 2) |
1922 | + fprintf (stderr, "%s", help_string); |
1923 | + else |
1924 | + printf ("%s", help_string); |
1925 | + |
1926 | + free (help_string); |
1927 | + return 0; |
1928 | + } |
1929 | + |
1930 | + if (debug && !ply_is_tracing ()) |
1931 | + ply_toggle_tracing (); |
1932 | + |
1933 | + if (mode_string != NULL) |
1934 | + { |
1935 | + if (strcmp (mode_string, "shutdown") == 0) |
1936 | + state.mode = PLY_MODE_SHUTDOWN; |
1937 | + else |
1938 | + state.mode = PLY_MODE_BOOT; |
1939 | + |
1940 | + free (mode_string); |
1941 | + } |
1942 | + |
1943 | + if (tty != NULL) |
1944 | + { |
1945 | + state.default_tty = tty; |
1946 | + } |
1947 | + |
1948 | + if (geteuid () != 0) |
1949 | + { |
1950 | + ply_error ("plymouthd must be run as root user"); |
1951 | + return EX_OSERR; |
1952 | + } |
1953 | + |
1954 | + chdir ("/"); |
1955 | + signal (SIGPIPE, SIG_IGN); |
1956 | + |
1957 | + if (! no_daemon) |
1958 | + { |
1959 | + daemon_handle = ply_create_daemon (pid_file); |
1960 | + |
1961 | + if (daemon_handle == NULL) |
1962 | + { |
1963 | + ply_error ("cannot daemonize: %m"); |
1964 | + return EX_UNAVAILABLE; |
1965 | + } |
1966 | + } |
1967 | + |
1968 | + if (debug) |
1969 | + debug_buffer = ply_buffer_new (); |
1970 | + |
1971 | + signal (SIGABRT, on_crash); |
1972 | + signal (SIGSEGV, on_crash); |
1973 | + |
1974 | + /* If we're shutting down we don't want to die until killed |
1975 | + */ |
1976 | + if (state.mode == PLY_MODE_SHUTDOWN) |
1977 | + signal (SIGTERM, SIG_IGN); |
1978 | + |
1979 | + /* before do anything we need to make sure we have a working |
1980 | + * environment. |
1981 | + */ |
1982 | + if (!initialize_environment (&state)) |
1983 | + { |
1984 | + if (errno == 0) |
1985 | + { |
1986 | + if (! no_daemon) |
1987 | + ply_detach_daemon (daemon_handle, 0); |
1988 | + return 0; |
1989 | + } |
1990 | + |
1991 | + ply_error ("could not setup basic operating environment: %m"); |
1992 | + if (! no_daemon) |
1993 | + ply_detach_daemon (daemon_handle, EX_OSERR); |
1994 | + return EX_OSERR; |
1995 | + } |
1996 | + |
1997 | + state.boot_buffer = ply_buffer_new (); |
1998 | + |
1999 | + if (attach_to_session) |
2000 | + { |
2001 | + state.should_be_attached = attach_to_session; |
2002 | + if (!attach_to_running_session (&state)) |
2003 | + ply_trace ("could not create session: %m"); |
2004 | + } |
2005 | + |
2006 | + state.boot_server = start_boot_server (&state); |
2007 | + |
2008 | + if (state.boot_server == NULL) |
2009 | + { |
2010 | + ply_error ("could not log bootup: %m"); |
2011 | + if (! no_daemon) |
2012 | + ply_detach_daemon (daemon_handle, EX_UNAVAILABLE); |
2013 | + return EX_UNAVAILABLE; |
2014 | + } |
2015 | + |
2016 | + if (! no_daemon) |
2017 | + if (!ply_detach_daemon (daemon_handle, 0)) |
2018 | + { |
2019 | + ply_error ("could not tell parent to exit: %m"); |
2020 | + return EX_UNAVAILABLE; |
2021 | + } |
2022 | + |
2023 | + state.progress = ply_progress_new (); |
2024 | + |
2025 | + ply_progress_load_cache (state.progress, |
2026 | + get_cache_file_for_mode (state.mode)); |
2027 | + |
2028 | + ply_trace ("entering event loop"); |
2029 | + exit_code = ply_event_loop_run (state.loop); |
2030 | + ply_trace ("exited event loop"); |
2031 | + |
2032 | + ply_progress_save_cache (state.progress, |
2033 | + get_cache_file_for_mode (state.mode)); |
2034 | + |
2035 | + ply_boot_splash_free (state.boot_splash); |
2036 | + state.boot_splash = NULL; |
2037 | + |
2038 | + ply_command_parser_free (state.command_parser); |
2039 | + |
2040 | + ply_boot_server_free (state.boot_server); |
2041 | + state.boot_server = NULL; |
2042 | + |
2043 | + ply_trace ("freeing terminal session"); |
2044 | + ply_terminal_session_free (state.session); |
2045 | + |
2046 | + ply_buffer_free (state.boot_buffer); |
2047 | + ply_progress_free (state.progress); |
2048 | + |
2049 | + ply_trace ("exiting with code %d", exit_code); |
2050 | + |
2051 | + if (debug_buffer != NULL) |
2052 | + { |
2053 | + dump_debug_buffer_to_file (); |
2054 | + ply_buffer_free (debug_buffer); |
2055 | + } |
2056 | + |
2057 | + ply_free_error_log(); |
2058 | + |
2059 | + return exit_code; |
2060 | +} |
2061 | +/* vim: set sts=4 ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ |
2062 | |
2063 | === added directory '.pc/initramfsless-boot.patch' |
2064 | === added directory '.pc/initramfsless-boot.patch/src' |
2065 | === added file '.pc/initramfsless-boot.patch/src/main.c' |
2066 | --- .pc/initramfsless-boot.patch/src/main.c 1970-01-01 00:00:00 +0000 |
2067 | +++ .pc/initramfsless-boot.patch/src/main.c 2013-11-30 04:03:08 +0000 |
2068 | @@ -0,0 +1,2003 @@ |
2069 | +/* main.c - boot messages monitor |
2070 | + * |
2071 | + * Copyright (C) 2007 Red Hat, Inc |
2072 | + * |
2073 | + * This file is free software; you can redistribute it and/or modify |
2074 | + * it under the terms of the GNU General Public License as published |
2075 | + * by the Free Software Foundation; either version 2 of the License, |
2076 | + * or (at your option) any later version. |
2077 | + * |
2078 | + * This file is distributed in the hope that it will be useful, but |
2079 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
2080 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2081 | + * General Public License for more details. |
2082 | + * |
2083 | + * You should have received a copy of the GNU General Public License |
2084 | + * along with this; see the file COPYING. If not, write to the Free |
2085 | + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
2086 | + * 02111-1307, USA. |
2087 | + * |
2088 | + * Written by: Ray Strode <rstrode@redhat.com> |
2089 | + */ |
2090 | +#include "config.h" |
2091 | + |
2092 | +#include <sys/stat.h> |
2093 | +#include <sys/types.h> |
2094 | +#include <limits.h> |
2095 | +#include <dirent.h> |
2096 | +#include <fcntl.h> |
2097 | +#include <stdlib.h> |
2098 | +#include <stdio.h> |
2099 | +#include <sysexits.h> |
2100 | +#include <sys/ioctl.h> |
2101 | +#include <unistd.h> |
2102 | +#include <wchar.h> |
2103 | +#include <paths.h> |
2104 | +#include <assert.h> |
2105 | + |
2106 | +#include <linux/kd.h> |
2107 | +#include <linux/vt.h> |
2108 | + |
2109 | +#include "ply-buffer.h" |
2110 | +#include "ply-command-parser.h" |
2111 | +#include "ply-boot-server.h" |
2112 | +#include "ply-boot-splash.h" |
2113 | +#include "ply-event-loop.h" |
2114 | +#include "ply-list.h" |
2115 | +#include "ply-logger.h" |
2116 | +#include "ply-terminal-session.h" |
2117 | +#include "ply-trigger.h" |
2118 | +#include "ply-utils.h" |
2119 | +#include "ply-progress.h" |
2120 | + |
2121 | +#ifndef PLY_MAX_COMMAND_LINE_SIZE |
2122 | +#define PLY_MAX_COMMAND_LINE_SIZE 512 |
2123 | +#endif |
2124 | + |
2125 | +#define BOOT_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/boot-duration" |
2126 | +#define SHUTDOWN_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/shutdown-duration" |
2127 | + |
2128 | +typedef enum { |
2129 | + PLY_MODE_BOOT, |
2130 | + PLY_MODE_SHUTDOWN |
2131 | +} ply_mode_t; |
2132 | + |
2133 | +typedef struct |
2134 | +{ |
2135 | + const char *keys; |
2136 | + ply_trigger_t *trigger; |
2137 | +} ply_keystroke_watch_t; |
2138 | + |
2139 | +typedef struct |
2140 | +{ |
2141 | + enum {PLY_ENTRY_TRIGGER_TYPE_PASSWORD, |
2142 | + PLY_ENTRY_TRIGGER_TYPE_QUESTION} |
2143 | + type; |
2144 | + const char *prompt; |
2145 | + ply_trigger_t *trigger; |
2146 | +} ply_entry_trigger_t; |
2147 | + |
2148 | +typedef struct |
2149 | +{ |
2150 | + ply_event_loop_t *loop; |
2151 | + ply_boot_server_t *boot_server; |
2152 | + ply_list_t *pixel_displays; |
2153 | + ply_list_t *text_displays; |
2154 | + ply_keyboard_t *keyboard; |
2155 | + ply_boot_splash_t *boot_splash; |
2156 | + ply_terminal_session_t *session; |
2157 | + ply_buffer_t *boot_buffer; |
2158 | + ply_progress_t *progress; |
2159 | + ply_list_t *keystroke_triggers; |
2160 | + ply_list_t *entry_triggers; |
2161 | + ply_buffer_t *entry_buffer; |
2162 | + ply_command_parser_t *command_parser; |
2163 | + ply_mode_t mode; |
2164 | + ply_renderer_t *renderer; |
2165 | + ply_terminal_t *terminal; |
2166 | + |
2167 | + ply_trigger_t *deactivate_trigger; |
2168 | + ply_trigger_t *quit_trigger; |
2169 | + |
2170 | + char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; |
2171 | + uint32_t no_boot_log : 1; |
2172 | + uint32_t showing_details : 1; |
2173 | + uint32_t system_initialized : 1; |
2174 | + uint32_t is_redirected : 1; |
2175 | + uint32_t is_attached : 1; |
2176 | + uint32_t should_be_attached : 1; |
2177 | + uint32_t should_retain_splash : 1; |
2178 | + uint32_t is_inactive : 1; |
2179 | + |
2180 | + char *kernel_console_tty; |
2181 | + char *override_splash_path; |
2182 | + char *system_default_splash_path; |
2183 | + char *distribution_default_splash_path; |
2184 | + const char *default_tty; |
2185 | + |
2186 | + int number_of_errors; |
2187 | + ply_list_t *pending_messages; |
2188 | +} state_t; |
2189 | + |
2190 | +static ply_boot_splash_t *start_boot_splash (state_t *state, |
2191 | + const char *theme_path); |
2192 | + |
2193 | +static void add_display_and_keyboard_for_terminal (state_t *state, |
2194 | + const char *tty_name); |
2195 | + |
2196 | +static void add_default_displays_and_keyboard (state_t *state); |
2197 | + |
2198 | +static bool attach_to_running_session (state_t *state); |
2199 | +static void on_escape_pressed (state_t *state); |
2200 | +static void dump_details_and_quit_splash (state_t *state); |
2201 | +static void update_display (state_t *state); |
2202 | + |
2203 | +static void on_error_message (ply_buffer_t *debug_buffer, |
2204 | + const void *bytes, |
2205 | + size_t number_of_bytes); |
2206 | +static ply_buffer_t *debug_buffer; |
2207 | +static char *debug_buffer_path = NULL; |
2208 | +static char *pid_file = NULL; |
2209 | +static void check_for_consoles (state_t *state, |
2210 | + const char *default_tty, |
2211 | + bool should_add_displays); |
2212 | +static void toggle_between_splash_and_details (state_t *state); |
2213 | + |
2214 | +static void |
2215 | +on_session_output (state_t *state, |
2216 | + const char *output, |
2217 | + size_t size) |
2218 | +{ |
2219 | + ply_buffer_append_bytes (state->boot_buffer, output, size); |
2220 | + if (state->boot_splash != NULL) |
2221 | + ply_boot_splash_update_output (state->boot_splash, |
2222 | + output, size); |
2223 | +} |
2224 | + |
2225 | +static void |
2226 | +on_session_finished (state_t *state) |
2227 | +{ |
2228 | + ply_trace ("got hang up on terminal session fd"); |
2229 | +} |
2230 | + |
2231 | +static void |
2232 | +on_update (state_t *state, |
2233 | + const char *status) |
2234 | +{ |
2235 | + ply_trace ("updating status to '%s'", status); |
2236 | + if (strncmp (status, "fsck:", 5)) |
2237 | + ply_progress_status_update (state->progress, |
2238 | + status); |
2239 | + if (state->boot_splash != NULL) |
2240 | + ply_boot_splash_update_status (state->boot_splash, |
2241 | + status); |
2242 | +} |
2243 | + |
2244 | +static void |
2245 | +flush_pending_messages (state_t *state) |
2246 | +{ |
2247 | + ply_list_node_t *node = ply_list_get_first_node (state->pending_messages); |
2248 | + while (node != NULL) |
2249 | + { |
2250 | + ply_list_node_t *next_node; |
2251 | + char *message = ply_list_node_get_data (node); |
2252 | + |
2253 | + ply_trace ("displaying queued message"); |
2254 | + |
2255 | + ply_boot_splash_display_message (state->boot_splash, message); |
2256 | + next_node = ply_list_get_next_node (state->pending_messages, node); |
2257 | + ply_list_remove_node (state->pending_messages, node); |
2258 | + free(message); |
2259 | + node = next_node; |
2260 | + } |
2261 | +} |
2262 | + |
2263 | +static void |
2264 | +show_detailed_splash (state_t *state) |
2265 | +{ |
2266 | + if (state->boot_splash != NULL) |
2267 | + return; |
2268 | + |
2269 | + ply_trace ("Showing detailed splash screen"); |
2270 | + state->boot_splash = start_boot_splash (state, |
2271 | + PLYMOUTH_THEME_PATH "details/details.plymouth"); |
2272 | + |
2273 | + if (state->boot_splash == NULL) |
2274 | + { |
2275 | + ply_trace ("Could not start detailed splash screen, exiting"); |
2276 | + exit (1); |
2277 | + } |
2278 | +} |
2279 | + |
2280 | +static void |
2281 | +find_override_splash (state_t *state) |
2282 | +{ |
2283 | + char *splash_string; |
2284 | + |
2285 | + if (state->override_splash_path != NULL) |
2286 | + return; |
2287 | + |
2288 | + splash_string = strstr (state->kernel_command_line, "plymouth:splash="); |
2289 | + |
2290 | + if (splash_string != NULL) |
2291 | + { |
2292 | + char *end; |
2293 | + splash_string = strdup (splash_string + strlen ("plymouth:splash=")); |
2294 | + |
2295 | + end = strstr (splash_string, " "); |
2296 | + |
2297 | + if (end != NULL) |
2298 | + *end = '\0'; |
2299 | + |
2300 | + ply_trace ("Splash is configured to be '%s'", splash_string); |
2301 | + |
2302 | + asprintf (&state->override_splash_path, |
2303 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
2304 | + splash_string, splash_string); |
2305 | + } |
2306 | +} |
2307 | + |
2308 | +static void |
2309 | +find_system_default_splash (state_t *state) |
2310 | +{ |
2311 | + ply_key_file_t *key_file; |
2312 | + char *splash_string; |
2313 | + |
2314 | + if (state->system_default_splash_path != NULL) |
2315 | + return; |
2316 | + |
2317 | + ply_trace ("Trying to load " PLYMOUTH_CONF_DIR "plymouthd.conf"); |
2318 | + key_file = ply_key_file_new (PLYMOUTH_CONF_DIR "plymouthd.conf"); |
2319 | + |
2320 | + if (!ply_key_file_load (key_file)) |
2321 | + { |
2322 | + ply_trace ("failed to load " PLYMOUTH_CONF_DIR "plymouthd.conf"); |
2323 | + ply_key_file_free (key_file); |
2324 | + return; |
2325 | + } |
2326 | + |
2327 | + splash_string = ply_key_file_get_value (key_file, "Daemon", "Theme"); |
2328 | + |
2329 | + ply_trace ("System default splash is configured to be '%s'", splash_string); |
2330 | + |
2331 | + asprintf (&state->system_default_splash_path, |
2332 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
2333 | + splash_string, splash_string); |
2334 | + free (splash_string); |
2335 | +} |
2336 | + |
2337 | +static void |
2338 | +find_distribution_default_splash (state_t *state) |
2339 | +{ |
2340 | + ply_key_file_t *key_file; |
2341 | + char *splash_string; |
2342 | + |
2343 | + if (state->distribution_default_splash_path != NULL) |
2344 | + return; |
2345 | + |
2346 | + ply_trace ("Trying to load " PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
2347 | + key_file = ply_key_file_new (PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
2348 | + |
2349 | + if (!ply_key_file_load (key_file)) |
2350 | + { |
2351 | + ply_trace ("failed to load " PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
2352 | + ply_key_file_free (key_file); |
2353 | + return; |
2354 | + } |
2355 | + |
2356 | + splash_string = ply_key_file_get_value (key_file, "Daemon", "Theme"); |
2357 | + |
2358 | + ply_trace ("Distribution default splash is configured to be '%s'", splash_string); |
2359 | + |
2360 | + asprintf (&state->distribution_default_splash_path, |
2361 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
2362 | + splash_string, splash_string); |
2363 | + free (splash_string); |
2364 | +} |
2365 | + |
2366 | +static void |
2367 | +show_default_splash (state_t *state) |
2368 | +{ |
2369 | + if (state->boot_splash != NULL) |
2370 | + return; |
2371 | + |
2372 | + ply_trace ("Showing splash screen"); |
2373 | + find_override_splash (state); |
2374 | + if (state->override_splash_path != NULL) |
2375 | + { |
2376 | + ply_trace ("Trying override splash at '%s'", state->override_splash_path); |
2377 | + state->boot_splash = start_boot_splash (state, |
2378 | + state->override_splash_path); |
2379 | + } |
2380 | + |
2381 | + find_system_default_splash (state); |
2382 | + if (state->boot_splash == NULL && |
2383 | + state->system_default_splash_path != NULL) |
2384 | + { |
2385 | + ply_trace ("Trying system default splash"); |
2386 | + state->boot_splash = start_boot_splash (state, |
2387 | + state->system_default_splash_path); |
2388 | + } |
2389 | + |
2390 | + find_distribution_default_splash (state); |
2391 | + if (state->boot_splash == NULL && |
2392 | + state->distribution_default_splash_path != NULL) |
2393 | + { |
2394 | + ply_trace ("Trying distribution default splash"); |
2395 | + state->boot_splash = start_boot_splash (state, |
2396 | + state->distribution_default_splash_path); |
2397 | + } |
2398 | + |
2399 | + if (state->boot_splash == NULL) |
2400 | + { |
2401 | + ply_trace ("Trying old scheme for default splash"); |
2402 | + state->boot_splash = start_boot_splash (state, |
2403 | + PLYMOUTH_THEME_PATH "default.plymouth"); |
2404 | + } |
2405 | + |
2406 | + if (state->boot_splash == NULL) |
2407 | + { |
2408 | + ply_trace ("Could not start default splash screen," |
2409 | + "showing text splash screen"); |
2410 | + state->boot_splash = start_boot_splash (state, |
2411 | + PLYMOUTH_THEME_PATH "text.plymouth"); |
2412 | + } |
2413 | + |
2414 | + if (state->boot_splash == NULL) |
2415 | + { |
2416 | + if (errno != ENOENT) |
2417 | + ply_error ("could not start boot splash: %m"); |
2418 | + show_detailed_splash (state); |
2419 | + } |
2420 | +} |
2421 | + |
2422 | +static void |
2423 | +on_ask_for_password (state_t *state, |
2424 | + const char *prompt, |
2425 | + ply_trigger_t *answer) |
2426 | +{ |
2427 | + ply_entry_trigger_t *entry_trigger; |
2428 | + |
2429 | + /* No splash, client will have to get password |
2430 | + */ |
2431 | + if (state->boot_splash == NULL) |
2432 | + { |
2433 | + ply_trace ("no splash loaded, replying immediately with no password"); |
2434 | + ply_trigger_pull (answer, NULL); |
2435 | + return; |
2436 | + } |
2437 | + |
2438 | + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); |
2439 | + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_PASSWORD; |
2440 | + entry_trigger->prompt = prompt; |
2441 | + entry_trigger->trigger = answer; |
2442 | + ply_trace ("queuing password request with boot splash"); |
2443 | + ply_list_append_data (state->entry_triggers, entry_trigger); |
2444 | + update_display (state); |
2445 | +} |
2446 | + |
2447 | +static void |
2448 | +on_ask_question (state_t *state, |
2449 | + const char *prompt, |
2450 | + ply_trigger_t *answer) |
2451 | +{ |
2452 | + ply_entry_trigger_t *entry_trigger; |
2453 | + |
2454 | + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); |
2455 | + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_QUESTION; |
2456 | + entry_trigger->prompt = prompt; |
2457 | + entry_trigger->trigger = answer; |
2458 | + ply_trace ("queuing question with boot splash"); |
2459 | + ply_list_append_data (state->entry_triggers, entry_trigger); |
2460 | + update_display (state); |
2461 | +} |
2462 | + |
2463 | +static void |
2464 | +on_display_message (state_t *state, |
2465 | + const char *message) |
2466 | +{ |
2467 | + ply_trace ("displaying message %s", message); |
2468 | + if (state->boot_splash != NULL) |
2469 | + ply_boot_splash_display_message (state->boot_splash, message); |
2470 | + else |
2471 | + ply_list_append_data (state->pending_messages, strdup(message)); |
2472 | +} |
2473 | + |
2474 | +static void |
2475 | +on_watch_for_keystroke (state_t *state, |
2476 | + const char *keys, |
2477 | + ply_trigger_t *trigger) |
2478 | +{ |
2479 | + ply_keystroke_watch_t *keystroke_trigger = |
2480 | + calloc (1, sizeof (ply_keystroke_watch_t)); |
2481 | + ply_trace ("watching for keystroke"); |
2482 | + keystroke_trigger->keys = keys; |
2483 | + keystroke_trigger->trigger = trigger; |
2484 | + ply_list_append_data (state->keystroke_triggers, keystroke_trigger); |
2485 | +} |
2486 | + |
2487 | +static void |
2488 | +on_ignore_keystroke (state_t *state, |
2489 | + const char *keys) |
2490 | +{ |
2491 | + ply_list_node_t *node; |
2492 | + |
2493 | + ply_trace ("ignoring for keystroke"); |
2494 | + |
2495 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
2496 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
2497 | + { |
2498 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
2499 | + if ((!keystroke_trigger->keys && !keys) || |
2500 | + (keystroke_trigger->keys && keys && strcmp(keystroke_trigger->keys, keys)==0)) |
2501 | + { |
2502 | + ply_trigger_pull (keystroke_trigger->trigger, NULL); |
2503 | + ply_list_remove_node (state->keystroke_triggers, node); |
2504 | + return; |
2505 | + } |
2506 | + } |
2507 | +} |
2508 | + |
2509 | +static void |
2510 | +on_progress_pause (state_t *state) |
2511 | +{ |
2512 | + ply_trace ("pausing progress"); |
2513 | + ply_progress_pause (state->progress); |
2514 | +} |
2515 | + |
2516 | +static void |
2517 | +on_progress_unpause (state_t *state) |
2518 | +{ |
2519 | + ply_trace ("unpausing progress"); |
2520 | + ply_progress_unpause (state->progress); |
2521 | +} |
2522 | + |
2523 | +static void |
2524 | +on_newroot (state_t *state, |
2525 | + const char *root_dir) |
2526 | +{ |
2527 | + if (state->mode != PLY_MODE_BOOT) |
2528 | + { |
2529 | + ply_trace ("new root is only supported in boot mode "); |
2530 | + return; |
2531 | + } |
2532 | + |
2533 | + ply_trace ("new root mounted at \"%s\", switching to it", root_dir); |
2534 | + chdir(root_dir); |
2535 | + chroot("."); |
2536 | + chdir("/"); |
2537 | + ply_progress_load_cache (state->progress, BOOT_DURATION_FILE); |
2538 | + if (state->boot_splash != NULL) |
2539 | + ply_boot_splash_root_mounted (state->boot_splash); |
2540 | +} |
2541 | + |
2542 | +static const char * |
2543 | +get_cache_file_for_mode (ply_mode_t mode) |
2544 | +{ |
2545 | + const char *filename; |
2546 | + |
2547 | + switch ((int)mode) |
2548 | + { |
2549 | + case PLY_MODE_BOOT: |
2550 | + filename = BOOT_DURATION_FILE; |
2551 | + break; |
2552 | + case PLY_MODE_SHUTDOWN: |
2553 | + filename = SHUTDOWN_DURATION_FILE; |
2554 | + break; |
2555 | + default: |
2556 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
2557 | + abort (); |
2558 | + break; |
2559 | + } |
2560 | + |
2561 | + ply_trace ("returning cache file '%s'", filename); |
2562 | + return filename; |
2563 | +} |
2564 | + |
2565 | +static const char * |
2566 | +get_log_file_for_mode (ply_mode_t mode) |
2567 | +{ |
2568 | + const char *filename; |
2569 | + |
2570 | + switch ((int)mode) |
2571 | + { |
2572 | + case PLY_MODE_BOOT: |
2573 | + filename = PLYMOUTH_LOG_DIRECTORY "/boot.log"; |
2574 | + break; |
2575 | + case PLY_MODE_SHUTDOWN: |
2576 | + filename = _PATH_DEVNULL; |
2577 | + break; |
2578 | + default: |
2579 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
2580 | + abort (); |
2581 | + break; |
2582 | + } |
2583 | + |
2584 | + ply_trace ("returning log file '%s'", filename); |
2585 | + return filename; |
2586 | +} |
2587 | + |
2588 | +static const char * |
2589 | +get_log_spool_file_for_mode (ply_mode_t mode) |
2590 | +{ |
2591 | + const char *filename; |
2592 | + |
2593 | + switch ((int)mode) |
2594 | + { |
2595 | + case PLY_MODE_BOOT: |
2596 | + filename = PLYMOUTH_SPOOL_DIRECTORY "/boot.log"; |
2597 | + break; |
2598 | + case PLY_MODE_SHUTDOWN: |
2599 | + filename = NULL; |
2600 | + break; |
2601 | + default: |
2602 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
2603 | + abort (); |
2604 | + break; |
2605 | + } |
2606 | + |
2607 | + ply_trace ("returning spool file '%s'", filename); |
2608 | + return filename; |
2609 | +} |
2610 | + |
2611 | +static void |
2612 | +spool_error (state_t *state) |
2613 | +{ |
2614 | + const char *logfile; |
2615 | + const char *logspool; |
2616 | + |
2617 | + ply_trace ("spooling error for viewer"); |
2618 | + |
2619 | + logfile = get_log_file_for_mode (state->mode); |
2620 | + logspool = get_log_spool_file_for_mode (state->mode); |
2621 | + |
2622 | + if (logfile != NULL && logspool != NULL) |
2623 | + { |
2624 | + unlink (logspool); |
2625 | + |
2626 | + ply_create_file_link (logfile, logspool); |
2627 | + } |
2628 | +} |
2629 | + |
2630 | +static void |
2631 | +prepare_logging (state_t *state) |
2632 | +{ |
2633 | + const char *logfile; |
2634 | + |
2635 | + if (!state->system_initialized) |
2636 | + { |
2637 | + ply_trace ("not preparing logging yet, system not initialized"); |
2638 | + return; |
2639 | + } |
2640 | + |
2641 | + if (state->session == NULL) |
2642 | + { |
2643 | + ply_trace ("not preparing logging, no session"); |
2644 | + return; |
2645 | + } |
2646 | + |
2647 | + logfile = get_log_file_for_mode (state->mode); |
2648 | + if (logfile != NULL) |
2649 | + { |
2650 | + ply_trace ("opening log '%s'", logfile); |
2651 | + ply_terminal_session_open_log (state->session, logfile); |
2652 | + |
2653 | + if (state->number_of_errors > 0) |
2654 | + spool_error (state); |
2655 | + } |
2656 | +} |
2657 | + |
2658 | +static void |
2659 | +on_system_initialized (state_t *state) |
2660 | +{ |
2661 | + ply_trace ("system now initialized, opening log"); |
2662 | + state->system_initialized = true; |
2663 | + |
2664 | + prepare_logging (state); |
2665 | +} |
2666 | + |
2667 | +static void |
2668 | +on_error (state_t *state) |
2669 | +{ |
2670 | + ply_trace ("encountered error during boot up"); |
2671 | + |
2672 | + if (state->system_initialized && state->number_of_errors == 0) |
2673 | + spool_error (state); |
2674 | + else |
2675 | + ply_trace ("not spooling because number of errors %d", state->number_of_errors); |
2676 | + |
2677 | + state->number_of_errors++; |
2678 | +} |
2679 | + |
2680 | +static bool |
2681 | +plymouth_should_ignore_show_splash_calls (state_t *state) |
2682 | +{ |
2683 | + ply_trace ("checking if plymouth should be running"); |
2684 | + if (state->mode != PLY_MODE_BOOT || ply_string_has_prefix (state->kernel_command_line, "plymouth:force-splash") || strstr (state->kernel_command_line, " plymouth:force-splash") != NULL) |
2685 | + return false; |
2686 | + |
2687 | + return ply_string_has_prefix (state->kernel_command_line, "init=") || strstr (state->kernel_command_line, " init=") != NULL; |
2688 | +} |
2689 | + |
2690 | +static bool |
2691 | +plymouth_should_show_default_splash (state_t *state) |
2692 | +{ |
2693 | + ply_trace ("checking if plymouth should show default splash"); |
2694 | + |
2695 | + const char const *strings[] = { |
2696 | + " single ", " single\n", "^single ", |
2697 | + " 1 ", " 1\n", "^1 ", |
2698 | + " s ", " s\n", "^s ", |
2699 | + " S ", " S\n", "^S ", |
2700 | + " -s ", " -s\n", "^-s ", |
2701 | + NULL |
2702 | + }; |
2703 | + int i; |
2704 | + |
2705 | + if (state->kernel_console_tty != NULL) |
2706 | + return false; |
2707 | + |
2708 | + for (i = 0; strings[i] != NULL; i++) |
2709 | + { |
2710 | + int cmp; |
2711 | + if (strings[i][0] == '^') |
2712 | + cmp = strncmp(state->kernel_command_line, strings[i]+1, |
2713 | + strlen(strings[i]+1)) == 0; |
2714 | + else |
2715 | + cmp = strstr (state->kernel_command_line, strings[i]) != NULL; |
2716 | + |
2717 | + if (cmp) |
2718 | + { |
2719 | + ply_trace ("kernel command line has option \"%s\"", strings[i]); |
2720 | + return false; |
2721 | + } |
2722 | + } |
2723 | + |
2724 | + return strstr (state->kernel_command_line, "rhgb") != NULL || (strstr (state->kernel_command_line, "splash") != NULL && strstr(state->kernel_command_line, "splash=verbose") == NULL); |
2725 | +} |
2726 | + |
2727 | +static void |
2728 | +remove_displays_and_keyboard (state_t *state) |
2729 | +{ |
2730 | + ply_list_node_t *node; |
2731 | + ply_trace ("removing displays and keyboard"); |
2732 | + |
2733 | + node = ply_list_get_first_node (state->pixel_displays); |
2734 | + while (node != NULL) |
2735 | + { |
2736 | + ply_list_node_t *next_node; |
2737 | + ply_pixel_display_t *display; |
2738 | + |
2739 | + ply_trace ("removing pixel display"); |
2740 | + next_node = ply_list_get_next_node (state->pixel_displays, node); |
2741 | + display = ply_list_node_get_data (node); |
2742 | + ply_pixel_display_free (display); |
2743 | + |
2744 | + ply_list_remove_node (state->pixel_displays, node); |
2745 | + |
2746 | + node = next_node; |
2747 | + } |
2748 | + |
2749 | + node = ply_list_get_first_node (state->text_displays); |
2750 | + while (node != NULL) |
2751 | + { |
2752 | + ply_list_node_t *next_node; |
2753 | + ply_text_display_t *display; |
2754 | + |
2755 | + ply_trace ("removing text display"); |
2756 | + next_node = ply_list_get_next_node (state->text_displays, node); |
2757 | + display = ply_list_node_get_data (node); |
2758 | + ply_text_display_free (display); |
2759 | + |
2760 | + ply_list_remove_node (state->text_displays, node); |
2761 | + |
2762 | + node = next_node; |
2763 | + } |
2764 | + |
2765 | + if (state->keyboard != NULL) |
2766 | + { |
2767 | + ply_trace ("removing keyboard"); |
2768 | + ply_keyboard_stop_watching_for_input (state->keyboard); |
2769 | + ply_keyboard_free (state->keyboard); |
2770 | + state->keyboard = NULL; |
2771 | + } |
2772 | +} |
2773 | + |
2774 | +static void |
2775 | +on_show_splash (state_t *state) |
2776 | +{ |
2777 | + bool has_display; |
2778 | + |
2779 | + if (state->is_inactive) |
2780 | + { |
2781 | + ply_trace ("show splash called while inactive"); |
2782 | + return; |
2783 | + } |
2784 | + |
2785 | + if (plymouth_should_ignore_show_splash_calls (state)) |
2786 | + { |
2787 | + ply_trace ("show splash called while ignoring show splash calls"); |
2788 | + dump_details_and_quit_splash (state); |
2789 | + return; |
2790 | + } |
2791 | + |
2792 | + check_for_consoles (state, state->default_tty, true); |
2793 | + |
2794 | + has_display = ply_list_get_length (state->pixel_displays) > 0 || |
2795 | + ply_list_get_length (state->text_displays) > 0; |
2796 | + |
2797 | + if (!state->is_attached && state->should_be_attached && has_display) |
2798 | + attach_to_running_session (state); |
2799 | + |
2800 | + if (!has_display && state->is_attached) |
2801 | + { |
2802 | + ply_trace ("no open seats, detaching session"); |
2803 | + ply_terminal_session_detach (state->session); |
2804 | + state->is_redirected = false; |
2805 | + state->is_attached = false; |
2806 | + } |
2807 | + |
2808 | + if (plymouth_should_show_default_splash (state)) |
2809 | + { |
2810 | + show_default_splash (state); |
2811 | + state->showing_details = false; |
2812 | + } |
2813 | + else |
2814 | + { |
2815 | + show_detailed_splash (state); |
2816 | + state->showing_details = true; |
2817 | + } |
2818 | + flush_pending_messages (state); |
2819 | +} |
2820 | + |
2821 | +static void |
2822 | +quit_splash (state_t *state) |
2823 | +{ |
2824 | + ply_trace ("quiting splash"); |
2825 | + if (state->boot_splash != NULL) |
2826 | + { |
2827 | + ply_trace ("freeing splash"); |
2828 | + ply_boot_splash_free (state->boot_splash); |
2829 | + state->boot_splash = NULL; |
2830 | + } |
2831 | + |
2832 | + ply_trace ("removing displays and keyboard"); |
2833 | + remove_displays_and_keyboard (state); |
2834 | + |
2835 | + if (state->renderer != NULL) |
2836 | + { |
2837 | + ply_renderer_close (state->renderer); |
2838 | + ply_renderer_free (state->renderer); |
2839 | + state->renderer = NULL; |
2840 | + } |
2841 | + |
2842 | + if (state->terminal != NULL) |
2843 | + { |
2844 | + if (!state->should_retain_splash) |
2845 | + { |
2846 | + ply_trace ("Not retaining splash, so deallocating VT"); |
2847 | + ply_terminal_deactivate_vt (state->terminal); |
2848 | + } |
2849 | + ply_terminal_close (state->terminal); |
2850 | + ply_terminal_free (state->terminal); |
2851 | + state->terminal = NULL; |
2852 | + } |
2853 | + |
2854 | + if (state->session != NULL) |
2855 | + { |
2856 | + ply_trace ("detaching session"); |
2857 | + ply_terminal_session_detach (state->session); |
2858 | + state->is_redirected = false; |
2859 | + state->is_attached = false; |
2860 | + } |
2861 | +} |
2862 | + |
2863 | +static void |
2864 | +dump_details_and_quit_splash (state_t *state) |
2865 | +{ |
2866 | + state->showing_details = false; |
2867 | + toggle_between_splash_and_details (state); |
2868 | + |
2869 | + if (state->renderer != NULL) |
2870 | + ply_renderer_deactivate (state->renderer); |
2871 | + if (state->boot_splash != NULL) |
2872 | + ply_boot_splash_hide (state->boot_splash); |
2873 | + |
2874 | + quit_splash (state); |
2875 | +} |
2876 | + |
2877 | +static void |
2878 | +on_hide_splash (state_t *state) |
2879 | +{ |
2880 | + if (state->is_inactive) |
2881 | + return; |
2882 | + |
2883 | + if (state->boot_splash == NULL) |
2884 | + return; |
2885 | + |
2886 | + ply_trace ("hiding boot splash"); |
2887 | + dump_details_and_quit_splash (state); |
2888 | +} |
2889 | + |
2890 | +#ifdef PLY_ENABLE_GDM_TRANSITION |
2891 | +static void |
2892 | +tell_gdm_to_transition (void) |
2893 | +{ |
2894 | + int fd; |
2895 | + |
2896 | + fd = creat ("/var/spool/gdm/force-display-on-active-vt", 0644); |
2897 | + close (fd); |
2898 | +} |
2899 | +#endif |
2900 | + |
2901 | +static void |
2902 | +quit_program (state_t *state) |
2903 | +{ |
2904 | + ply_trace ("exiting event loop"); |
2905 | + ply_event_loop_exit (state->loop, 0); |
2906 | + |
2907 | + if (pid_file != NULL) |
2908 | + { |
2909 | + unlink (pid_file); |
2910 | + free (pid_file); |
2911 | + pid_file = NULL; |
2912 | + } |
2913 | + |
2914 | +#ifdef PLY_ENABLE_GDM_TRANSITION |
2915 | + if (state->should_retain_splash) |
2916 | + { |
2917 | + tell_gdm_to_transition (); |
2918 | + } |
2919 | +#endif |
2920 | + |
2921 | + if (state->deactivate_trigger != NULL) |
2922 | + { |
2923 | + ply_trigger_pull (state->deactivate_trigger, NULL); |
2924 | + state->deactivate_trigger = NULL; |
2925 | + } |
2926 | + if (state->quit_trigger != NULL) |
2927 | + { |
2928 | + ply_trigger_pull (state->quit_trigger, NULL); |
2929 | + state->quit_trigger = NULL; |
2930 | + } |
2931 | +} |
2932 | + |
2933 | +static void |
2934 | +deactivate_splash (state_t *state) |
2935 | +{ |
2936 | + assert (!state->is_inactive); |
2937 | + |
2938 | + if (state->renderer != NULL) |
2939 | + { |
2940 | + ply_trace ("deactivating renderer"); |
2941 | + ply_renderer_deactivate (state->renderer); |
2942 | + } |
2943 | + |
2944 | + if (state->keyboard != NULL) |
2945 | + { |
2946 | + ply_trace ("deactivating keyboard"); |
2947 | + ply_keyboard_stop_watching_for_input (state->keyboard); |
2948 | + } |
2949 | + |
2950 | + if ((state->session != NULL) && state->is_attached) |
2951 | + { |
2952 | + ply_trace ("deactivating terminal session"); |
2953 | + ply_terminal_session_detach (state->session); |
2954 | + state->is_redirected = false; |
2955 | + state->is_attached = false; |
2956 | + } |
2957 | + |
2958 | + if (state->terminal != NULL) |
2959 | + { |
2960 | + ply_trace ("deactivating terminal"); |
2961 | + ply_terminal_stop_watching_for_vt_changes (state->terminal); |
2962 | + ply_terminal_set_buffered_input (state->terminal); |
2963 | + ply_terminal_ignore_mode_changes (state->terminal, true); |
2964 | + } |
2965 | + |
2966 | + state->is_inactive = true; |
2967 | + |
2968 | + ply_trigger_pull (state->deactivate_trigger, NULL); |
2969 | + state->deactivate_trigger = NULL; |
2970 | +} |
2971 | + |
2972 | +static void |
2973 | +on_boot_splash_idle (state_t *state) |
2974 | +{ |
2975 | + ply_trace ("boot splash idle"); |
2976 | + |
2977 | + /* In the case where we've received both a deactivate command and a |
2978 | + * quit command, the quit command takes precedence. |
2979 | + */ |
2980 | + if (state->quit_trigger != NULL) |
2981 | + { |
2982 | + if (!state->should_retain_splash) |
2983 | + { |
2984 | + ply_trace ("hiding splash"); |
2985 | + if (state->renderer != NULL) |
2986 | + ply_renderer_deactivate (state->renderer); |
2987 | + if (state->boot_splash != NULL) |
2988 | + ply_boot_splash_hide (state->boot_splash); |
2989 | + } |
2990 | + |
2991 | + ply_trace ("quitting splash"); |
2992 | + quit_splash (state); |
2993 | + ply_trace ("quitting program"); |
2994 | + quit_program (state); |
2995 | + } |
2996 | + else if (state->deactivate_trigger != NULL) |
2997 | + { |
2998 | + ply_trace ("deactivating splash"); |
2999 | + deactivate_splash (state); |
3000 | + } |
3001 | +} |
3002 | + |
3003 | + |
3004 | +static void |
3005 | +on_deactivate (state_t *state, |
3006 | + ply_trigger_t *deactivate_trigger) |
3007 | +{ |
3008 | + if ((state->deactivate_trigger != NULL) || state->is_inactive) |
3009 | + { |
3010 | + ply_trigger_add_handler (state->deactivate_trigger, |
3011 | + (ply_trigger_handler_t) |
3012 | + ply_trigger_pull, |
3013 | + deactivate_trigger); |
3014 | + return; |
3015 | + } |
3016 | + |
3017 | + state->deactivate_trigger = deactivate_trigger; |
3018 | + |
3019 | + ply_trace ("deactivating"); |
3020 | + if (state->boot_splash != NULL) |
3021 | + { |
3022 | + ply_boot_splash_become_idle (state->boot_splash, |
3023 | + (ply_boot_splash_on_idle_handler_t) |
3024 | + on_boot_splash_idle, |
3025 | + state); |
3026 | + } |
3027 | + else |
3028 | + { |
3029 | + ply_trace ("deactivating splash"); |
3030 | + deactivate_splash (state); |
3031 | + } |
3032 | +} |
3033 | + |
3034 | +static void |
3035 | +on_reactivate (state_t *state) |
3036 | +{ |
3037 | + if (!state->is_inactive) |
3038 | + return; |
3039 | + |
3040 | + if (state->terminal != NULL) |
3041 | + { |
3042 | + ply_terminal_watch_for_vt_changes (state->terminal); |
3043 | + ply_terminal_set_unbuffered_input (state->terminal); |
3044 | + ply_terminal_ignore_mode_changes (state->terminal, false); |
3045 | + } |
3046 | + |
3047 | + if ((state->session != NULL) && state->should_be_attached) |
3048 | + { |
3049 | + ply_trace ("reactivating terminal session"); |
3050 | + attach_to_running_session (state); |
3051 | + } |
3052 | + |
3053 | + if (state->keyboard != NULL) |
3054 | + { |
3055 | + ply_trace ("activating keyboard"); |
3056 | + ply_keyboard_watch_for_input (state->keyboard); |
3057 | + } |
3058 | + |
3059 | + if (state->renderer != NULL) |
3060 | + { |
3061 | + ply_trace ("activating renderer"); |
3062 | + ply_renderer_activate (state->renderer); |
3063 | + } |
3064 | + |
3065 | + state->is_inactive = false; |
3066 | + |
3067 | + update_display (state); |
3068 | +} |
3069 | + |
3070 | +static void |
3071 | +on_quit (state_t *state, |
3072 | + bool retain_splash, |
3073 | + ply_trigger_t *quit_trigger) |
3074 | +{ |
3075 | + if (state->quit_trigger != NULL) |
3076 | + { |
3077 | + ply_trigger_add_handler (state->quit_trigger, |
3078 | + (ply_trigger_handler_t) |
3079 | + ply_trigger_pull, |
3080 | + quit_trigger); |
3081 | + return; |
3082 | + } |
3083 | + |
3084 | + state->quit_trigger = quit_trigger; |
3085 | + state->should_retain_splash = retain_splash; |
3086 | + |
3087 | + ply_trace ("time to quit, closing log"); |
3088 | + if (state->session != NULL) |
3089 | + ply_terminal_session_close_log (state->session); |
3090 | + ply_trace ("unloading splash"); |
3091 | + |
3092 | + if (state->is_inactive && !retain_splash) |
3093 | + { |
3094 | + /* We've been deactivated and X failed to start |
3095 | + */ |
3096 | + dump_details_and_quit_splash (state); |
3097 | + quit_program (state); |
3098 | + } |
3099 | + else if (state->boot_splash != NULL) |
3100 | + { |
3101 | + ply_boot_splash_become_idle (state->boot_splash, |
3102 | + (ply_boot_splash_on_idle_handler_t) |
3103 | + on_boot_splash_idle, |
3104 | + state); |
3105 | + } |
3106 | + else |
3107 | + quit_program (state); |
3108 | +} |
3109 | + |
3110 | +static bool |
3111 | +on_has_active_vt (state_t *state) |
3112 | +{ |
3113 | + if (state->terminal != NULL) |
3114 | + return ply_terminal_is_active (state->terminal); |
3115 | + else |
3116 | + return false; |
3117 | +} |
3118 | + |
3119 | +static ply_boot_server_t * |
3120 | +start_boot_server (state_t *state) |
3121 | +{ |
3122 | + ply_boot_server_t *server; |
3123 | + |
3124 | + server = ply_boot_server_new ((ply_boot_server_update_handler_t) on_update, |
3125 | + (ply_boot_server_ask_for_password_handler_t) on_ask_for_password, |
3126 | + (ply_boot_server_ask_question_handler_t) on_ask_question, |
3127 | + (ply_boot_server_display_message_handler_t) on_display_message, |
3128 | + (ply_boot_server_watch_for_keystroke_handler_t) on_watch_for_keystroke, |
3129 | + (ply_boot_server_ignore_keystroke_handler_t) on_ignore_keystroke, |
3130 | + (ply_boot_server_progress_pause_handler_t) on_progress_pause, |
3131 | + (ply_boot_server_progress_unpause_handler_t) on_progress_unpause, |
3132 | + (ply_boot_server_show_splash_handler_t) on_show_splash, |
3133 | + (ply_boot_server_hide_splash_handler_t) on_hide_splash, |
3134 | + (ply_boot_server_newroot_handler_t) on_newroot, |
3135 | + (ply_boot_server_system_initialized_handler_t) on_system_initialized, |
3136 | + (ply_boot_server_error_handler_t) on_error, |
3137 | + (ply_boot_server_deactivate_handler_t) on_deactivate, |
3138 | + (ply_boot_server_reactivate_handler_t) on_reactivate, |
3139 | + (ply_boot_server_quit_handler_t) on_quit, |
3140 | + (ply_boot_server_has_active_vt_handler_t) on_has_active_vt, |
3141 | + state); |
3142 | + |
3143 | + if (!ply_boot_server_listen (server)) |
3144 | + { |
3145 | + ply_save_errno (); |
3146 | + ply_boot_server_free (server); |
3147 | + ply_restore_errno (); |
3148 | + return NULL; |
3149 | + } |
3150 | + |
3151 | + ply_boot_server_attach_to_event_loop (server, state->loop); |
3152 | + |
3153 | + return server; |
3154 | +} |
3155 | + |
3156 | + |
3157 | +static void |
3158 | +update_display (state_t *state) |
3159 | +{ |
3160 | + if (!state->boot_splash) return; |
3161 | + |
3162 | + ply_list_node_t *node; |
3163 | + node = ply_list_get_first_node (state->entry_triggers); |
3164 | + if (node) |
3165 | + { |
3166 | + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); |
3167 | + if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) |
3168 | + { |
3169 | + int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), |
3170 | + ply_buffer_get_size (state->entry_buffer)); |
3171 | + bullets = MAX(0, bullets); |
3172 | + ply_boot_splash_display_password (state->boot_splash, |
3173 | + entry_trigger->prompt, |
3174 | + bullets); |
3175 | + } |
3176 | + else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) |
3177 | + { |
3178 | + ply_boot_splash_display_question (state->boot_splash, |
3179 | + entry_trigger->prompt, |
3180 | + ply_buffer_get_bytes (state->entry_buffer)); |
3181 | + } |
3182 | + else { |
3183 | + ply_trace("unkown entry type"); |
3184 | + } |
3185 | + } |
3186 | + else |
3187 | + { |
3188 | + ply_boot_splash_display_normal (state->boot_splash); |
3189 | + } |
3190 | + |
3191 | +} |
3192 | + |
3193 | +static void |
3194 | +toggle_between_splash_and_details (state_t *state) |
3195 | +{ |
3196 | + ply_trace ("toggling between splash and details"); |
3197 | + if (state->boot_splash != NULL) |
3198 | + { |
3199 | + ply_trace ("hiding and freeing current splash"); |
3200 | + ply_boot_splash_hide (state->boot_splash); |
3201 | + ply_boot_splash_free (state->boot_splash); |
3202 | + state->boot_splash = NULL; |
3203 | + } |
3204 | + |
3205 | + if (!state->showing_details) |
3206 | + { |
3207 | + show_detailed_splash (state); |
3208 | + state->showing_details = true; |
3209 | + } |
3210 | + else |
3211 | + { |
3212 | + show_default_splash (state); |
3213 | + state->showing_details = false; |
3214 | + } |
3215 | + update_display (state); |
3216 | +} |
3217 | + |
3218 | +static void |
3219 | +on_escape_pressed (state_t *state) |
3220 | +{ |
3221 | + ply_trace ("escape key pressed"); |
3222 | + toggle_between_splash_and_details (state); |
3223 | +} |
3224 | + |
3225 | +static void |
3226 | +on_keyboard_input (state_t *state, |
3227 | + const char *keyboard_input, |
3228 | + size_t character_size) |
3229 | +{ |
3230 | + ply_list_node_t *node; |
3231 | + node = ply_list_get_first_node (state->entry_triggers); |
3232 | + if (node) |
3233 | + { /* \x3 (ETX) is Ctrl+C and \x4 (EOT) is Ctrl+D */ |
3234 | + if (character_size == 1 && ( keyboard_input[0] == '\x3' || keyboard_input[0] == '\x4' )) |
3235 | + { |
3236 | + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); |
3237 | + ply_trigger_pull (entry_trigger->trigger, "\x3"); |
3238 | + ply_buffer_clear (state->entry_buffer); |
3239 | + ply_list_remove_node (state->entry_triggers, node); |
3240 | + free (entry_trigger); |
3241 | + } |
3242 | + else |
3243 | + { |
3244 | + ply_buffer_append_bytes (state->entry_buffer, keyboard_input, character_size); |
3245 | + } |
3246 | + update_display (state); |
3247 | + } |
3248 | + else |
3249 | + { |
3250 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
3251 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
3252 | + { |
3253 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
3254 | + if (!keystroke_trigger->keys || strstr(keystroke_trigger->keys, keyboard_input)) /* assume strstr works on utf8 arrays */ |
3255 | + { |
3256 | + ply_trigger_pull (keystroke_trigger->trigger, keyboard_input); |
3257 | + ply_list_remove_node (state->keystroke_triggers, node); |
3258 | + free(keystroke_trigger); |
3259 | + return; |
3260 | + } |
3261 | + } |
3262 | + return; |
3263 | + } |
3264 | +} |
3265 | + |
3266 | +static void |
3267 | +on_backspace (state_t *state) |
3268 | +{ |
3269 | + ssize_t bytes_to_remove; |
3270 | + ssize_t previous_character_size; |
3271 | + const char *bytes; |
3272 | + size_t size; |
3273 | + ply_list_node_t *node = ply_list_get_first_node (state->entry_triggers); |
3274 | + if (!node) return; |
3275 | + |
3276 | + bytes = ply_buffer_get_bytes (state->entry_buffer); |
3277 | + size = ply_buffer_get_size (state->entry_buffer); |
3278 | + |
3279 | + bytes_to_remove = MIN(size, PLY_UTF8_CHARACTER_SIZE_MAX); |
3280 | + while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < bytes_to_remove) |
3281 | + { |
3282 | + if (previous_character_size > 0) |
3283 | + bytes_to_remove -= previous_character_size; |
3284 | + else |
3285 | + bytes_to_remove--; |
3286 | + } |
3287 | + |
3288 | + ply_buffer_remove_bytes_at_end (state->entry_buffer, bytes_to_remove); |
3289 | + update_display (state); |
3290 | +} |
3291 | + |
3292 | +static void |
3293 | +on_enter (state_t *state, |
3294 | + const char *line) |
3295 | +{ |
3296 | + ply_list_node_t *node; |
3297 | + node = ply_list_get_first_node (state->entry_triggers); |
3298 | + if (node) |
3299 | + { |
3300 | + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); |
3301 | + const char* reply_text = ply_buffer_get_bytes (state->entry_buffer); |
3302 | + ply_trigger_pull (entry_trigger->trigger, reply_text); |
3303 | + ply_buffer_clear (state->entry_buffer); |
3304 | + ply_list_remove_node (state->entry_triggers, node); |
3305 | + free (entry_trigger); |
3306 | + update_display (state); |
3307 | + } |
3308 | + else |
3309 | + { |
3310 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
3311 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
3312 | + { |
3313 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
3314 | + if (!keystroke_trigger->keys || strstr(keystroke_trigger->keys, "\n")) /* assume strstr works on utf8 arrays */ |
3315 | + { |
3316 | + ply_trigger_pull (keystroke_trigger->trigger, line); |
3317 | + ply_list_remove_node (state->keystroke_triggers, node); |
3318 | + free(keystroke_trigger); |
3319 | + return; |
3320 | + } |
3321 | + } |
3322 | + return; |
3323 | + } |
3324 | +} |
3325 | + |
3326 | +static void |
3327 | +set_keyboard (state_t *state, |
3328 | + ply_keyboard_t *keyboard) |
3329 | +{ |
3330 | + state->keyboard = keyboard; |
3331 | + |
3332 | + ply_keyboard_add_escape_handler (keyboard, (ply_keyboard_escape_handler_t) |
3333 | + on_escape_pressed, state); |
3334 | + ply_trace ("listening for keystrokes"); |
3335 | + ply_keyboard_add_input_handler (keyboard, |
3336 | + (ply_keyboard_input_handler_t) |
3337 | + on_keyboard_input, state); |
3338 | + ply_trace ("listening for backspace"); |
3339 | + ply_keyboard_add_backspace_handler (keyboard, |
3340 | + (ply_keyboard_backspace_handler_t) |
3341 | + on_backspace, state); |
3342 | + ply_trace ("listening for enter"); |
3343 | + ply_keyboard_add_enter_handler (keyboard, |
3344 | + (ply_keyboard_enter_handler_t) |
3345 | + on_enter, state); |
3346 | +} |
3347 | +static void |
3348 | +add_display_and_keyboard_for_terminal (state_t *state, |
3349 | + const char *tty_name) |
3350 | +{ |
3351 | + ply_text_display_t *display; |
3352 | + ply_keyboard_t *keyboard; |
3353 | + |
3354 | + ply_trace ("adding display and keyboard for %s", tty_name); |
3355 | + |
3356 | + state->terminal = ply_terminal_new (tty_name); |
3357 | + |
3358 | + // urgh |
3359 | + if (!ply_terminal_open (state->terminal)) |
3360 | + return; |
3361 | + |
3362 | + keyboard = ply_keyboard_new_for_terminal (state->terminal); |
3363 | + display = ply_text_display_new (state->terminal); |
3364 | + |
3365 | + ply_list_append_data (state->text_displays, display); |
3366 | + state->keyboard = keyboard; |
3367 | + set_keyboard (state, keyboard); |
3368 | +} |
3369 | + |
3370 | +static void |
3371 | +add_pixel_displays_from_renderer (state_t *state, |
3372 | + ply_renderer_t *renderer) |
3373 | +{ |
3374 | + ply_list_t *heads; |
3375 | + ply_list_node_t *node; |
3376 | + |
3377 | + heads = ply_renderer_get_heads (renderer); |
3378 | + |
3379 | + ply_trace ("Adding displays for %d heads", |
3380 | + ply_list_get_length (heads)); |
3381 | + |
3382 | + node = ply_list_get_first_node (heads); |
3383 | + while (node != NULL) |
3384 | + { |
3385 | + ply_list_node_t *next_node; |
3386 | + ply_renderer_head_t *head; |
3387 | + ply_pixel_display_t *display; |
3388 | + |
3389 | + head = ply_list_node_get_data (node); |
3390 | + next_node = ply_list_get_next_node (heads, node); |
3391 | + |
3392 | + display = ply_pixel_display_new (renderer, head); |
3393 | + |
3394 | + ply_list_append_data (state->pixel_displays, display); |
3395 | + |
3396 | + node = next_node; |
3397 | + } |
3398 | + |
3399 | +} |
3400 | + |
3401 | +static void |
3402 | +add_default_displays_and_keyboard (state_t *state) |
3403 | +{ |
3404 | + ply_renderer_t *renderer; |
3405 | + ply_keyboard_t *keyboard; |
3406 | + ply_terminal_t *terminal; |
3407 | + ply_text_display_t *text_display; |
3408 | + |
3409 | + ply_trace ("adding default displays and keyboard"); |
3410 | + |
3411 | + terminal = ply_terminal_new (state->default_tty); |
3412 | + |
3413 | + renderer = ply_renderer_new (NULL, terminal); |
3414 | + |
3415 | + if (!ply_renderer_open (renderer)) |
3416 | + { |
3417 | + ply_trace ("could not open renderer /dev/fb"); |
3418 | + ply_renderer_free (renderer); |
3419 | + ply_terminal_free (terminal); |
3420 | + |
3421 | + add_display_and_keyboard_for_terminal (state, state->default_tty); |
3422 | + return; |
3423 | + } |
3424 | + |
3425 | + state->terminal = terminal; |
3426 | + |
3427 | + keyboard = ply_keyboard_new_for_renderer (renderer); |
3428 | + set_keyboard (state, keyboard); |
3429 | + |
3430 | + add_pixel_displays_from_renderer (state, renderer); |
3431 | + |
3432 | + text_display = ply_text_display_new (state->terminal); |
3433 | + ply_list_append_data (state->text_displays, text_display); |
3434 | + |
3435 | + state->renderer = renderer; |
3436 | +} |
3437 | + |
3438 | +static void |
3439 | +add_displays_and_keyboard_to_boot_splash (state_t *state, |
3440 | + ply_boot_splash_t *splash) |
3441 | +{ |
3442 | + ply_list_node_t *node; |
3443 | + |
3444 | + ply_trace ("setting keyboard on boot splash"); |
3445 | + if (state->keyboard != NULL) |
3446 | + ply_boot_splash_set_keyboard (splash, state->keyboard); |
3447 | + |
3448 | + node = ply_list_get_first_node (state->pixel_displays); |
3449 | + while (node != NULL) |
3450 | + { |
3451 | + ply_pixel_display_t *display; |
3452 | + ply_list_node_t *next_node; |
3453 | + |
3454 | + display = ply_list_node_get_data (node); |
3455 | + next_node = ply_list_get_next_node (state->pixel_displays, node); |
3456 | + ply_trace ("adding pixel display on boot splash"); |
3457 | + ply_boot_splash_add_pixel_display (splash, display); |
3458 | + |
3459 | + node = next_node; |
3460 | + } |
3461 | + |
3462 | + node = ply_list_get_first_node (state->text_displays); |
3463 | + while (node != NULL) |
3464 | + { |
3465 | + ply_text_display_t *display; |
3466 | + ply_list_node_t *next_node; |
3467 | + |
3468 | + display = ply_list_node_get_data (node); |
3469 | + next_node = ply_list_get_next_node (state->text_displays, node); |
3470 | + |
3471 | + ply_trace ("adding text display on boot splash"); |
3472 | + ply_boot_splash_add_text_display (splash, display); |
3473 | + |
3474 | + node = next_node; |
3475 | + } |
3476 | +} |
3477 | + |
3478 | +static ply_boot_splash_t * |
3479 | +start_boot_splash (state_t *state, |
3480 | + const char *theme_path) |
3481 | +{ |
3482 | + ply_boot_splash_t *splash; |
3483 | + ply_boot_splash_mode_t splash_mode; |
3484 | + |
3485 | + ply_trace ("Loading boot splash theme '%s'", |
3486 | + theme_path); |
3487 | + |
3488 | + splash = ply_boot_splash_new (theme_path, |
3489 | + PLYMOUTH_PLUGIN_PATH, |
3490 | + state->boot_buffer, |
3491 | + state->terminal); |
3492 | + |
3493 | + if (!ply_boot_splash_load (splash)) |
3494 | + { |
3495 | + ply_save_errno (); |
3496 | + ply_boot_splash_free (splash); |
3497 | + ply_restore_errno (); |
3498 | + return NULL; |
3499 | + } |
3500 | + |
3501 | + ply_trace ("attaching plugin to event loop"); |
3502 | + ply_boot_splash_attach_to_event_loop (splash, state->loop); |
3503 | + |
3504 | + ply_trace ("attaching progress to plugin"); |
3505 | + ply_boot_splash_attach_progress (splash, state->progress); |
3506 | + |
3507 | + add_displays_and_keyboard_to_boot_splash (state, splash); |
3508 | + |
3509 | + ply_trace ("showing plugin"); |
3510 | + if (state->mode == PLY_MODE_SHUTDOWN) |
3511 | + splash_mode = PLY_BOOT_SPLASH_MODE_SHUTDOWN; |
3512 | + else |
3513 | + splash_mode = PLY_BOOT_SPLASH_MODE_BOOT_UP; |
3514 | + |
3515 | + if (!ply_boot_splash_show (splash, splash_mode)) |
3516 | + { |
3517 | + ply_save_errno (); |
3518 | + ply_boot_splash_unset_keyboard (splash); |
3519 | + ply_boot_splash_free (splash); |
3520 | + ply_restore_errno (); |
3521 | + return NULL; |
3522 | + } |
3523 | + |
3524 | + ply_keyboard_watch_for_input (state->keyboard); |
3525 | + |
3526 | + update_display (state); |
3527 | + return splash; |
3528 | +} |
3529 | + |
3530 | +static bool |
3531 | +attach_to_running_session (state_t *state) |
3532 | +{ |
3533 | + ply_terminal_session_t *session; |
3534 | + ply_terminal_session_flags_t flags; |
3535 | + bool should_be_redirected; |
3536 | + |
3537 | + flags = 0; |
3538 | + |
3539 | + should_be_redirected = !state->no_boot_log; |
3540 | + |
3541 | + if (should_be_redirected) |
3542 | + flags |= PLY_TERMINAL_SESSION_FLAGS_REDIRECT_CONSOLE; |
3543 | + |
3544 | + if (state->session == NULL) |
3545 | + { |
3546 | + ply_trace ("creating new terminal session"); |
3547 | + session = ply_terminal_session_new (NULL); |
3548 | + |
3549 | + ply_terminal_session_attach_to_event_loop (session, state->loop); |
3550 | + } |
3551 | + else |
3552 | + { |
3553 | + session = state->session; |
3554 | + ply_trace ("session already created"); |
3555 | + } |
3556 | + |
3557 | + if (!ply_terminal_session_attach (session, flags, |
3558 | + (ply_terminal_session_output_handler_t) |
3559 | + on_session_output, |
3560 | + (ply_terminal_session_done_handler_t) |
3561 | + (should_be_redirected? on_session_finished: NULL), |
3562 | + -1, state)) |
3563 | + { |
3564 | + ply_save_errno (); |
3565 | + ply_terminal_session_free (session); |
3566 | + ply_buffer_free (state->boot_buffer); |
3567 | + state->boot_buffer = NULL; |
3568 | + ply_restore_errno (); |
3569 | + |
3570 | + state->is_redirected = false; |
3571 | + state->is_attached = false; |
3572 | + return false; |
3573 | + } |
3574 | + |
3575 | + state->is_redirected = should_be_redirected; |
3576 | + state->is_attached = true; |
3577 | + state->session = session; |
3578 | + |
3579 | + return true; |
3580 | +} |
3581 | + |
3582 | +static bool |
3583 | +get_kernel_command_line (state_t *state) |
3584 | +{ |
3585 | + int fd; |
3586 | + |
3587 | + ply_trace ("opening /proc/cmdline"); |
3588 | + fd = open ("proc/cmdline", O_RDONLY); |
3589 | + |
3590 | + if (fd < 0) |
3591 | + { |
3592 | + ply_trace ("couldn't open it: %m"); |
3593 | + return false; |
3594 | + } |
3595 | + |
3596 | + ply_trace ("reading kernel command line"); |
3597 | + if (read (fd, state->kernel_command_line, sizeof (state->kernel_command_line)) < 0) |
3598 | + { |
3599 | + ply_trace ("couldn't read it: %m"); |
3600 | + return false; |
3601 | + } |
3602 | + |
3603 | + ply_trace ("Kernel command line is: '%s'", state->kernel_command_line); |
3604 | + close (fd); |
3605 | + return true; |
3606 | +} |
3607 | + |
3608 | +static void |
3609 | +check_verbosity (state_t *state) |
3610 | +{ |
3611 | + char *path; |
3612 | + |
3613 | + ply_trace ("checking if tracing should be enabled"); |
3614 | + |
3615 | + path = NULL; |
3616 | + if ((strstr (state->kernel_command_line, " plymouth:debug ") != NULL) |
3617 | + || (strstr (state->kernel_command_line, "plymouth:debug ") != NULL) |
3618 | + || (strstr (state->kernel_command_line, " plymouth:debug") != NULL) |
3619 | + || (path = strstr (state->kernel_command_line, " plymouth:debug=file:")) != NULL) |
3620 | + { |
3621 | +#ifdef LOG_TO_DEBUG_FILE |
3622 | + int fd; |
3623 | +#endif |
3624 | + |
3625 | + ply_trace ("tracing should be enabled!"); |
3626 | + if (!ply_is_tracing ()) |
3627 | + ply_toggle_tracing (); |
3628 | + |
3629 | + if (path != NULL && debug_buffer_path == NULL) |
3630 | + { |
3631 | + char *end; |
3632 | + |
3633 | + path += strlen (" plymouth:debug=file:"); |
3634 | + debug_buffer_path = strdup (path); |
3635 | + end = strstr (debug_buffer_path, " "); |
3636 | + |
3637 | + if (end != NULL) |
3638 | + *end = '\0'; |
3639 | + |
3640 | + debug_buffer_path = path; |
3641 | + } |
3642 | + |
3643 | + if (debug_buffer == NULL) |
3644 | + debug_buffer = ply_buffer_new (); |
3645 | + |
3646 | +#ifdef LOG_TO_DEBUG_FILE |
3647 | + fd = open ("/dev/console", O_RDWR); |
3648 | + ply_logger_set_output_fd (ply_logger_get_error_default (), fd); |
3649 | +#endif |
3650 | + } |
3651 | + else |
3652 | + ply_trace ("tracing shouldn't be enabled!"); |
3653 | + |
3654 | + if (debug_buffer != NULL) |
3655 | + { |
3656 | + if (debug_buffer_path == NULL) |
3657 | + debug_buffer_path = strdup (PLYMOUTH_LOG_DIRECTORY "/plymouth-debug.log"); |
3658 | + |
3659 | + ply_logger_add_filter (ply_logger_get_error_default (), |
3660 | + (ply_logger_filter_handler_t) |
3661 | + on_error_message, |
3662 | + debug_buffer); |
3663 | + |
3664 | + } |
3665 | +} |
3666 | + |
3667 | +static void |
3668 | +check_logging (state_t *state) |
3669 | +{ |
3670 | + ply_trace ("checking if console messages should be redirected and logged"); |
3671 | + |
3672 | + if ((strstr (state->kernel_command_line, " plymouth:nolog ") != NULL) |
3673 | + || (strstr (state->kernel_command_line, "plymouth:nolog ") != NULL) |
3674 | + || (strstr (state->kernel_command_line, " plymouth:nolog") != NULL)) |
3675 | + { |
3676 | + ply_trace ("logging won't be enabled!"); |
3677 | + state->no_boot_log = true; |
3678 | + } |
3679 | + else |
3680 | + { |
3681 | + ply_trace ("logging will be enabled!"); |
3682 | + state->no_boot_log = false; |
3683 | + } |
3684 | +} |
3685 | + |
3686 | +static void |
3687 | +check_for_consoles (state_t *state, |
3688 | + const char *default_tty, |
3689 | + bool should_add_displays) |
3690 | +{ |
3691 | + char *console_key; |
3692 | + char *remaining_command_line; |
3693 | + |
3694 | + ply_trace ("checking for consoles%s", |
3695 | + should_add_displays? " and adding displays": ""); |
3696 | + |
3697 | + remaining_command_line = state->kernel_command_line; |
3698 | + while ((console_key = strstr (remaining_command_line, " console=")) != NULL) |
3699 | + { |
3700 | + char *end; |
3701 | + ply_trace ("serial console found!"); |
3702 | + |
3703 | + free (state->kernel_console_tty); |
3704 | + state->kernel_console_tty = strdup (console_key + strlen (" console=")); |
3705 | + |
3706 | + remaining_command_line = console_key + strlen (" console="); |
3707 | + |
3708 | + end = strpbrk (state->kernel_console_tty, " \n\t\v,"); |
3709 | + |
3710 | + if (end != NULL) |
3711 | + { |
3712 | + *end = '\0'; |
3713 | + remaining_command_line += end - state->kernel_console_tty; |
3714 | + } |
3715 | + |
3716 | + if (strcmp (state->kernel_console_tty, "tty0") == 0 || strcmp (state->kernel_console_tty, "/dev/tty0") == 0) |
3717 | + { |
3718 | + free (state->kernel_console_tty); |
3719 | + state->kernel_console_tty = strdup (default_tty); |
3720 | + } |
3721 | + |
3722 | + if (should_add_displays) |
3723 | + add_display_and_keyboard_for_terminal (state, state->kernel_console_tty); |
3724 | + } |
3725 | + |
3726 | + ply_trace ("There are currently %d text displays", |
3727 | + ply_list_get_length (state->text_displays)); |
3728 | + if (should_add_displays && ply_list_get_length (state->text_displays) == 0) |
3729 | + add_default_displays_and_keyboard (state); |
3730 | +} |
3731 | + |
3732 | +static bool |
3733 | +redirect_standard_io_to_device (const char *device) |
3734 | +{ |
3735 | + int fd; |
3736 | + char *file; |
3737 | + |
3738 | + ply_trace ("redirecting stdio to %s", device); |
3739 | + |
3740 | + if (strncmp (device, "/dev/", strlen ("/dev/")) == 0) |
3741 | + file = strdup (device); |
3742 | + else |
3743 | + asprintf (&file, "/dev/%s", device); |
3744 | + |
3745 | + fd = open (file, O_RDWR | O_APPEND); |
3746 | + |
3747 | + free (file); |
3748 | + |
3749 | + if (fd < 0) |
3750 | + return false; |
3751 | + |
3752 | + dup2 (fd, STDIN_FILENO); |
3753 | + dup2 (fd, STDOUT_FILENO); |
3754 | + dup2 (fd, STDERR_FILENO); |
3755 | + |
3756 | + close (fd); |
3757 | + |
3758 | + return true; |
3759 | +} |
3760 | + |
3761 | +static bool |
3762 | +initialize_environment (state_t *state) |
3763 | +{ |
3764 | + ply_trace ("initializing minimal work environment"); |
3765 | + |
3766 | + if (!get_kernel_command_line (state)) |
3767 | + return false; |
3768 | + |
3769 | + check_verbosity (state); |
3770 | + check_logging (state); |
3771 | + |
3772 | + state->keystroke_triggers = ply_list_new (); |
3773 | + state->entry_triggers = ply_list_new (); |
3774 | + state->entry_buffer = ply_buffer_new(); |
3775 | + state->pixel_displays = ply_list_new (); |
3776 | + state->text_displays = ply_list_new (); |
3777 | + state->pending_messages = ply_list_new (); |
3778 | + state->keyboard = NULL; |
3779 | + |
3780 | + if (!state->default_tty) |
3781 | + { |
3782 | + if (state->mode == PLY_MODE_SHUTDOWN) |
3783 | + { |
3784 | + state->default_tty = SHUTDOWN_TTY; |
3785 | + } |
3786 | + else |
3787 | + state->default_tty = BOOT_TTY; |
3788 | + } |
3789 | + |
3790 | + check_for_consoles (state, state->default_tty, false); |
3791 | + |
3792 | + if (state->kernel_console_tty != NULL) |
3793 | + redirect_standard_io_to_device (state->kernel_console_tty); |
3794 | + else |
3795 | + redirect_standard_io_to_device (state->default_tty); |
3796 | + |
3797 | + ply_trace ("initialized minimal work environment"); |
3798 | + return true; |
3799 | +} |
3800 | + |
3801 | +static void |
3802 | +on_error_message (ply_buffer_t *debug_buffer, |
3803 | + const void *bytes, |
3804 | + size_t number_of_bytes) |
3805 | +{ |
3806 | + ply_buffer_append_bytes (debug_buffer, bytes, number_of_bytes); |
3807 | +} |
3808 | + |
3809 | +static void |
3810 | +dump_debug_buffer_to_file (void) |
3811 | +{ |
3812 | + int fd; |
3813 | + const char *bytes; |
3814 | + size_t size; |
3815 | + |
3816 | + fd = open (debug_buffer_path, |
3817 | + O_WRONLY | O_CREAT | O_TRUNC, 0600); |
3818 | + |
3819 | + if (fd < 0) |
3820 | + return; |
3821 | + |
3822 | + size = ply_buffer_get_size (debug_buffer); |
3823 | + bytes = ply_buffer_get_bytes (debug_buffer); |
3824 | + ply_write (fd, bytes, size); |
3825 | + close (fd); |
3826 | +} |
3827 | + |
3828 | + #include <termios.h> |
3829 | + #include <unistd.h> |
3830 | +static void |
3831 | +on_crash (int signum) |
3832 | +{ |
3833 | + struct termios term_attributes; |
3834 | + int fd; |
3835 | + |
3836 | + fd = open ("/dev/tty1", O_RDWR | O_NOCTTY); |
3837 | + if (fd < 0) fd = open ("/dev/hvc0", O_RDWR | O_NOCTTY); |
3838 | + |
3839 | + ioctl (fd, KDSETMODE, KD_TEXT); |
3840 | + |
3841 | + tcgetattr (fd, &term_attributes); |
3842 | + |
3843 | + term_attributes.c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON; |
3844 | + term_attributes.c_oflag |= OPOST; |
3845 | + term_attributes.c_lflag |= ECHO | ICANON | ISIG | IEXTEN; |
3846 | + |
3847 | + tcsetattr (fd, TCSAFLUSH, &term_attributes); |
3848 | + |
3849 | + close (fd); |
3850 | + |
3851 | + if (debug_buffer != NULL) |
3852 | + { |
3853 | + dump_debug_buffer_to_file (); |
3854 | + pause (); |
3855 | + } |
3856 | + |
3857 | + if (pid_file != NULL) |
3858 | + { |
3859 | + unlink (pid_file); |
3860 | + free (pid_file); |
3861 | + pid_file = NULL; |
3862 | + } |
3863 | + |
3864 | + signal (signum, SIG_DFL); |
3865 | + raise(signum); |
3866 | +} |
3867 | + |
3868 | +int |
3869 | +main (int argc, |
3870 | + char **argv) |
3871 | +{ |
3872 | + state_t state = { 0 }; |
3873 | + int exit_code; |
3874 | + bool should_help = false; |
3875 | + bool no_daemon = false; |
3876 | + bool debug = false; |
3877 | + bool attach_to_session; |
3878 | + ply_daemon_handle_t *daemon_handle; |
3879 | + char *mode_string = NULL; |
3880 | + char *tty = NULL; |
3881 | + |
3882 | + state.command_parser = ply_command_parser_new ("plymouthd", "Boot splash control server"); |
3883 | + |
3884 | + state.loop = ply_event_loop_get_default (); |
3885 | + |
3886 | + ply_command_parser_add_options (state.command_parser, |
3887 | + "help", "This help message", PLY_COMMAND_OPTION_TYPE_FLAG, |
3888 | + "attach-to-session", "Redirect console messages from screen to log", PLY_COMMAND_OPTION_TYPE_FLAG, |
3889 | + "no-daemon", "Do not daemonize", PLY_COMMAND_OPTION_TYPE_FLAG, |
3890 | + "debug", "Output debugging information", PLY_COMMAND_OPTION_TYPE_FLAG, |
3891 | + "debug-file", "File to output debugging information to", PLY_COMMAND_OPTION_TYPE_STRING, |
3892 | + "mode", "Mode is one of: boot, shutdown", PLY_COMMAND_OPTION_TYPE_STRING, |
3893 | + "pid-file", "Write the pid of the daemon to a file", PLY_COMMAND_OPTION_TYPE_STRING, |
3894 | + "tty", "TTY to use instead of default", PLY_COMMAND_OPTION_TYPE_STRING, |
3895 | + NULL); |
3896 | + |
3897 | + if (!ply_command_parser_parse_arguments (state.command_parser, state.loop, argv, argc)) |
3898 | + { |
3899 | + char *help_string; |
3900 | + |
3901 | + help_string = ply_command_parser_get_help_string (state.command_parser); |
3902 | + |
3903 | + ply_error ("%s", help_string); |
3904 | + |
3905 | + free (help_string); |
3906 | + return EX_USAGE; |
3907 | + } |
3908 | + |
3909 | + ply_command_parser_get_options (state.command_parser, |
3910 | + "help", &should_help, |
3911 | + "attach-to-session", &attach_to_session, |
3912 | + "mode", &mode_string, |
3913 | + "no-daemon", &no_daemon, |
3914 | + "debug", &debug, |
3915 | + "debug-file", &debug_buffer_path, |
3916 | + "pid-file", &pid_file, |
3917 | + "tty", &tty, |
3918 | + NULL); |
3919 | + |
3920 | + if (should_help) |
3921 | + { |
3922 | + char *help_string; |
3923 | + |
3924 | + help_string = ply_command_parser_get_help_string (state.command_parser); |
3925 | + |
3926 | + if (argc < 2) |
3927 | + fprintf (stderr, "%s", help_string); |
3928 | + else |
3929 | + printf ("%s", help_string); |
3930 | + |
3931 | + free (help_string); |
3932 | + return 0; |
3933 | + } |
3934 | + |
3935 | + if (debug && !ply_is_tracing ()) |
3936 | + ply_toggle_tracing (); |
3937 | + |
3938 | + if (mode_string != NULL) |
3939 | + { |
3940 | + if (strcmp (mode_string, "shutdown") == 0) |
3941 | + state.mode = PLY_MODE_SHUTDOWN; |
3942 | + else |
3943 | + state.mode = PLY_MODE_BOOT; |
3944 | + |
3945 | + free (mode_string); |
3946 | + } |
3947 | + |
3948 | + if (tty != NULL) |
3949 | + { |
3950 | + state.default_tty = tty; |
3951 | + } |
3952 | + |
3953 | + if (geteuid () != 0) |
3954 | + { |
3955 | + ply_error ("plymouthd must be run as root user"); |
3956 | + return EX_OSERR; |
3957 | + } |
3958 | + |
3959 | + chdir ("/"); |
3960 | + signal (SIGPIPE, SIG_IGN); |
3961 | + |
3962 | + if (! no_daemon) |
3963 | + { |
3964 | + daemon_handle = ply_create_daemon (pid_file); |
3965 | + |
3966 | + if (daemon_handle == NULL) |
3967 | + { |
3968 | + ply_error ("cannot daemonize: %m"); |
3969 | + return EX_UNAVAILABLE; |
3970 | + } |
3971 | + } |
3972 | + |
3973 | + if (debug) |
3974 | + debug_buffer = ply_buffer_new (); |
3975 | + |
3976 | + signal (SIGABRT, on_crash); |
3977 | + signal (SIGSEGV, on_crash); |
3978 | + |
3979 | + /* If we're shutting down we don't want to die until killed |
3980 | + */ |
3981 | + if (state.mode == PLY_MODE_SHUTDOWN) |
3982 | + signal (SIGTERM, SIG_IGN); |
3983 | + |
3984 | + /* before do anything we need to make sure we have a working |
3985 | + * environment. |
3986 | + */ |
3987 | + if (!initialize_environment (&state)) |
3988 | + { |
3989 | + if (errno == 0) |
3990 | + { |
3991 | + if (! no_daemon) |
3992 | + ply_detach_daemon (daemon_handle, 0); |
3993 | + return 0; |
3994 | + } |
3995 | + |
3996 | + ply_error ("could not setup basic operating environment: %m"); |
3997 | + if (! no_daemon) |
3998 | + ply_detach_daemon (daemon_handle, EX_OSERR); |
3999 | + return EX_OSERR; |
4000 | + } |
4001 | + |
4002 | + state.boot_buffer = ply_buffer_new (); |
4003 | + |
4004 | + if (attach_to_session) |
4005 | + { |
4006 | + state.should_be_attached = attach_to_session; |
4007 | + if (!attach_to_running_session (&state)) |
4008 | + { |
4009 | + ply_error ("could not create session: %m"); |
4010 | + if (! no_daemon) |
4011 | + ply_detach_daemon (daemon_handle, EX_UNAVAILABLE); |
4012 | + return EX_UNAVAILABLE; |
4013 | + } |
4014 | + } |
4015 | + |
4016 | + state.boot_server = start_boot_server (&state); |
4017 | + |
4018 | + if (state.boot_server == NULL) |
4019 | + { |
4020 | + ply_error ("could not log bootup: %m"); |
4021 | + if (! no_daemon) |
4022 | + ply_detach_daemon (daemon_handle, EX_UNAVAILABLE); |
4023 | + return EX_UNAVAILABLE; |
4024 | + } |
4025 | + |
4026 | + if (! no_daemon) |
4027 | + if (!ply_detach_daemon (daemon_handle, 0)) |
4028 | + { |
4029 | + ply_error ("could not tell parent to exit: %m"); |
4030 | + return EX_UNAVAILABLE; |
4031 | + } |
4032 | + |
4033 | + state.progress = ply_progress_new (); |
4034 | + |
4035 | + ply_progress_load_cache (state.progress, |
4036 | + get_cache_file_for_mode (state.mode)); |
4037 | + |
4038 | + ply_trace ("entering event loop"); |
4039 | + exit_code = ply_event_loop_run (state.loop); |
4040 | + ply_trace ("exited event loop"); |
4041 | + |
4042 | + ply_progress_save_cache (state.progress, |
4043 | + get_cache_file_for_mode (state.mode)); |
4044 | + |
4045 | + ply_boot_splash_free (state.boot_splash); |
4046 | + state.boot_splash = NULL; |
4047 | + |
4048 | + ply_command_parser_free (state.command_parser); |
4049 | + |
4050 | + ply_boot_server_free (state.boot_server); |
4051 | + state.boot_server = NULL; |
4052 | + |
4053 | + ply_trace ("freeing terminal session"); |
4054 | + ply_terminal_session_free (state.session); |
4055 | + |
4056 | + ply_buffer_free (state.boot_buffer); |
4057 | + ply_progress_free (state.progress); |
4058 | + |
4059 | + ply_trace ("exiting with code %d", exit_code); |
4060 | + |
4061 | + if (debug_buffer != NULL) |
4062 | + { |
4063 | + dump_debug_buffer_to_file (); |
4064 | + ply_buffer_free (debug_buffer); |
4065 | + } |
4066 | + |
4067 | + ply_free_error_log(); |
4068 | + |
4069 | + return exit_code; |
4070 | +} |
4071 | +/* vim: set sts=4 ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ |
4072 | |
4073 | === added directory '.pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch' |
4074 | === added directory '.pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src' |
4075 | === added file '.pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src/main.c' |
4076 | --- .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src/main.c 1970-01-01 00:00:00 +0000 |
4077 | +++ .pc/main-Don-t-watch-for-keyboard-input-if-no-keyboard.patch/src/main.c 2013-11-30 04:03:08 +0000 |
4078 | @@ -0,0 +1,1986 @@ |
4079 | +/* main.c - boot messages monitor |
4080 | + * |
4081 | + * Copyright (C) 2007 Red Hat, Inc |
4082 | + * |
4083 | + * This file is free software; you can redistribute it and/or modify |
4084 | + * it under the terms of the GNU General Public License as published |
4085 | + * by the Free Software Foundation; either version 2 of the License, |
4086 | + * or (at your option) any later version. |
4087 | + * |
4088 | + * This file is distributed in the hope that it will be useful, but |
4089 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
4090 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4091 | + * General Public License for more details. |
4092 | + * |
4093 | + * You should have received a copy of the GNU General Public License |
4094 | + * along with this; see the file COPYING. If not, write to the Free |
4095 | + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
4096 | + * 02111-1307, USA. |
4097 | + * |
4098 | + * Written by: Ray Strode <rstrode@redhat.com> |
4099 | + */ |
4100 | +#include "config.h" |
4101 | + |
4102 | +#include <sys/stat.h> |
4103 | +#include <sys/types.h> |
4104 | +#include <limits.h> |
4105 | +#include <dirent.h> |
4106 | +#include <fcntl.h> |
4107 | +#include <stdlib.h> |
4108 | +#include <stdio.h> |
4109 | +#include <sysexits.h> |
4110 | +#include <sys/ioctl.h> |
4111 | +#include <unistd.h> |
4112 | +#include <wchar.h> |
4113 | +#include <paths.h> |
4114 | +#include <assert.h> |
4115 | + |
4116 | +#include <linux/kd.h> |
4117 | +#include <linux/vt.h> |
4118 | + |
4119 | +#include "ply-buffer.h" |
4120 | +#include "ply-command-parser.h" |
4121 | +#include "ply-boot-server.h" |
4122 | +#include "ply-boot-splash.h" |
4123 | +#include "ply-event-loop.h" |
4124 | +#include "ply-list.h" |
4125 | +#include "ply-logger.h" |
4126 | +#include "ply-terminal-session.h" |
4127 | +#include "ply-trigger.h" |
4128 | +#include "ply-utils.h" |
4129 | +#include "ply-progress.h" |
4130 | + |
4131 | +#ifndef PLY_MAX_COMMAND_LINE_SIZE |
4132 | +#define PLY_MAX_COMMAND_LINE_SIZE 512 |
4133 | +#endif |
4134 | + |
4135 | +#define BOOT_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/boot-duration" |
4136 | +#define SHUTDOWN_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/shutdown-duration" |
4137 | + |
4138 | +typedef enum { |
4139 | + PLY_MODE_BOOT, |
4140 | + PLY_MODE_SHUTDOWN |
4141 | +} ply_mode_t; |
4142 | + |
4143 | +typedef struct |
4144 | +{ |
4145 | + const char *keys; |
4146 | + ply_trigger_t *trigger; |
4147 | +} ply_keystroke_watch_t; |
4148 | + |
4149 | +typedef struct |
4150 | +{ |
4151 | + enum {PLY_ENTRY_TRIGGER_TYPE_PASSWORD, |
4152 | + PLY_ENTRY_TRIGGER_TYPE_QUESTION} |
4153 | + type; |
4154 | + const char *prompt; |
4155 | + ply_trigger_t *trigger; |
4156 | +} ply_entry_trigger_t; |
4157 | + |
4158 | +typedef struct |
4159 | +{ |
4160 | + ply_event_loop_t *loop; |
4161 | + ply_boot_server_t *boot_server; |
4162 | + ply_list_t *pixel_displays; |
4163 | + ply_list_t *text_displays; |
4164 | + ply_keyboard_t *keyboard; |
4165 | + ply_boot_splash_t *boot_splash; |
4166 | + ply_terminal_session_t *session; |
4167 | + ply_buffer_t *boot_buffer; |
4168 | + ply_progress_t *progress; |
4169 | + ply_list_t *keystroke_triggers; |
4170 | + ply_list_t *entry_triggers; |
4171 | + ply_buffer_t *entry_buffer; |
4172 | + ply_command_parser_t *command_parser; |
4173 | + ply_mode_t mode; |
4174 | + ply_renderer_t *renderer; |
4175 | + ply_terminal_t *terminal; |
4176 | + |
4177 | + ply_trigger_t *deactivate_trigger; |
4178 | + ply_trigger_t *quit_trigger; |
4179 | + |
4180 | + char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; |
4181 | + uint32_t no_boot_log : 1; |
4182 | + uint32_t showing_details : 1; |
4183 | + uint32_t system_initialized : 1; |
4184 | + uint32_t is_redirected : 1; |
4185 | + uint32_t is_attached : 1; |
4186 | + uint32_t should_be_attached : 1; |
4187 | + uint32_t should_retain_splash : 1; |
4188 | + uint32_t is_inactive : 1; |
4189 | + |
4190 | + char *kernel_console_tty; |
4191 | + char *override_splash_path; |
4192 | + char *system_default_splash_path; |
4193 | + char *distribution_default_splash_path; |
4194 | + const char *default_tty; |
4195 | + |
4196 | + int number_of_errors; |
4197 | + ply_list_t *pending_messages; |
4198 | +} state_t; |
4199 | + |
4200 | +static ply_boot_splash_t *start_boot_splash (state_t *state, |
4201 | + const char *theme_path); |
4202 | + |
4203 | +static void add_display_and_keyboard_for_terminal (state_t *state, |
4204 | + const char *tty_name); |
4205 | + |
4206 | +static void add_default_displays_and_keyboard (state_t *state); |
4207 | + |
4208 | +static bool attach_to_running_session (state_t *state); |
4209 | +static void on_escape_pressed (state_t *state); |
4210 | +static void dump_details_and_quit_splash (state_t *state); |
4211 | +static void update_display (state_t *state); |
4212 | + |
4213 | +static void on_error_message (ply_buffer_t *debug_buffer, |
4214 | + const void *bytes, |
4215 | + size_t number_of_bytes); |
4216 | +static ply_buffer_t *debug_buffer; |
4217 | +static char *debug_buffer_path = NULL; |
4218 | +static char *pid_file = NULL; |
4219 | +static void check_for_consoles (state_t *state, |
4220 | + const char *default_tty, |
4221 | + bool should_add_displays); |
4222 | +static void toggle_between_splash_and_details (state_t *state); |
4223 | + |
4224 | +static void |
4225 | +on_session_output (state_t *state, |
4226 | + const char *output, |
4227 | + size_t size) |
4228 | +{ |
4229 | + ply_buffer_append_bytes (state->boot_buffer, output, size); |
4230 | + if (state->boot_splash != NULL) |
4231 | + ply_boot_splash_update_output (state->boot_splash, |
4232 | + output, size); |
4233 | +} |
4234 | + |
4235 | +static void |
4236 | +on_session_finished (state_t *state) |
4237 | +{ |
4238 | + ply_trace ("got hang up on terminal session fd"); |
4239 | +} |
4240 | + |
4241 | +static void |
4242 | +on_update (state_t *state, |
4243 | + const char *status) |
4244 | +{ |
4245 | + ply_trace ("updating status to '%s'", status); |
4246 | + if (strncmp (status, "fsck:", 5)) |
4247 | + ply_progress_status_update (state->progress, |
4248 | + status); |
4249 | + if (state->boot_splash != NULL) |
4250 | + ply_boot_splash_update_status (state->boot_splash, |
4251 | + status); |
4252 | +} |
4253 | + |
4254 | +static void |
4255 | +flush_pending_messages (state_t *state) |
4256 | +{ |
4257 | + ply_list_node_t *node = ply_list_get_first_node (state->pending_messages); |
4258 | + while (node != NULL) |
4259 | + { |
4260 | + ply_list_node_t *next_node; |
4261 | + char *message = ply_list_node_get_data (node); |
4262 | + |
4263 | + ply_trace ("displaying queued message"); |
4264 | + |
4265 | + ply_boot_splash_display_message (state->boot_splash, message); |
4266 | + next_node = ply_list_get_next_node (state->pending_messages, node); |
4267 | + ply_list_remove_node (state->pending_messages, node); |
4268 | + free(message); |
4269 | + node = next_node; |
4270 | + } |
4271 | +} |
4272 | + |
4273 | +static void |
4274 | +show_detailed_splash (state_t *state) |
4275 | +{ |
4276 | + if (state->boot_splash != NULL) |
4277 | + return; |
4278 | + |
4279 | + ply_trace ("Showing detailed splash screen"); |
4280 | + state->boot_splash = start_boot_splash (state, |
4281 | + PLYMOUTH_THEME_PATH "details/details.plymouth"); |
4282 | + |
4283 | + if (state->boot_splash == NULL) |
4284 | + { |
4285 | + ply_trace ("Could not start detailed splash screen, exiting"); |
4286 | + exit (1); |
4287 | + } |
4288 | +} |
4289 | + |
4290 | +static void |
4291 | +find_override_splash (state_t *state) |
4292 | +{ |
4293 | + char *splash_string; |
4294 | + |
4295 | + if (state->override_splash_path != NULL) |
4296 | + return; |
4297 | + |
4298 | + splash_string = strstr (state->kernel_command_line, "plymouth:splash="); |
4299 | + |
4300 | + if (splash_string != NULL) |
4301 | + { |
4302 | + char *end; |
4303 | + splash_string = strdup (splash_string + strlen ("plymouth:splash=")); |
4304 | + |
4305 | + end = splash_string + strcspn (splash_string, " \n"); |
4306 | + *end = '\0'; |
4307 | + |
4308 | + ply_trace ("Splash is configured to be '%s'", splash_string); |
4309 | + |
4310 | + asprintf (&state->override_splash_path, |
4311 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
4312 | + splash_string, splash_string); |
4313 | + } |
4314 | +} |
4315 | + |
4316 | +static void |
4317 | +find_system_default_splash (state_t *state) |
4318 | +{ |
4319 | + ply_key_file_t *key_file; |
4320 | + char *splash_string; |
4321 | + |
4322 | + if (state->system_default_splash_path != NULL) |
4323 | + return; |
4324 | + |
4325 | + ply_trace ("Trying to load " PLYMOUTH_CONF_DIR "plymouthd.conf"); |
4326 | + key_file = ply_key_file_new (PLYMOUTH_CONF_DIR "plymouthd.conf"); |
4327 | + |
4328 | + if (!ply_key_file_load (key_file)) |
4329 | + { |
4330 | + ply_trace ("failed to load " PLYMOUTH_CONF_DIR "plymouthd.conf"); |
4331 | + ply_key_file_free (key_file); |
4332 | + return; |
4333 | + } |
4334 | + |
4335 | + splash_string = ply_key_file_get_value (key_file, "Daemon", "Theme"); |
4336 | + |
4337 | + ply_trace ("System default splash is configured to be '%s'", splash_string); |
4338 | + |
4339 | + asprintf (&state->system_default_splash_path, |
4340 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
4341 | + splash_string, splash_string); |
4342 | + free (splash_string); |
4343 | +} |
4344 | + |
4345 | +static void |
4346 | +find_distribution_default_splash (state_t *state) |
4347 | +{ |
4348 | + ply_key_file_t *key_file; |
4349 | + char *splash_string; |
4350 | + |
4351 | + if (state->distribution_default_splash_path != NULL) |
4352 | + return; |
4353 | + |
4354 | + ply_trace ("Trying to load " PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
4355 | + key_file = ply_key_file_new (PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
4356 | + |
4357 | + if (!ply_key_file_load (key_file)) |
4358 | + { |
4359 | + ply_trace ("failed to load " PLYMOUTH_POLICY_DIR "plymouthd.defaults"); |
4360 | + ply_key_file_free (key_file); |
4361 | + return; |
4362 | + } |
4363 | + |
4364 | + splash_string = ply_key_file_get_value (key_file, "Daemon", "Theme"); |
4365 | + |
4366 | + ply_trace ("Distribution default splash is configured to be '%s'", splash_string); |
4367 | + |
4368 | + asprintf (&state->distribution_default_splash_path, |
4369 | + PLYMOUTH_THEME_PATH "%s/%s.plymouth", |
4370 | + splash_string, splash_string); |
4371 | + free (splash_string); |
4372 | +} |
4373 | + |
4374 | +static void |
4375 | +show_default_splash (state_t *state) |
4376 | +{ |
4377 | + if (state->boot_splash != NULL) |
4378 | + return; |
4379 | + |
4380 | + ply_trace ("Showing splash screen"); |
4381 | + find_override_splash (state); |
4382 | + if (state->override_splash_path != NULL) |
4383 | + { |
4384 | + ply_trace ("Trying override splash at '%s'", state->override_splash_path); |
4385 | + state->boot_splash = start_boot_splash (state, |
4386 | + state->override_splash_path); |
4387 | + } |
4388 | + |
4389 | + find_system_default_splash (state); |
4390 | + if (state->boot_splash == NULL && |
4391 | + state->system_default_splash_path != NULL) |
4392 | + { |
4393 | + ply_trace ("Trying system default splash"); |
4394 | + state->boot_splash = start_boot_splash (state, |
4395 | + state->system_default_splash_path); |
4396 | + } |
4397 | + |
4398 | + find_distribution_default_splash (state); |
4399 | + if (state->boot_splash == NULL && |
4400 | + state->distribution_default_splash_path != NULL) |
4401 | + { |
4402 | + ply_trace ("Trying distribution default splash"); |
4403 | + state->boot_splash = start_boot_splash (state, |
4404 | + state->distribution_default_splash_path); |
4405 | + } |
4406 | + |
4407 | + if (state->boot_splash == NULL) |
4408 | + { |
4409 | + ply_trace ("Trying old scheme for default splash"); |
4410 | + state->boot_splash = start_boot_splash (state, |
4411 | + PLYMOUTH_THEME_PATH "default.plymouth"); |
4412 | + } |
4413 | + |
4414 | + if (state->boot_splash == NULL) |
4415 | + { |
4416 | + ply_trace ("Could not start default splash screen," |
4417 | + "showing text splash screen"); |
4418 | + state->boot_splash = start_boot_splash (state, |
4419 | + PLYMOUTH_THEME_PATH "text.plymouth"); |
4420 | + } |
4421 | + |
4422 | + if (state->boot_splash == NULL) |
4423 | + { |
4424 | + if (errno != ENOENT) |
4425 | + ply_error ("could not start boot splash: %m"); |
4426 | + show_detailed_splash (state); |
4427 | + } |
4428 | +} |
4429 | + |
4430 | +static void |
4431 | +on_ask_for_password (state_t *state, |
4432 | + const char *prompt, |
4433 | + ply_trigger_t *answer) |
4434 | +{ |
4435 | + ply_entry_trigger_t *entry_trigger; |
4436 | + |
4437 | + /* No splash, client will have to get password |
4438 | + */ |
4439 | + if (state->boot_splash == NULL) |
4440 | + { |
4441 | + ply_trace ("no splash loaded, replying immediately with no password"); |
4442 | + ply_trigger_pull (answer, NULL); |
4443 | + return; |
4444 | + } |
4445 | + |
4446 | + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); |
4447 | + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_PASSWORD; |
4448 | + entry_trigger->prompt = prompt; |
4449 | + entry_trigger->trigger = answer; |
4450 | + ply_trace ("queuing password request with boot splash"); |
4451 | + ply_list_append_data (state->entry_triggers, entry_trigger); |
4452 | + update_display (state); |
4453 | +} |
4454 | + |
4455 | +static void |
4456 | +on_ask_question (state_t *state, |
4457 | + const char *prompt, |
4458 | + ply_trigger_t *answer) |
4459 | +{ |
4460 | + ply_entry_trigger_t *entry_trigger; |
4461 | + |
4462 | + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); |
4463 | + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_QUESTION; |
4464 | + entry_trigger->prompt = prompt; |
4465 | + entry_trigger->trigger = answer; |
4466 | + ply_trace ("queuing question with boot splash"); |
4467 | + ply_list_append_data (state->entry_triggers, entry_trigger); |
4468 | + update_display (state); |
4469 | +} |
4470 | + |
4471 | +static void |
4472 | +on_display_message (state_t *state, |
4473 | + const char *message) |
4474 | +{ |
4475 | + ply_trace ("displaying message %s", message); |
4476 | + if (state->boot_splash != NULL) |
4477 | + ply_boot_splash_display_message (state->boot_splash, message); |
4478 | + else |
4479 | + ply_list_append_data (state->pending_messages, strdup(message)); |
4480 | +} |
4481 | + |
4482 | +static void |
4483 | +on_watch_for_keystroke (state_t *state, |
4484 | + const char *keys, |
4485 | + ply_trigger_t *trigger) |
4486 | +{ |
4487 | + ply_keystroke_watch_t *keystroke_trigger = |
4488 | + calloc (1, sizeof (ply_keystroke_watch_t)); |
4489 | + ply_trace ("watching for keystroke"); |
4490 | + keystroke_trigger->keys = keys; |
4491 | + keystroke_trigger->trigger = trigger; |
4492 | + ply_list_append_data (state->keystroke_triggers, keystroke_trigger); |
4493 | +} |
4494 | + |
4495 | +static void |
4496 | +on_ignore_keystroke (state_t *state, |
4497 | + const char *keys) |
4498 | +{ |
4499 | + ply_list_node_t *node; |
4500 | + |
4501 | + ply_trace ("ignoring for keystroke"); |
4502 | + |
4503 | + for (node = ply_list_get_first_node (state->keystroke_triggers); node; |
4504 | + node = ply_list_get_next_node (state->keystroke_triggers, node)) |
4505 | + { |
4506 | + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); |
4507 | + if ((!keystroke_trigger->keys && !keys) || |
4508 | + (keystroke_trigger->keys && keys && strcmp(keystroke_trigger->keys, keys)==0)) |
4509 | + { |
4510 | + ply_trigger_pull (keystroke_trigger->trigger, NULL); |
4511 | + ply_list_remove_node (state->keystroke_triggers, node); |
4512 | + return; |
4513 | + } |
4514 | + } |
4515 | +} |
4516 | + |
4517 | +static void |
4518 | +on_progress_pause (state_t *state) |
4519 | +{ |
4520 | + ply_trace ("pausing progress"); |
4521 | + ply_progress_pause (state->progress); |
4522 | +} |
4523 | + |
4524 | +static void |
4525 | +on_progress_unpause (state_t *state) |
4526 | +{ |
4527 | + ply_trace ("unpausing progress"); |
4528 | + ply_progress_unpause (state->progress); |
4529 | +} |
4530 | + |
4531 | +static void |
4532 | +on_newroot (state_t *state, |
4533 | + const char *root_dir) |
4534 | +{ |
4535 | + if (state->mode != PLY_MODE_BOOT) |
4536 | + { |
4537 | + ply_trace ("new root is only supported in boot mode "); |
4538 | + return; |
4539 | + } |
4540 | + |
4541 | + ply_trace ("new root mounted at \"%s\", switching to it", root_dir); |
4542 | + chdir(root_dir); |
4543 | + chroot("."); |
4544 | + chdir("/"); |
4545 | + ply_progress_load_cache (state->progress, BOOT_DURATION_FILE); |
4546 | + if (state->boot_splash != NULL) |
4547 | + ply_boot_splash_root_mounted (state->boot_splash); |
4548 | +} |
4549 | + |
4550 | +static const char * |
4551 | +get_cache_file_for_mode (ply_mode_t mode) |
4552 | +{ |
4553 | + const char *filename; |
4554 | + |
4555 | + switch ((int)mode) |
4556 | + { |
4557 | + case PLY_MODE_BOOT: |
4558 | + filename = BOOT_DURATION_FILE; |
4559 | + break; |
4560 | + case PLY_MODE_SHUTDOWN: |
4561 | + filename = SHUTDOWN_DURATION_FILE; |
4562 | + break; |
4563 | + default: |
4564 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
4565 | + abort (); |
4566 | + break; |
4567 | + } |
4568 | + |
4569 | + ply_trace ("returning cache file '%s'", filename); |
4570 | + return filename; |
4571 | +} |
4572 | + |
4573 | +static const char * |
4574 | +get_log_file_for_mode (ply_mode_t mode) |
4575 | +{ |
4576 | + const char *filename; |
4577 | + |
4578 | + switch ((int)mode) |
4579 | + { |
4580 | + case PLY_MODE_BOOT: |
4581 | + filename = PLYMOUTH_LOG_DIRECTORY "/boot.log"; |
4582 | + break; |
4583 | + case PLY_MODE_SHUTDOWN: |
4584 | + filename = _PATH_DEVNULL; |
4585 | + break; |
4586 | + default: |
4587 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
4588 | + abort (); |
4589 | + break; |
4590 | + } |
4591 | + |
4592 | + ply_trace ("returning log file '%s'", filename); |
4593 | + return filename; |
4594 | +} |
4595 | + |
4596 | +static const char * |
4597 | +get_log_spool_file_for_mode (ply_mode_t mode) |
4598 | +{ |
4599 | + const char *filename; |
4600 | + |
4601 | + switch ((int)mode) |
4602 | + { |
4603 | + case PLY_MODE_BOOT: |
4604 | + filename = PLYMOUTH_SPOOL_DIRECTORY "/boot.log"; |
4605 | + break; |
4606 | + case PLY_MODE_SHUTDOWN: |
4607 | + filename = NULL; |
4608 | + break; |
4609 | + default: |
4610 | + fprintf (stderr, "Unhandled case in %s line %d\n", __FILE__, __LINE__); |
4611 | + abort (); |
4612 | + break; |
4613 | + } |
4614 | + |
4615 | + ply_trace ("returning spool file '%s'", filename); |
4616 | + return filename; |
4617 | +} |
4618 | + |
4619 | +static void |
4620 | +spool_error (state_t *state) |
4621 | +{ |
4622 | + const char *logfile; |
4623 | + const char *logspool; |
4624 | + |
4625 | + ply_trace ("spooling error for viewer"); |
4626 | + |
4627 | + logfile = get_log_file_for_mode (state->mode); |
4628 | + logspool = get_log_spool_file_for_mode (state->mode); |
4629 | + |
4630 | + if (logfile != NULL && logspool != NULL) |
4631 | + { |
4632 | + unlink (logspool); |
4633 | + |
4634 | + ply_create_file_link (logfile, logspool); |
4635 | + } |
4636 | +} |
4637 | + |
4638 | +static void |
4639 | +prepare_logging (state_t *state) |
4640 | +{ |
4641 | + const char *logfile; |
4642 | + |
4643 | + if (!state->system_initialized) |
4644 | + { |
4645 | + ply_trace ("not preparing logging yet, system not initialized"); |
4646 | + return; |
4647 | + } |
4648 | + |
4649 | + if (state->session == NULL) |
4650 | + { |
4651 | + ply_trace ("not preparing logging, no session"); |
4652 | + return; |
4653 | + } |
4654 | + |
4655 | + logfile = get_log_file_for_mode (state->mode); |
4656 | + if (logfile != NULL) |
4657 | + { |
4658 | + ply_trace ("opening log '%s'", logfile); |
4659 | + ply_terminal_session_open_log (state->session, logfile); |
4660 | + |
4661 | + if (state->number_of_errors > 0) |
4662 | + spool_error (state); |
4663 | + } |
4664 | +} |
4665 | + |
4666 | +static void |
4667 | +on_system_initialized (state_t *state) |
4668 | +{ |
4669 | + ply_trace ("system now initialized, opening log"); |
4670 | + state->system_initialized = true; |
4671 | + |
4672 | + prepare_logging (state); |
4673 | +} |
4674 | + |
4675 | +static void |
4676 | +on_error (state_t *state) |
4677 | +{ |
4678 | + ply_trace ("encountered error during boot up"); |
4679 | + |
4680 | + if (state->system_initialized && state->number_of_errors == 0) |
4681 | + spool_error (state); |
4682 | + else |
4683 | + ply_trace ("not spooling because number of errors %d", state->number_of_errors); |
4684 | + |
4685 | + state->number_of_errors++; |
4686 | +} |
4687 | + |
4688 | +static bool |
4689 | +plymouth_should_ignore_show_splash_calls (state_t *state) |
4690 | +{ |
4691 | + ply_trace ("checking if plymouth should be running"); |
4692 | + if (state->mode != PLY_MODE_BOOT || ply_string_has_prefix (state->kernel_command_line, "plymouth:force-splash") || strstr (state->kernel_command_line, " plymouth:force-splash") != NULL) |
4693 | + return false; |
4694 | + |
4695 | + return ply_string_has_prefix (state->kernel_command_line, "init=") || strstr (state->kernel_command_line, " init=") != NULL; |
4696 | +} |
4697 | + |
4698 | +static bool |
4699 | +plymouth_should_show_default_splash (state_t *state) |
4700 | +{ |
4701 | + ply_trace ("checking if plymouth should show default splash"); |
4702 | + |
4703 | + const char const *strings[] = { |
4704 | + " single ", " single\n", "^single ", |
4705 | + " 1 ", " 1\n", "^1 ", |
4706 | + " s ", " s\n", "^s ", |
4707 | + " S ", " S\n", "^S ", |
4708 | + " -s ", " -s\n", "^-s ", |
4709 | + NULL |
4710 | + }; |
4711 | + int i; |
4712 | + |
4713 | + if (state->kernel_console_tty != NULL) |
4714 | + return false; |
4715 | + |
4716 | + for (i = 0; strings[i] != NULL; i++) |
4717 | + { |
4718 | + int cmp; |
4719 | + if (strings[i][0] == '^') |
4720 | + cmp = strncmp(state->kernel_command_line, strings[i]+1, |
4721 | + strlen(strings[i]+1)) == 0; |
4722 | + else |
4723 | + cmp = strstr (state->kernel_command_line, strings[i]) != NULL; |
4724 | + |
4725 | + if (cmp) |
4726 | + { |
4727 | + ply_trace ("kernel command line has option \"%s\"", strings[i]); |
4728 | + return false; |
4729 | + } |
4730 | + } |
4731 | + |
4732 | + return strstr (state->kernel_command_line, "rhgb") != NULL || (strstr (state->kernel_command_line, "splash") != NULL && strstr(state->kernel_command_line, "splash=verbose") == NULL); |
4733 | +} |
4734 | + |
4735 | +static void |
4736 | +remove_displays_and_keyboard (state_t *state) |
4737 | +{ |
4738 | + ply_list_node_t *node; |
4739 | + ply_trace ("removing displays and keyboard"); |
4740 | + |
4741 | + node = ply_list_get_first_node (state->pixel_displays); |
4742 | + while (node != NULL) |
4743 | + { |
4744 | + ply_list_node_t *next_node; |
4745 | + ply_pixel_display_t *display; |
4746 | + |
4747 | + ply_trace ("removing pixel display"); |
4748 | + next_node = ply_list_get_next_node (state->pixel_displays, node); |
4749 | + display = ply_list_node_get_data (node); |
4750 | + ply_pixel_display_free (display); |
4751 | + |
4752 | + ply_list_remove_node (state->pixel_displays, node); |
4753 | + |
4754 | + node = next_node; |
4755 | + } |
4756 | + |
4757 | + node = ply_list_get_first_node (state->text_displays); |
4758 | + while (node != NULL) |
4759 | + { |
4760 | + ply_list_node_t *next_node; |
4761 | + ply_text_display_t *display; |
4762 | + |
4763 | + ply_trace ("removing text display"); |
4764 | + next_node = ply_list_get_next_node (state->text_displays, node); |
4765 | + display = ply_list_node_get_data (node); |
4766 | + ply_text_display_free (display); |
4767 | + |
4768 | + ply_list_remove_node (state->text_displays, node); |
4769 | + |
4770 | + node = next_node; |
4771 | + } |
4772 | + |
4773 | + if (state->keyboard != NULL) |
4774 | + { |
4775 | + ply_trace ("removing keyboard"); |
4776 | + ply_keyboard_stop_watching_for_input (state->keyboard); |
4777 | + ply_keyboard_free (state->keyboard); |
4778 | + state->keyboard = NULL; |
4779 | + } |
4780 | +} |
4781 | + |
4782 | +static void |
4783 | +on_show_splash (state_t *state) |
4784 | +{ |
4785 | + bool has_display; |
4786 | + |
4787 | + if (state->is_inactive) |
4788 | + { |
4789 | + ply_trace ("show splash called while inactive"); |
4790 | + return; |
4791 | + } |
4792 | + |
4793 | + if (plymouth_should_ignore_show_splash_calls (state)) |
4794 | + { |
4795 | + ply_trace ("show splash called while ignoring show splash calls"); |
4796 | + dump_details_and_quit_splash (state); |
4797 | + return; |
4798 | + } |
4799 | + |
4800 | + check_for_consoles (state, state->default_tty, true); |
4801 | + |
4802 | + has_display = ply_list_get_length (state->pixel_displays) > 0 || |
4803 | + ply_list_get_length (state->text_displays) > 0; |
4804 | + |
4805 | + if (!state->is_attached && state->should_be_attached && has_display) |
4806 | + attach_to_running_session (state); |
4807 | + |
4808 | + if (!has_display && state->is_attached) |
4809 | + { |
4810 | + ply_trace ("no open seats, detaching session"); |
4811 | + ply_terminal_session_detach (state->session); |
4812 | + state->is_redirected = false; |
4813 | + state->is_attached = false; |
4814 | + } |
4815 | + |
4816 | + if (plymouth_should_show_default_splash (state)) |
4817 | + { |
4818 | + show_default_splash (state); |
4819 | + state->showing_details = false; |
4820 | + } |
4821 | + else |
4822 | + { |
4823 | + show_detailed_splash (state); |
4824 | + state->showing_details = true; |
4825 | + } |
4826 | + flush_pending_messages (state); |
4827 | +} |
4828 | + |
4829 | +static void |
4830 | +quit_splash (state_t *state) |
4831 | +{ |
4832 | + ply_trace ("quiting splash"); |
4833 | + if (state->boot_splash != NULL) |
4834 | + { |
4835 | + ply_trace ("freeing splash"); |
4836 | + ply_boot_splash_free (state->boot_splash); |
4837 | + state->boot_splash = NULL; |
4838 | + } |
4839 | + |
4840 | + ply_trace ("removing displays and keyboard"); |
4841 | + remove_displays_and_keyboard (state); |
4842 | + |
4843 | + if (state->renderer != NULL) |
4844 | + { |
4845 | + ply_renderer_close (state->renderer); |
4846 | + ply_renderer_free (state->renderer); |
4847 | + state->renderer = NULL; |
4848 | + } |
4849 | + |
4850 | + if (state->terminal != NULL) |
4851 | + { |
4852 | + if (!state->should_retain_splash) |
4853 | + { |
4854 | + ply_trace ("Not retaining splash, so deallocating VT"); |
4855 | + ply_terminal_deactivate_vt (state->terminal); |
4856 | + } |
4857 | + ply_terminal_close (state->terminal); |
4858 | + ply_terminal_free (state->terminal); |
4859 | + state->terminal = NULL; |
4860 | + } |
4861 | + |
4862 | + if (state->session != NULL) |
4863 | + { |
4864 | + ply_trace ("detaching session"); |
4865 | + ply_terminal_session_detach (state->session); |
4866 | + state->is_redirected = false; |
4867 | + state->is_attached = false; |
4868 | + } |
4869 | +} |
4870 | + |
4871 | +static void |
4872 | +dump_details_and_quit_splash (state_t *state) |
4873 | +{ |
4874 | + state->showing_details = false; |
4875 | + toggle_between_splash_and_details (state); |
4876 | + |
4877 | + if (state->renderer != NULL) |
4878 | + ply_renderer_deactivate (state->renderer); |
4879 | + if (state->boot_splash != NULL) |
4880 | + ply_boot_splash_hide (state->boot_splash); |
4881 | + |
4882 | + quit_splash (state); |
4883 | +} |
4884 | + |
4885 | +static void |
4886 | +on_hide_splash (state_t *state) |
4887 | +{ |
4888 | + if (state->is_inactive) |
4889 | + return; |
4890 | + |
4891 | + if (state->boot_splash == NULL) |
4892 | + return; |
4893 | + |
4894 | + ply_trace ("hiding boot splash"); |
4895 | + dump_details_and_quit_splash (state); |
4896 | +} |
4897 | + |
4898 | +#ifdef PLY_ENABLE_GDM_TRANSITION |
4899 | +static void |
4900 | +tell_gdm_to_transition (void) |
4901 | +{ |
4902 | + int fd; |
4903 | + |
4904 | + fd = creat ("/var/spool/gdm/force-display-on-active-vt", 0644); |
4905 | + close (fd); |
4906 | +} |
4907 | +#endif |
4908 | + |
4909 | +static void |
4910 | +quit_program (state_t *state) |
4911 | +{ |
4912 | + ply_trace ("exiting event loop"); |
4913 | + ply_event_loop_exit (state->loop, 0); |
4914 | + |
4915 | + if (pid_file != NULL) |
4916 | + { |
4917 | + unlink (pid_file); |
4918 | + free (pid_file); |
4919 | + pid_file = NULL; |
4920 | + } |
4921 | + |
4922 | +#ifdef PLY_ENABLE_GDM_TRANSITION |
4923 | + if (state->should_retain_splash) |
4924 | + { |
4925 | + tell_gdm_to_transition (); |
4926 | + } |
4927 | +#endif |
4928 | + |
4929 | + if (state->deactivate_trigger != NULL) |
4930 | + { |
4931 | + ply_trigger_pull (state->deactivate_trigger, NULL); |
4932 | + state->deactivate_trigger = NULL; |
4933 | + } |
4934 | + if (state->quit_trigger != NULL) |
4935 | + { |
4936 | + ply_trigger_pull (state->quit_trigger, NULL); |
4937 | + state->quit_trigger = NULL; |
4938 | + } |
4939 | +} |
4940 | + |
4941 | +static void |
4942 | +deactivate_splash (state_t *state) |
4943 | +{ |
4944 | + assert (!state->is_inactive); |
4945 | + |
4946 | + if (state->renderer != NULL) |
4947 | + { |
4948 | + ply_trace ("deactivating renderer"); |
4949 | + ply_renderer_deactivate (state->renderer); |
4950 | + } |
4951 | + |
4952 | + if (state->keyboard != NULL) |
4953 | + { |
4954 | + ply_trace ("deactivating keyboard"); |
4955 | + ply_keyboard_stop_watching_for_input (state->keyboard); |
4956 | + } |
4957 | + |
4958 | + if ((state->session != NULL) && state->is_attached) |
4959 | + { |
4960 | + ply_trace ("deactivating terminal session"); |
4961 | + ply_terminal_session_detach (state->session); |
4962 | + state->is_redirected = false; |
4963 | + state->is_attached = false; |
4964 | + } |
4965 | + |
4966 | + if (state->terminal != NULL) |
4967 | + { |
4968 | + ply_trace ("deactivating terminal"); |
4969 | + ply_terminal_stop_watching_for_vt_changes (state->terminal); |
4970 | + ply_terminal_set_buffered_input (state->terminal); |
4971 | + ply_terminal_ignore_mode_changes (state->terminal, true); |
4972 | + } |
4973 | + |
4974 | + state->is_inactive = true; |
4975 | + |
4976 | + ply_trigger_pull (state->deactivate_trigger, NULL); |
4977 | + state->deactivate_trigger = NULL; |
4978 | +} |
4979 | + |
4980 | +static void |
4981 | +on_boot_splash_idle (state_t *state) |
4982 | +{ |
4983 | + ply_trace ("boot splash idle"); |
4984 | + |
4985 | + /* In the case where we've received both a deactivate command and a |
4986 | + * quit command, the quit command takes precedence. |
4987 | + */ |
4988 | + if (state->quit_trigger != NULL) |
4989 | + { |
4990 | + if (!state->should_retain_splash) |
4991 | + { |
4992 | + ply_trace ("hiding splash"); |
4993 | + if (state->renderer != NULL) |
4994 | + ply_renderer_deactivate (state->renderer); |
4995 | + if (state->boot_splash != NULL) |
4996 | + ply_boot_splash_hide (state->boot_splash); |
4997 | + } |
4998 | + |
4999 | + ply_trace ("quitting splash"); |
5000 | + quit_splash (state); |