/* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2009,2010 Free Software Foundation, Inc. * * VAS_EBOOT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VAS_EBOOT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAS_EBOOT. If not, see . */ #include #include #include #include #include #include VAS_EBOOT_MOD_LICENSE ("GPLv3+"); struct VasEBoot_term_autoload *VasEBoot_term_input_autoload = NULL; struct VasEBoot_term_autoload *VasEBoot_term_output_autoload = NULL; struct abstract_terminal { struct abstract_terminal *next; struct abstract_terminal *prev; const char *name; VasEBoot_err_t (*init) (struct abstract_terminal *term); VasEBoot_err_t (*fini) (struct abstract_terminal *term); }; static VasEBoot_err_t handle_command (int argc, char **args, struct abstract_terminal **enabled, struct abstract_terminal **disabled, struct VasEBoot_term_autoload *autoloads, const char *active_str, const char *available_str) { int i; struct abstract_terminal *term; struct VasEBoot_term_autoload *aut; if (argc == 0) { VasEBoot_puts_ (active_str); for (term = *enabled; term; term = term->next) VasEBoot_printf ("%s ", term->name); VasEBoot_printf ("\n"); VasEBoot_puts_ (available_str); for (term = *disabled; term; term = term->next) VasEBoot_printf ("%s ", term->name); /* This is quadratic but we don't expect mode than 30 terminal modules ever. */ for (aut = autoloads; aut; aut = aut->next) { for (term = *disabled; term; term = term->next) if (VasEBoot_strcmp (term->name, aut->name) == 0 || (aut->name[0] && aut->name[VasEBoot_strlen (aut->name) - 1] == '*' && VasEBoot_memcmp (term->name, aut->name, VasEBoot_strlen (aut->name) - 1) == 0)) break; if (!term) for (term = *enabled; term; term = term->next) if (VasEBoot_strcmp (term->name, aut->name) == 0 || (aut->name[0] && aut->name[VasEBoot_strlen (aut->name) - 1] == '*' && VasEBoot_memcmp (term->name, aut->name, VasEBoot_strlen (aut->name) - 1) == 0)) break; if (!term) VasEBoot_printf ("%s ", aut->name); } VasEBoot_printf ("\n"); return VAS_EBOOT_ERR_NONE; } i = 0; if (VasEBoot_strcmp (args[0], "--append") == 0 || VasEBoot_strcmp (args[0], "--remove") == 0) i++; if (i == argc) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("no terminal specified")); for (; i < argc; i++) { int again = 0; while (1) { for (term = *disabled; term; term = term->next) if (VasEBoot_strcmp (args[i], term->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", term->name) == 0)) break; if (term == 0) for (term = *enabled; term; term = term->next) if (VasEBoot_strcmp (args[i], term->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", term->name) == 0)) break; if (term) break; if (again) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), args[i]); for (aut = autoloads; aut; aut = aut->next) if (VasEBoot_strcmp (args[i], aut->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", aut->name) == 0) || (aut->name[0] && aut->name[VasEBoot_strlen (aut->name) - 1] == '*' && VasEBoot_memcmp (args[i], aut->name, VasEBoot_strlen (aut->name) - 1) == 0)) { VasEBoot_dl_t mod; mod = VasEBoot_dl_load (aut->modname); if (mod) VasEBoot_dl_ref (mod); VasEBoot_errno = VAS_EBOOT_ERR_NONE; break; } if (VasEBoot_memcmp (args[i], "serial_usb", sizeof ("serial_usb") - 1) == 0 && VasEBoot_term_poll_usb) { VasEBoot_term_poll_usb (1); again = 1; continue; } if (!aut) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), args[i]); again = 1; } } if (VasEBoot_strcmp (args[0], "--append") == 0) { for (i = 1; i < argc; i++) { for (term = *disabled; term; term = term->next) if (VasEBoot_strcmp (args[i], term->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", term->name) == 0)) break; if (term) { if (term->init && term->init (term) != VAS_EBOOT_ERR_NONE) return VasEBoot_errno; VasEBoot_list_remove (VAS_EBOOT_AS_LIST (term)); VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (enabled), VAS_EBOOT_AS_LIST (term)); } } return VAS_EBOOT_ERR_NONE; } if (VasEBoot_strcmp (args[0], "--remove") == 0) { for (i = 1; i < argc; i++) { for (term = *enabled; term; term = term->next) if (VasEBoot_strcmp (args[i], term->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", term->name) == 0)) break; if (term) { if (!term->next && term == *enabled) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "can't remove the last terminal"); VasEBoot_list_remove (VAS_EBOOT_AS_LIST (term)); if (term->fini) term->fini (term); VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (disabled), VAS_EBOOT_AS_LIST (term)); } } return VAS_EBOOT_ERR_NONE; } for (i = 0; i < argc; i++) { for (term = *disabled; term; term = term->next) if (VasEBoot_strcmp (args[i], term->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", term->name) == 0)) break; if (term) { if (term->init && term->init (term) != VAS_EBOOT_ERR_NONE) return VasEBoot_errno; VasEBoot_list_remove (VAS_EBOOT_AS_LIST (term)); VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (enabled), VAS_EBOOT_AS_LIST (term)); } } { struct abstract_terminal *next; for (term = *enabled; term; term = next) { next = term->next; for (i = 0; i < argc; i++) if (VasEBoot_strcmp (args[i], term->name) == 0 || (VasEBoot_strcmp (args[i], "ofconsole") == 0 && VasEBoot_strcmp ("console", term->name) == 0)) break; if (i == argc) { if (!term->next && term == *enabled) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "can't remove the last terminal"); VasEBoot_list_remove (VAS_EBOOT_AS_LIST (term)); if (term->fini) term->fini (term); VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (disabled), VAS_EBOOT_AS_LIST (term)); } } } return VAS_EBOOT_ERR_NONE; } static VasEBoot_err_t VasEBoot_cmd_terminal_input (VasEBoot_command_t cmd __attribute__ ((unused)), int argc, char **args) { (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_inputs, struct abstract_terminal *, next); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_inputs, struct abstract_terminal *, prev); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_inputs, struct abstract_terminal *, name); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_inputs, struct abstract_terminal *, init); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_inputs, struct abstract_terminal *, fini); return handle_command (argc, args, (struct abstract_terminal **) (void *) &VasEBoot_term_inputs, (struct abstract_terminal **) (void *) &VasEBoot_term_inputs_disabled, VasEBoot_term_input_autoload, N_("Active input terminals:"), N_("Available input terminals:")); } static VasEBoot_err_t VasEBoot_cmd_terminal_output (VasEBoot_command_t cmd __attribute__ ((unused)), int argc, char **args) { (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_outputs, struct abstract_terminal *, next); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_outputs, struct abstract_terminal *, prev); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_outputs, struct abstract_terminal *, name); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_outputs, struct abstract_terminal *, init); (void) VAS_EBOOT_FIELD_MATCH (VasEBoot_term_outputs, struct abstract_terminal *, fini); return handle_command (argc, args, (struct abstract_terminal **) (void *) &VasEBoot_term_outputs, (struct abstract_terminal **) (void *) &VasEBoot_term_outputs_disabled, VasEBoot_term_output_autoload, N_("Active output terminals:"), N_("Available output terminals:")); } static VasEBoot_command_t cmd_terminal_input, cmd_terminal_output; VAS_EBOOT_MOD_INIT(terminal) { cmd_terminal_input = VasEBoot_register_command ("terminal_input", VasEBoot_cmd_terminal_input, N_("[--append|--remove] " "[TERMINAL1] [TERMINAL2] ..."), N_("List or select an input terminal.")); cmd_terminal_output = VasEBoot_register_command ("terminal_output", VasEBoot_cmd_terminal_output, N_("[--append|--remove] " "[TERMINAL1] [TERMINAL2] ..."), N_("List or select an output terminal.")); } VAS_EBOOT_MOD_FINI(terminal) { VasEBoot_unregister_command (cmd_terminal_input); VasEBoot_unregister_command (cmd_terminal_output); }