source: mainline/uspace/app/bdsh/input.c@ 3061bc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3061bc1 was 1b20da0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on non-empty lines, in certain file types.

Command used: tools/srepl '\([^[:space:]]\)\s\+$' '\1' -- *.c *.h *.py *.sh *.s *.S *.ag

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