summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/shell/shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libmisc/shell/shell.c')
-rw-r--r--cpukit/libmisc/shell/shell.c605
1 files changed, 406 insertions, 199 deletions
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
index 1e5962b1e3..9cefc80255 100644
--- a/cpukit/libmisc/shell/shell.c
+++ b/cpukit/libmisc/shell/shell.c
@@ -1,11 +1,11 @@
-/*
- *
- * Instantatiate a new terminal shell.
- *
- * Author:
+/**
+ * @file
*
- * WORK: fernando.ruiz@ctv.es
- * HOME: correo@fernando-ruiz.com
+ * @brief Instantatiate a new terminal shell.
+ */
+
+/*
+ * Copyright (c) 2001 Fernando Ruiz Casas <fruizcasas@gmail.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -49,11 +49,13 @@
#define shell_std_debug(...)
#endif
+#define SHELL_MAGIC rtems_build_name('S', 'E', 'N', 'V')
+
const rtems_shell_env_t rtems_global_shell_env = {
- .magic = rtems_build_name('S', 'E', 'N', 'V'),
+ .magic = SHELL_MAGIC,
.managed = false,
.devname = CONSOLE_DEVICE_NAME,
- .taskname = "SHGL",
+ .taskname = "RTSH",
.exit_shell = false,
.forever = true,
.echo = false,
@@ -198,6 +200,8 @@ static bool rtems_shell_set_shell_env(
rtems_shell_env_key_handle *handle;
int eno;
+ rtems_shell_init_environment();
+
handle = malloc(sizeof(rtems_shell_env_key_handle));
if (handle == NULL) {
rtems_error(0, "no memory for shell env key handle)");
@@ -267,12 +271,13 @@ void rtems_shell_dup_current_env(rtems_shell_env_t *copy)
if (env != NULL) {
shell_std_debug("dup: existing parent\n");
*copy = *env;
- }
- else {
+
+ /*
+ * Duplicated environments are not managed.
+ */
+ copy->managed = false;
+ } else {
*copy = rtems_global_shell_env;
- copy->magic = rtems_build_name('S', 'E', 'N', 'V');
- copy->devname = CONSOLE_DEVICE_NAME;
- copy->taskname = "RTSH";
copy->parent_stdout = stdout;
copy->parent_stdin = stdin;
copy->parent_stderr = stderr;
@@ -281,10 +286,6 @@ void rtems_shell_dup_current_env(rtems_shell_env_t *copy)
fileno(copy->parent_stdout), copy->parent_stdout,
fileno(copy->parent_stdin), copy->parent_stdin);
}
- /*
- * Duplicated environments are not managed.
- */
- copy->managed = false;
}
/*
@@ -313,32 +314,21 @@ static int rtems_shell_line_editor(
int c;
int col;
int last_col;
- int output;
char line[size];
char new_line[size];
int up;
int cmd = -1;
int inserting = 1;
int in_fileno = fileno(in);
- int out_fileno;
-
- _Assert(out != NULL);
- out_fileno = fileno(out);
-
- /*
- * Only this task can use this file descriptor because calling
- * fileno will block if another thread call made a call on this
- * descriptor.
- */
- output = (out && isatty(in_fileno));
col = last_col = 0;
tcdrain(in_fileno);
- if (out)
- tcdrain(out_fileno);
+ if (out != NULL) {
+ tcdrain(fileno(out));
+ }
- if (output && prompt)
+ if (out != NULL && prompt != NULL)
fprintf(out, "\r%s", prompt);
line[0] = 0;
@@ -346,7 +336,7 @@ static int rtems_shell_line_editor(
for (;;) {
- if (output)
+ if (out != NULL)
fflush(out);
extended_key = rtems_shell_getchar(in);
@@ -368,15 +358,14 @@ static int rtems_shell_line_editor(
switch (c)
{
case RTEMS_SHELL_KEYS_END:
- if (output)
+ if (out != NULL)
fprintf(out, "%s", line + col);
col = (int) strlen (line);
break;
case RTEMS_SHELL_KEYS_HOME:
- if (output) {
- if (prompt)
- fprintf(out,"\r%s", prompt);
+ if (out != NULL && prompt != NULL) {
+ fprintf(out,"\r%s", prompt);
}
col = 0;
break;
@@ -407,7 +396,7 @@ static int rtems_shell_line_editor(
int end;
int bs;
rtems_shell_move_left(line + col, 1);
- if (output) {
+ if (out != NULL) {
fprintf(out,"\r%s%s ", prompt, line);
end = (int) strlen (line);
for (bs = 0; bs < ((end - col) + 1); bs++)
@@ -426,9 +415,8 @@ static int rtems_shell_line_editor(
switch (c)
{
case 1: /*Control-a*/
- if (output) {
- if (prompt)
- fprintf(out,"\r%s", prompt);
+ if (out != NULL && prompt != NULL) {
+ fprintf(out,"\r%s", prompt);
}
col = 0;
break;
@@ -437,7 +425,7 @@ static int rtems_shell_line_editor(
if (col > 0)
{
col--;
- if (output)
+ if (out != NULL)
fputc('\b', out);
}
break;
@@ -446,7 +434,7 @@ static int rtems_shell_line_editor(
if (strlen(line)) {
if (col < strlen(line)) {
rtems_shell_move_left(line + col, 1);
- if (output) {
+ if (out != NULL) {
int bs;
fprintf(out,"%s \b", line + col);
for (bs = 0; bs < ((int) strlen (line) - col); bs++)
@@ -458,26 +446,26 @@ static int rtems_shell_line_editor(
/* Fall through */
case EOF:
- if (output)
+ if (out != NULL)
fputc('\n', out);
return -2;
case 5: /*Control-e*/
- if (output)
+ if (out != NULL)
fprintf(out, "%s", line + col);
col = (int) strlen (line);
break;
case 6: /* Control-F */
if ((col < size) && (line[col] != '\0')) {
- if (output)
+ if (out != NULL)
fputc(line[col], out);
col++;
}
break;
case 7: /* Control-G */
- if (output) {
+ if (out != NULL) {
/*
* The (int) cast is needed because the width specifier (%*)
* must be an int, but strlen() returns a size_t. Without
@@ -492,7 +480,7 @@ static int rtems_shell_line_editor(
case 11: /*Control-k*/
if (line[col]) {
- if (output) {
+ if (out != NULL) {
int end = strlen(line);
int bs;
fprintf(out,"%*c", end - col, ' ');
@@ -504,7 +492,7 @@ static int rtems_shell_line_editor(
break;
case '\f':
- if (output) {
+ if (out != NULL) {
int end;
int bs;
fputc('\f',out);
@@ -522,7 +510,7 @@ static int rtems_shell_line_editor(
int bs;
col--;
rtems_shell_move_left(line + col, 1);
- if (output) {
+ if (out != NULL) {
fprintf(out,"\b%s \b", line + col);
for (bs = 0; bs < ((int) strlen (line) - col); bs++)
fputc('\b', out);
@@ -536,7 +524,7 @@ static int rtems_shell_line_editor(
/*
* Process the command.
*/
- if (output)
+ if (out != NULL)
fprintf(out,"\n");
/*
@@ -564,7 +552,7 @@ static int rtems_shell_line_editor(
case 16: /* Control-P */
if ((cmd >= (count - 1)) || (strlen(cmds[cmd + 1]) == 0)) {
- if (output)
+ if (out != NULL)
fputc('\x7', out);
break;
}
@@ -584,7 +572,7 @@ static int rtems_shell_line_editor(
cmd++;
} else {
if (cmd < 0) {
- if (output)
+ if (out != NULL)
fprintf(out, "\x7");
break;
}
@@ -602,7 +590,7 @@ static int rtems_shell_line_editor(
col = strlen (line);
- if (output) {
+ if (out != NULL) {
fprintf(out,"\r%s%*c", prompt, clen, ' ');
fprintf(out,"\r%s%s", prompt, line);
}
@@ -615,17 +603,17 @@ static int rtems_shell_line_editor(
char tmp;
if (col == strlen(line)) {
col--;
- if (output)
+ if (out != NULL)
fprintf(out,"\b");
}
tmp = line[col];
line[col] = line[col - 1];
line[col - 1] = tmp;
- if (output)
+ if (out != NULL)
fprintf(out,"\b%c%c", line[col - 1], line[col]);
col++;
} else {
- if (output)
+ if (out != NULL)
fputc('\x7', out);
}
break;
@@ -639,7 +627,7 @@ static int rtems_shell_line_editor(
int bs;
rtems_shell_move_left(line, col);
- if (output) {
+ if (out != NULL) {
fprintf(out,"\r%s%*c", prompt, clen, ' ');
fprintf(out,"\r%s%s", prompt, line);
@@ -658,7 +646,7 @@ static int rtems_shell_line_editor(
int ch, bs;
for (ch = end + 1; ch > col; ch--)
line[ch] = line[ch - 1];
- if (output) {
+ if (out != NULL) {
fprintf(out, "%s", line + col);
for (bs = 0; bs < (end - col + 1); bs++)
fputc('\b', out);
@@ -667,7 +655,7 @@ static int rtems_shell_line_editor(
line[col++] = c;
if (col > end)
line[col] = '\0';
- if (output)
+ if (out != NULL)
fputc(c, out);
}
break;
@@ -817,6 +805,183 @@ void rtems_shell_print_env(
}
#endif
+/*
+ * Wait for the string to return or timeout.
+ */
+static bool rtems_shell_term_wait_for(const int fd, const char* str, const int timeout)
+{
+ int msec = timeout;
+ int i = 0;
+ while (msec-- > 0 && str[i] != '\0') {
+ char ch[2];
+ if (read(fd, &ch[0], 1) == 1) {
+ fflush(stdout);
+ if (ch[0] != str[i++]) {
+ return false;
+ }
+ msec = timeout;
+ } else {
+ usleep(1000);
+ }
+ }
+ if (msec == 0) {
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Buffer a string up to the end string
+ */
+static int rtems_shell_term_buffer_until(const int fd,
+ char* buf,
+ const int size,
+ const char* end,
+ const int timeout)
+{
+ int msec = timeout;
+ int i = 0;
+ int e = 0;
+ memset(&buf[0], 0, size);
+ while (msec-- > 0 && i < size && end[e] != '\0') {
+ char ch[2];
+ if (read(fd, &ch[0], 1) == 1) {
+ fflush(stdout);
+ buf[i++] = ch[0];
+ if (ch[0] == end[e]) {
+ e++;
+ } else {
+ e = 0;
+ }
+ msec = timeout;
+ } else {
+ usleep(1000);
+ }
+ }
+ if (msec == 0 || end[e] != '\0') {
+ return -1;
+ }
+ i -= e;
+ if (i < size) {
+ buf[i] = '\0';
+ }
+ return i;
+}
+
+/*
+ * Determine if the terminal has the row and column values
+ * swapped
+ *
+ * https://github.com/tmux/tmux/issues/3457
+ *
+ * Tmux has a bug where the lines and cols are swapped. There is a lag
+ * in the time it takes to get the fix into code so see if tmux is
+ * running and which version and work around the bug.
+ *
+ * The terminal device needs to have VMIN=0, and VTIME=0
+ */
+static bool rtems_shell_term_row_column_swapped(const int fd, const int timeout) {
+ char buf[64];
+ memset(&buf[0], 0, sizeof(buf));
+ /*
+ * CSI > Ps q
+ * Ps = 0 => DCS > | text ST
+ */
+ fputs("\033[>0q", stdout);
+ fflush(stdout);
+ if (rtems_shell_term_wait_for(fd, "\033P>|", timeout)) {
+ int len = rtems_shell_term_buffer_until(fd, buf, sizeof(buf), "\033\\", timeout);
+ if (len > 0) {
+ if (memcmp(buf, "tmux ", 5) == 0) {
+ static const char* bad_versions[] = {
+ "3.2", "3.2a", "3.3", "3.3a"
+ };
+ size_t i;
+ for (i = 0; i < RTEMS_ARRAY_SIZE(bad_versions); ++i) {
+ if (strcmp(bad_versions[i], buf + 5) == 0) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+/*
+ * Direct method to get the size of an XTERM window.
+ *
+ * If you do not use an XTERM the env variables are not define.
+ */
+static void rtems_shell_winsize( void )
+{
+ const int fd = fileno(stdin);
+ struct winsize ws;
+ const int timeout = 150;
+ char buf[64];
+ bool ok = false;
+ int lines = 0;
+ int cols = 0;
+ int r;
+ r = ioctl(fd, TIOCGWINSZ, &ws);
+ if (r == 0) {
+ ok = true;
+ lines = ws.ws_row;
+ cols = ws.ws_col;
+ } else if (isatty(fd)) {
+ struct termios cterm;
+ if (tcgetattr(fd, &cterm) >= 0) {
+ struct termios term = cterm;
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr (fd, TCSADRAIN, &term) >= 0) {
+ memset(&buf[0], 0, sizeof(buf));
+ /*
+ * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Miscellaneous
+ *
+ * CSI 1 8 t
+ */
+ fputs("\033[18t", stdout);
+ fflush(stdout);
+ if (rtems_shell_term_wait_for(fd, "\033[8;", timeout)) {
+ int len = rtems_shell_term_buffer_until(fd, buf, sizeof(buf), ";", timeout);
+ if (len > 0) {
+ int i;
+ lines = 0;
+ i = 0;
+ while (i < len) {
+ lines *= 10;
+ lines += buf[i++] - '0';
+ }
+ len = rtems_shell_term_buffer_until(fd, buf, sizeof(buf), "t", timeout);
+ if (len > 0) {
+ cols = 0;
+ i = 0;
+ while (i < len) {
+ cols *= 10;
+ cols += buf[i++] - '0';
+ }
+ ok = true;
+ }
+ }
+ }
+ }
+ if (rtems_shell_term_row_column_swapped(fd, timeout)) {
+ int tmp = lines;
+ lines = cols;
+ cols = tmp;
+ }
+ tcsetattr (fd, TCSADRAIN, &cterm);
+ }
+ }
+ if (ok) {
+ snprintf(buf, sizeof(buf) - 1, "%d", lines);
+ setenv("LINES", buf, 1);
+ snprintf(buf, sizeof(buf) - 1, "%d", cols);
+ setenv("COLUMNS", buf, 1);
+ }
+}
+
static rtems_task rtems_shell_task(rtems_task_argument task_argument)
{
rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
@@ -851,129 +1016,32 @@ static bool rtems_shell_init_user_env(void)
#define RTEMS_SHELL_CMD_COUNT (32)
#define RTEMS_SHELL_PROMPT_SIZE (128)
-bool rtems_shell_main_loop(
- rtems_shell_env_t *shell_env
+static bool shell_main_loop(
+ rtems_shell_env_t *shell_env,
+ bool interactive,
+ FILE *line_editor_output
)
{
- struct termios term;
- struct termios previous_term;
- char *prompt = NULL;
- int cmd;
- int cmd_count = 1; /* assume a script and so only 1 command line */
- char *cmds[RTEMS_SHELL_CMD_COUNT];
- char *cmd_argv;
- int argc;
- char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
- bool result = true;
- bool input_file = false;
- int line = 0;
- FILE *stdinToClose = NULL;
- FILE *stdoutToClose = NULL;
-
- rtems_shell_init_environment();
-
- if (shell_env->magic != rtems_build_name('S', 'E', 'N', 'V')) {
- rtems_error(0, "invalid shell environment passed to the main loop)");
- return false;
- }
-
- if (!rtems_shell_set_shell_env(shell_env))
- return false;
-
- if (!rtems_shell_init_user_env()) {
- rtems_error(0, "rtems_shell_init_user_env");
- rtems_shell_clear_shell_env();
- return false;
- }
-
- shell_std_debug("env: %p\n", shell_env);
-
- if (shell_env->output == NULL || strcmp(shell_env->output, "stdout") == 0) {
- if (shell_env->parent_stdout != NULL)
- stdout = shell_env->parent_stdout;
- }
- else if (strcmp(shell_env->output, "stderr") == 0) {
- if (shell_env->parent_stderr != NULL)
- stdout = shell_env->parent_stderr;
- else
- stdout = stderr;
- } else if (strcmp(shell_env->output, "/dev/null") == 0) {
- if (stdout == NULL) {
- fprintf(stderr, "shell: stdout is NULLs\n");
- rtems_shell_clear_shell_env();
- return false;
- }
- fclose (stdout);
- } else {
- FILE *output = fopen(shell_env->output,
- shell_env->output_append ? "a" : "w");
- if (output == NULL) {
- fprintf(stderr, "shell: open output %s failed: %s\n",
- shell_env->output, strerror(errno));
- rtems_shell_clear_shell_env();
- return false;
- }
- stdout = output;
- stdoutToClose = output;
- }
-
- if (shell_env->input == NULL || strcmp(shell_env->input, "stdin") == 0) {
- if (shell_env->parent_stdin != NULL)
- stdin = shell_env->parent_stdin;
- } else {
- FILE *input = fopen(shell_env->input, "r");
- if (input == NULL) {
- fprintf(stderr, "shell: open input %s failed: %s\n",
- shell_env->input, strerror(errno));
- if (stdoutToClose != NULL)
- fclose(stdoutToClose);
- rtems_shell_clear_shell_env();
+ bool result = false;
+ int line = 0;
+ int cmd_count;
+ char *cmds[RTEMS_SHELL_CMD_COUNT];
+ char *cmd_argv;
+ char *prompt;
+
+ if (interactive) {
+ prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
+ if (prompt == NULL) {
+ fprintf(stderr, "shell: cannot allocate prompt memory\n");
return false;
}
- stdin = input;
- stdinToClose = input;
- shell_env->forever = false;
- input_file = true;
- }
- if (!input_file) {
- if (stdin == NULL) {
- fprintf(stderr, "shell: stdin is NULLs\n");
- if (stdoutToClose != NULL)
- fclose(stdoutToClose);
- rtems_shell_clear_shell_env();
- return false;
- }
- /* Make a raw terminal, Linux Manuals */
- if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
- term = previous_term;
- term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- term.c_oflag &= ~OPOST;
- term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
- term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
- term.c_cflag |= CLOCAL | CREAD;
- term.c_cc[VMIN] = 1;
- term.c_cc[VTIME] = 0;
- if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
- fprintf(stderr,
- "shell: cannot set terminal attributes(%s)\n",shell_env->devname);
- }
- }
cmd_count = RTEMS_SHELL_CMD_COUNT;
- prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
- if (!prompt)
- fprintf(stderr,
- "shell: cannot allocate prompt memory\n");
+ } else {
+ prompt = NULL;
+ cmd_count = 1;
}
- shell_std_debug("child out: %d (%p)\n", fileno(stdout), stdout);
- shell_std_debug("child in: %d (%p)\n", fileno(stdin), stdin);
-
- /* Do not buffer if interactive else leave buffered */
- if (!input_file)
- setvbuf(stdin, NULL, _IONBF, 0);
- setvbuf(stdout, NULL, _IONBF, 0);
-
/*
* Allocate the command line buffers.
*/
@@ -988,6 +1056,7 @@ bool rtems_shell_main_loop(
}
if (cmd_argv && cmds[0]) {
+ size_t cmd;
memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
@@ -1018,23 +1087,25 @@ bool rtems_shell_main_loop(
}
if (result) {
- const char *c;
memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
- if (!input_file) {
+
+ if (interactive) {
rtems_shell_cat_file(stdout,"/etc/motd");
fprintf(stdout, "\n"
"RTEMS Shell on %s. Use 'help' to list commands.\n",
shell_env->devname);
- }
-
- if (input_file)
- chdir(shell_env->cwd);
- else
chdir("/"); /* XXX: chdir to getpwent homedir */
+ } else {
+ chdir(shell_env->cwd);
+ }
shell_env->exit_shell = false;
for (;;) {
+ const char *c;
+ int argc;
+ char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
+
/* Prompt section */
if (prompt) {
rtems_shell_get_prompt(shell_env, prompt,
@@ -1044,7 +1115,7 @@ bool rtems_shell_main_loop(
/* getcmd section */
cmd = rtems_shell_line_editor(cmds, cmd_count,
RTEMS_SHELL_CMD_SIZE, prompt,
- stdin, stdout);
+ stdin, line_editor_output);
if (cmd == -1)
continue; /* empty line */
@@ -1090,7 +1161,9 @@ bool rtems_shell_main_loop(
memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE);
if (!rtems_shell_make_args(cmd_argv, &argc, argv,
RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
- int exit_code = rtems_shell_execute_cmd(argv[0], argc, argv);
+ int exit_code;
+ rtems_shell_winsize();
+ exit_code = rtems_shell_execute_cmd(argv[0], argc, argv);
if (shell_env->exit_code != NULL)
*shell_env->exit_code = exit_code;
if (exit_code != 0 && shell_env->exit_on_error)
@@ -1107,16 +1180,156 @@ bool rtems_shell_main_loop(
}
shell_std_debug("end: %d %d\n", result, shell_env->forever);
} while (result && shell_env->forever);
+ }
+
+ free(cmds[0]);
+ free(cmd_argv);
+ free(prompt);
+
+ return result;
+}
+
+bool rtems_shell_run_main_loop(
+ rtems_shell_env_t *shell_env,
+ bool interactive,
+ FILE *line_editor_output
+)
+{
+ bool result;
+ if (shell_env->magic != SHELL_MAGIC) {
+ return false;
+ }
+
+ if (!rtems_shell_init_user_env()) {
+ return false;
}
- if (cmds[0])
- free (cmds[0]);
- if (cmd_argv)
- free (cmd_argv);
- if (prompt)
- free (prompt);
+ if (!rtems_shell_set_shell_env(shell_env)) {
+ return false;
+ }
+
+ result = shell_main_loop(shell_env, interactive, line_editor_output);
+ rtems_shell_clear_shell_env();
+ return result;
+}
+
+bool rtems_shell_main_loop(
+ rtems_shell_env_t *shell_env
+)
+{
+ struct termios term;
+ struct termios previous_term;
+ bool result;
+ bool interactive = true;
+ FILE *stdinToClose = NULL;
+ FILE *stdoutToClose = NULL;
+ FILE *line_editor_output;
+
+ if (shell_env->magic != SHELL_MAGIC) {
+ rtems_error(0, "invalid shell environment passed to the main loop)");
+ return false;
+ }
+
+ if (!rtems_shell_set_shell_env(shell_env))
+ return false;
+
+ if (!rtems_shell_init_user_env()) {
+ rtems_error(0, "rtems_shell_init_user_env");
+ rtems_shell_clear_shell_env();
+ return false;
+ }
+
+ shell_std_debug("env: %p\n", shell_env);
+
+ if (shell_env->output == NULL || strcmp(shell_env->output, "stdout") == 0) {
+ if (shell_env->parent_stdout != NULL)
+ stdout = shell_env->parent_stdout;
+ }
+ else if (strcmp(shell_env->output, "stderr") == 0) {
+ if (shell_env->parent_stderr != NULL)
+ stdout = shell_env->parent_stderr;
+ else
+ stdout = stderr;
+ } else if (strcmp(shell_env->output, "/dev/null") == 0) {
+ if (stdout == NULL) {
+ fprintf(stderr, "shell: stdout is NULLs\n");
+ rtems_shell_clear_shell_env();
+ return false;
+ }
+ fclose (stdout);
+ } else {
+ FILE *output = fopen(shell_env->output,
+ shell_env->output_append ? "a" : "w");
+ if (output == NULL) {
+ fprintf(stderr, "shell: open output %s failed: %s\n",
+ shell_env->output, strerror(errno));
+ rtems_shell_clear_shell_env();
+ return false;
+ }
+ stdout = output;
+ stdoutToClose = output;
+ }
+
+ if (shell_env->input == NULL || strcmp(shell_env->input, "stdin") == 0) {
+ if (shell_env->parent_stdin != NULL)
+ stdin = shell_env->parent_stdin;
+ } else {
+ FILE *input = fopen(shell_env->input, "r");
+ if (input == NULL) {
+ fprintf(stderr, "shell: open input %s failed: %s\n",
+ shell_env->input, strerror(errno));
+ if (stdoutToClose != NULL)
+ fclose(stdoutToClose);
+ rtems_shell_clear_shell_env();
+ return false;
+ }
+ stdin = input;
+ stdinToClose = input;
+ shell_env->forever = false;
+ interactive = false;
+ }
+
+ if (interactive) {
+ if (stdin == NULL) {
+ fprintf(stderr, "shell: stdin is NULLs\n");
+ if (stdoutToClose != NULL)
+ fclose(stdoutToClose);
+ rtems_shell_clear_shell_env();
+ return false;
+ }
+ /* Make a raw terminal, Linux Manuals */
+ if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
+ term = previous_term;
+ term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ term.c_oflag &= ~OPOST;
+ term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
+ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ term.c_cflag |= CLOCAL | CREAD;
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
+ fprintf(stderr,
+ "shell: cannot set terminal attributes(%s)\n",shell_env->devname);
+ }
+ }
+ }
+
+ shell_std_debug("child out: %d (%p)\n", fileno(stdout), stdout);
+ shell_std_debug("child in: %d (%p)\n", fileno(stdin), stdin);
+
+ /* Do not buffer if interactive else leave buffered */
+ if (interactive)
+ setvbuf(stdin, NULL, _IONBF, 0);
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (isatty(fileno(stdin))) {
+ line_editor_output = stdout;
+ } else {
+ line_editor_output = NULL;
+ }
+ result = shell_main_loop(shell_env, interactive, line_editor_output);
shell_std_debug("child in-to-close: %p\n", stdinToClose);
shell_std_debug("child out-to-close: %p\n", stdoutToClose);
@@ -1149,7 +1362,6 @@ static rtems_status_code rtems_shell_run (
const char *output,
bool output_append,
rtems_id wake_on_end,
- int *exit_code,
bool echo,
rtems_shell_login_check_t login_check
)
@@ -1165,7 +1377,7 @@ static rtems_status_code rtems_shell_run (
name = rtems_build_name(
task_name[0], task_name[1], task_name[2], task_name[3]);
else
- name = rtems_build_name( 'S', 'E', 'N', 'V' );
+ name = SHELL_MAGIC;
sc = rtems_task_create(
name,
@@ -1202,7 +1414,6 @@ static rtems_status_code rtems_shell_run (
shell_env->parent_stdout = stdout;
shell_env->parent_stderr = stderr;
shell_env->wake_on_end = wake_on_end;
- shell_env->exit_code = exit_code;
shell_env->login_check = login_check;
shell_env->uid = getuid();
shell_env->gid = getgid();
@@ -1229,7 +1440,7 @@ static rtems_status_code rtems_shell_run (
sc = rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT, 0, &out);
}
- shell_std_debug("run: end: sc:%d ec:%d\n", sc, *exit_code);
+ shell_std_debug("run: end: sc:%d\n", sc);
return sc;
}
@@ -1245,7 +1456,6 @@ rtems_status_code rtems_shell_init(
)
{
rtems_id to_wake = RTEMS_ID_NONE;
- int exit_code = 0;
if ( wait )
to_wake = rtems_task_self();
@@ -1261,7 +1471,6 @@ rtems_status_code rtems_shell_init(
"stdout", /* output */
false, /* output_append */
to_wake, /* wake_on_end */
- &exit_code, /* exit code of command */
false, /* echo */
login_check /* login check */
);
@@ -1279,7 +1488,6 @@ rtems_status_code rtems_shell_script (
)
{
rtems_id to_wake = RTEMS_ID_NONE;
- int exit_code = 0;
rtems_status_code sc;
shell_std_debug("script: in: %s out: %s\n", input, output);
@@ -1298,7 +1506,6 @@ rtems_status_code rtems_shell_script (
output, /* output */
output_append, /* output_append */
to_wake, /* wake_on_end */
- &exit_code, /* exit_code */
echo, /* echo */
NULL /* login check */
);