allow chaining commands with '&&'
This commit is contained in:
parent
df20aeeda6
commit
db4653a2d2
2 changed files with 90 additions and 41 deletions
|
|
@ -41,9 +41,7 @@ void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz) {
|
||||||
int i = 0, n = 0, j = 0;
|
int i = 0, n = 0, j = 0;
|
||||||
char cur_word_buf[1024];
|
char cur_word_buf[1024];
|
||||||
|
|
||||||
/*case '#':
|
/*
|
||||||
do_clear = 1;
|
|
||||||
break;
|
|
||||||
case '|':
|
case '|':
|
||||||
if (i + 1 < sz) {
|
if (i + 1 < sz) {
|
||||||
if (buf[i + 1] == '|') {
|
if (buf[i + 1] == '|') {
|
||||||
|
|
@ -56,18 +54,6 @@ void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz) {
|
||||||
}
|
}
|
||||||
do_clear = 1;
|
do_clear = 1;
|
||||||
break;
|
break;
|
||||||
case '&':
|
|
||||||
if (i + 1 < sz) {
|
|
||||||
if (buf[i + 1] == '&') {
|
|
||||||
msh_lexer_push_item(lexer, MSH_LEXER_ITEM_TYPE_OP_AND, buf, 2);
|
|
||||||
last = i + 2;
|
|
||||||
} else {
|
|
||||||
msh_lexer_push_item(lexer, MSH_LEXER_ITEM_TYPE_OP_CONTROL, buf, 1);
|
|
||||||
last = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
do_clear = 1;
|
|
||||||
break;
|
|
||||||
case ';':
|
case ';':
|
||||||
msh_lexer_push_item(lexer, MSH_LEXER_ITEM_TYPE_OP_SEMICOLON, buf, 1);
|
msh_lexer_push_item(lexer, MSH_LEXER_ITEM_TYPE_OP_SEMICOLON, buf, 1);
|
||||||
do_clear = 1;
|
do_clear = 1;
|
||||||
|
|
@ -94,11 +80,22 @@ void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz) {
|
||||||
quote_mode = !quote_mode;
|
quote_mode = !quote_mode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '&':
|
||||||
|
if (i + 1 < sz) {
|
||||||
|
if (buf[i + 1] == '&') {
|
||||||
|
msh_lexer_push_item(lexer, MSH_LEXER_ITEM_TYPE_OP_AND, buf, 2);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
msh_lexer_push_item(lexer, MSH_LEXER_ITEM_TYPE_OP_CONTROL, buf, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
if (quote_mode == 1) {
|
if (quote_mode == 1) {
|
||||||
goto do_add;
|
goto do_add;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* fallthrough */
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\0':
|
case '\0':
|
||||||
cur_word_buf[n++] = '\0';
|
cur_word_buf[n++] = '\0';
|
||||||
|
|
@ -122,25 +119,13 @@ lexer_cancel:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int msh_lexer_execute(msh_lexer *lexer) {
|
static int do_exec(msh_lexer *lexer, char *cmd, char **args, int *n,
|
||||||
msh_lexer_item_list *list = lexer->item_list_head;
|
int *exec_status) {
|
||||||
char *cmd = list->item->str;
|
|
||||||
SIZE_TYPE cmd_size = list->item->strlen;
|
|
||||||
|
|
||||||
SIZE_TYPE args_size = 0;
|
|
||||||
char is_first_arg = 0, exec_success = 0, exec_status = 0;
|
|
||||||
unsigned short i = 0, n = 0, j = 0, counter = 0;
|
|
||||||
char full_path[PATH_MAX];
|
char full_path[PATH_MAX];
|
||||||
char *args[512];
|
char is_first_arg = 0, exec_success = 0;
|
||||||
|
unsigned short i = 0, j = 0, counter = 0;
|
||||||
|
|
||||||
while (list != 0) {
|
args[*n] = 0;
|
||||||
if (!list->item) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
args[n++] = list->item->str;
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
args[n++] = 0;
|
|
||||||
|
|
||||||
/* Do nothing on blank commands */
|
/* Do nothing on blank commands */
|
||||||
if (*cmd == '\0') {
|
if (*cmd == '\0') {
|
||||||
|
|
@ -162,19 +147,20 @@ int msh_lexer_execute(msh_lexer *lexer) {
|
||||||
} else {
|
} else {
|
||||||
/* loop through all the path entries and check if the file exists in them.
|
/* loop through all the path entries and check if the file exists in them.
|
||||||
*/
|
*/
|
||||||
i = 0, n = 0, j = 0;
|
i = 0, *n = 0, j = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
full_path[n++] = lexer->path[j];
|
full_path[*n] = lexer->path[j];
|
||||||
|
*n += 1;
|
||||||
if (lexer->path[j] == '\0') {
|
if (lexer->path[j] == '\0') {
|
||||||
full_path[n - 1] = msh_path_seperator;
|
full_path[*n - 1] = msh_path_seperator;
|
||||||
for (i = 0; cmd[i] != 0; i++) {
|
for (i = 0; cmd[i] != 0; i++) {
|
||||||
full_path[i + n] = cmd[i];
|
full_path[i + *n] = cmd[i];
|
||||||
}
|
}
|
||||||
n += i;
|
*n += i;
|
||||||
full_path[n++] = '\0';
|
full_path[*n++] = '\0';
|
||||||
|
|
||||||
if (msh_path_exists(full_path)) {
|
if (msh_path_exists(full_path)) {
|
||||||
exec_status = msh_execute(full_path, args);
|
msh_execute(full_path, args);
|
||||||
exec_success = 1;
|
exec_success = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +169,7 @@ int msh_lexer_execute(msh_lexer *lexer) {
|
||||||
if (counter > 2) {
|
if (counter > 2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n = 0;
|
*n = 0;
|
||||||
} else {
|
} else {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -193,10 +179,62 @@ int msh_lexer_execute(msh_lexer *lexer) {
|
||||||
if (!exec_success) {
|
if (!exec_success) {
|
||||||
msh_print_strings("msh: ", cmd, ": command not found\n\r", 0);
|
msh_print_strings("msh: ", cmd, ": command not found\n\r", 0);
|
||||||
}
|
}
|
||||||
|
/* flush out args */
|
||||||
|
for (i = 0; i < 512; i++) {
|
||||||
|
if (args[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
args[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msh_lexer_execute(msh_lexer *lexer) {
|
||||||
|
msh_lexer_item_list *list = lexer->item_list_head;
|
||||||
|
char *cmd = list->item->str;
|
||||||
|
SIZE_TYPE cmd_size;
|
||||||
|
int i = 0, n = 0, exec_status = 0;
|
||||||
|
SIZE_TYPE args_size = 0;
|
||||||
|
char *args[512];
|
||||||
|
|
||||||
|
while (list != 0) {
|
||||||
|
if (!list->item) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (list->item->type) {
|
||||||
|
case MSH_LEXER_ITEM_TYPE_UNKNOWN:
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_WORD:
|
||||||
|
if (cmd == 0 && *list->item->str != '\0') {
|
||||||
|
cmd = list->item->str;
|
||||||
|
} else {
|
||||||
|
args[n++] = list->item->str;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_COMMENT:
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_OP_OR:
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_OP_AND:
|
||||||
|
do_exec(lexer, cmd, args, &n, &exec_status);
|
||||||
|
n = 0;
|
||||||
|
cmd = 0;
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_OP_PIPE:
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_OP_CONTROL:
|
||||||
|
break;
|
||||||
|
case MSH_LEXER_ITEM_TYPE_OP_SEMICOLON:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
do_exec(lexer, cmd, args, &n, &exec_status);
|
||||||
|
|
||||||
msh_lexer_flush(lexer);
|
msh_lexer_flush(lexer);
|
||||||
|
|
||||||
return exec_status == 0 ? exec_status : exec_success;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void msh_lexer_flush(msh_lexer *lexer) {
|
void msh_lexer_flush(msh_lexer *lexer) {
|
||||||
|
|
|
||||||
|
|
@ -95,12 +95,23 @@ const char *msh_working_directory();
|
||||||
*/
|
*/
|
||||||
void msh_set_working_directory(const char *);
|
void msh_set_working_directory(const char *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type representing an OS's process.
|
||||||
|
* !! Do NOT use the fields directly, use the appropriate macros instead.
|
||||||
|
*/
|
||||||
|
typedef struct msh_process_t {
|
||||||
|
#ifdef __linux__
|
||||||
|
SIZE_TYPE __pid;
|
||||||
|
#endif
|
||||||
|
} msh_process;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute given command with args.
|
* Execute given command with args.
|
||||||
*
|
*
|
||||||
* cmd is self explanatory, args is a null terminated array of strings based on
|
* cmd is self explanatory, args is a null terminated array of strings based on
|
||||||
* the arguments the user provided.
|
* the arguments the user provided.
|
||||||
*
|
*
|
||||||
|
* Returns the process to be waited on.
|
||||||
*
|
*
|
||||||
* Non-zero return values are the exit status. -1 implies the command was not
|
* Non-zero return values are the exit status. -1 implies the command was not
|
||||||
* found.
|
* found.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue