<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 22, 2022, 6:02 AM  <<a href="mailto:chrisj@rtems.org">chrisj@rtems.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Chris Johns <<a href="mailto:chrisj@rtems.org" target="_blank" rel="noreferrer">chrisj@rtems.org</a>><br>
<br>
Closes #4763<br>
---<br>
 cpukit/libmisc/shell/main_edit.c | 17 +++++-<br>
 cpukit/libmisc/shell/main_help.c | 94 ++++++++++++++++++++------------<br>
 cpukit/libmisc/shell/shell.c     | 83 +++++++++++++++++++++++++++-<br>
 3 files changed, 154 insertions(+), 40 deletions(-)<br>
<br>
diff --git a/cpukit/libmisc/shell/main_edit.c b/cpukit/libmisc/shell/main_edit.c<br>
index 4cc742719a..16c44f2a11 100644<br>
--- a/cpukit/libmisc/shell/main_edit.c<br>
+++ b/cpukit/libmisc/shell/main_edit.c<br>
@@ -755,8 +755,21 @@ static void get_console_size(struct env *env) {<br>
   env->cols = ws.ws_col;<br>
   env->lines = ws.ws_row - 1;<br>
 #elif defined(__rtems__)<br>
-  env->cols = 80;<br>
-  env->lines = 25;<br>
+  char* e;<br>
+  e = getenv("LINES");<br>
+  if (e != NULL) {<br>
+    int lines = strtol(e, 0, 10);<br>
+    if (lines > 0) {<br>
+      env->lines = lines - 1;<br>
+    }<br>
+  }<br>
+  e = getenv("COLUMNS");<br>
+  if (e != NULL) {<br>
+    int cols = strtol(e, 0, 10);<br>
+    if (cols > 0) {<br>
+      env->cols = cols - 1;<br>
+    }<br>
+  }<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Does this lose the default values if the environment variables are not set?</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 #else<br>
   struct term *term = gettib()->proc->term;<br>
   env->cols = term->cols;<br>
diff --git a/cpukit/libmisc/shell/main_help.c b/cpukit/libmisc/shell/main_help.c<br>
index 564bc30a9c..e6d939d08f 100644<br>
--- a/cpukit/libmisc/shell/main_help.c<br>
+++ b/cpukit/libmisc/shell/main_help.c<br>
@@ -22,23 +22,34 @@<br>
 #include "internal.h"<br>
 #include <string.h><br>
<br>
+static int rtems_shell_help_pause(int line, int lines) {<br>
+  if (lines && line >= lines - 1) {<br>
+    printf("\rPress any key to continue...");<br>
+    (void) getchar();<br>
+    printf("\r%*c\r", 29, ' ');<br>
+    line = 0;<br>
+  }<br>
+  return line;<br>
+}<br>
+<br>
 /*<br>
  * show the help for one command.<br>
  */<br>
 static int rtems_shell_help_cmd(<br>
-  const rtems_shell_cmd_t *shell_cmd<br>
+  const rtems_shell_cmd_t *shell_cmd, int indent, int line,<br>
+  int cols, int lines<br>
 )<br>
 {<br>
   const char * pc;<br>
-  int    col,line;<br>
+  int    col;<br>
<br>
   if (!rtems_shell_can_see_cmd(shell_cmd)) {<br>
     return 0;<br>
   }<br>
<br>
-  printf("%-12.12s - ",shell_cmd->name);<br>
-  col = 14;<br>
-  line = 1;<br>
+  printf("%-*s - ", indent, shell_cmd->name);<br>
+  indent += 3;<br>
+  col = indent;<br>
   if (shell_cmd->alias) {<br>
     printf("is an <alias> for command '%s'",shell_cmd->alias->name);<br>
   } else if (shell_cmd->usage) {<br>
@@ -48,8 +59,10 @@ static int rtems_shell_help_cmd(<br>
         case '\r':<br>
           break;<br>
         case '\n':<br>
-          putchar('\n');<br>
-          col = 0;<br>
+          if (*(pc + 1) != '\0') {<br>
+            putchar('\n');<br>
+            col = 0;<br>
+          }<br>
           break;<br>
         default:<br>
           putchar(*pc);<br>
@@ -57,19 +70,21 @@ static int rtems_shell_help_cmd(<br>
           break;<br>
       }<br>
       pc++;<br>
-      if (col>78) { /* What daring... 78?*/<br>
+      if (col > (cols - 3)) {<br>
         if (*pc) {<br>
           putchar('\n');<br>
           col = 0;<br>
         }<br>
       }<br>
-      if (!col && *pc) {<br>
-        printf("            ");<br>
-        col = 12;line++;<br>
+      if (col == 0 && *pc) {<br>
+        line = rtems_shell_help_pause(line + 1, lines);<br>
+        printf("%*c", indent, ' ');<br>
+        col = indent;<br>
       }<br>
     }<br>
   }<br>
   puts("");<br>
+  line = rtems_shell_help_pause(line + 1, lines);<br>
   return line;<br>
 }<br>
<br>
@@ -83,15 +98,27 @@ static int rtems_shell_help(<br>
   char * argv[]<br>
 )<br>
 {<br>
-  int col,line,lines,arg;<br>
-  char* lines_env;<br>
+  int col,line,cols,lines,arg,indent;<br>
+  char *lines_env, *cols_env;<br>
   rtems_shell_topic_t *topic;<br>
+  rtems_shell_cmd_t *shell_cmd;<br>
<br>
+  lines = 16;<br>
+  cols = 80;<br>
   lines_env = getenv("SHELL_LINES");<br>
-  if (lines_env)<br>
+  if (lines_env) {<br>
     lines = strtol(lines_env, 0, 0);<br>
-  else<br>
-    lines = 16;<br>
+  } else {<br>
+    lines_env = getenv("LINES");<br>
+    if (lines_env) {<br>
+      lines = strtol(lines_env, 0, 0);<br>
+    }<br>
+  }<br>
+<br>
+  cols_env = getenv("COLUMNS");<br>
+  if (cols_env) {<br>
+    cols = strtol(cols_env, 0, 0);<br>
+  }<br>
<br>
   if (argc<2) {<br>
     printf("help: The topics are\n");<br>
@@ -101,7 +128,7 @@ static int rtems_shell_help(<br>
       if (!col){<br>
         col = printf("  %s",topic->topic);<br>
       } else {<br>
-        if ((col+strlen(topic->topic)+2)>78){<br>
+        if ((col+strlen(topic->topic)+2)>(cols - 2)){<br>
           printf("\n");<br>
           col = printf("  %s",topic->topic);<br>
         } else {<br>
@@ -113,18 +140,19 @@ static int rtems_shell_help(<br>
     printf("\n");<br>
     return 1;<br>
   }<br>
+  indent = 0;<br>
+  shell_cmd = rtems_shell_first_cmd;<br>
+  while (shell_cmd) {<br>
+    size_t len = strlen(shell_cmd->name);<br>
+    if (len > indent) {<br>
+      indent = len;<br>
+    }<br>
+    shell_cmd = shell_cmd->next;<br>
+  }<br>
   line = 0;<br>
   for (arg = 1;arg<argc;arg++) {<br>
     const char *cur = argv[arg];<br>
-    rtems_shell_cmd_t *shell_cmd;<br>
-<br>
-    if (lines && (line > lines)) {<br>
-      printf("Press any key to continue...");<br>
-      (void) getchar(); /* we only want to know a character was pressed */<br>
-      printf("\n");<br>
-      line = 0;<br>
-    }<br>
-    topic  =  rtems_shell_lookup_topic(cur);<br>
+    topic = rtems_shell_lookup_topic(cur);<br>
     if (topic == NULL) {<br>
       if ((shell_cmd = rtems_shell_lookup_cmd(cur)) == NULL) {<br>
         if (strcmp(cur, "all") != 0) {<br>
@@ -132,11 +160,11 @@ static int rtems_shell_help(<br>
             "help: topic or cmd '%s' not found. Try <help> alone for a list\n",<br>
             cur<br>
           );<br>
-          line++;<br>
+          line = rtems_shell_help_pause(line + 1, lines);<br>
           continue;<br>
         }<br>
       } else {<br>
-        line+= rtems_shell_help_cmd(shell_cmd);<br>
+        line = rtems_shell_help_cmd(shell_cmd, indent, line, cols, lines);<br>
         continue;<br>
       }<br>
     }<br>
@@ -144,18 +172,12 @@ static int rtems_shell_help(<br>
     line++;<br>
     shell_cmd = rtems_shell_first_cmd;<br>
     while (shell_cmd) {<br>
-      if (topic == NULL || !strcmp(topic->topic,shell_cmd->topic))<br>
-        line+= rtems_shell_help_cmd(shell_cmd);<br>
-      if (lines && (line > lines)) {<br>
-        printf("Press any key to continue...");<br>
-        (void) getchar();<br>
-        printf("\n");<br>
-        line = 0;<br>
+      if (topic == NULL || !strcmp(topic->topic,shell_cmd->topic)) {<br>
+        line = rtems_shell_help_cmd(shell_cmd, indent, line, cols, lines);<br>
       }<br>
       shell_cmd = shell_cmd->next;<br>
     }<br>
   }<br>
-  puts("");<br>
   return 0;<br>
 }<br>
<br>
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c<br>
index 64f90be121..cd83aa56d1 100644<br>
--- a/cpukit/libmisc/shell/shell.c<br>
+++ b/cpukit/libmisc/shell/shell.c<br>
@@ -1,6 +1,6 @@<br>
 /**<br>
  * @file<br>
- * <br>
+ *<br>
  * @brief Instantatiate a new terminal shell.<br>
  */<br>
<br>
@@ -805,6 +805,83 @@ void rtems_shell_print_env(<br>
 }<br>
 #endif<br>
<br>
+/*<br>
+ * Direct method to get the size of an XTERM window.<br>
+ *<br>
+ * If you do not use an XTERM the env variables are not define.<br>
+ */<br>
+static void rtems_shell_winsize( void )<br>
+{<br>
+  const int fd = fileno(stdin);<br>
+  struct winsize ws;<br>
+  char buf[64];<br>
+  bool ok = false;<br>
+  int lines = 0;<br>
+  int cols = 0;<br>
+  int r;<br>
+  r = ioctl(fd, TIOCGWINSZ, &ws);<br>
+  if (r == 0) {<br>
+    ok = true;<br>
+    lines = ws.ws_row;<br>
+    cols = ws.ws_col;<br>
+  } else if (isatty(fd)) {<br>
+    struct termios cterm;<br>
+    if (tcgetattr(fd, &cterm) >= 0) {<br>
+      struct termios term = cterm;<br>
+      term.c_cc[VMIN] = 0;<br>
+      term.c_cc[VTIME] = 0;<br>
+      if (tcsetattr (fd, TCSADRAIN, &term) >= 0) {<br>
+        int msec = 50;<br>
+        int len = 0;<br>
+        int i = 0;<br>
+        memset(&buf[0], 0, sizeof(buf));<br>
+        /*<br>
+         * <a href="https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Miscellaneous" rel="noreferrer noreferrer" target="_blank">https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Miscellaneous</a><br>
+         *<br>
+         * CSI 1 8 t<br>
+         */<br>
+        fputs("\033[18t", stdout);<br>
+        fflush(stdout);<br>
+        while (msec-- > 0 && len < sizeof(buf)) {<br>
+          char ch[2];<br>
+          if (read(fd, &ch[0], 1) == 1) {<br>
+            buf[len++] = ch[0];<br>
+            msec = 50;<br>
+          } else {<br>
+            usleep(1000);<br>
+          }<br>
+        }<br>
+        while (i < len) {<br>
+          static const char resp[] = "\033[8;";<br>
+          if (memcmp(resp, &buf[i], sizeof(resp) - 1) == 0) {<br>
+            i += sizeof(resp) - 1;<br>
+            while (i < len && buf[i] != ';') {<br>
+              lines *= 10;<br>
+              lines += buf[i++] - '0';<br>
+            }<br>
+            cols = 0;<br>
+            ++i;<br>
+            while (i < len && buf[i] != 't') {<br>
+              cols *= 10;<br>
+              cols += buf[i++] - '0';<br>
+            }<br>
+          } else {<br>
+            i++;<br>
+          }<br>
+          ok = true;<br>
+        }<br>
+      }<br>
+      tcsetattr (fd, TCSADRAIN, &cterm);<br>
+    }<br>
+  }<br>
+  if (ok) {<br>
+    snprintf(buf, sizeof(buf) - 1, "%d", lines);<br>
+    setenv("LINES", buf, 1);<br>
+    snprintf(buf, sizeof(buf) - 1, "%d", cols);<br>
+    setenv("COLUMNS", buf, 1);<br>
+  }<br>
+}<br>
+<br>
 static rtems_task rtems_shell_task(rtems_task_argument task_argument)<br>
 {<br>
   rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;<br>
@@ -984,7 +1061,9 @@ static bool shell_main_loop(<br>
           memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE);<br>
           if (!rtems_shell_make_args(cmd_argv, &argc, argv,<br>
                                      RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {<br>
-            int exit_code = rtems_shell_execute_cmd(argv[0], argc, argv);<br>
+            int exit_code;<br>
+            rtems_shell_winsize();<br>
+            exit_code = rtems_shell_execute_cmd(argv[0], argc, argv);<br>
             if (shell_env->exit_code != NULL)<br>
               *shell_env->exit_code = exit_code;<br>
             if (exit_code != 0 && shell_env->exit_on_error)<br>
-- <br>
2.19.1<br>
<br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank" rel="noreferrer">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</blockquote></div></div></div>