Changes in / [18b5175d:d231a54] in mainline
- Location:
- uspace/app/bdsh
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/input.c
r18b5175d rd231a54 56 56 #include "tok.h" 57 57 58 #define MAX_PIPES 10U59 60 58 extern volatile unsigned int cli_quit; 61 59 … … 65 63 /* Private helpers */ 66 64 static int run_command(char **, cliuser_t *, iostate_t *); 65 static void print_pipe_usage(void); 67 66 68 67 typedef struct { … … 80 79 81 80 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;141 81 } 142 82 … … 148 88 static errno_t process_input_nohup(cliuser_t *usr, list_t *alias_hups, size_t count_executed_hups) 149 89 { 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 159 90 if (count_executed_hups >= HUBS_MAX) { 160 91 cli_error(CL_EFAIL, "%s: maximal alias hubs reached\n", PACKAGE_NAME); … … 167 98 token_t *tokens = tokens_buf; 168 99 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 169 108 if (usr->line == NULL) { 170 109 free(tokens_buf); … … 192 131 } 193 132 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 */ 197 139 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; 219 145 } 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; 223 208 } 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; 232 243 goto finit; 233 244 } 234 245 } 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;243 246 244 247 iostate_t new_iostate = { … … 251 254 FILE *to = NULL; 252 255 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; 330 280 } 331 281 … … 362 312 363 313 return rc; 314 } 315 316 void 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 364 324 } 365 325 -
uspace/app/bdsh/tok.c
r18b5175d rd231a54 138 138 return rc; 139 139 } 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 == '\'') { 179 141 /* 180 142 * A string starts with a quote (') and ends again with a quote. -
uspace/app/bdsh/tok.h
r18b5175d rd231a54 33 33 TOKTYPE_TEXT, 34 34 TOKTYPE_PIPE, 35 TOKTYPE_RDIN,36 TOKTYPE_RDOU,37 TOKTYPE_RDAP,38 35 TOKTYPE_SPACE 39 36 } token_type_t;
Note:
See TracChangeset
for help on using the changeset viewer.