|
@@ -1,12 +1,13 @@
|
|
|
#include "esh_main_loop.h"
|
|
|
#include "esh_misc.h"
|
|
|
#include "esh_history.h"
|
|
|
+#include "esh_init.h"
|
|
|
|
|
|
void EShRunLoop() {
|
|
|
struct termios orig_term_attr;
|
|
|
struct termios new_term_attr;
|
|
|
|
|
|
- /* set the terminal to raw mode */
|
|
|
+ /* set the terminal to semi-raw mode */
|
|
|
tcgetattr(fileno(stdin), &orig_term_attr);
|
|
|
memcpy(&new_term_attr, &orig_term_attr, sizeof(struct termios));
|
|
|
new_term_attr.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
|
|
@@ -182,9 +183,10 @@ void EShRunLoop() {
|
|
|
EShAddCommandToHistory(command);
|
|
|
|
|
|
EShJob* jobs;
|
|
|
- int jobs_num;
|
|
|
+ int jobs_num = 0;
|
|
|
|
|
|
- EShParseCommandIntoJobs(command, &jobs, &jobs_num);
|
|
|
+ jobs = EShParseCommandIntoJobs(command, &jobs_num);
|
|
|
+ // EShPrintJobsDebugInfo(command, jobs, jobs_num);
|
|
|
EShExecuteJobs(jobs_num, jobs);
|
|
|
}
|
|
|
|
|
@@ -197,13 +199,80 @@ void EShShowMsg() {
|
|
|
printf("%s", esh_info_global->invite_message);
|
|
|
}
|
|
|
|
|
|
-void EShParseCommandIntoJobs(char* command, EShJob** jobs_ptr, int* jobs_num_ptr) {
|
|
|
+EShJob* EShParseCommandIntoJobs(char* command, int* jobs_num) {
|
|
|
+ EShJob* jobs = EShMakeJobsList();
|
|
|
|
|
|
+ *jobs_num = 1;
|
|
|
+ int current_job_cmd_length = 0;
|
|
|
+
|
|
|
+ for (int i = 0; i < strlen(command); ++i) {
|
|
|
+ ESH_JOB_DELIMITER delimiter = EshIsJobDelimiter(command + i);
|
|
|
+
|
|
|
+ if (delimiter != NOT_A_DELIMITER) {
|
|
|
+ EShSplitJobCommand(&jobs[*jobs_num - 1], ' ');
|
|
|
+
|
|
|
+ if (delimiter == SEMICOLON) {
|
|
|
+ jobs[*jobs_num].job_start_condition = NO_CONDITION;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (delimiter == LOGIC_AND) {
|
|
|
+ jobs[*jobs_num].job_start_condition = PREVIOUS_EXIT_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (delimiter == LOGIC_OR) {
|
|
|
+ jobs[*jobs_num].job_start_condition = PREVIOUS_EXIT_FAILED;
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: delimiter == BIT_OR and BIT_AND
|
|
|
+
|
|
|
+ ++(*jobs_num);
|
|
|
+ current_job_cmd_length = 0;
|
|
|
+
|
|
|
+ i += EShGetJobDelimiterSize(EshIsJobDelimiter(command + i)) - 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ jobs[*jobs_num - 1].command[current_job_cmd_length] = command[i];
|
|
|
+ ++current_job_cmd_length;
|
|
|
+ }
|
|
|
+
|
|
|
+ EShSplitJobCommand(&jobs[*jobs_num - 1], ' ');
|
|
|
+ return jobs;
|
|
|
+}
|
|
|
+
|
|
|
+void EShSplitJobCommand(EShJob* job, char delim) {
|
|
|
+ int token_status = 0; // 0 - token result[result_size] finished
|
|
|
+ // 1 - token result[result_size] not finished
|
|
|
+ int current_token_length = 0;
|
|
|
+ for (int i = 0; i < strlen(job->command); ++i) {
|
|
|
+ while (job->command[i] == delim && i < strlen(job->command)) {
|
|
|
+ if (token_status == 1) {
|
|
|
+ token_status = 0;
|
|
|
+ }
|
|
|
+ ++i;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == strlen(job->command)) {
|
|
|
+ if (token_status == 1) {
|
|
|
+ ++job->command_tokens_num;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (token_status == 0) {
|
|
|
+ token_status = 1;
|
|
|
+ ++job->command_tokens_num;
|
|
|
+ current_token_length = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ job->command_tokens[job->command_tokens_num - 1][current_token_length] = job->command[i];
|
|
|
+ ++current_token_length;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void EShExecuteJobs(int jobs_num, EShJob* jobs_list) {
|
|
|
for (int i = 0; i < jobs_num; ++i) {
|
|
|
- EShRunJob(jobs_list[i]);
|
|
|
+ EShRunJob(&jobs_list[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -213,10 +282,14 @@ void EShSetJobCommandType(EShJob* job) {
|
|
|
|
|
|
void EShRunJob(EShJob* job) {
|
|
|
// TODO: PIPES INIT & BG PROCESS SUPPORT
|
|
|
-
|
|
|
int pid = fork();
|
|
|
if (pid == 0) {
|
|
|
- execvp(job->command[0], job->command);
|
|
|
+ for (int i = job->command_tokens_num; i < esh_info_global->max_command_tokens; ++i) {
|
|
|
+ free(job->command_tokens[i]);
|
|
|
+ job->command_tokens[i] = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ execvp(job->command_tokens[0], job->command_tokens);
|
|
|
printf("Esh: run command %s failed.\n", job->command);
|
|
|
exit(1); // execlp failed
|
|
|
} else {
|
|
@@ -240,3 +313,20 @@ void EShProcessInnerJob(const char* command) {
|
|
|
void EShProcessExecJob(const char* command) {
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+void EShPrintJobsDebugInfo(const char* command, EShJob* jobs, int jobs_num) {
|
|
|
+ printf("\nD: Splitted command (%s) into %d jobs:\n", command, jobs_num);
|
|
|
+ for (int i = 0; i < jobs_num; ++i) {
|
|
|
+ printf("===================\n"
|
|
|
+ "Job #%d:\n"
|
|
|
+ "Cmd: %s\n"
|
|
|
+ "Cmd tokens: %d ",
|
|
|
+ i, jobs[i].command, jobs[i].command_tokens_num);
|
|
|
+
|
|
|
+ for (int j = 0; j < jobs[i].command_tokens_num; ++j) {
|
|
|
+ printf("{%s} ", jobs[i].command_tokens[j]);
|
|
|
+ }
|
|
|
+ printf("\n===================\n");
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+}
|