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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e4f8c77 was 36ab7c7, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Standardize formatting of copyright headers in Bdsh and add some that were
missing.

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