source: mainline/uspace/app/bdsh/input.c@ 36ab7c7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 36ab7c7 was 36ab7c7, checked in by Jiri Svoboda <jiri@…>, 15 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
RevLine 
[36ab7c7]1/*
2 * Copyright (c) 2008 Tim Post
[216d6fc]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
[36ab7c7]6 * modification, are permitted provided that the following conditions
7 * are met:
[216d6fc]8 *
[36ab7c7]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.
[216d6fc]16 *
[36ab7c7]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.
[216d6fc]27 */
28
29#include <stdio.h>
30#include <stdlib.h>
[19f857a]31#include <str.h>
[73878c1]32#include <io/console.h>
33#include <io/keycode.h>
34#include <io/style.h>
[7e0cb78]35#include <io/color.h>
[3bf907a]36#include <vfs/vfs.h>
[371a012]37#include <clipboard.h>
[f1b37d6]38#include <macros.h>
[6071a8f]39#include <errno.h>
[da2bd08]40#include <assert.h>
[6071a8f]41#include <bool.h>
[36a75a2]42#include <tinput.h>
[216d6fc]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"
[6939edb]50#include "tok.h"
[216d6fc]51
[5db9084]52extern volatile unsigned int cli_quit;
53
[ed372da]54/** Text input field. */
[36a75a2]55static tinput_t *tinput;
[88944695]56
[6939edb]57/* Private helpers */
[6ea9a1d]58static int run_command(char **, cliuser_t *, iostate_t *);
[ae45201]59static void print_pipe_usage(void);
[659e9473]60
[216d6fc]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 */
[28ee877e]64int process_input(cliuser_t *usr)
[216d6fc]65{
66 char *cmd[WORD_MAX];
67 int rc = 0;
[6939edb]68 tokenizer_t tok;
[ae45201]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;
[216d6fc]74
75 if (NULL == usr->line)
76 return CL_EFAIL;
77
[6939edb]78 rc = tok_init(&tok, usr->line, cmd, WORD_MAX);
79 if (rc != EOK) {
80 goto finit;
[216d6fc]81 }
[6939edb]82
83 rc = tok_tokenize(&tok);
84 if (rc != EOK) {
85 goto finit;
86 }
87
[ae45201]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
[6ea9a1d]140 iostate_t new_iostate = {
141 .stdin = stdin,
142 .stdout = stdout,
143 .stderr = stderr
144 };
145
146 FILE *from = NULL;
147 FILE *to = NULL;
[ae45201]148
149 if (redir_from) {
[6ea9a1d]150 from = fopen(redir_from, "r");
[ae45201]151 if (from == NULL) {
152 printf("Cannot open file %s\n", redir_from);
153 rc = errno;
[6ea9a1d]154 goto finit_with_files;
[ae45201]155 }
[6ea9a1d]156 new_iostate.stdin = from;
[ae45201]157 }
158
[6ea9a1d]159
[ae45201]160 if (redir_to) {
[6ea9a1d]161 to = fopen(redir_to, "w");
[ae45201]162 if (to == NULL) {
163 printf("Cannot open file %s\n", redir_to);
164 rc = errno;
[6ea9a1d]165 goto finit_with_files;
[ae45201]166 }
[6ea9a1d]167 new_iostate.stdout = to;
[ae45201]168 }
169
[6ea9a1d]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 }
[6939edb]179
180finit:
[216d6fc]181 if (NULL != usr->line) {
182 free(usr->line);
183 usr->line = (char *) NULL;
184 }
[6939edb]185 tok_fini(&tok);
[216d6fc]186
187 return rc;
188}
189
[ae45201]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
[6ea9a1d]200int run_command(char **cmd, cliuser_t *usr, iostate_t *new_iostate)
[659e9473]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) {
[6ea9a1d]211 return run_builtin(id, cmd, usr, new_iostate);
[659e9473]212 }
213
214 /* Is it a module ? */
215 if ((id = (is_module(cmd[0]))) > -1) {
[6ea9a1d]216 return run_module(id, cmd, new_iostate);
[659e9473]217 }
218
219 /* See what try_exec thinks of it */
[6ea9a1d]220 return try_exec(cmd[0], cmd, new_iostate);
[659e9473]221}
222
[216d6fc]223void get_input(cliuser_t *usr)
224{
[19528516]225 char *str;
[5db9084]226 int rc;
[79ae36dd]227
228 console_flush(tinput->console);
229 console_set_style(tinput->console, STYLE_EMPHASIS);
[216d6fc]230 printf("%s", usr->prompt);
[79ae36dd]231 console_flush(tinput->console);
232 console_set_style(tinput->console, STYLE_NORMAL);
[9805cde]233
[5db9084]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 }
[19528516]246
247 /* Check for empty input. */
248 if (str_cmp(str, "") == 0) {
249 free(str);
[216d6fc]250 return;
[19528516]251 }
[216d6fc]252
[19528516]253 usr->line = str;
[216d6fc]254 return;
255}
[da2bd08]256
[36a75a2]257int input_init(void)
[da2bd08]258{
[36a75a2]259 tinput = tinput_new();
260 if (tinput == NULL) {
261 printf("Failed to initialize input.\n");
262 return 1;
263 }
264
265 return 0;
[da2bd08]266}
Note: See TracBrowser for help on using the repository browser.