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