Changeset 9bfb74a in mainline
- Timestamp:
- 2024-11-28T23:11:39Z (5 days ago)
- Parents:
- 12dd36c (diff), 12f5a1be (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Manuele Conti <conti.manuele@…> (2024-11-28 23:11:39)
- git-committer:
- GitHub <noreply@…> (2024-11-28 23:11:39)
- Location:
- uspace/app/bdsh
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/input.c
r12dd36c r9bfb74a 56 56 #include "tok.h" 57 57 58 #define MAX_PIPES 10U 59 58 60 extern volatile unsigned int cli_quit; 59 61 … … 63 65 /* Private helpers */ 64 66 static int run_command(char **, cliuser_t *, iostate_t *); 65 static void print_pipe_usage(void);66 67 67 68 typedef struct { … … 79 80 80 81 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; 81 141 } 82 142 … … 88 148 static errno_t process_input_nohup(cliuser_t *usr, list_t *alias_hups, size_t count_executed_hups) 89 149 { 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 90 159 if (count_executed_hups >= HUBS_MAX) { 91 160 cli_error(CL_EFAIL, "%s: maximal alias hubs reached\n", PACKAGE_NAME); … … 98 167 token_t *tokens = tokens_buf; 99 168 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 108 169 if (usr->line == NULL) { 109 170 free(tokens_buf); … … 131 192 } 132 193 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 */ 194 cmd_argc = tokens_length; 195 unsigned wait_from = 0; 196 unsigned wait_to = 0; 139 197 for (i = 0, pipe_count = 0; i < tokens_length; i++) { 140 if (tokens[i].type == TOKTYPE_PIPE) { 141 if (pipe_count >= 2) { 142 print_pipe_usage(); 143 rc = ENOTSUP; 144 goto finit; 145 } 146 pipe_pos[pipe_count] = i; 147 pipe_count++; 148 } 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; 219 } 220 if (wait_to) { 221 redir_to = tokens[i].text; 222 wait_to = 0; 223 } 224 break; 225 226 default: 227 break; 228 } 229 230 if (pipe_count > MAX_PIPES) { 231 rc = ENOTSUP; 232 goto finit; 233 } 234 } 235 236 if (wait_from || wait_to) { 237 printf("Parse error near `\\n'\n"); 238 goto finit; 149 239 } 150 240 151 241 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; 208 } 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; 243 goto finit; 244 } 245 } 242 unsigned int cmd_token_end = cmd_argc; 246 243 247 244 iostate_t new_iostate = { … … 254 251 FILE *to = NULL; 255 252 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; 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; 280 330 } 281 331 … … 312 362 313 363 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 324 364 } 325 365 -
uspace/app/bdsh/tok.c
r12dd36c r9bfb74a 138 138 return rc; 139 139 } 140 } else if (next_char == '\'') { 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 == '\'') { 141 179 /* 142 180 * A string starts with a quote (') and ends again with a quote. -
uspace/app/bdsh/tok.h
r12dd36c r9bfb74a 33 33 TOKTYPE_TEXT, 34 34 TOKTYPE_PIPE, 35 TOKTYPE_RDIN, 36 TOKTYPE_RDOU, 37 TOKTYPE_RDAP, 35 38 TOKTYPE_SPACE 36 39 } token_type_t;
Note:
See TracChangeset
for help on using the changeset viewer.