source: mainline/uspace/app/bdsh/input.c@ a35b458

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

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • 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.