2 * daemon_cmd.c -- Code handling the daemon commands.
4 * Copyright (C) 2005-2007 Michal Januszewski <spock@gentoo.org>
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License v2. See the file COPYING in the main directory of this archive for
14 #include <sys/types.h>
26 * 'exit' command handler.
28 int cmd_exit(void **args
)
32 pthread_cancel(th_switchmon
);
33 pthread_mutex_lock(&mtx_paint
);
35 if (ctty
== CTTY_SILENT
) {
36 if (config
.effects
& FBSPL_EFF_FADEOUT
)
37 fbsplashr_render_screen(theme
, true, false, FBSPL_EFF_FADEOUT
);
39 if (!args
[0] || strcmp(args
[0], "staysilent")) {
40 /* Switch to the verbose tty if we're in silent mode when the
41 * 'exit' command is received. */
42 ioctl(fd_tty0
, VT_ACTIVATE
, config
.tty_v
);
46 pthread_mutex_unlock(&mtx_paint
);
48 pthread_kill(th_sighandler
, SIGINT
);
49 pthread_join(th_sighandler
, NULL
);
51 fbsplashr_theme_free(theme
);
53 fbsplash_lib_cleanup();
55 for (i
= svcs
.head
; i
!= NULL
; ) {
64 /* We never get here */
69 * 'set theme' command handler.
71 * Switches to a new theme.
73 int cmd_set_theme(void **args
)
75 fbsplash_acc_theme_set(args
[0]);
76 pthread_mutex_lock(&mtx_paint
);
78 pthread_mutex_unlock(&mtx_paint
);
84 * 'set mode' command handler.
86 * Switches the splash to verbose or silent mode.
88 int cmd_set_mode(void **args
)
93 if (!strcmp(args
[0], "silent")) {
95 } else if (!strcmp(args
[0], "verbose")) {
101 itv
.it_interval
.tv_sec
= 0;
102 itv
.it_interval
.tv_usec
= 0;
103 itv
.it_value
.tv_sec
= 0;
104 itv
.it_value
.tv_usec
= 250000;
107 if (ioctl(fd_tty0
, VT_ACTIVATE
, n
) == -1) {
108 iprint(MSG_ERROR
, "Switch to tty%d failed with: %d '%s'\n", n
, errno
, strerror(errno
));
113 * Interrupt the VT_WAITACTIVE call every 0.25s. This makes sure we actually
114 * return from this function in a timely manner and that we can complete the
115 * switch to silent mode even when someone does a VT_ACTIVATE before our
118 * This fixes the problem of the silent mode not being activated when
119 * rebooting directly from X.
122 alarm_type
= ALRM_INTERRUPT
;
123 setitimer(ITIMER_REAL
, &itv
, NULL
);
125 if (ioctl(fd_tty0
, VT_WAITACTIVE
, n
) == -1) {
126 if (i
< 9 && errno
== EINTR
)
129 iprint(MSG_ERROR
, "Wait for tty%d failed with: %d '%s'\n", n
, errno
, strerror(errno
));
137 * 'set gpm' command handler.
139 * Creates a GPM client for the silent tty.
141 int cmd_set_gpm(void **args
)
147 conn
.defaultMask
= 0;
150 pthread_mutex_lock(&mtx_tty
);
151 fd_gpm
= Gpm_Open(&conn
, config
.tty_s
);
152 pthread_mutex_unlock(&mtx_tty
);
160 * 'set effects' command handler.
162 * Makes it possible to dynamically enable special effects.
164 int cmd_set_effects(void **args
)
168 config
.effects
= FBSPL_EFF_NONE
;
170 for (i
= 0; i
< 4; i
++) {
174 if (!strcmp(args
[i
], "fadein")) {
175 config
.effects
|= FBSPL_EFF_FADEIN
;
176 } else if (!strcmp(args
[i
], "fadeout")) {
177 config
.effects
|= FBSPL_EFF_FADEOUT
;
185 * 'set tty' command handlers.
187 * Assigns a TTY for verbose/silent splash screen.
189 int cmd_set_tty(void **args
)
191 /* Make sure the new tty setting is sane. */
192 if (*(int*)args
[1] < 0 || *(int*)args
[1] > MAX_NR_CONSOLES
)
195 if (!strcmp(args
[0], "silent")) {
196 pthread_mutex_lock(&mtx_tty
);
198 /* Do nothing if the new tty is the same as the old one. */
199 if (config
.tty_s
== *(int*)args
[1]) {
200 pthread_mutex_unlock(&mtx_tty
);
204 pthread_cancel(th_switchmon
);
206 switchmon_start(UPD_SILENT
, *(int*)args
[1]);
207 pthread_mutex_unlock(&mtx_tty
);
214 } else if (!strcmp(args
[0], "verbose")) {
216 pthread_mutex_lock(&mtx_tty
);
218 /* Do nothing if the new tty is the same as the old one. */
219 if (config
.tty_v
== *(int*)args
[1]) {
220 pthread_mutex_unlock(&mtx_tty
);
224 config
.tty_v
= *(int*)args
[1];
225 pthread_mutex_unlock(&mtx_tty
);
234 * 'set event dev' command handler.
236 * Sets a new event device to monitor for keypresses.
238 int cmd_set_event_dev(void **args
)
243 evdev
= strdup(args
[0]);
245 pthread_cancel(th_switchmon
);
250 fd_evdev
= open(evdev
, O_RDONLY
);
252 switchmon_start(UPD_MON
, config
.tty_s
);
258 * 'paint' command handler.
260 * Updates the picture displayed on the screen.
262 int cmd_paint(void **args
)
266 pthread_mutex_lock(&mtx_paint
);
272 if (ctty
!= CTTY_SILENT
)
275 fbsplashr_render_screen(theme
, false, false, FBSPL_EFF_NONE
);
277 pthread_mutex_unlock(&mtx_paint
);
282 * 'repaint' command handler.
284 * Repaints the whole screen.
286 int cmd_repaint(void **args
)
290 pthread_mutex_lock(&mtx_paint
);
296 if (ctty
!= CTTY_SILENT
)
299 if (config
.effects
& FBSPL_EFF_FADEIN
) {
300 config
.effects
&= ~FBSPL_EFF_FADEIN
;
301 fbsplashr_render_screen(theme
, true, false, FBSPL_EFF_FADEIN
);
303 fbsplashr_render_screen(theme
, true, false, FBSPL_EFF_NONE
);
306 pthread_mutex_unlock(&mtx_paint
);
312 * 'progress' command handler.
314 * Updates the progress indicator. Note that this only updates
315 * an internal variable, it doesn't update the image on the screen.
317 int cmd_progress(void **args
)
319 fbsplashr_progress_set(theme
, *(int*)args
[0]);
324 * 'set message' command handler.
326 * Sets the system message. This only has any effect if the
327 * splash daemon was compiled with support for truetype fonts.
329 int cmd_set_mesg(void **args
)
331 fbsplashr_message_set(theme
, args
[0]);
336 * 'log' command handler.
338 * Appends a line of text to the fbsplash message log.
340 int cmd_log(void **args
)
342 /* TODO: possibly move this to libfbsplashrender */
345 if (theme
->log_cnt
<= theme
->log_lines
) {
346 list_add(&theme
->msglog
, strndup(args
[0], theme
->log_cols
));
348 list_ringadd(&theme
->msglog
, strndup(args
[0], theme
->log_cols
));
355 * 'set autoverbose' command handler.
357 int cmd_set_autoverbose(void **args
)
359 config
.autoverbose
= *(int*)args
[0];
364 * 'paint rect' command handler.
366 * Paints a rectangular part of the background buffer on thre
369 int cmd_paint_rect(void **args
)
374 pthread_mutex_lock(&mtx_paint
);
379 if (ctty
!= CTTY_SILENT
)
382 re
.x1
= *(int*)args
[0];
383 re
.x2
= *(int*)args
[2];
384 re
.y1
= *(int*)args
[1];
385 re
.y2
= *(int*)args
[3];
411 if (re
.x1
>= theme
->xres
)
412 re
.x1
= theme
->xres
-1;
414 if (re
.x2
>= theme
->xres
)
415 re
.x2
= theme
->xres
-1;
417 if (re
.y1
>= theme
->yres
)
418 re
.y1
= theme
->yres
-1;
420 if (re
.y2
>= theme
->yres
)
421 re
.y2
= theme
->yres
-1;
423 paint_rect(theme
, fb_mem
, theme
->bgbuf
, re
.x1
, re
.y1
, re
.x2
, re
.y2
);
426 pthread_mutex_unlock(&mtx_paint
);
431 * 'update_svc' command handler.
433 * Updates status of a specific service.
435 int cmd_update_svc(void **args
)
442 if (!parse_svc_state(args
[1], &state
))
445 clock_gettime(CLOCK_MONOTONIC
, &ts
);
447 for (i
= svcs
.head
; i
!= NULL
; i
= i
->next
) {
448 ss
= (svc_state
*)i
->p
;
449 if (!strcmp(ss
->svc
, args
[0]))
453 ss
= malloc(sizeof(svc_state
));
454 ss
->svc
= strdup(args
[0]);
460 if (ss
->state
== e_svc_start
) {
462 } else if (ss
->state
== e_svc_started
|| ss
->state
== e_svc_start_failed
) {
463 ss
->ts
.tv_sec
= ts
.tv_sec
- ss
->ts
.tv_sec
;
464 ss
->ts
.tv_nsec
= ts
.tv_nsec
- ss
->ts
.tv_nsec
;
466 /* Check for overflow of the nanoseconds field */
467 if (ss
->ts
.tv_nsec
< 0) {
469 ss
->ts
.tv_nsec
+= 1000000000;
473 pthread_mutex_lock(&mtx_paint
);
474 invalidate_service(theme
, args
[0], state
);
475 pthread_mutex_lock(&mtx_anim
);
476 pthread_cond_signal(&cnd_anim
);
477 pthread_mutex_unlock(&mtx_anim
);
478 pthread_mutex_unlock(&mtx_paint
);
483 int cmd_dump_svc_timings(void **args
)
487 FILE *fp
= fopen("/lib/splash/cache/svc_timings", "w");
492 for (i
= svcs
.head
; i
!= NULL
; i
= i
->next
) {
493 ss
= (svc_state
*)i
->p
;
494 if (ss
->svc
&& (ss
->ts
.tv_sec
> 0 || ss
->ts
.tv_nsec
> 0)) {
495 fprintf(fp
, "%s: %d.%.6d\n", ss
->svc
, (int)ss
->ts
.tv_sec
, (int)(ss
->ts
.tv_nsec
/1000));
503 cmdhandler known_cmds
[] =
505 { .cmd
= "set theme",
506 .handler
= cmd_set_theme
,
512 .handler
= cmd_set_mode
,
518 .handler
= cmd_set_tty
,
523 { .cmd
= "set event dev",
524 .handler
= cmd_set_event_dev
,
529 { .cmd
= "set message",
530 .handler
= cmd_set_mesg
,
535 { .cmd
= "set autoverbose",
536 .handler
= cmd_set_autoverbose
,
542 .handler
= cmd_set_gpm
,
547 { .cmd
= "set effects",
548 .handler
= cmd_set_effects
,
553 { .cmd
= "paint rect",
554 .handler
= cmd_paint_rect
,
560 .handler
= cmd_paint
,
566 .handler
= cmd_repaint
,
572 .handler
= cmd_progress
,
577 { .cmd
= "update_svc",
578 .handler
= cmd_update_svc
,
584 { .cmd = "dump_svc_timings",
585 .handler = cmd_dump_svc_timings,
604 * FIFO communication handler.
606 int daemon_comm(FILE *fp_fifo
)
613 while (fgets(buf
, PIPE_BUF
, fp_fifo
)) {
618 memset(&args
, 0, sizeof(args
));
620 buf
[strlen(buf
)-1] = 0;
622 for (i
= 0; i
< sizeof(known_cmds
)/sizeof(known_cmds
[0]); i
++) {
623 k
= strlen(known_cmds
[i
].cmd
);
625 if (strncmp(buf
, known_cmds
[i
].cmd
, k
))
628 for (j
= 0; j
< known_cmds
[i
].args
; j
++) {
629 for (; buf
[k
] == ' '; buf
[k
] = 0, k
++);
635 switch (known_cmds
[i
].specs
[j
]) {
638 for (; buf
[k
] != ' ' && buf
[k
]; k
++);
642 args_i
[j
] = strtol(&(buf
[k
]), &t
, 0);
646 args
[j
] = &(args_i
[j
]);
652 known_cmds
[i
].handler(args
);
654 /* Activate the autoverbose timer. */
655 if (config
.autoverbose
> 0) {
656 struct itimerval itv
;
658 itv
.it_interval
.tv_sec
= 0;
659 itv
.it_interval
.tv_usec
= 0;
660 itv
.it_value
.tv_sec
= config
.autoverbose
;
661 itv
.it_value
.tv_usec
= 0;
663 alarm_type
= ALRM_AUTOVERBOSE
;
664 setitimer(ITIMER_REAL
, &itv
, NULL
);