terminal.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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. GRUB_MOD_LICENSE ("GPLv3+");
  25. struct grub_term_autoload *grub_term_input_autoload = NULL;
  26. struct grub_term_autoload *grub_term_output_autoload = NULL;
  27. struct abstract_terminal
  28. {
  29. struct abstract_terminal *next;
  30. const char *name;
  31. grub_err_t (*init) (struct abstract_terminal *term);
  32. grub_err_t (*fini) (struct abstract_terminal *term);
  33. };
  34. static grub_err_t
  35. handle_command (int argc, char **args, struct abstract_terminal **enabled,
  36. struct abstract_terminal **disabled,
  37. struct grub_term_autoload *autoloads,
  38. const char *active_str,
  39. const char *available_str)
  40. {
  41. int i;
  42. struct abstract_terminal *term;
  43. struct grub_term_autoload *aut;
  44. if (argc == 0)
  45. {
  46. grub_puts_ (active_str);
  47. for (term = *enabled; term; term = term->next)
  48. grub_printf ("%s ", term->name);
  49. grub_printf ("\n");
  50. grub_puts_ (available_str);
  51. for (term = *disabled; term; term = term->next)
  52. grub_printf ("%s ", term->name);
  53. /* This is quadratic but we don't expect mode than 30 terminal
  54. modules ever. */
  55. for (aut = autoloads; aut; aut = aut->next)
  56. {
  57. for (term = *disabled; term; term = term->next)
  58. if (grub_strcmp (term->name, aut->name) == 0
  59. || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
  60. && grub_memcmp (term->name, aut->name,
  61. grub_strlen (aut->name) - 1) == 0))
  62. break;
  63. if (!term)
  64. for (term = *enabled; term; term = term->next)
  65. if (grub_strcmp (term->name, aut->name) == 0
  66. || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
  67. && grub_memcmp (term->name, aut->name,
  68. grub_strlen (aut->name) - 1) == 0))
  69. break;
  70. if (!term)
  71. grub_printf ("%s ", aut->name);
  72. }
  73. grub_printf ("\n");
  74. return GRUB_ERR_NONE;
  75. }
  76. i = 0;
  77. if (grub_strcmp (args[0], "--append") == 0
  78. || grub_strcmp (args[0], "--remove") == 0)
  79. i++;
  80. if (i == argc)
  81. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
  82. for (; i < argc; i++)
  83. {
  84. int again = 0;
  85. while (1)
  86. {
  87. for (term = *disabled; term; term = term->next)
  88. if (grub_strcmp (args[i], term->name) == 0)
  89. break;
  90. if (term == 0)
  91. for (term = *enabled; term; term = term->next)
  92. if (grub_strcmp (args[i], term->name) == 0)
  93. break;
  94. if (term)
  95. break;
  96. if (again)
  97. return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
  98. args[i]);
  99. for (aut = autoloads; aut; aut = aut->next)
  100. if (grub_strcmp (args[i], aut->name) == 0
  101. || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
  102. && grub_memcmp (args[i], aut->name,
  103. grub_strlen (aut->name) - 1) == 0))
  104. {
  105. grub_dl_t mod;
  106. mod = grub_dl_load (aut->modname);
  107. if (mod)
  108. grub_dl_ref (mod);
  109. grub_errno = GRUB_ERR_NONE;
  110. break;
  111. }
  112. if (!aut)
  113. return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
  114. args[i]);
  115. again = 1;
  116. }
  117. }
  118. if (grub_strcmp (args[0], "--append") == 0)
  119. {
  120. for (i = 1; i < argc; i++)
  121. {
  122. for (term = *disabled; term; term = term->next)
  123. if (grub_strcmp (args[i], term->name) == 0)
  124. break;
  125. if (term)
  126. {
  127. if (term->init && term->init (term) != GRUB_ERR_NONE)
  128. return grub_errno;
  129. grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  130. grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  131. }
  132. }
  133. return GRUB_ERR_NONE;
  134. }
  135. if (grub_strcmp (args[0], "--remove") == 0)
  136. {
  137. for (i = 1; i < argc; i++)
  138. {
  139. for (term = *enabled; term; term = term->next)
  140. if (grub_strcmp (args[i], term->name) == 0)
  141. break;
  142. if (term)
  143. {
  144. if (!term->next && term == *enabled)
  145. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  146. "can't remove the last terminal");
  147. grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  148. if (term->fini)
  149. term->fini (term);
  150. grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  151. }
  152. }
  153. return GRUB_ERR_NONE;
  154. }
  155. for (i = 0; i < argc; i++)
  156. {
  157. for (term = *disabled; term; term = term->next)
  158. if (grub_strcmp (args[i], term->name) == 0)
  159. break;
  160. if (term)
  161. {
  162. if (term->init && term->init (term) != GRUB_ERR_NONE)
  163. return grub_errno;
  164. grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  165. grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  166. }
  167. }
  168. {
  169. struct abstract_terminal *next;
  170. for (term = *enabled; term; term = next)
  171. {
  172. next = term->next;
  173. for (i = 0; i < argc; i++)
  174. if (grub_strcmp (args[i], term->name) == 0)
  175. break;
  176. if (i == argc)
  177. {
  178. if (!term->next && term == *enabled)
  179. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  180. "can't remove the last terminal");
  181. grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
  182. if (term->fini)
  183. term->fini (term);
  184. grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
  185. }
  186. }
  187. }
  188. return GRUB_ERR_NONE;
  189. }
  190. static grub_err_t
  191. grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
  192. int argc, char **args)
  193. {
  194. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next);
  195. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name);
  196. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
  197. (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
  198. return handle_command (argc, args,
  199. (struct abstract_terminal **) (void *) &grub_term_inputs,
  200. (struct abstract_terminal **) (void *) &grub_term_inputs_disabled,
  201. grub_term_input_autoload,
  202. N_ ("Active input terminals:"),
  203. N_ ("Available input terminals:"));
  204. }
  205. static grub_err_t
  206. grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
  207. int argc, char **args)
  208. {
  209. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next);
  210. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
  211. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
  212. (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);
  213. return handle_command (argc, args,
  214. (struct abstract_terminal **) (void *) &grub_term_outputs,
  215. (struct abstract_terminal **) (void *) &grub_term_outputs_disabled,
  216. grub_term_output_autoload,
  217. N_ ("Active output terminals:"),
  218. N_ ("Available output terminals:"));
  219. }
  220. static grub_command_t cmd_terminal_input, cmd_terminal_output;
  221. GRUB_MOD_INIT(terminal)
  222. {
  223. cmd_terminal_input =
  224. grub_register_command ("terminal_input", grub_cmd_terminal_input,
  225. N_("[--append|--remove] "
  226. "[TERMINAL1] [TERMINAL2] ..."),
  227. N_("List or select an input terminal."));
  228. cmd_terminal_output =
  229. grub_register_command ("terminal_output", grub_cmd_terminal_output,
  230. N_("[--append|--remove] "
  231. "[TERMINAL1] [TERMINAL2] ..."),
  232. N_("List or select an output terminal."));
  233. }
  234. GRUB_MOD_FINI(terminal)
  235. {
  236. grub_unregister_command (cmd_terminal_input);
  237. grub_unregister_command (cmd_terminal_output);
  238. }