Changes in / [f0920f9f:49aaa0e] in mainline


Ignore:
Location:
uspace/app/bdsh
Files:
3 edited

Legend:

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

    rf0920f9f r49aaa0e  
    5656#include "tok.h"
    5757
    58 #define MAX_PIPES 10U
    59 
    6058extern volatile unsigned int cli_quit;
    6159
     
    6563/* Private helpers */
    6664static int run_command(char **, cliuser_t *, iostate_t *);
     65static void print_pipe_usage(void);
    6766
    6867typedef struct {
     
    8079
    8180        return false;
    82 }
    83 
    84 static errno_t find_alias(char **cmd, list_t *alias_hups, alias_t **data)
    85 {
    86         errno_t rc = EOK;
    87 
    88         /* test if the passed cmd is an alias */
    89         odlink_t *alias_link = odict_find_eq(&alias_dict, (void *)cmd[0], NULL);
    90         if (alias_link != NULL) {
    91                 *data = odict_get_instance(alias_link, alias_t, odict);
    92                 /* check if the alias already has been resolved once */
    93                 if (! find_alias_hup(*data, alias_hups)) {
    94                         alias_hup_t *hup = (alias_hup_t *)calloc(1, sizeof(alias_hup_t));
    95                         if (hup == NULL) {
    96                                 cli_error(CL_EFAIL, "%s: cannot allocate alias structure\n", PACKAGE_NAME);
    97                                 rc = ENOMEM;
    98                                 goto exit;
    99                         }
    100                         hup->alias = *data;
    101                         list_append(&hup->alias_hup_link, alias_hups);
    102                 }
    103         }
    104 
    105 exit:
    106         return rc;
    107 }
    108 
    109 static errno_t replace_alias(token_t *tokens, unsigned int tokens_start, unsigned int tokens_len, alias_t *data, char **cmd, char **line)
    110 {
    111         errno_t rc = EOK;
    112         const size_t input_length = str_size(*line) - str_size(cmd[0]) + str_size(data->value) + 1;
    113         char *newline = (char *)malloc(input_length);
    114         if (newline == NULL) {
    115                 cli_error(CL_EFAIL, "%s: cannot allocate input structure\n", PACKAGE_NAME);
    116                 rc = ENOMEM;
    117                 goto exit;
    118         }
    119 
    120         newline[0] = '\0';
    121 
    122         unsigned int cmd_replace_index = tokens_start;
    123         for (unsigned int i = 0; i < tokens_len; i++) {
    124                 if (i == cmd_replace_index) {
    125                         /* if there is a pipe symbol than cmd_token_start will point at the SPACE after the pipe symbol */
    126                         if (tokens[i].type == TOKTYPE_SPACE) {
    127                                 tokens_start++;
    128                                 str_append(*line, input_length, tokens[i].text);
    129                                 continue;
    130                         }
    131 
    132                         str_append(newline, input_length, data->value);
    133                 } else {
    134                         str_append(newline, input_length, tokens[i].text);
    135                 }
    136         }
    137 
    138         *line = newline;
    139 exit:
    140         return rc;
    14181}
    14282
     
    14888static errno_t process_input_nohup(cliuser_t *usr, list_t *alias_hups, size_t count_executed_hups)
    14989{
    150         char *cmd[WORD_MAX];
    151         size_t cmd_argc = 0;
    152         errno_t rc = EOK;
    153         tokenizer_t tok;
    154         unsigned int i, pipe_count;
    155         unsigned int pipe_pos[MAX_PIPES];
    156         char *redir_from = NULL;
    157         char *redir_to = NULL;
    158 
    15990        if (count_executed_hups >= HUBS_MAX) {
    16091                cli_error(CL_EFAIL, "%s: maximal alias hubs reached\n", PACKAGE_NAME);
     
    16798        token_t *tokens = tokens_buf;
    16899
     100        char *cmd[WORD_MAX];
     101        errno_t rc = EOK;
     102        tokenizer_t tok;
     103        unsigned int i, pipe_count, processed_pipes;
     104        unsigned int pipe_pos[2];
     105        char *redir_from = NULL;
     106        char *redir_to = NULL;
     107
    169108        if (usr->line == NULL) {
    170109                free(tokens_buf);
     
    192131        }
    193132
    194         cmd_argc = tokens_length;
    195         unsigned wait_from = 0;
    196         unsigned wait_to = 0;
     133        /*
     134         * Until full support for pipes is implemented, allow for a simple case:
     135         * [from <file> |] command [| to <file>]
     136         *
     137         * First find the pipes and check that there are no more
     138         */
    197139        for (i = 0, pipe_count = 0; i < tokens_length; i++) {
    198                 switch (tokens[i].type) {
    199                 case  TOKTYPE_PIPE:
    200                         pipe_pos[pipe_count++] = i;
    201                         cmd_argc = i;
    202                         redir_from = redir_to = tmpnam(NULL);
    203                         break;
    204 
    205                 case TOKTYPE_RDIN:
    206                         wait_from = 1;
    207                         cmd_argc = i;
    208                         break;
    209 
    210                 case TOKTYPE_RDOU:
    211                         wait_to = 1;
    212                         cmd_argc = i;
    213                         break;
    214 
    215                 case TOKTYPE_TEXT:
    216                         if (wait_from) {
    217                                 redir_from = tokens[i].text;
    218                                 wait_from = 0;
     140                if (tokens[i].type == TOKTYPE_PIPE) {
     141                        if (pipe_count >= 2) {
     142                                print_pipe_usage();
     143                                rc = ENOTSUP;
     144                                goto finit;
    219145                        }
    220                         if (wait_to) {
    221                                 redir_to = tokens[i].text;
    222                                 wait_to = 0;
     146                        pipe_pos[pipe_count] = i;
     147                        pipe_count++;
     148                }
     149        }
     150
     151        unsigned int cmd_token_start = 0;
     152        unsigned int cmd_token_end = tokens_length;
     153
     154        processed_pipes = 0;
     155
     156        /* Check if the first part (from <file> |) is present */
     157        if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
     158                /* Ignore the first three tokens (from, file, pipe) and set from */
     159                redir_from = tokens[2].text;
     160                cmd_token_start = pipe_pos[0] + 1;
     161                processed_pipes++;
     162        }
     163
     164        /* Check if the second part (| to <file>) is present */
     165        if ((pipe_count - processed_pipes) > 0 &&
     166            (pipe_pos[processed_pipes] == tokens_length - 4 ||
     167            (pipe_pos[processed_pipes] == tokens_length - 5 &&
     168            tokens[tokens_length - 4].type == TOKTYPE_SPACE)) &&
     169            str_cmp(tokens[tokens_length - 3].text, "to") == 0) {
     170                /* Ignore the last three tokens (pipe, to, file) and set to */
     171                redir_to = tokens[tokens_length - 1].text;
     172                cmd_token_end = pipe_pos[processed_pipes];
     173                processed_pipes++;
     174        }
     175
     176        if (processed_pipes != pipe_count) {
     177                print_pipe_usage();
     178                rc = ENOTSUP;
     179                goto finit;
     180        }
     181
     182        /* Convert tokens of the command to string array */
     183        unsigned int cmd_pos = 0;
     184        for (i = cmd_token_start; i < cmd_token_end; i++) {
     185                if (tokens[i].type != TOKTYPE_SPACE) {
     186                        cmd[cmd_pos++] = tokens[i].text;
     187                }
     188        }
     189        cmd[cmd_pos++] = NULL;
     190
     191        if (cmd[0] == NULL) {
     192                print_pipe_usage();
     193                rc = ENOTSUP;
     194                goto finit;
     195        }
     196
     197        /* test if the passed cmd is an alias */
     198        odlink_t *alias_link = odict_find_eq(&alias_dict, (void *)cmd[0], NULL);
     199        if (alias_link != NULL) {
     200                alias_t *data = odict_get_instance(alias_link, alias_t, odict);
     201                /* check if the alias already has been resolved once */
     202                if (!find_alias_hup(data, alias_hups)) {
     203                        alias_hup_t *hup = (alias_hup_t *)calloc(1, sizeof(alias_hup_t));
     204                        if (hup == NULL) {
     205                                cli_error(CL_EFAIL, "%s: cannot allocate alias structure\n", PACKAGE_NAME);
     206                                rc = ENOMEM;
     207                                goto finit;
    223208                        }
    224                         break;
    225 
    226                 default:
    227                         break;
    228                 }
    229 
    230                 if (pipe_count > MAX_PIPES) {
    231                         rc = ENOTSUP;
     209
     210                        hup->alias = data;
     211                        list_append(&hup->alias_hup_link, alias_hups);
     212
     213                        char *oldLine = usr->line;
     214                        const size_t input_length = str_size(usr->line) - str_size(cmd[0]) + str_size(data->value) + 1;
     215                        usr->line = (char *)malloc(input_length);
     216                        if (usr->line == NULL) {
     217                                cli_error(CL_EFAIL, "%s: cannot allocate input structure\n", PACKAGE_NAME);
     218                                rc = ENOMEM;
     219                                goto finit;
     220                        }
     221
     222                        usr->line[0] = '\0';
     223
     224                        unsigned int cmd_replace_index = cmd_token_start;
     225                        for (i = 0; i < tokens_length; i++) {
     226                                if (i == cmd_replace_index) {
     227                                        /* if there is a pipe symbol than cmd_token_start will point at the SPACE after the pipe symbol */
     228                                        if (tokens[i].type == TOKTYPE_SPACE) {
     229                                                cmd_replace_index++;
     230                                                str_append(usr->line, input_length, tokens[i].text);
     231                                                continue;
     232                                        }
     233
     234                                        str_append(usr->line, input_length, data->value);
     235                                } else {
     236                                        str_append(usr->line, input_length, tokens[i].text);
     237                                }
     238                        }
     239
     240                        /* reprocess input after string replace */
     241                        rc = process_input_nohup(usr, alias_hups, count_executed_hups + 1);
     242                        usr->line = oldLine;
    232243                        goto finit;
    233244                }
    234245        }
    235 
    236         if (wait_from || wait_to) {
    237                 printf("Parse error near `\\n'\n");
    238                 goto finit;
    239         }
    240 
    241         unsigned int cmd_token_start = 0;
    242         unsigned int cmd_token_end = cmd_argc;
    243246
    244247        iostate_t new_iostate = {
     
    251254        FILE *to = NULL;
    252255
    253 
    254         for (unsigned p = 0; p <= pipe_count; p++) {
    255                 /* Convert tokens of the command to string array */
    256                 unsigned int cmd_pos = 0;
    257                 for (i = cmd_token_start; i < cmd_token_end; i++) {
    258                         if (tokens[i].type != TOKTYPE_SPACE) {
    259                                 cmd[cmd_pos++] = tokens[i].text;
    260                         }
    261                 }
    262                 cmd[cmd_pos] = NULL;
    263 
    264                 if (cmd[0] == NULL) {
    265                         printf("Command not found.\n");
    266                         rc = ENOTSUP;
    267                         goto finit;
    268                 }
    269 
    270                 alias_t *data = NULL;
    271                 rc = find_alias(cmd, alias_hups, &data);
    272                 if (rc != EOK) {
    273                         goto finit;
    274                 }
    275 
    276                 if (data != NULL) {
    277                         rc = replace_alias(tokens, cmd_token_start, tokens_length, data, cmd, &usr->line);
    278                         if (rc == EOK) {
    279                                 /* reprocess input after string replace */
    280                                 rc = process_input_nohup(usr, alias_hups, count_executed_hups + 1);
    281                         }
    282                         goto finit;
    283                 }
    284 
    285                 if (redir_to) {
    286                         if ((p < pipe_count) || (pipe_count == 0)) {
    287                                 to = fopen(redir_to, "w");
    288                                 if (to == NULL) {
    289                                         printf("Cannot open file %s\n", redir_to);
    290                                         rc = errno;
    291                                         goto finit_with_files;
    292                                 }
    293                                 new_iostate.stdout = to;
    294                         }
    295                 }
    296 
    297                 if (redir_from) {
    298                         if ((p && p == pipe_count) || (pipe_count == 0)) {
    299                                 from = fopen(redir_from, "r");
    300                                 if (from == NULL) {
    301                                         printf("Cannot open file %s\n", redir_from);
    302                                         rc = errno;
    303                                         goto finit_with_files;
    304                                 }
    305                                 new_iostate.stdin = from;
    306                         }
    307                 }
    308 
    309                 if (run_command(cmd, usr, &new_iostate) == 0) {
    310                         rc = EOK;
    311                 } else {
    312                         rc = EINVAL;
    313                 }
    314 
    315                 if (to) {
    316                         fclose(to);
    317                         to = NULL;
    318                 }
    319                 if (from) {
    320                         fclose(from);
    321                         from = NULL;
    322                 }
    323                 // Restore the Standard Input, Output and Error file descriptors
    324                 new_iostate.stdin = stdin;
    325                 new_iostate.stdout = stdout;
    326                 new_iostate.stderr = stderr;
    327 
    328                 cmd_token_start = cmd_token_end + 1;
    329                 cmd_token_end = (p < pipe_count - 1) ? pipe_pos[p + 1] : tokens_length;
     256        if (redir_from) {
     257                from = fopen(redir_from, "r");
     258                if (from == NULL) {
     259                        printf("Cannot open file %s\n", redir_from);
     260                        rc = errno;
     261                        goto finit_with_files;
     262                }
     263                new_iostate.stdin = from;
     264        }
     265
     266        if (redir_to) {
     267                to = fopen(redir_to, "w");
     268                if (to == NULL) {
     269                        printf("Cannot open file %s\n", redir_to);
     270                        rc = errno;
     271                        goto finit_with_files;
     272                }
     273                new_iostate.stdout = to;
     274        }
     275
     276        if (run_command(cmd, usr, &new_iostate) == 0) {
     277                rc = EOK;
     278        } else {
     279                rc = EINVAL;
    330280        }
    331281
     
    362312
    363313        return rc;
     314}
     315
     316void print_pipe_usage(void)
     317{
     318        printf("Invalid syntax!\n");
     319        printf("Usage of redirection (pipes in the future):\n");
     320        printf("from filename | command ...\n");
     321        printf("from filename | command ... | to filename\n");
     322        printf("command ... | to filename\n");
     323
    364324}
    365325
  • uspace/app/bdsh/tok.c

    rf0920f9f r49aaa0e  
    138138                                return rc;
    139139                        }
    140                 } else if (next_char == '<') {
    141                         if (tok_pending_chars(tok)) {
    142                                 rc = tok_push_token(tok);
    143                                 if (rc != EOK) {
    144                                         return rc;
    145                                 }
    146                         }
    147 
    148                         tok_start_token(tok, TOKTYPE_RDIN);
    149 
    150                         rc = tok_push_char(tok, tok_get_char(tok));
    151                         if (rc != EOK) {
    152                                 return rc;
    153                         }
    154 
    155                         rc = tok_push_token(tok);
    156                         if (rc != EOK) {
    157                                 return rc;
    158                         }
    159                 } else if (next_char == '>') {
    160                         if (tok_pending_chars(tok)) {
    161                                 rc = tok_push_token(tok);
    162                                 if (rc != EOK) {
    163                                         return rc;
    164                                 }
    165                         }
    166 
    167                         tok_start_token(tok, TOKTYPE_RDOU);
    168 
    169                         rc = tok_push_char(tok, tok_get_char(tok));
    170                         if (rc != EOK) {
    171                                 return rc;
    172                         }
    173 
    174                         rc = tok_push_token(tok);
    175                         if (rc != EOK) {
    176                                 return rc;
    177                         }
    178                 }  else if (next_char == '\'') {
     140                } else if (next_char == '\'') {
    179141                        /*
    180142                         * A string starts with a quote (') and ends again with a quote.
  • uspace/app/bdsh/tok.h

    rf0920f9f r49aaa0e  
    3333        TOKTYPE_TEXT,
    3434        TOKTYPE_PIPE,
    35         TOKTYPE_RDIN,
    36         TOKTYPE_RDOU,
    37         TOKTYPE_RDAP,
    3835        TOKTYPE_SPACE
    3936} token_type_t;
Note: See TracChangeset for help on using the changeset viewer.