/* ply-boot-client.h - APIs for talking to the boot status daemon
*
* Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
{
ply_boot_client_t *client;
char *command;
- char *argument;
+ char *argument_1;
+ char *argument_2;
ply_boot_client_response_handler_t handler;
ply_boot_client_response_handler_t failed_handler;
void *user_data;
static ply_boot_client_request_t *
ply_boot_client_request_new (ply_boot_client_t *client,
const char *request_command,
- const char *request_argument,
+ const char *request_argument_1,
+ const char *request_argument_2,
ply_boot_client_response_handler_t handler,
ply_boot_client_response_handler_t failed_handler,
void *user_data)
request = calloc (1, sizeof (ply_boot_client_request_t));
request->client = client;
request->command = strdup (request_command);
- if (request_argument != NULL)
- request->argument = strdup (request_argument);
+ if (request_argument_1 != NULL)
+ request->argument_1 = strdup (request_argument_1);
+ if (request_argument_2 != NULL)
+ request->argument_2 = strdup (request_argument_2);
request->handler = handler;
request->failed_handler = failed_handler;
request->user_data = user_data;
if (request == NULL)
return;
free (request->command);
- if (request->argument != NULL)
- free (request->argument);
+ free (request->argument_1);
+ free (request->argument_2);
free (request);
}
size_t *request_size)
{
char *request_string;
+ int ret;
assert (client != NULL);
assert (request != NULL);
assert (request->command != NULL);
- if (request->argument == NULL)
+ if (request->argument_1 == NULL && request->argument_2 == NULL)
{
request_string = strdup (request->command);
*request_size = strlen (request_string) + 1;
return request_string;
}
- assert (strlen (request->argument) <= UCHAR_MAX);
+ assert (strlen (request->argument_1) <= UCHAR_MAX);
request_string = NULL;
- asprintf (&request_string, "%s\002%c%s", request->command,
- (char) (strlen (request->argument) + 1), request->argument);
- *request_size = strlen (request_string) + 1;
+
+ if (request->argument_2 == NULL)
+ {
+ ret = asprintf (&request_string, "%s\002%c%s", request->command,
+ (char) (strlen (request->argument_1) + 1), request->argument_1);
+ }
+ else
+ {
+ assert (request->argument_1 != NULL);
+ assert (strlen (request->argument_2) <= UCHAR_MAX);
+ ret = asprintf (&request_string, "%s\003%c%s%c%c%s", request->command,
+ (char) (strlen (request->argument_1) + 1),
+ request->argument_1,
+ 0,
+ (char) (strlen (request->argument_2) + 1),
+ request->argument_2);
+ }
+
+ assert (ret > 0);
+
+ *request_size = (size_t)ret + 1;
return request_string;
}
static void
ply_boot_client_queue_request (ply_boot_client_t *client,
const char *request_command,
- const char *request_argument,
+ const char *request_argument_1,
+ const char *request_argument_2,
ply_boot_client_response_handler_t handler,
ply_boot_client_response_handler_t failed_handler,
void *user_data)
assert (client != NULL);
assert (client->loop != NULL);
assert (request_command != NULL);
- assert (request_argument == NULL || strlen (request_argument) <= UCHAR_MAX);
+ assert (request_argument_1 == NULL || strlen (request_argument_1) <= UCHAR_MAX);
+ assert (request_argument_2 == NULL || strlen (request_argument_2) <= UCHAR_MAX);
if (client->daemon_can_take_request_watch == NULL &&
client->socket_fd >= 0)
ply_boot_client_request_t *request;
request = ply_boot_client_request_new (client, request_command,
- request_argument,
+ request_argument_1,
+ request_argument_2,
handler, failed_handler, user_data);
ply_list_append_data (client->requests_to_send, request);
}
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PING,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
+}
+
+void ply_boot_client_register_operation (ply_boot_client_t *client,
+ const char *operation_id,
+ const char *name,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data)
+{
+ assert (client != NULL);
+
+ ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_REGISTER,
+ operation_id, name, handler, failed_handler, user_data);
+
+
+}
+void ply_boot_client_unregister_operation (ply_boot_client_t *client,
+ const char *operation_id,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data)
+{
+ assert (client != NULL);
+
+ ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_UNREGISTER,
+ operation_id, NULL, handler, failed_handler, user_data);
}
void
ply_boot_client_update_daemon (ply_boot_client_t *client,
const char *status,
+ const char *operation_id,
ply_boot_client_response_handler_t handler,
ply_boot_client_response_handler_t failed_handler,
void *user_data)
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_UPDATE,
- status, handler, failed_handler, user_data);
+ status, operation_id, handler, failed_handler, user_data);
}
void
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_CHANGE_MODE,
- new_mode, handler, failed_handler, user_data);
+ new_mode, NULL, handler, failed_handler, user_data);
}
void
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_SYSTEM_UPDATE,
- progress, handler, failed_handler, user_data);
+ progress, NULL, handler, failed_handler, user_data);
}
void
assert (root_dir != NULL);
ply_boot_client_queue_request(client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_NEWROOT,
- root_dir, handler, failed_handler, user_data);
+ root_dir, NULL, handler, failed_handler, user_data);
}
void
assert (message != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_MESSAGE,
- message, handler, failed_handler, user_data);
+ message, NULL, handler, failed_handler, user_data);
}
void
assert (message != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HIDE_MESSAGE,
- message, handler, failed_handler, user_data);
+ message, NULL, handler, failed_handler, user_data);
}
void
ply_boot_client_queue_request (client,
PLY_BOOT_PROTOCOL_REQUEST_TYPE_SYSTEM_INITIALIZED,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD,
- prompt, (ply_boot_client_response_handler_t)
+ prompt, NULL, (ply_boot_client_response_handler_t)
handler, failed_handler, user_data);
}
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_CACHED_PASSWORD,
- NULL, (ply_boot_client_response_handler_t)
+ NULL, NULL, (ply_boot_client_response_handler_t)
handler, failed_handler, user_data);
}
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION,
- prompt, (ply_boot_client_response_handler_t)
+ prompt, NULL, (ply_boot_client_response_handler_t)
handler, failed_handler, user_data);
}
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE,
- keys, (ply_boot_client_response_handler_t)
+ keys, NULL, (ply_boot_client_response_handler_t)
handler, failed_handler, user_data);
}
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE_REMOVE,
- keys, (ply_boot_client_response_handler_t)
+ keys, NULL, (ply_boot_client_response_handler_t)
handler, failed_handler, user_data);
}
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_SPLASH,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HIDE_SPLASH,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_DEACTIVATE,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
assert (client != NULL);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_REACTIVATE,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
arg[0] = (char) (retain_splash != false);
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUIT,
- arg, handler, failed_handler, user_data);
+ arg, NULL, handler, failed_handler, user_data);
}
void
void *user_data)
{
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PROGRESS_PAUSE,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
void *user_data)
{
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PROGRESS_UNPAUSE,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
void *user_data)
{
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HAS_ACTIVE_VT,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
void *user_data)
{
ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_ERROR,
- NULL, handler, failed_handler, user_data);
+ NULL, NULL, handler, failed_handler, user_data);
}
void
/* ply-boot-client.h - APIs for talking to the boot status daemon
*
* Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
ply_boot_client_response_handler_t handler,
ply_boot_client_response_handler_t failed_handler,
void *user_data);
+void ply_boot_client_register_operation (ply_boot_client_t *client,
+ const char *operation_id,
+ const char *name,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data);
+void ply_boot_client_unregister_operation (ply_boot_client_t *client,
+ const char *operation_id,
+ ply_boot_client_response_handler_t handler,
+ ply_boot_client_response_handler_t failed_handler,
+ void *user_data);
void ply_boot_client_update_daemon (ply_boot_client_t *client,
const char *new_status,
+ const char *operation_id,
ply_boot_client_response_handler_t handler,
ply_boot_client_response_handler_t failed_handler,
void *user_data);
/* plymouth.c - updates boot status
*
* Copyright (C) 2007 Red Hat, Inc
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
on_failure, state);
}
+static void
+on_register_operation_request (state_t *state,
+ const char *command)
+{
+ char *name;
+ char *operation_id;
+
+ name = NULL;
+ operation_id = NULL;
+ ply_command_parser_get_command_options (state->command_parser,
+ command,
+ "name", &name,
+ "operation-id", &operation_id,
+ NULL);
+
+ if (operation_id != NULL && name != NULL)
+ {
+ ply_boot_client_register_operation(state->client, operation_id, name,
+ (ply_boot_client_response_handler_t)
+ on_success,
+ (ply_boot_client_response_handler_t)
+ on_failure, state);
+ }
+ else
+ {
+ ply_error ("unknown operation id or name");
+ ply_event_loop_exit (state->loop, 1);
+ }
+}
+
+static void
+on_unregister_operation_request (state_t *state,
+ const char *command)
+{
+ char *operation_id;
+
+ operation_id = NULL;
+ ply_command_parser_get_command_options (state->command_parser,
+ command,
+ "operation-id", &operation_id,
+ NULL);
+
+ if (operation_id != NULL)
+ {
+ ply_boot_client_unregister_operation(state->client, operation_id,
+ (ply_boot_client_response_handler_t)
+ on_success,
+ (ply_boot_client_response_handler_t)
+ on_failure, state);
+ }
+ else
+ {
+ ply_error ("unknown operation id");
+ ply_event_loop_exit (state->loop, 1);
+ }
+}
+
static void
on_update_request (state_t *state,
const char *command)
{
char *status;
+ const char *operation_id;
status = NULL;
+ operation_id = NULL;
ply_command_parser_get_command_options (state->command_parser,
command,
+ "operation-id", &operation_id,
"status", &status,
NULL);
+ if (operation_id == NULL)
+ operation_id = "";
+
if (status != NULL)
{
- ply_boot_client_update_daemon (state->client, status,
+
+ ply_boot_client_update_daemon (state->client, status, operation_id,
(ply_boot_client_response_handler_t)
on_success,
(ply_boot_client_response_handler_t)
PLY_COMMAND_OPTION_TYPE_INTEGER,
NULL);
+ ply_command_parser_add_command (state.command_parser,
+ "register-operation", "Tell boot daemon to register operation",
+ (ply_command_handler_t)
+ on_register_operation_request, &state,
+ "operation-id", "Operation id",
+ PLY_COMMAND_OPTION_TYPE_STRING,
+ "name", "Operation name",
+ PLY_COMMAND_OPTION_TYPE_STRING,
+ NULL);
+
+ ply_command_parser_add_command (state.command_parser,
+ "unregister-operation", "Tell boot daemon to unregister operation",
+ (ply_command_handler_t)
+ on_unregister_operation_request, &state,
+ "operation-id", "Operation id",
+ PLY_COMMAND_OPTION_TYPE_STRING,
+ NULL);
+
ply_command_parser_add_command (state.command_parser,
"update", "Tell daemon about boot status changes",
(ply_command_handler_t)
on_update_request, &state,
+ "operation-id", "Tell daemon operation id",
+ PLY_COMMAND_OPTION_TYPE_STRING,
"status", "Tell daemon the current boot status",
PLY_COMMAND_OPTION_TYPE_STRING,
NULL);
(ply_boot_client_response_handler_t)
on_failure, &state);
else if (status != NULL)
- ply_boot_client_update_daemon (state.client, status,
+ ply_boot_client_update_daemon (state.client, status, NULL,
(ply_boot_client_response_handler_t)
on_success,
(ply_boot_client_response_handler_t)
/* ply-boot-splash-plugin.h - plugin interface for ply_boot_splash_t
*
* Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
ply_boot_splash_mode_t mode);
void (* system_update) (ply_boot_splash_plugin_t *plugin,
int progress);
+ void (* register_operation) (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id,
+ const char *name);
+ void (* unregister_operation) (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id);
void (* update_status) (ply_boot_splash_plugin_t *plugin,
- const char *status);
+ const char *status,
+ const char *operation_id);
void (* on_boot_output) (ply_boot_splash_plugin_t *plugin,
const char *output,
size_t size);
/* ply-boot-splash.h - APIs for putting up a splash screen
*
* Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
return true;
}
+void ply_boot_splash_register_operation (ply_boot_splash_t *splash,
+ const char *operation_id,
+ const char *name)
+{
+ assert (splash != NULL);
+ assert (operation_id != NULL);
+ assert (name != NULL);
+ assert (splash->plugin_interface != NULL);
+ assert (splash->plugin != NULL);
+ assert (splash->plugin_interface->register_operation != NULL);
+
+ splash->plugin_interface->register_operation (splash->plugin, operation_id, name);
+}
+
+void ply_boot_splash_unregister_operation (ply_boot_splash_t *splash,
+ const char *operation_id)
+{
+ assert (splash != NULL);
+ assert (operation_id != NULL);
+ assert (splash->plugin_interface != NULL);
+ assert (splash->plugin != NULL);
+ assert (splash->plugin_interface->register_operation != NULL);
+
+ splash->plugin_interface->unregister_operation (splash->plugin, operation_id);
+}
+
void
ply_boot_splash_update_status (ply_boot_splash_t *splash,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (splash != NULL);
assert (status != NULL);
assert (splash->plugin_interface->update_status != NULL);
assert (splash->mode != PLY_BOOT_SPLASH_MODE_INVALID);
- splash->plugin_interface->update_status (splash->plugin, status);
+ splash->plugin_interface->update_status (splash->plugin, status, operation_id);
}
void
ply_boot_splash_mode_t mode);
bool ply_boot_splash_system_update (ply_boot_splash_t *splash,
int progress);
+void ply_boot_splash_register_operation (ply_boot_splash_t *splash,
+ const char *operation_id,
+ const char *name);
+void ply_boot_splash_unregister_operation (ply_boot_splash_t *splash,
+ const char *operation_id);
void ply_boot_splash_update_status (ply_boot_splash_t *splash,
- const char *status);
+ const char *status,
+ const char *operation_id);
void ply_boot_splash_update_output (ply_boot_splash_t *splash,
const char *output,
size_t size);
/* ply-progress.c - calculats boot progress
*
* Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
typedef struct
{
double time;
+ char* id;
char* string;
uint32_t disabled : 1;
} ply_progress_message_t;
ply_progress_message_t *message = ply_list_node_get_data (node);
next_node = ply_list_get_next_node (progress->current_message_list, node);
+ free (message->id);
free (message->string);
free (message);
node = next_node;
ply_progress_message_t *message = ply_list_node_get_data (node);
next_node = ply_list_get_next_node (progress->previous_message_list, node);
+ free (message->id);
free (message->string);
free (message);
node = next_node;
static ply_progress_message_t*
-ply_progress_message_search (ply_list_t *message_list, const char* string)
+ply_progress_message_search (ply_list_t *message_list, const char* id, const char* string)
{
ply_list_node_t *node;
node = ply_list_get_first_node (message_list);
while (node)
{
ply_progress_message_t *message = ply_list_node_get_data (node);
- if (strcmp(string, message->string)==0)
+ if (strcmp(id, message->id)==0 && strcmp(string, message->string)==0)
return message;
node = ply_list_get_next_node (message_list, node);
}
static ply_progress_message_t*
-ply_progress_message_search_next (ply_list_t *message_list, double time)
+ply_progress_message_search_next (ply_list_t *message_list, const char* id, double time)
{
ply_list_node_t *node;
node = ply_list_get_first_node (message_list);
while (node)
{
ply_progress_message_t *message = ply_list_node_get_data (node);
- if (message->time > time && (!best || message->time < best->time))
+ if (strcmp(id, message->id)==0 && message->time > time && (!best || message->time < best->time))
best = message;
node = ply_list_get_next_node (message_list, node);
}
int items_matched;
double time;
int string_size=81;
+ char *ptr;
+ char *id;
char *string;
char colon;
int i=0;
}
i++;
}
+
+ ptr = strchr(string, ':');
+ if (!ptr)
+ id = strdup("");
+ else
+ {
+ *ptr = 0;
+ id = string;
+ string = strdup(ptr+1);
+ }
+
ply_progress_message_t* message = malloc(sizeof(ply_progress_message_t));
message->time = time;
+ message->id = id;
message->string = string;
ply_list_append_data(progress->previous_message_list, message);
}
ply_progress_message_t *message = ply_list_node_get_data (node);
double percentage = message->time / cur_time;
if (!message->disabled)
- fprintf (fp, "%.3lf:%s\n", percentage, message->string);
+ fprintf (fp, "%.3lf:%s:%s\n", percentage, message->id, message->string);
node = ply_list_get_next_node (progress->current_message_list, node);
}
fclose (fp);
void
ply_progress_status_update (ply_progress_t* progress,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
ply_progress_message_t *message, *message_next;
- message = ply_progress_message_search(progress->current_message_list, status);
+ message = ply_progress_message_search(progress->current_message_list, operation_id, status);
if (message)
{
message->disabled = true;
} /* Remove duplicates as they confuse things*/
else
{
- message = ply_progress_message_search(progress->previous_message_list, status);
+ message = ply_progress_message_search(progress->previous_message_list, operation_id, status);
if (message)
{
- message_next = ply_progress_message_search_next(progress->previous_message_list, message->time);
+ message_next = ply_progress_message_search_next(progress->previous_message_list, operation_id, message->time);
if (message_next)
progress->next_message_percentage = message_next->time;
else
}
message = malloc(sizeof(ply_progress_message_t));
message->time = ply_progress_get_time (progress);
+ message->id = strdup(operation_id);
message->string = strdup(status);
message->disabled = false;
ply_list_append_data(progress->current_message_list, message);
void ply_progress_pause (ply_progress_t* progress);
void ply_progress_unpause (ply_progress_t* progress);
void ply_progress_save_cache (ply_progress_t* progress, const char *filename);
-void ply_progress_status_update (ply_progress_t* progress, const char *status);
+void ply_progress_status_update (ply_progress_t* progress, const char *status, const char *operation_id);
#endif /* PLY_PROGRESS_H */
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
/* main.c - boot messages monitor
*
* Copyright (C) 2007 Red Hat, Inc
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
ply_trace ("got hang up on terminal session fd");
}
+static void
+on_register (state_t *state,
+ const char *operation_id,
+ const char *name)
+{
+ ply_trace ("register operation '%s' with name '%s'", operation_id, name);
+ if (state->boot_splash != NULL)
+ ply_boot_splash_register_operation (state->boot_splash,
+ operation_id, name);
+}
+
+static void
+on_unregister (state_t *state,
+ const char *operation_id)
+{
+ ply_trace ("register operation '%s'", operation_id);
+ if (state->boot_splash != NULL)
+ ply_boot_splash_unregister_operation (state->boot_splash,
+ operation_id);
+}
+
static void
on_update (state_t *state,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
- ply_trace ("updating status to '%s'", status);
+ ply_trace ("updating status of operation '%s' to '%s'", operation_id, status);
ply_progress_status_update (state->progress,
- status);
+ status, operation_id);
if (state->boot_splash != NULL)
ply_boot_splash_update_status (state->boot_splash,
- status);
+ status, operation_id);
}
static void
{
ply_boot_server_t *server;
- server = ply_boot_server_new ((ply_boot_server_update_handler_t) on_update,
+ server = ply_boot_server_new ((ply_boot_server_register_handler_t) on_register,
+ (ply_boot_server_unregister_handler_t) on_unregister,
+ (ply_boot_server_update_handler_t) on_update,
(ply_boot_server_change_mode_handler_t) on_change_mode,
(ply_boot_server_system_update_handler_t) on_system_update,
(ply_boot_server_ask_for_password_handler_t) on_ask_for_password,
/* details.c - boot splash plugin
*
* Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
ply_text_display_t *display;
} view_t;
+typedef struct
+{
+ char *operation_id;
+ char *name;
+} operation_t;
+
ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin);
ply_list_t *views;
ply_boot_splash_display_type_t state;
ply_list_t *messages;
-
+ ply_list_t *operations;
};
static view_t *
plugin->messages = NULL;
}
+static operation_t *
+operation_new (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id,
+ const char *name)
+{
+ operation_t *operation;
+ operation = malloc (sizeof(operation_t));
+ operation->operation_id = strdup (operation_id);
+ operation->name = strdup (name);
+ return operation;
+}
+
+static void
+operation_free (operation_t *operation)
+{
+ free (operation->operation_id);
+ free (operation->name);
+ free (operation);
+}
+
+static void
+free_operations (ply_boot_splash_plugin_t *plugin)
+{
+ ply_list_node_t *node;
+
+ node = ply_list_get_first_node (plugin->operations);
+
+ while (node != NULL)
+ {
+ ply_list_node_t *next_node;
+ operation_t *operation;
+
+ operation = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (plugin->operations, node);
+
+ operation_free (operation);
+ ply_list_remove_node (plugin->operations, node);
+
+ node = next_node;
+ }
+
+ ply_list_free (plugin->operations);
+ plugin->operations = NULL;
+}
+
+static const char *
+get_operation_name (ply_boot_splash_plugin_t *plugin, const char *id)
+{
+ ply_list_node_t *node;
+
+ node = ply_list_get_first_node (plugin->operations);
+
+ while (node != NULL)
+ {
+ operation_t *operation;
+
+ operation = ply_list_node_get_data (node);
+ if (strcmp(operation->operation_id, id) == 0)
+ {
+ return operation->name;
+ }
+
+ node = ply_list_get_next_node (plugin->operations, node);
+
+ }
+
+ return NULL;
+}
+
static ply_boot_splash_plugin_t *
create_plugin (ply_key_file_t *key_file)
{
plugin = calloc (1, sizeof (ply_boot_splash_plugin_t));
plugin->views = ply_list_new ();
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
+ plugin->operations = ply_list_new ();
plugin->messages = ply_list_new ();
return plugin;
}
detach_from_event_loop (plugin);
}
+ free_operations (plugin);
free_messages (plugin);
free_views (plugin);
return true;
}
+static void
+register_operation (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id,
+ const char *name)
+{
+ operation_t *operation;
+ assert (plugin != NULL);
+ assert (operation_id != NULL);
+ assert (name != NULL);
+
+ ply_trace ("register operation");
+
+ operation = operation_new (plugin, operation_id, name);
+ ply_list_append_data (plugin->operations, operation);
+}
+
+static void
+unregister_operation (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id)
+{
+ assert (plugin != NULL);
+ assert (operation_id != NULL);
+
+ ply_trace ("unregister operation");
+
+ ply_list_node_t *node;
+
+ node = ply_list_get_first_node (plugin->operations);
+
+ while (node != NULL)
+ {
+ operation_t *operation;
+
+ operation = ply_list_node_get_data (node);
+ if (strcmp(operation->operation_id, operation_id) == 0)
+ {
+ ply_list_remove_node(plugin->operations, node);
+ return;
+ }
+
+ node = ply_list_get_next_node (plugin->operations, node);
+
+ }
+}
+
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (plugin != NULL);
+ assert (status != NULL);
ply_trace ("status update");
+
+ if (operation_id != NULL)
+ {
+ const char *operation_name = get_operation_name (plugin, operation_id);
+ if (operation_name != NULL)
+ {
+ char *message;
+ asprintf (&message, "%s... [%s]\r\n", operation_name, status);
+ if (message != NULL)
+ {
+ write_on_views (plugin, message, strlen (message));
+ free(message);
+ }
+ }
+ }
}
static void
.add_text_display = add_text_display,
.remove_text_display = remove_text_display,
.show_splash_screen = show_splash_screen,
+ .register_operation = register_operation,
+ .unregister_operation = unregister_operation,
.update_status = update_status,
.on_boot_output = on_boot_output,
.hide_splash_screen = hide_splash_screen,
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (plugin != NULL);
return start_animation (plugin);
}
+static void
+register_operation (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id,
+ const char *name)
+{
+ script_lib_plymouth_on_register_operation (plugin->script_state,
+ plugin->script_plymouth_lib,
+ operation_id,
+ name);
+}
+
+static void
+unregister_operation (ply_boot_splash_plugin_t *plugin,
+ const char *operation_id)
+{
+ script_lib_plymouth_on_unregister_operation (plugin->script_state,
+ plugin->script_plymouth_lib,
+ operation_id);
+}
+
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
script_lib_plymouth_on_update_status (plugin->script_state,
plugin->script_plymouth_lib,
- status);
+ status,
+ operation_id);
}
static void
.add_pixel_display = add_pixel_display,
.remove_pixel_display = remove_pixel_display,
.show_splash_screen = show_splash_screen,
+ .register_operation = register_operation,
+ .unregister_operation = unregister_operation,
.update_status = update_status,
.on_boot_progress = on_boot_progress,
.hide_splash_screen = hide_splash_screen,
data->script_boot_progress_func = script_obj_new_null ();
data->script_root_mounted_func = script_obj_new_null ();
data->script_keyboard_input_func = script_obj_new_null ();
+ data->script_register_operation_func = script_obj_new_null ();
+ data->script_unregister_operation_func = script_obj_new_null ();
data->script_update_status_func = script_obj_new_null ();
data->script_display_normal_func = script_obj_new_null ();
data->script_display_password_func = script_obj_new_null ();
&data->script_keyboard_input_func,
"function",
NULL);
+ script_add_native_function (plymouth_hash,
+ "SetRegisterOperationFunction",
+ plymouth_set_function,
+ &data->script_register_operation_func,
+ "function",
+ NULL);
+ script_add_native_function (plymouth_hash,
+ "SetUnregisterOperationFunction",
+ plymouth_set_function,
+ &data->script_unregister_operation_func,
+ "function",
+ NULL);
script_add_native_function (plymouth_hash,
"SetUpdateStatusFunction",
plymouth_set_function,
script_obj_unref (data->script_boot_progress_func);
script_obj_unref (data->script_root_mounted_func);
script_obj_unref (data->script_keyboard_input_func);
+ script_obj_unref (data->script_register_operation_func);
+ script_obj_unref (data->script_unregister_operation_func);
script_obj_unref (data->script_update_status_func);
script_obj_unref (data->script_display_normal_func);
script_obj_unref (data->script_display_password_func);
script_obj_unref (ret.object);
}
+void script_lib_plymouth_on_register_operation (script_state_t *state,
+ script_lib_plymouth_data_t *data,
+ const char *operation_id,
+ const char *name)
+{
+ script_obj_t *new_name_obj = script_obj_new_string (name);
+ script_obj_t *new_operation_id_obj = script_obj_new_string (operation_id);
+ script_return_t ret = script_execute_object (state,
+ data->script_register_operation_func,
+ NULL,
+ new_operation_id_obj,
+ new_name_obj,
+ NULL);
+ script_obj_unref (new_name_obj);
+ script_obj_unref (new_operation_id_obj);
+ script_obj_unref (ret.object);
+}
+
+void script_lib_plymouth_on_unregister_operation (script_state_t *state,
+ script_lib_plymouth_data_t *data,
+ const char *operation_id)
+{
+ script_obj_t *new_operation_id_obj = script_obj_new_string (operation_id);
+ script_return_t ret = script_execute_object (state,
+ data->script_unregister_operation_func,
+ NULL,
+ new_operation_id_obj,
+ NULL);
+ script_obj_unref (new_operation_id_obj);
+ script_obj_unref (ret.object);
+}
+
void script_lib_plymouth_on_update_status (script_state_t *state,
script_lib_plymouth_data_t *data,
- const char *new_status)
+ const char *new_status,
+ const char *operation_id)
{
script_obj_t *new_status_obj = script_obj_new_string (new_status);
+ script_obj_t *new_operation_id_obj = script_obj_new_string (operation_id);
script_return_t ret = script_execute_object (state,
data->script_update_status_func,
NULL,
new_status_obj,
+ new_operation_id_obj,
NULL);
script_obj_unref (new_status_obj);
+ script_obj_unref (new_operation_id_obj);
script_obj_unref (ret.object);
}
script_obj_t *script_boot_progress_func;
script_obj_t *script_root_mounted_func;
script_obj_t *script_keyboard_input_func;
+ script_obj_t *script_register_operation_func;
+ script_obj_t *script_unregister_operation_func;
script_obj_t *script_update_status_func;
script_obj_t *script_display_normal_func;
script_obj_t *script_display_password_func;
void script_lib_plymouth_on_keyboard_input (script_state_t *state,
script_lib_plymouth_data_t *data,
const char *keyboard_input);
+void script_lib_plymouth_on_register_operation (script_state_t *state,
+ script_lib_plymouth_data_t *data,
+ const char *operation_id,
+ const char *name);
+void script_lib_plymouth_on_unregister_operation (script_state_t *state,
+ script_lib_plymouth_data_t *data,
+ const char *operation_id);
void script_lib_plymouth_on_update_status (script_state_t *state,
script_lib_plymouth_data_t *data,
- const char *new_status);
+ const char *new_status,
+ const char *operation_id);
void script_lib_plymouth_on_display_normal (script_state_t *state,
script_lib_plymouth_data_t *data);
void script_lib_plymouth_on_display_password (script_state_t *state,
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (plugin != NULL);
}
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (plugin != NULL);
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (plugin != NULL);
}
static void
update_status (ply_boot_splash_plugin_t *plugin,
- const char *status)
+ const char *status,
+ const char *operation_id)
{
assert (plugin != NULL);
}
#define PLY_BOOT_PROTOCOL_TRIMMED_ABSTRACT_SOCKET_PATH "/org/freedesktop/plymouthd"
#define PLY_BOOT_PROTOCOL_OLD_ABSTRACT_SOCKET_PATH "/ply-boot-protocol"
#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_PING "P"
+#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_REGISTER "O"
+#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_UNREGISTER "o"
#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_UPDATE "U"
#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_CHANGE_MODE "C"
#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_SYSTEM_UPDATE "u"
/* ply-boot-server.c - listens for and processes boot-status events
*
* Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
ply_list_t *cached_passwords;
int socket_fd;
+ ply_boot_server_register_handler_t register_handler;
+ ply_boot_server_unregister_handler_t unregister_handler;
ply_boot_server_update_handler_t update_handler;
ply_boot_server_change_mode_handler_t change_mode_handler;
ply_boot_server_system_update_handler_t system_update_handler;
};
ply_boot_server_t *
-ply_boot_server_new (ply_boot_server_update_handler_t update_handler,
+ply_boot_server_new (ply_boot_server_register_handler_t register_handler,
+ ply_boot_server_unregister_handler_t unregister_handler,
+ ply_boot_server_update_handler_t update_handler,
ply_boot_server_change_mode_handler_t change_mode_handler,
ply_boot_server_system_update_handler_t system_update_handler,
ply_boot_server_ask_for_password_handler_t ask_for_password_handler,
server->cached_passwords = ply_list_new ();
server->loop = NULL;
server->is_listening = false;
+ server->register_handler = register_handler;
+ server->unregister_handler = unregister_handler;
server->update_handler = update_handler;
server->change_mode_handler = change_mode_handler;
server->system_update_handler = system_update_handler;
static bool
ply_boot_connection_read_request (ply_boot_connection_t *connection,
char **command,
- char **argument)
+ char **argument_1,
+ char **argument_2)
{
uint8_t header[2];
+ uint8_t argument_1_size = 0;
+ uint8_t argument_2_size = 0;
assert (connection != NULL);
assert (connection->fd >= 0);
*command = calloc (2, sizeof (char));
*command[0] = header[0];
- *argument = NULL;
- if (header[1] == '\002')
+ *argument_1 = NULL;
+ *argument_2 = NULL;
+ if (header[1] == '\002' || header[1] == '\003')
{
- uint8_t argument_size;
+ if (!ply_read (connection->fd, &argument_1_size, sizeof (uint8_t)))
+ {
+ free (*command);
+ return false;
+ }
- if (!ply_read (connection->fd, &argument_size, sizeof (uint8_t)))
+ *argument_1 = calloc (argument_1_size, sizeof (char));
+
+ if (!ply_read (connection->fd, *argument_1, argument_1_size))
{
+ free (*argument_1);
free (*command);
return false;
}
+ }
- *argument = calloc (argument_size, sizeof (char));
+ if (header[1] == '\003')
+ {
+ if (!ply_read (connection->fd, &argument_2_size, sizeof (uint8_t)))
+ {
+ free (*argument_1);
+ free (*command);
+ return false;
+ }
+
+ *argument_2 = calloc (argument_2_size, sizeof (char));
- if (!ply_read (connection->fd, *argument, argument_size))
+ if (!ply_read (connection->fd, *argument_2, argument_2_size))
{
- free (*argument);
+ free (*argument_1);
+ free (*argument_2);
free (*command);
return false;
}
if (!ply_get_credentials_from_fd (connection->fd, &connection->pid, &connection->uid, NULL))
{
ply_trace ("couldn't read credentials from connection: %m");
- free (*argument);
+ free (*argument_1);
+ free (*argument_2);
free (*command);
return false;
}
ply_boot_connection_on_request (ply_boot_connection_t *connection)
{
ply_boot_server_t *server;
- char *command, *argument;
+ char *command, *argument_1, *argument_2;
assert (connection != NULL);
assert (connection->fd >= 0);
assert (server != NULL);
if (!ply_boot_connection_read_request (connection,
- &command, &argument))
+ &command, &argument_1, &argument_2))
{
ply_trace ("could not read connection request");
return;
ply_trace ("got update request");
if (server->update_handler != NULL)
- server->update_handler (server->user_data, argument, server);
- free (argument);
+ server->update_handler (server->user_data, argument_1, argument_2, server);
+ free (argument_1);
+ free (argument_2);
+ free (command);
+ return;
+ }
+ else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_REGISTER) == 0)
+ {
+ if (!ply_write (connection->fd,
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK,
+ strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK)))
+ ply_trace ("could not finish writing update reply: %m");
+
+ if (server->register_handler != NULL)
+ server->register_handler (server->user_data, argument_1, argument_2, server);
+ free (argument_1);
+ free (argument_2);
+ free (command);
+ return;
+ }
+ else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_UNREGISTER) == 0)
+ {
+ if (!ply_write (connection->fd,
+ PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK,
+ strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK)))
+ ply_trace ("could not finish writing update reply: %m");
+
+ if (server->unregister_handler != NULL)
+ server->unregister_handler (server->user_data, argument_1, server);
+ free (argument_1);
free (command);
return;
}
ply_trace ("got change mode notification");
if (server->change_mode_handler != NULL)
- server->change_mode_handler (server->user_data, argument, server);
- free (argument);
+ server->change_mode_handler (server->user_data, argument_1, server);
+ free (argument_1);
+ free (argument_2);
free (command);
return;
}
long int value;
char *endptr = NULL;
- value = strtol (argument, &endptr, 10);
+ value = strtol (argument_1, &endptr, 10);
if (endptr == NULL || *endptr != '\0' || value < 0 || value > 100)
{
- ply_error ("failed to parse percentage %s", argument);
+ ply_error ("failed to parse percentage %s", argument_1);
value = 0;
}
if (server->system_update_handler != NULL)
server->system_update_handler (server->user_data, value, server);
- free (argument);
+ free (argument_1);
+ free (argument_2);
free (command);
return;
}
if (server->deactivate_handler != NULL)
server->deactivate_handler (server->user_data, deactivate_trigger, server);
- free (argument);
+ free (argument_1);
+ free (argument_2);
free (command);
return;
}
bool retain_splash;
ply_trigger_t *quit_trigger;
- retain_splash = (bool) argument[0];
+ retain_splash = (bool) argument_1[0];
ply_trace ("got quit %srequest", retain_splash? "--retain-splash " : "");
if (server->quit_handler != NULL)
server->quit_handler (server->user_data, retain_splash, quit_trigger, server);
- free(argument);
+ free(argument_1);
+ free(argument_2);
free(command);
return;
}
if (server->ask_for_password_handler != NULL)
server->ask_for_password_handler (server->user_data,
- argument,
+ argument_1,
answer,
server);
/* will reply later
if (server->ask_question_handler != NULL)
server->ask_question_handler (server->user_data,
- argument,
+ argument_1,
answer,
server);
/* will reply later
{
ply_trace ("got show message request");
if (server->display_message_handler != NULL)
- server->display_message_handler(server->user_data, argument, server);
+ server->display_message_handler(server->user_data, argument_1, server);
}
else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HIDE_MESSAGE) == 0)
{
ply_trace ("got hide message request");
if (server->hide_message_handler != NULL)
- server->hide_message_handler(server->user_data, argument, server);
+ server->hide_message_handler(server->user_data, argument_1, server);
}
else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE) == 0)
{
if (server->watch_for_keystroke_handler != NULL)
server->watch_for_keystroke_handler (server->user_data,
- argument,
+ argument_1,
answer,
server);
/* will reply later
ply_trace ("got keystroke remove request");
if (server->ignore_keystroke_handler != NULL)
server->ignore_keystroke_handler (server->user_data,
- argument,
+ argument_1,
server);
}
else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PROGRESS_PAUSE) == 0)
{
ply_trace ("got newroot request");
if (server->newroot_handler != NULL)
- server->newroot_handler(server->user_data, argument, server);
+ server->newroot_handler(server->user_data, argument_1, server);
}
else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_HAS_ACTIVE_VT) == 0)
{
typedef struct _ply_boot_server ply_boot_server_t;
+typedef void (* ply_boot_server_register_handler_t) (void *user_data,
+ const char *operation_id,
+ const char *name,
+ ply_boot_server_t *server);
+
+typedef void (* ply_boot_server_unregister_handler_t) (void *user_data,
+ const char *operation_id,
+ ply_boot_server_t *server);
+
typedef void (* ply_boot_server_update_handler_t) (void *user_data,
const char *status,
+ const char *operation_id,
ply_boot_server_t *server);
typedef void (* ply_boot_server_change_mode_handler_t) (void *user_data,
ply_boot_server_t *server);
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
-ply_boot_server_t *ply_boot_server_new (ply_boot_server_update_handler_t update_handler,
+ply_boot_server_t *ply_boot_server_new (ply_boot_server_register_handler_t register_handler,
+ ply_boot_server_unregister_handler_t unregister_handler,
+ ply_boot_server_update_handler_t update_handler,
ply_boot_server_change_mode_handler_t change_mode_handler,
ply_boot_server_system_update_handler_t system_update_handler,
ply_boot_server_ask_for_password_handler_t ask_for_password_handler,