HelenOS sources
This source file includes following definitions.
- find_alias_hup
- process_input_nohup
- process_input
- print_pipe_usage
- run_command
- get_input
- input_init
#include <stdio.h>
#include <stdlib.h>
#include <str.h>
#include <io/console.h>
#include <io/keycode.h>
#include <io/style.h>
#include <io/color.h>
#include <vfs/vfs.h>
#include <clipboard.h>
#include <macros.h>
#include <errno.h>
#include <assert.h>
#include <stdbool.h>
#include <tinput.h>
#include <adt/odict.h>
#include <adt/list.h>
#include "config.h"
#include "compl.h"
#include "util.h"
#include "scli.h"
#include "input.h"
#include "errors.h"
#include "exec.h"
#include "tok.h"
extern volatile unsigned int cli_quit;
static tinput_t *tinput;
static int run_command(char **, cliuser_t *, iostate_t *);
static void print_pipe_usage(void);
typedef struct {
link_t alias_hup_link;
alias_t *alias;
} alias_hup_t;
static bool find_alias_hup(alias_t *alias, list_t *alias_hups)
{
list_foreach(*alias_hups, alias_hup_link, alias_hup_t, link) {
if (alias == link->alias) {
return true;
}
}
return false;
}
static errno_t process_input_nohup(cliuser_t *usr, list_t *alias_hups, size_t count_executed_hups)
{
if (count_executed_hups >= HUBS_MAX) {
cli_error(CL_EFAIL, "%s: maximal alias hubs reached\n", PACKAGE_NAME);
return ELIMIT;
}
token_t *tokens_buf = calloc(WORD_MAX, sizeof(token_t));
if (tokens_buf == NULL)
return ENOMEM;
token_t *tokens = tokens_buf;
char *cmd[WORD_MAX];
errno_t rc = EOK;
tokenizer_t tok;
unsigned int i, pipe_count, processed_pipes;
unsigned int pipe_pos[2];
char *redir_from = NULL;
char *redir_to = NULL;
if (usr->line == NULL) {
free(tokens_buf);
return EINVAL;
}
rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
if (rc != EOK) {
goto finit;
}
size_t tokens_length;
rc = tok_tokenize(&tok, &tokens_length);
if (rc != EOK) {
goto finit;
}
if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
tokens++;
tokens_length--;
}
if (tokens_length > 0 && tokens[tokens_length - 1].type == TOKTYPE_SPACE) {
tokens_length--;
}
for (i = 0, pipe_count = 0; i < tokens_length; i++) {
if (tokens[i].type == TOKTYPE_PIPE) {
if (pipe_count >= 2) {
print_pipe_usage();
rc = ENOTSUP;
goto finit;
}
pipe_pos[pipe_count] = i;
pipe_count++;
}
}
unsigned int cmd_token_start = 0;
unsigned int cmd_token_end = tokens_length;
processed_pipes = 0;
if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
redir_from = tokens[2].text;
cmd_token_start = pipe_pos[0] + 1;
processed_pipes++;
}
if ((pipe_count - processed_pipes) > 0 &&
(pipe_pos[processed_pipes] == tokens_length - 4 ||
(pipe_pos[processed_pipes] == tokens_length - 5 &&
tokens[tokens_length - 4].type == TOKTYPE_SPACE)) &&
str_cmp(tokens[tokens_length - 3].text, "to") == 0) {
redir_to = tokens[tokens_length - 1].text;
cmd_token_end = pipe_pos[processed_pipes];
processed_pipes++;
}
if (processed_pipes != pipe_count) {
print_pipe_usage();
rc = ENOTSUP;
goto finit;
}
unsigned int cmd_pos = 0;
for (i = cmd_token_start; i < cmd_token_end; i++) {
if (tokens[i].type != TOKTYPE_SPACE) {
cmd[cmd_pos++] = tokens[i].text;
}
}
cmd[cmd_pos++] = NULL;
if (cmd[0] == NULL) {
print_pipe_usage();
rc = ENOTSUP;
goto finit;
}
odlink_t *alias_link = odict_find_eq(&alias_dict, (void *)cmd[0], NULL);
if (alias_link != NULL) {
alias_t *data = odict_get_instance(alias_link, alias_t, odict);
if (!find_alias_hup(data, alias_hups)) {
alias_hup_t *hup = (alias_hup_t *)calloc(1, sizeof(alias_hup_t));
if (hup == NULL) {
cli_error(CL_EFAIL, "%s: cannot allocate alias structure\n", PACKAGE_NAME);
rc = ENOMEM;
goto finit;
}
hup->alias = data;
list_append(&hup->alias_hup_link, alias_hups);
char *oldLine = usr->line;
const size_t input_length = str_size(usr->line) - str_size(cmd[0]) + str_size(data->value) + 1;
usr->line = (char *)malloc(input_length);
if (usr->line == NULL) {
cli_error(CL_EFAIL, "%s: cannot allocate input structure\n", PACKAGE_NAME);
rc = ENOMEM;
goto finit;
}
usr->line[0] = '\0';
unsigned int cmd_replace_index = cmd_token_start;
for (i = 0; i < tokens_length; i++) {
if (i == cmd_replace_index) {
if (tokens[i].type == TOKTYPE_SPACE) {
cmd_replace_index++;
str_append(usr->line, input_length, tokens[i].text);
continue;
}
str_append(usr->line, input_length, data->value);
} else {
str_append(usr->line, input_length, tokens[i].text);
}
}
rc = process_input_nohup(usr, alias_hups, count_executed_hups + 1);
usr->line = oldLine;
goto finit;
}
}
iostate_t new_iostate = {
.stdin = stdin,
.stdout = stdout,
.stderr = stderr
};
FILE *from = NULL;
FILE *to = NULL;
if (redir_from) {
from = fopen(redir_from, "r");
if (from == NULL) {
printf("Cannot open file %s\n", redir_from);
rc = errno;
goto finit_with_files;
}
new_iostate.stdin = from;
}
if (redir_to) {
to = fopen(redir_to, "w");
if (to == NULL) {
printf("Cannot open file %s\n", redir_to);
rc = errno;
goto finit_with_files;
}
new_iostate.stdout = to;
}
if (run_command(cmd, usr, &new_iostate) == 0) {
rc = EOK;
} else {
rc = EINVAL;
}
finit_with_files:
if (from != NULL) {
fclose(from);
}
if (to != NULL) {
fclose(to);
}
finit:
if (NULL != usr->line) {
free(usr->line);
usr->line = (char *) NULL;
}
tok_fini(&tok);
free(tokens_buf);
return rc;
}
errno_t process_input(cliuser_t *usr)
{
list_t alias_hups;
list_initialize(&alias_hups);
errno_t rc = process_input_nohup(usr, &alias_hups, 0);
list_foreach_safe(alias_hups, cur_link, next_link) {
alias_hup_t *cur_item = list_get_instance(cur_link, alias_hup_t, alias_hup_link);
free(cur_item);
}
return rc;
}
void print_pipe_usage(void)
{
printf("Invalid syntax!\n");
printf("Usage of redirection (pipes in the future):\n");
printf("from filename | command ...\n");
printf("from filename | command ... | to filename\n");
printf("command ... | to filename\n");
}
int run_command(char **cmd, cliuser_t *usr, iostate_t *new_iostate)
{
int id = 0;
if (NULL == cmd[0]) {
return CL_ENOENT;
}
if ((id = (is_builtin(cmd[0]))) > -1) {
return run_builtin(id, cmd, usr, new_iostate);
}
if ((id = (is_module(cmd[0]))) > -1) {
return run_module(id, cmd, new_iostate);
}
return try_exec(cmd[0], cmd, new_iostate);
}
void get_input(cliuser_t *usr)
{
char *str;
errno_t rc;
tinput_set_prompt(tinput, usr->prompt);
rc = tinput_read(tinput, &str);
if (rc == ENOENT) {
cli_quit = 1;
putchar('\n');
return;
}
if (rc != EOK) {
cli_quit = 1;
return;
}
if (str_cmp(str, "") == 0) {
free(str);
return;
}
usr->line = str;
return;
}
int input_init(void)
{
tinput = tinput_new();
if (tinput == NULL) {
printf("Failed to initialize input.\n");
return 1;
}
tinput_set_compl_ops(tinput, &compl_ops);
return 0;
}
HelenOS homepage, sources at GitHub