[PATCH 2/6] shell: Refactor rtems_shell_main_loop()

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Apr 6 07:17:28 UTC 2022


Disentangle the shell main loop from setup and teardown code.  Move main
loop into shell_main_loop().
---
 cpukit/libmisc/shell/shell.c | 284 ++++++++++++++++++-----------------
 1 file changed, 150 insertions(+), 134 deletions(-)

diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
index aa1952e883..11d8ab4846 100644
--- a/cpukit/libmisc/shell/shell.c
+++ b/cpukit/libmisc/shell/shell.c
@@ -838,134 +838,30 @@ 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;
-  FILE           *line_editor_output;
-
-  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");
-  }
-
-  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);
-
-  if (isatty(fileno(stdin))) {
-     line_editor_output = stdout;
   } else {
-     line_editor_output = NULL;
+    prompt = NULL;
+    cmd_count = 1;
   }
 
   /*
@@ -982,6 +878,7 @@ bool rtems_shell_main_loop(
   }
 
   if (cmd_argv && cmds[0]) {
+    size_t cmd;
 
     memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
 
@@ -1012,23 +909,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,
@@ -1101,16 +1000,133 @@ 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_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;
+
+  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();
+      return false;
+    }
+    stdin = input;
+    stdinToClose = input;
+    shell_env->forever = false;
+    interactive = false;
   }
 
-  if (cmds[0])
-    free (cmds[0]);
-  if (cmd_argv)
-    free (cmd_argv);
-  if (prompt)
-    free (prompt);
+  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);
 
-- 
2.34.1



More information about the devel mailing list