Ignore:
File:
1 edited

Legend:

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

    r5db9084 rb48d046  
    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)
    62 {
     67int process_input(cliuser_t *usr)
     68{
     69        token_t *tokens = calloc(WORD_MAX, sizeof(token_t));
     70        if (tokens == NULL)
     71                return ENOMEM;
     72       
    6373        char *cmd[WORD_MAX];
    64         int n = 0, i = 0;
    6574        int rc = 0;
    66         char *tmp;
    67 
    68         if (NULL == usr->line)
     75        tokenizer_t tok;
     76        unsigned int i, pipe_count, processed_pipes;
     77        unsigned int pipe_pos[2];
     78        char *redir_from = NULL;
     79        char *redir_to = NULL;
     80
     81        if (usr->line == NULL) {
     82                free(tokens);
    6983                return CL_EFAIL;
    70 
    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 
     84        }
     85
     86        rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
     87        if (rc != EOK) {
     88                goto finit;
     89        }
     90       
     91        size_t tokens_length;
     92        rc = tok_tokenize(&tok, &tokens_length);
     93        if (rc != EOK) {
     94                goto finit;
     95        }
     96       
     97        if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
     98                tokens++;
     99                tokens_length--;
     100        }
     101       
     102        if (tokens_length > 0 && tokens[tokens_length-1].type == TOKTYPE_SPACE) {
     103                tokens_length--;
     104        }
     105       
     106        /* Until full support for pipes is implemented, allow for a simple case:
     107         * [from <file> |] command [| to <file>]
     108         *
     109         * First find the pipes and check that there are no more
     110         */
     111        for (i = 0, pipe_count = 0; i < tokens_length; i++) {
     112                if (tokens[i].type == TOKTYPE_PIPE) {
     113                        if (pipe_count >= 2) {
     114                                print_pipe_usage();
     115                                rc = ENOTSUP;
     116                                goto finit;
     117                        }
     118                        pipe_pos[pipe_count] = i;
     119                        pipe_count++;
     120                }
     121        }
     122       
     123        unsigned int cmd_token_start = 0;
     124        unsigned int cmd_token_end = tokens_length;
     125       
     126        processed_pipes = 0;
     127       
     128        /* Check if the first part (from <file> |) is present */
     129        if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
     130                /* Ignore the first three tokens (from, file, pipe) and set from */
     131                redir_from = tokens[2].text;
     132                cmd_token_start = pipe_pos[0]+1;
     133                processed_pipes++;
     134        }
     135       
     136        /* Check if the second part (| to <file>) is present */
     137        if ((pipe_count - processed_pipes) > 0 &&
     138            (pipe_pos[processed_pipes] == tokens_length - 4 ||
     139            (pipe_pos[processed_pipes] == tokens_length - 5 &&
     140            tokens[tokens_length-4].type == TOKTYPE_SPACE )) &&
     141            str_cmp(tokens[tokens_length-3].text, "to") == 0) {
     142                /* Ignore the last three tokens (pipe, to, file) and set to */
     143                redir_to = tokens[tokens_length-1].text;
     144                cmd_token_end = pipe_pos[processed_pipes];
     145                processed_pipes++;
     146        }
     147       
     148        if (processed_pipes != pipe_count) {
     149                print_pipe_usage();
     150                rc = ENOTSUP;
     151                goto finit;
     152        }
     153       
     154        /* Convert tokens of the command to string array */
     155        unsigned int cmd_pos = 0;
     156        for (i = cmd_token_start; i < cmd_token_end; i++) {
     157                if (tokens[i].type != TOKTYPE_SPACE) {
     158                        cmd[cmd_pos++] = tokens[i].text;
     159                }
     160        }
     161        cmd[cmd_pos++] = NULL;
     162       
     163        if (cmd[0] == NULL) {
     164                print_pipe_usage();
     165                rc = ENOTSUP;
     166                goto finit;
     167        }
     168       
     169        iostate_t new_iostate = {
     170                .stdin = stdin,
     171                .stdout = stdout,
     172                .stderr = stderr
     173        };
     174       
     175        FILE *from = NULL;
     176        FILE *to = NULL;
     177       
     178        if (redir_from) {
     179                from = fopen(redir_from, "r");
     180                if (from == NULL) {
     181                        printf("Cannot open file %s\n", redir_from);
     182                        rc = errno;
     183                        goto finit_with_files;
     184                }
     185                new_iostate.stdin = from;
     186        }
     187       
     188       
     189        if (redir_to) {
     190                to = fopen(redir_to, "w");
     191                if (to == NULL) {
     192                        printf("Cannot open file %s\n", redir_to);
     193                        rc = errno;
     194                        goto finit_with_files;
     195                }
     196                new_iostate.stdout = to;
     197        }
     198       
     199        rc = run_command(cmd, usr, &new_iostate);
     200       
     201finit_with_files:
     202        if (from != NULL) {
     203                fclose(from);
     204        }
     205        if (to != NULL) {
     206                fclose(to);
     207        }
     208       
    97209finit:
    98210        if (NULL != usr->line) {
     
    100212                usr->line = (char *) NULL;
    101213        }
    102         if (NULL != tmp)
    103                 free(tmp);
     214        tok_fini(&tok);
     215        free(tokens);
    104216
    105217        return rc;
     218}
     219
     220void print_pipe_usage()
     221{
     222        printf("Invalid syntax!\n");
     223        printf("Usage of redirection (pipes in the future):\n");
     224        printf("from filename | command ...\n");
     225        printf("from filename | command ... | to filename\n");
     226        printf("command ... | to filename\n");
     227       
     228}
     229
     230int run_command(char **cmd, cliuser_t *usr, iostate_t *new_iostate)
     231{
     232        int id = 0;
     233       
     234        /* We have rubbish */
     235        if (NULL == cmd[0]) {
     236                return CL_ENOENT;
     237        }
     238       
     239        /* Is it a builtin command ? */
     240        if ((id = (is_builtin(cmd[0]))) > -1) {
     241                return run_builtin(id, cmd, usr, new_iostate);
     242        }
     243       
     244        /* Is it a module ? */
     245        if ((id = (is_module(cmd[0]))) > -1) {
     246                return run_module(id, cmd, new_iostate);
     247        }
     248
     249        /* See what try_exec thinks of it */
     250        return try_exec(cmd[0], cmd, new_iostate);
    106251}
    107252
     
    110255        char *str;
    111256        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);
     257       
     258        tinput_set_prompt(tinput, usr->prompt);
    118259
    119260        rc = tinput_read(tinput, &str);
     
    148289        }
    149290
     291        tinput_set_compl_ops(tinput, &compl_ops);
     292
    150293        return 0;
    151294}
Note: See TracChangeset for help on using the changeset viewer.