source: mainline/uspace/app/bdsh/input.c@ 5f9a52e

Last change on this file since 5f9a52e was 5f9a52e, checked in by Manuele Conti <manuele.conti@…>, 4 years ago

Remove comment out code

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * Copyright (c) 2008 Tim Post
3 * Copyright (c) 2011 Jiri Svoboda
4 * Copyright (c) 2011 Martin Sucha
5 * Copyright (c) 2018 Matthieu Riolo
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * - The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <str.h>
35#include <io/console.h>
36#include <io/keycode.h>
37#include <io/style.h>
38#include <io/color.h>
39#include <vfs/vfs.h>
40#include <clipboard.h>
41#include <macros.h>
42#include <errno.h>
43#include <assert.h>
44#include <stdbool.h>
45#include <tinput.h>
46#include <adt/odict.h>
47#include <adt/list.h>
48
49#include "config.h"
50#include "compl.h"
51#include "util.h"
52#include "scli.h"
53#include "input.h"
54#include "errors.h"
55#include "exec.h"
56#include "tok.h"
57
58#define MAX_PIPES 10U
59
60extern volatile unsigned int cli_quit;
61
62/** Text input field. */
63static tinput_t *tinput;
64
65/* Private helpers */
66static int run_command(char **, cliuser_t *, iostate_t *);
67
68typedef struct {
69 link_t alias_hup_link;
70 alias_t *alias;
71} alias_hup_t;
72#if 0
73static bool find_alias_hup(alias_t *alias, list_t *alias_hups)
74{
75 list_foreach(*alias_hups, alias_hup_link, alias_hup_t, link) {
76 if (alias == link->alias) {
77 return true;
78 }
79 }
80
81 return false;
82}
83#endif
84/*
85 * Tokenizes input from console, sees if the first word is a built-in, if so
86 * invokes the built-in entry point (a[0]) passing all arguments in a[] to
87 * the handler
88 */
89static errno_t process_input_nohup(cliuser_t *usr, list_t *alias_hups, size_t count_executed_hups)
90{
91 char *cmd[WORD_MAX];
92 size_t cmd_argc = 0;
93 errno_t rc = EOK;
94 tokenizer_t tok;
95 unsigned int i, pipe_count;
96 unsigned int pipe_pos[MAX_PIPES];
97 char *redir_from = NULL;
98 char *redir_to = NULL;
99
100 if (count_executed_hups >= HUBS_MAX) {
101 cli_error(CL_EFAIL, "%s: maximal alias hubs reached\n", PACKAGE_NAME);
102 return ELIMIT;
103 }
104
105 token_t *tokens_buf = calloc(WORD_MAX, sizeof(token_t));
106 if (tokens_buf == NULL)
107 return ENOMEM;
108 token_t *tokens = tokens_buf;
109
110 if (usr->line == NULL) {
111 free(tokens_buf);
112 return EINVAL;
113 }
114
115 rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
116 if (rc != EOK) {
117 goto finit;
118 }
119
120 size_t tokens_length;
121 rc = tok_tokenize(&tok, &tokens_length);
122 if (rc != EOK) {
123 goto finit;
124 }
125
126 if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
127 tokens++;
128 tokens_length--;
129 }
130
131 if (tokens_length > 0 && tokens[tokens_length - 1].type == TOKTYPE_SPACE) {
132 tokens_length--;
133 }
134
135 cmd_argc = tokens_length;
136 for (i = 0, pipe_count = 0; i < tokens_length; i++) {
137 switch (tokens[i].type) {
138 case TOKTYPE_PIPE:
139 pipe_pos[pipe_count++] = i;
140 cmd_argc = i;
141 redir_to = (char *)"/tmp/pipe";
142 break;
143
144 case TOKTYPE_RDIN:
145 redir_from = tokens[i + 1].text;
146 cmd_argc = i;
147 break;
148
149 case TOKTYPE_RDOU:
150 redir_to = tokens[i + 1].text;
151 cmd_argc = i;
152 break;
153
154 default:
155 break;
156 }
157 if (pipe_count > MAX_PIPES) {
158 rc = ENOTSUP;
159 goto finit;
160 }
161 }
162
163 unsigned int cmd_token_start = 0;
164 unsigned int cmd_token_end = cmd_argc;
165
166 iostate_t new_iostate = {
167 .stdin = stdin,
168 .stdout = stdout,
169 .stderr = stderr
170 };
171
172 FILE *from = NULL;
173 FILE *to = NULL;
174
175 if (redir_from) {
176 from = fopen(redir_from, "r");
177 if (from == NULL) {
178 printf("Cannot open file %s\n", redir_from);
179 rc = errno;
180 goto finit_with_files;
181 }
182 new_iostate.stdin = from;
183 }
184
185 if (redir_to) {
186 to = fopen(redir_to, "w");
187 if (to == NULL) {
188 printf("Cannot open file %s\n", redir_to);
189 rc = errno;
190 goto finit_with_files;
191 }
192 new_iostate.stdout = to;
193 }
194
195 for (unsigned p = 0; p < pipe_count; p++) {
196 /* Convert tokens of the command to string array */
197 unsigned int cmd_pos = 0;
198 for (i = cmd_token_start; i < cmd_token_end; i++) {
199 if (tokens[i].type != TOKTYPE_SPACE) {
200 cmd[cmd_pos++] = tokens[i].text;
201 }
202 }
203 cmd[cmd_pos++] = NULL;
204
205 if (cmd[0] == NULL) {
206 printf("Command not found.\n");
207 rc = ENOTSUP;
208 goto finit;
209 }
210
211 if (p < pipe_count - 1) {
212 new_iostate.stdout = to;
213 } else {
214 new_iostate.stdin = to;
215 }
216
217 if (run_command(cmd, usr, &new_iostate) == 0) {
218 rc = EOK;
219 } else {
220 rc = EINVAL;
221 }
222
223 // Restore the Standard Input, Output and Error file descriptors
224 new_iostate.stdin = stdin;
225 new_iostate.stdout = stdout;
226 new_iostate.stderr = stderr;
227
228 cmd_token_start = cmd_token_end + 1;
229 cmd_token_end = (p < pipe_count - 1) ? pipe_pos[p + 1] : tokens_length;
230 }
231
232 unsigned int cmd_pos = 0;
233 for (i = cmd_token_start; i < cmd_token_end; i++) {
234 if (tokens[i].type != TOKTYPE_SPACE) {
235 cmd[cmd_pos++] = tokens[i].text;
236 }
237 }
238 cmd[cmd_pos++] = NULL;
239
240 if (cmd[0] == NULL) {
241 printf("Command not found.\n");
242 rc = ENOTSUP;
243 goto finit;
244 }
245
246 if (pipe_count) {
247 fseek(to, 0, SEEK_SET);
248 new_iostate.stdin = to;
249 }
250
251
252 if (run_command(cmd, usr, &new_iostate) == 0) {
253 rc = EOK;
254 } else {
255 rc = EINVAL;
256 }
257
258finit_with_files:
259 if (from != NULL) {
260 fclose(from);
261 }
262 if (to != NULL) {
263 fclose(to);
264 }
265
266finit:
267 if (NULL != usr->line) {
268 free(usr->line);
269 usr->line = (char *) NULL;
270 }
271 tok_fini(&tok);
272 free(tokens_buf);
273
274 return rc;
275}
276
277errno_t process_input(cliuser_t *usr)
278{
279 list_t alias_hups;
280 list_initialize(&alias_hups);
281
282 errno_t rc = process_input_nohup(usr, &alias_hups, 0);
283
284 list_foreach_safe(alias_hups, cur_link, next_link) {
285 alias_hup_t *cur_item = list_get_instance(cur_link, alias_hup_t, alias_hup_link);
286 free(cur_item);
287 }
288
289 return rc;
290}
291
292int run_command(char **cmd, cliuser_t *usr, iostate_t *new_iostate)
293{
294 int id = 0;
295
296 /* We have rubbish */
297 if (NULL == cmd[0]) {
298 return CL_ENOENT;
299 }
300
301 /* Is it a builtin command ? */
302 if ((id = (is_builtin(cmd[0]))) > -1) {
303 return run_builtin(id, cmd, usr, new_iostate);
304 }
305
306 /* Is it a module ? */
307 if ((id = (is_module(cmd[0]))) > -1) {
308 return run_module(id, cmd, new_iostate);
309 }
310
311 /* See what try_exec thinks of it */
312 return try_exec(cmd[0], cmd, new_iostate);
313}
314
315void get_input(cliuser_t *usr)
316{
317 char *str;
318 errno_t rc;
319
320 tinput_set_prompt(tinput, usr->prompt);
321
322 rc = tinput_read(tinput, &str);
323 if (rc == ENOENT) {
324 /* User requested exit */
325 cli_quit = 1;
326 putchar('\n');
327 return;
328 }
329
330 if (rc != EOK) {
331 /* Error in communication with console */
332 cli_quit = 1;
333 return;
334 }
335
336 /* Check for empty input. */
337 if (str_cmp(str, "") == 0) {
338 free(str);
339 return;
340 }
341
342 usr->line = str;
343 return;
344}
345
346int input_init(void)
347{
348 tinput = tinput_new();
349 if (tinput == NULL) {
350 printf("Failed to initialize input.\n");
351 return 1;
352 }
353
354 tinput_set_compl_ops(tinput, &compl_ops);
355
356 return 0;
357}
Note: See TracBrowser for help on using the repository browser.