Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/input.c

    r5db9084 rb2727f18  
    1 /* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
     1/*
     2 * Copyright (c) 2008 Tim Post
     3 * Copyright (c) 2011 Jiri Svoboda
     4 * Copyright (c) 2011 Martin Sucha
    25 * All rights reserved.
    36 *
    47 * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions are met:
     8 * modification, are permitted provided that the following conditions
     9 * are met:
    610 *
    7  * Redistributions of source code must retain the above copyright notice, this
    8  * list of conditions and the following disclaimer.
     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.
    918 *
    10  * Redistributions in binary form must reproduce the above copyright notice,
    11  * this list of conditions and the following disclaimer in the documentation
    12  * and/or other materials provided with the distribution.
    13  *
    14  * Neither the name of the original program's authors nor the names of its
    15  * contributors may be used to endorse or promote products derived from this
    16  * software without specific prior written permission.
    17  *
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    28  * POSSIBILITY OF SUCH DAMAGE.
     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.
    2929 */
    3030
     
    4545
    4646#include "config.h"
     47#include "compl.h"
    4748#include "util.h"
    4849#include "scli.h"
     
    5051#include "errors.h"
    5152#include "exec.h"
     53#include "tok.h"
    5254
    5355extern volatile unsigned int cli_quit;
     
    5557/** Text input field. */
    5658static tinput_t *tinput;
     59
     60/* Private helpers */
     61static int run_command(char **, cliuser_t *, iostate_t *);
     62static void print_pipe_usage(void);
    5763
    5864/* Tokenizes input from console, sees if the first word is a built-in, if so
    5965 * invokes the built-in entry point (a[0]) passing all arguments in a[] to
    6066 * the handler */
    61 int tok_input(cliuser_t *usr)
     67int process_input(cliuser_t *usr)
    6268{
    6369        char *cmd[WORD_MAX];
    64         int n = 0, i = 0;
     70        token_t tokens_space[WORD_MAX];
     71        token_t *tokens = tokens_space;
    6572        int rc = 0;
    66         char *tmp;
     73        tokenizer_t tok;
     74        unsigned int i, pipe_count, processed_pipes;
     75        unsigned int pipe_pos[2];
     76        char *redir_from = NULL;
     77        char *redir_to = NULL;
    6778
    6879        if (NULL == usr->line)
    6980                return CL_EFAIL;
    7081
    71         tmp = str_dup(usr->line);
    72 
    73         cmd[n] = strtok(tmp, " ");
    74         while (cmd[n] && n < WORD_MAX) {
    75                 cmd[++n] = strtok(NULL, " ");
    76         }
    77 
    78         /* We have rubbish */
    79         if (NULL == cmd[0]) {
    80                 rc = CL_ENOENT;
    81                 goto finit;
    82         }
    83 
    84         /* Its a builtin command ? */
    85         if ((i = (is_builtin(cmd[0]))) > -1) {
    86                 rc = run_builtin(i, cmd, usr);
    87                 goto finit;
    88         /* Its a module ? */
    89         } else if ((i = (is_module(cmd[0]))) > -1) {
    90                 rc = run_module(i, cmd);
    91                 goto finit;
    92         }
    93 
    94         /* See what try_exec thinks of it */
    95         rc = try_exec(cmd[0], cmd);
    96 
     82        rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
     83        if (rc != EOK) {
     84                goto finit;
     85        }
     86       
     87        size_t tokens_length;
     88        rc = tok_tokenize(&tok, &tokens_length);
     89        if (rc != EOK) {
     90                goto finit;
     91        }
     92       
     93        if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
     94                tokens++;
     95                tokens_length--;
     96        }
     97       
     98        if (tokens_length > 0 && tokens[tokens_length-1].type == TOKTYPE_SPACE) {
     99                tokens_length--;
     100        }
     101       
     102        /* Until full support for pipes is implemented, allow for a simple case:
     103         * [from <file> |] command [| to <file>]
     104         *
     105         * First find the pipes and check that there are no more
     106         */
     107        for (i = 0, pipe_count = 0; i < tokens_length; i++) {
     108                if (tokens[i].type == TOKTYPE_PIPE) {
     109                        if (pipe_count >= 2) {
     110                                print_pipe_usage();
     111                                rc = ENOTSUP;
     112                                goto finit;
     113                        }
     114                        pipe_pos[pipe_count] = i;
     115                        pipe_count++;
     116                }
     117        }
     118       
     119        unsigned int cmd_token_start = 0;
     120        unsigned int cmd_token_end = tokens_length;
     121       
     122        processed_pipes = 0;
     123       
     124        /* Check if the first part (from <file> |) is present */
     125        if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
     126                /* Ignore the first three tokens (from, file, pipe) and set from */
     127                redir_from = tokens[2].text;
     128                cmd_token_start = pipe_pos[0]+1;
     129                processed_pipes++;
     130        }
     131       
     132        /* Check if the second part (| to <file>) is present */
     133        if ((pipe_count - processed_pipes) > 0 &&
     134            (pipe_pos[processed_pipes] == tokens_length - 4 ||
     135            (pipe_pos[processed_pipes] == tokens_length - 5 &&
     136            tokens[tokens_length-4].type == TOKTYPE_SPACE )) &&
     137            str_cmp(tokens[tokens_length-3].text, "to") == 0) {
     138                /* Ignore the last three tokens (pipe, to, file) and set to */
     139                redir_to = tokens[tokens_length-1].text;
     140                cmd_token_end = pipe_pos[processed_pipes];
     141                processed_pipes++;
     142        }
     143       
     144        if (processed_pipes != pipe_count) {
     145                print_pipe_usage();
     146                rc = ENOTSUP;
     147                goto finit;
     148        }
     149       
     150        /* Convert tokens of the command to string array */
     151        unsigned int cmd_pos = 0;
     152        for (i = cmd_token_start; i < cmd_token_end; i++) {
     153                if (tokens[i].type != TOKTYPE_SPACE) {
     154                        cmd[cmd_pos++] = tokens[i].text;
     155                }
     156        }
     157        cmd[cmd_pos++] = NULL;
     158       
     159        if (cmd[0] == NULL) {
     160                print_pipe_usage();
     161                rc = ENOTSUP;
     162                goto finit;
     163        }
     164       
     165        iostate_t new_iostate = {
     166                .stdin = stdin,
     167                .stdout = stdout,
     168                .stderr = stderr
     169        };
     170       
     171        FILE *from = NULL;
     172        FILE *to = NULL;
     173       
     174        if (redir_from) {
     175                from = fopen(redir_from, "r");
     176                if (from == NULL) {
     177                        printf("Cannot open file %s\n", redir_from);
     178                        rc = errno;
     179                        goto finit_with_files;
     180                }
     181                new_iostate.stdin = from;
     182        }
     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        rc = run_command(cmd, usr, &new_iostate);
     196       
     197finit_with_files:
     198        if (from != NULL) {
     199                fclose(from);
     200        }
     201        if (to != NULL) {
     202                fclose(to);
     203        }
     204       
    97205finit:
    98206        if (NULL != usr->line) {
     
    100208                usr->line = (char *) NULL;
    101209        }
    102         if (NULL != tmp)
    103                 free(tmp);
     210        tok_fini(&tok);
    104211
    105212        return rc;
     213}
     214
     215void print_pipe_usage()
     216{
     217        printf("Invalid syntax!\n");
     218        printf("Usage of redirection (pipes in the future):\n");
     219        printf("from filename | command ...\n");
     220        printf("from filename | command ... | to filename\n");
     221        printf("command ... | to filename\n");
     222       
     223}
     224
     225int run_command(char **cmd, cliuser_t *usr, iostate_t *new_iostate)
     226{
     227        int id = 0;
     228       
     229        /* We have rubbish */
     230        if (NULL == cmd[0]) {
     231                return CL_ENOENT;
     232        }
     233       
     234        /* Is it a builtin command ? */
     235        if ((id = (is_builtin(cmd[0]))) > -1) {
     236                return run_builtin(id, cmd, usr, new_iostate);
     237        }
     238       
     239        /* Is it a module ? */
     240        if ((id = (is_module(cmd[0]))) > -1) {
     241                return run_module(id, cmd, new_iostate);
     242        }
     243
     244        /* See what try_exec thinks of it */
     245        return try_exec(cmd[0], cmd, new_iostate);
    106246}
    107247
     
    110250        char *str;
    111251        int rc;
    112 
    113         fflush(stdout);
    114         console_set_style(fphone(stdout), STYLE_EMPHASIS);
    115         printf("%s", usr->prompt);
    116         fflush(stdout);
    117         console_set_style(fphone(stdout), STYLE_NORMAL);
     252       
     253        tinput_set_prompt(tinput, usr->prompt);
    118254
    119255        rc = tinput_read(tinput, &str);
     
    148284        }
    149285
     286        tinput_set_compl_ops(tinput, &compl_ops);
     287
    150288        return 0;
    151289}
Note: See TracChangeset for help on using the changeset viewer.