terminal.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2009,2010 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/mm.h>
  19. #include <grub/dl.h>
  20. #include <grub/command.h>
  21. #include <grub/term.h>
  22. #include <grub/i18n.h>
  23. #include <grub/misc.h>
  24. struct abstract_terminal
  25. {
  26. struct abstract_terminal *next;
  27. const char *name;
  28. grub_err_t (*init) (void);
  29. grub_err_t (*fini) (void);
  30. };
  31. static grub_err_t
  32. handle_command (int argc, char **args, struct abstract_terminal **enabled,
  33. struct abstract_terminal **disabled,
  34. struct grub_term_autoload *autoloads,
  35. const char *active_str,
  36. const char *available_str)
  37. {
  38. int i;
  39. struct abstract_terminal *term;
  40. struct grub_term_autoload *aut;
  41. if (argc == 0)
  42. {
  43. grub_puts_ (active_str);
  44. for (term = *enabled; term; term = term->next)
  45. grub_printf ("%s ", term->name);
  46. grub_printf ("\n");
  47. grub_puts_ (available_str);
  48. for (term = *disabled; term; term = term->next)
  49. grub_printf ("%s ", term->name);
  50. /* This is quadratic but we don't expect mode than 30 terminal
  51. modules ever. */
  52. for (aut = autoloads; aut; aut = aut->next)
  53. {
  54. for (term = *disabled; term; term = term->next)
  55. if (grub_strcmp (term->name, aut->name) == 0)
  56. break;
  57. if (!term)
  58. for (term = *enabled; term; term = term->next)
  59. if (grub_strcmp (term->name, aut->name) == 0)
  60. break;
  61. if (!term)
  62. grub_printf ("%s ", aut->name);
  63. }
  64. grub_printf ("\n");
  65. return GRUB_ERR_NONE;
  66. }
  67. i = 0;
  68. if (grub_strcmp (args[0], "--append") == 0
  69. || grub_strcmp (args[0], "--remove") == 0)
  70. i++;
  71. if (i == argc)
  72. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
  73. for (; i < argc; i++)
  74. {
  75. int again = 0;
  76. while (1)
  77. {
  78. for (term = *disabled; term; term = term->next)
  79. if (grub_strcmp (args[i], term->name) == 0)
  80. break;
  81. if (term == 0)
  82. for (term = *enabled; term; term = term->next)
  83. if (grub_strcmp (args[i], term->name) == 0)
  84. break;
  85. if (term)
  86. break;
  87. if (again)
  88. return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
  89. args[i]);
  90. for (aut = autoloads; aut; aut = aut->next)
  91. if (grub_strcmp (args[i], aut->name) == 0)
  92. {
  93. grub_dl_t mod;
  94. mod = grub_dl_load (aut->modname);
  95. if (mod)
  96. grub_dl_ref (mod);
  97. grub_errno = GRUB_ERR_NONE;
  98. break;
  99. }
  100. if (!aut)
  101. return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
  102. args[i]);
  103. again = 1;
  104. }
  105. }
  106. if (grub_strcmp (args[0], "--append") == 0)
  107. {
  108. for (i = 1; i < argc; i++)
  109. {
  110. for (term = *disabled; term; term = term->next)
  111. if (grub_strcmp (args[i], term->name) == 0)
  112. break;
  113. if (term)
  114. {
  115. if (term->init && term->init () != GRUB_ERR_NONE)
  116. return grub_errno;
  117. grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  118. grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  119. }
  120. }
  121. return GRUB_ERR_NONE;
  122. }
  123. if (grub_strcmp (args[0], "--remove") == 0)
  124. {
  125. for (i = 1; i < argc; i++)
  126. {
  127. for (term = *enabled; term; term = term->next)
  128. if (grub_strcmp (args[i], term->name) == 0)
  129. break;
  130. if (term)
  131. {
  132. if (!term->next && term == *enabled)
  133. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  134. "can't remove the last terminal");
  135. grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  136. if (term->fini)
  137. term->fini ();
  138. grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  139. }
  140. }
  141. return GRUB_ERR_NONE;
  142. }
  143. for (i = 0; i < argc; i++)
  144. {
  145. for (term = *disabled; term; term = term->next)
  146. if (grub_strcmp (args[i], term->name) == 0)
  147. break;
  148. if (term)
  149. {
  150. if (term->init && term->init () != GRUB_ERR_NONE)
  151. return grub_errno;
  152. grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  153. grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  154. }
  155. }
  156. {
  157. struct abstract_terminal *next;
  158. for (term = *enabled; term; term = next)
  159. {
  160. next = term->next;
  161. for (i = 0; i < argc; i++)
  162. if (grub_strcmp (args[i], term->name) == 0)
  163. break;
  164. if (i == argc)
  165. {
  166. if (!term->next && term == *enabled)
  167. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  168. "can't remove the last terminal");
  169. grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  170. if (term->fini)
  171. term->fini ();
  172. grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  173. }
  174. }
  175. }
  176. return GRUB_ERR_NONE;
  177. }
  178. static grub_err_t
  179. grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
  180. int argc, char **args)
  181. {
  182. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next);
  183. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name);
  184. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
  185. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
  186. return handle_command (argc, args,
  187. (struct abstract_terminal **) &grub_term_inputs,
  188. (struct abstract_terminal **) &grub_term_inputs_disabled,
  189. grub_term_input_autoload,
  190. N_ ("Active input terminals:"),
  191. N_ ("Available input terminals:"));
  192. }
  193. static grub_err_t
  194. grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
  195. int argc, char **args)
  196. {
  197. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next);
  198. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
  199. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
  200. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);
  201. return handle_command (argc, args, (struct abstract_terminal **) &grub_term_outputs,
  202. (struct abstract_terminal **) &grub_term_outputs_disabled,
  203. grub_term_output_autoload,
  204. N_ ("Active output terminals:"),
  205. N_ ("Available output terminals:"));
  206. }
  207. static grub_command_t cmd_terminal_input, cmd_terminal_output;
  208. GRUB_MOD_INIT(terminal)
  209. {
  210. cmd_terminal_input =
  211. grub_register_command ("terminal_input", grub_cmd_terminal_input,
  212. N_("[--append|--remove] "
  213. "[TERMINAL1] [TERMINAL2] ..."),
  214. N_("List or select an input terminal."));
  215. cmd_terminal_output =
  216. grub_register_command ("terminal_output", grub_cmd_terminal_output,
  217. N_("[--append|--remove] "
  218. "[TERMINAL1] [TERMINAL2] ..."),
  219. N_("List or select an output terminal."));
  220. }
  221. GRUB_MOD_FINI(terminal)
  222. {
  223. grub_unregister_command (cmd_terminal_input);
  224. grub_unregister_command (cmd_terminal_output);
  225. }