summaryrefslogtreecommitdiffstats
path: root/c/src/libmisc
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2000-06-14 17:22:59 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2000-06-14 17:22:59 +0000
commit32e2554f105163017052572a1830f3caa19ba625 (patch)
tree3486575ad9ab7b4bfdfa253ed51d62954e57b920 /c/src/libmisc
parentPatch from Chris Johns <cjohns@cybertec.com.au> to enhance network (diff)
downloadrtems-32e2554f105163017052572a1830f3caa19ba625.tar.bz2
Patch rtems-4.5-beta3-mon.diff from Chris Johns <cjohns@cybertec.com.au>
to: I have also added the ability to register and unregister commands. This allows me to create a set of monitor commands for the network stack plus basic memory dump/patch commands (needs a working probe interface). I will also look at a basic ls/cd/rm/mv/cp command set at some stage. I have been thinking about changing the monitor in the future to more like a light weight RTEMS shell, `eshell' for embedded shell. This is a story for another day but is a process or getting the commands to map to the filesystem (eg, major=commands, minor=command) and supporting an environment. The filesystem provide a structure for the commands.
Diffstat (limited to 'c/src/libmisc')
-rw-r--r--c/src/libmisc/monitor/mon-command.c695
-rw-r--r--c/src/libmisc/monitor/mon-monitor.c233
-rw-r--r--c/src/libmisc/monitor/monitor.h7
3 files changed, 761 insertions, 174 deletions
diff --git a/c/src/libmisc/monitor/mon-command.c b/c/src/libmisc/monitor/mon-command.c
index 5c733b60d9..cf25325880 100644
--- a/c/src/libmisc/monitor/mon-command.c
+++ b/c/src/libmisc/monitor/mon-command.c
@@ -14,9 +14,420 @@
#include <string.h>
/*
+ * CCJ: 26-3-2000, adding command history and command line
+ * editing. This code is donated from My Right Boot and not
+ * covered by GPL, only the RTEMS license.
+ */
+
+/*
+ * Some key labels to define special keys.
+ */
+
+#define KEYS_EXTENDED (0x8000)
+#define KEYS_NORMAL_MASK (0x00ff)
+#define KEYS_INS (0)
+#define KEYS_DEL (1)
+#define KEYS_UARROW (2)
+#define KEYS_DARROW (3)
+#define KEYS_LARROW (4)
+#define KEYS_RARROW (5)
+#define KEYS_HOME (6)
+#define KEYS_END (7)
+#define KEYS_F1 (8)
+#define KEYS_F2 (9)
+#define KEYS_F3 (10)
+#define KEYS_F4 (11)
+#define KEYS_F5 (12)
+#define KEYS_F6 (13)
+#define KEYS_F7 (14)
+#define KEYS_F8 (15)
+#define KEYS_F9 (16)
+#define KEYS_F10 (17)
+
+#define RTEMS_COMMAND_BUFFER_SIZE (75)
+
+static char monitor_prompt[32];
+static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
+static int pos;
+static int logged_in;
+
+/*
+ * History data.
+ */
+
+#define RTEMS_COMMAND_HISTORIES (20)
+
+static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
+static int history_pos[RTEMS_COMMAND_HISTORIES];
+static int history;
+static int history_next;
+
+/*
+ * Translation tables. Not sure if this is the best way to
+ * handle this, how-ever I wish to avoid the overhead of
+ * including a more complete and standard environment such
+ * as ncurses.
+ */
+
+struct translation_table
+{
+ char expecting;
+ struct translation_table *branch;
+ unsigned int key;
+};
+
+static struct translation_table trans_two[] =
+{
+ { '~', 0, KEYS_INS },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_three[] =
+{
+ { '~', 0, KEYS_DEL },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab_csi[] =
+{
+ { '2', trans_two, 0 },
+ { '3', trans_three, 0 },
+ { 'A', 0, KEYS_UARROW },
+ { 'B', 0, KEYS_DARROW },
+ { 'D', 0, KEYS_LARROW },
+ { 'C', 0, KEYS_RARROW },
+ { 'F', 0, KEYS_END },
+ { 'H', 0, KEYS_HOME },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab_O[] =
+{
+ { '1', 0, KEYS_F1 },
+ { '2', 0, KEYS_F2 },
+ { '3', 0, KEYS_F3 },
+ { '4', 0, KEYS_F4 },
+ { '5', 0, KEYS_F5 },
+ { '6', 0, KEYS_F6 },
+ { '7', 0, KEYS_F7 },
+ { '8', 0, KEYS_F8 },
+ { '9', 0, KEYS_F9 },
+ { ':', 0, KEYS_F10 },
+ { 'P', 0, KEYS_F1 },
+ { 'Q', 0, KEYS_F2 },
+ { 'R', 0, KEYS_F3 },
+ { 'S', 0, KEYS_F4 },
+ { 'T', 0, KEYS_F5 },
+ { 'U', 0, KEYS_F6 },
+ { 'V', 0, KEYS_F7 },
+ { 'W', 0, KEYS_F8 },
+ { 'X', 0, KEYS_F9 },
+ { 'Y', 0, KEYS_F10 },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab[] =
+{
+ { '[', trans_tab_csi, 0 }, /* CSI command sequences */
+ { 'O', trans_tab_O, 0 }, /* O are the fuction keys */
+ { 0, 0, 0 }
+};
+
+/*
+ * Perform a basic tranlation for some ANSI/VT100 key codes.
+ * This code could do with a timeout on the ESC as it is
+ * now lost from the input stream. It is not* used by the
+ * line editor below so considiered not worth the effort.
+ */
+
+static unsigned int
+rtems_monitor_getchar (
+)
+{
+ struct translation_table *translation = 0;
+ for (;;)
+ {
+ char c = getchar ();
+ if (c == 27)
+ translation = trans_tab;
+ else
+ {
+ /*
+ * If no translation happing just pass through
+ * and return the key.
+ */
+ if (translation)
+ {
+ /*
+ * Scan the current table for the key, and if found
+ * see if this key is a fork. If so follow it and
+ * wait else return the extended key.
+ */
+ int index = 0;
+ int branched = 0;
+ while ((translation[index].expecting != '\0') ||
+ (translation[index].key != '\0'))
+ {
+ if (translation[index].expecting == c)
+ {
+ /*
+ * A branch is take if more keys are to come.
+ */
+ if (translation[index].branch == 0)
+ return KEYS_EXTENDED | translation[index].key;
+ else
+ {
+ translation = translation[index].branch;
+ branched = 1;
+ break;
+ }
+ }
+ index++;
+ }
+ /*
+ * Who knows what these keys are, just drop them.
+ */
+ if (!branched)
+ translation = 0;
+ }
+ else
+ return c;
+ }
+ }
+}
+
+/*
+ * The line editor with history.
+ */
+
+static int
+rtems_monitor_line_editor (
+ char *command
+)
+{
+ int repeating = 0;
+
+ memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
+ history = history_next;
+ pos = 0;
+
+ if (!logged_in)
+ printf ("\nMonitor ready, press enter to login.\n\n");
+ else
+ printf ("%s $ ", monitor_prompt);
+
+ while (1)
+ {
+ unsigned int extended_key = rtems_monitor_getchar ();
+ char c = extended_key & KEYS_NORMAL_MASK;
+
+ /*
+ * Make the extended_key usable as a boolean.
+ */
+ extended_key &= ~KEYS_NORMAL_MASK;
+
+ if (!extended_key && !logged_in)
+ {
+ if (c == '\n')
+ {
+ logged_in = 1;
+ /*
+ * The prompt has changed from `>' to `$' to help know
+ * which version of the monitor code people are using.
+ */
+ printf("%s $ ", monitor_prompt);
+ }
+ }
+ else
+ {
+ if (extended_key)
+ {
+ switch (c)
+ {
+ case KEYS_END:
+ printf (buffer + pos);
+ pos = (int) strlen (buffer);
+ break;
+
+ case KEYS_HOME:
+ printf ("\r%s $ ", monitor_prompt);
+ pos = 0;
+ break;
+
+ case KEYS_LARROW:
+ if (pos > 0)
+ {
+ pos--;
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_RARROW:
+ if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
+ {
+ putchar (buffer[pos]);
+ pos++;
+ }
+ break;
+
+ case KEYS_UARROW:
+ /*
+ * If we are moving up the histories then we need to save the working
+ * buffer.
+ */
+ if (history)
+ {
+ int end;
+ int bs;
+ if (history == history_next)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ }
+ history--;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ printf ("\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ printf ("\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DARROW:
+ if (history < history_next)
+ {
+ int end;
+ int bs;
+ history++;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ printf ("\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ printf ("\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DEL:
+ if (buffer[pos] != '\0')
+ {
+ int end;
+ int bs;
+ strcpy (&buffer[pos], &buffer[pos + 1]);
+ printf ("\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\b':
+ case '\x7e':
+ case '\x7f':
+ if (pos > 0)
+ {
+ int bs;
+ pos--;
+ strcpy (buffer + pos, buffer + pos + 1);
+ printf ("\b%s \b", buffer + pos);
+ for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case '\n':
+ /*
+ * Process the command.
+ */
+ printf ("\n");
+ repeating = 1;
+ /*
+ * Only process the history if we have a command and
+ *a history.
+ */
+ if (strlen (buffer))
+ {
+ if (history_next && (history == history_next))
+ {
+ /*
+ * Do not place the last command into the history
+ *if the same.
+ */
+ if (strcmp (history_buffer[history_next - 1], buffer))
+ repeating = 0;
+ }
+ else
+ repeating = 0;
+ }
+ if (!repeating)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
+ history_next++;
+ else
+ {
+ memmove (history_buffer[0], history_buffer[1],
+ RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
+ memmove (&history_pos[0], &history_pos[1],
+ sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
+ }
+ }
+ else
+ {
+ if (history_next)
+ memcpy (buffer, history_buffer[history_next - 1],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ }
+ memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
+ return repeating;
+ break;
+
+ default:
+ if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
+ (c >= ' ') && (c <= 'z'))
+ {
+ int end;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ end = strlen (buffer);
+ if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
+ {
+ int ch, bs;
+ for (ch = end + 1; ch > pos; ch--)
+ buffer[ch] = buffer[ch - 1];
+ printf (buffer + pos);
+ for (bs = 0; bs < (end - pos + 1); bs++)
+ putchar ('\b');
+ }
+ buffer[pos++] = c;
+ if (pos > end)
+ buffer[pos] = '\0';
+ putchar (c);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
* make_argv(cp): token-count
- * Break up the command line in 'cp' into global argv[] and argc (return
- * value).
+ * Break up the command line in 'cp' into global argv[] and argc (return
+ * value).
*/
int
@@ -25,16 +436,16 @@ rtems_monitor_make_argv(
int *argc_p,
char **argv)
{
- int argc = 0;
+ int argc = 0;
- while ((cp = strtok(cp, " \t\n\r")))
- {
- argv[argc++] = cp;
- cp = (char *) NULL;
- }
- argv[argc] = (char *) NULL; /* end of argv */
+ while ((cp = strtok(cp, " \t\n\r")))
+ {
+ argv[argc++] = cp;
+ cp = (char *) NULL;
+ }
+ argv[argc] = (char *) NULL; /* end of argv */
- return *argc_p = argc;
+ return *argc_p = argc;
}
@@ -50,34 +461,29 @@ rtems_monitor_command_read(char *command,
int *argc,
char **argv)
{
- static char monitor_prompt[32];
-
- /*
- * put node number in the prompt if we are multiprocessing
- */
+ /*
+ * put node number in the prompt if we are multiprocessing
+ */
- if (!rtems_configuration_get_user_multiprocessing_table())
- sprintf(monitor_prompt, "%s", MONITOR_PROMPT);
- else if (rtems_monitor_default_node != rtems_monitor_node)
- sprintf(monitor_prompt, "%d-%s-%d", rtems_monitor_node, MONITOR_PROMPT, rtems_monitor_default_node);
- else
- sprintf(monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
+ if (!rtems_configuration_get_user_multiprocessing_table ())
+ sprintf (monitor_prompt, "%s", MONITOR_PROMPT);
+ else if (rtems_monitor_default_node != rtems_monitor_node)
+ sprintf (monitor_prompt, "%d-%s-%d", rtems_monitor_node,
+ MONITOR_PROMPT, rtems_monitor_default_node);
+ else
+ sprintf (monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
#ifdef RTEMS_UNIX
- /* RTEMS on unix gets so many interrupt system calls this is hosed */
- printf("%s> ", monitor_prompt);
- fflush(stdout);
- while (gets(command) == (char *) 0)
- ;
+ /* RTEMS on unix gets so many interrupt system calls this is hosed */
+ printf ("%s> ", monitor_prompt);
+ fflush (stdout);
+ while (gets(command) == (char *) 0)
+ ;
#else
- do
- {
- printf("%s> ", monitor_prompt);
- fflush(stdout);
- } while (gets(command) == (char *) 0);
+ rtems_monitor_line_editor (command);
#endif
- return rtems_monitor_make_argv(command, argc, argv);
+ return rtems_monitor_make_argv (command, argc, argv);
}
/*
@@ -92,74 +498,177 @@ rtems_monitor_command_lookup(
char **argv
)
{
- rtems_monitor_command_entry_t *p;
- rtems_monitor_command_entry_t *abbreviated_match = 0;
- int abbreviated_matches = 0;
- char *command;
- int command_length;
+ char *command;
- command = argv[0];
+ command = argv[0];
- if ((table == 0) || (command == 0))
- goto failed;
+ if ((table == 0) || (command == 0))
+ return 0;
- command_length = strlen(command);
+ while (table)
+ {
+ if (table->command)
+ {
+ if (STREQ (command, table->command)) /* exact match */
+ {
+ if (table->command_function == 0)
+ return 0;
+ return table;
+ }
+ }
+ table = table->next;
+ }
- for (p = table; p->command; p++)
- if (STREQ(command, p->command)) /* exact match */
- goto done;
- else if (STRNEQ(command, p->command, command_length))
- {
- abbreviated_matches++;
- abbreviated_match = p;
- }
+ return 0;
+}
- /* no perfect match; is there a non-ambigous abbreviated match? */
- if ( ! abbreviated_match)
- {
- printf("Unrecognized command '%s'; try 'help'\n", command);
- goto failed;
- }
+void
+rtems_monitor_show_help (
+ rtems_monitor_command_entry_t *help_cmd,
+ int max_cmd_len
+)
+{
+#define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
+
+ if (help_cmd && help_cmd->command)
+ {
+ const char *help = help_cmd->usage;
+ int help_len = strlen (help);
+ int spaces = max_cmd_len - strlen (help_cmd->command);
+ int show_this_line = 0;
+ int line_one = 1;
+ int c;
- if (abbreviated_matches > 1)
+ printf ("%s", help_cmd->command);
+
+ if (help_len == 0)
{
- printf("Command '%s' is ambiguous; try 'help'\n", command);
- goto failed;
+ printf (" - No help associated.\n");
+ return;
}
-
- p = abbreviated_match;
+
+ while (help_len)
+ {
+ printf ("%*c", spaces, ' ');
+
+ if (line_one)
+ printf (" - ");
-done:
- if (p->command_function == 0)
- goto failed;
- return p;
+ spaces = max_cmd_len + 2;
+ line_one = 0;
-failed:
- return 0;
+ /*
+ * See if greater then the line length if so, work back
+ * from the end for a space, tab or lf or cr.
+ */
+
+ if (help_len > MAX_HELP_LINE_LENGTH)
+ {
+ for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ show_this_line;
+ show_this_line--)
+ if ((help[show_this_line] == ' ') ||
+ (help[show_this_line] == '\n') ||
+ (help[show_this_line] == '\r'))
+ break;
+
+ /*
+ * If show_this_line is 0, it is a very long word !!
+ */
+
+ if (show_this_line == 0)
+ show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ }
+ else
+ show_this_line = help_len;
+
+ for (c = 0; c < show_this_line; c++)
+ if ((help[c] == '\r') || (help[c] == '\n'))
+ show_this_line = c;
+ else
+ putchar (help[c]);
+
+ printf ("\n");
+
+ help += show_this_line;
+ help_len -= show_this_line;
+
+ /*
+ * Move past the line feeds or what ever else is being skipped.
+ */
+
+ while (help_len)
+ {
+ if ((*help != '\r') && (*help != '\n'))
+ break;
+
+ if (*help != ' ')
+ {
+ help++;
+ help_len--;
+ break;
+ }
+ help++;
+ help_len--;
+ }
+ }
+ }
}
void
-rtems_monitor_command_usage(rtems_monitor_command_entry_t *table,
- char *command_string)
+rtems_monitor_command_usage(
+ rtems_monitor_command_entry_t *table,
+ char *command_string
+)
{
- rtems_monitor_command_entry_t *help = 0;
- char *help_command_argv[2];
+ rtems_monitor_command_entry_t *command = table;
+ int max_cmd_len = 0;
- /* if first entry in table is a usage, then print it out */
- if (command_string == 0)
- {
- if (STREQ(table->command, "--usage--") && table->usage)
- help = table;
- }
+ /* if first entry in table is a usage, then print it out */
+
+ if (command_string && (*command_string != '\0'))
+ {
+ char *argv[2];
+
+ argv[0] = command_string;
+ argv[1] = 0;
+
+ command = rtems_monitor_command_lookup (table, 1, argv);
+
+ if (command)
+ rtems_monitor_show_help (command, strlen (command_string));
else
- {
- help_command_argv[0] = command_string;
- help_command_argv[1] = 0;
- help = rtems_monitor_command_lookup(table, 1, help_command_argv);
- }
+ printf ("Unrecognised command; try just 'help'\n");
+ return;
+ }
+
+ /*
+ * Find the largest command size.
+ */
+
+ while (command)
+ {
+ int len = strlen (command->command);
+
+ if (len > max_cmd_len)
+ max_cmd_len = len;
- if (help)
- printf("%s\n", help->usage);
+ command = command->next;
+ }
+
+ max_cmd_len++;
+
+ command = table;
+
+ /*
+ * Now some nice formatting for the help.
+ */
+
+ while (command)
+ {
+ rtems_monitor_show_help (command, max_cmd_len);
+ command = command->next;
+ }
}
@@ -171,16 +680,16 @@ rtems_monitor_help_cmd(
boolean verbose
)
{
- int arg;
- rtems_monitor_command_entry_t *command;
+ int arg;
+ rtems_monitor_command_entry_t *command;
- command = (rtems_monitor_command_entry_t *) command_arg;
+ command = (rtems_monitor_command_entry_t *) command_arg;
- if (argc == 1)
- rtems_monitor_command_usage(command, 0);
- else
- {
- for (arg=1; argv[arg]; arg++)
- rtems_monitor_command_usage(command, argv[arg]);
- }
+ if (argc == 1)
+ rtems_monitor_command_usage(command, 0);
+ else
+ {
+ for (arg = 1; argv[arg]; arg++)
+ rtems_monitor_command_usage(command, argv[arg]);
+ }
}
diff --git a/c/src/libmisc/monitor/mon-monitor.c b/c/src/libmisc/monitor/mon-monitor.c
index 289425d8e4..478e904feb 100644
--- a/c/src/libmisc/monitor/mon-monitor.c
+++ b/c/src/libmisc/monitor/mon-monitor.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <termios.h>
#include <unistd.h>
#include <rtems/monitor.h>
@@ -54,186 +55,174 @@ unsigned32 rtems_monitor_default_node; /* current default for commands */
rtems_symbol_table_t *rtems_monitor_symbols;
/*
+ * User registered commands.
+ */
+
+rtems_monitor_command_entry_t rtems_registered_commands;
+
+/*
* The top-level commands
*/
rtems_monitor_command_entry_t rtems_monitor_commands[] = {
- { "--usage--",
- "\n"
- "RTEMS monitor\n"
- "\n"
- "Commands (may be abbreviated)\n"
- "\n"
- " help -- get this message or command specific help\n"
- " pause -- pause monitor for a specified number of ticks\n"
- " exit -- invoke a fatal RTEMS error\n"
- " symbol -- show entries from symbol table\n"
- " continue -- put monitor to sleep waiting for explicit wakeup\n"
- " config -- show system configuration\n"
- " itask -- list init tasks\n"
- " mpci -- list mpci config\n"
- " task -- show task information\n"
- " queue -- show message queue information\n"
- " extension -- user extensions\n"
- " driver -- show information about named drivers\n"
- " dname -- show information about named drivers\n"
- " object -- generic object information\n"
- " node -- specify default node for commands that take id's\n"
-#ifdef CPU_INVOKE_DEBUGGER
- " debugger -- invoke system debugger\n"
-#endif
- ,
- 0,
- 0,
- (unsigned32) rtems_monitor_commands,
- },
{ "config",
- "config\n"
- " Show the system configuration.\n",
+ "Show the system configuration.",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_CONFIG,
+ &rtems_monitor_commands[1],
},
{ "itask",
- "itask\n"
- " List init tasks for the system\n",
+ "List init tasks for the system",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_INIT_TASK,
+ &rtems_monitor_commands[2],
},
{ "mpci",
- "mpci\n"
- " Show the MPCI system configuration, if configured.\n",
+ "Show the MPCI system configuration, if configured.",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_MPCI,
+ &rtems_monitor_commands[3],
},
{ "pause",
- "pause [ticks]\n"
- " monitor goes to \"sleep\" for specified ticks (default is 1)\n"
- " monitor will resume at end of period or if explicitly awakened\n",
+ "Monitor goes to \"sleep\" for specified ticks (default is 1). "
+ "Monitor will resume at end of period or if explicitly awakened\n"
+ " pause [ticks]",
0,
rtems_monitor_pause_cmd,
0,
+ &rtems_monitor_commands[4],
},
{ "continue",
- "continue\n"
- " put the monitor to sleep waiting for an explicit wakeup from the\n"
- " program running.\n",
+ "Put the monitor to sleep waiting for an explicit wakeup from the "
+ "program running.\n",
0,
rtems_monitor_continue_cmd,
0,
+ &rtems_monitor_commands[5],
},
{ "go",
- "go\n"
- " Alias for 'continue'\n",
+ "Alias for 'continue'",
0,
rtems_monitor_continue_cmd,
0,
+ &rtems_monitor_commands[6],
},
{ "node",
- "node [ node number ]\n"
- " Specify default node number for commands that take id's\n",
+ "Specify default node number for commands that take id's.\n"
+ " node [ node number ]",
0,
rtems_monitor_node_cmd,
0,
+ &rtems_monitor_commands[7],
},
{ "symbol",
- "symbol [ symbolname [symbolname ... ] ]\n"
- " display value associated with specified symbol.\n"
- " Defaults to displaying all known symbols.\n",
+ "Display value associated with specified symbol. "
+ "Defaults to displaying all known symbols.\n"
+ " symbol [ symbolname [symbolname ... ] ]",
0,
rtems_monitor_symbol_cmd,
(unsigned32) &rtems_monitor_symbols,
+ &rtems_monitor_commands[8],
},
{ "extension",
- "extension [id [id ...] ]\n"
- " display information about specified extensions.\n"
- " Default is to display information about all extensions on this node\n",
+ "Display information about specified extensions. "
+ "Default is to display information about all extensions on this node.\n"
+ " extension [id [id ...] ]",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_EXTENSION,
+ &rtems_monitor_commands[9],
},
{ "task",
- "task [id [id ...] ]\n"
- " display information about the specified tasks.\n"
- " Default is to display information about all tasks on this node\n",
+ "Display information about the specified tasks. "
+ "Default is to display information about all tasks on this node.\n"
+ " task [id [id ...] ]",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_TASK,
+ &rtems_monitor_commands[10],
},
{ "queue",
- "queue [id [id ... ] ]\n"
- " display information about the specified message queues\n"
- " Default is to display information about all queues on this node\n",
+ "Display information about the specified message queues. "
+ "Default is to display information about all queues on this node.\n"
+ " queue [id [id ... ] ]",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_QUEUE,
+ &rtems_monitor_commands[11],
},
{ "object",
- "object [id [id ...] ]\n"
- " display information about specified RTEMS objects.\n"
- " Object id's must include 'type' information.\n"
- " (which may normally be defaulted)\n",
+ "Display information about specified RTEMS objects. "
+ "Object id's must include 'type' information. "
+ "(which may normally be defaulted)\n"
+ " object [id [id ...] ]",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_INVALID,
+ &rtems_monitor_commands[12],
},
{ "driver",
- "driver [ major [ major ... ] ]\n"
- " Display the RTEMS device driver table.\n",
+ "Display the RTEMS device driver table.\n"
+ " driver [ major [ major ... ] ]",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_DRIVER,
+ &rtems_monitor_commands[13],
},
{ "dname",
- "dname\n"
- " Displays information about named drivers.\n",
+ "Displays information about named drivers.\n",
0,
rtems_monitor_object_cmd,
RTEMS_MONITOR_OBJECT_DNAME,
+ &rtems_monitor_commands[14],
},
{ "exit",
- "exit [status]\n"
- " Invoke 'rtems_fatal_error_occurred' with 'status'\n"
- " (default is RTEMS_SUCCESSFUL)\n",
+ "Invoke 'rtems_fatal_error_occurred' with 'status' "
+ "(default is RTEMS_SUCCESSFUL)\n"
+ " exit [status]",
0,
rtems_monitor_fatal_cmd,
RTEMS_SUCCESSFUL,
+ &rtems_monitor_commands[15],
},
{ "fatal",
- "fatal [status]\n"
- " 'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n",
+ "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
+ " fatal [status]",
0,
rtems_monitor_fatal_cmd,
RTEMS_TASK_EXITTED, /* exit value */
+ &rtems_monitor_commands[16],
},
{ "quit",
- "quit [status]\n"
- " Alias for 'exit'\n",
+ "Alias for 'exit'\n",
0,
rtems_monitor_fatal_cmd,
RTEMS_SUCCESSFUL, /* exit value */
+ &rtems_monitor_commands[17],
},
{ "help",
- "help [ command [ command ] ]\n"
- " provide information about commands\n"
- " Default is show basic command summary.\n",
+ "Provide information about commands. "
+ "Default is show basic command summary.\n"
+ "help [ command [ command ] ]",
0,
rtems_monitor_help_cmd,
(unsigned32) rtems_monitor_commands,
+ &rtems_monitor_commands[18],
},
#ifdef CPU_INVOKE_DEBUGGER
{ "debugger",
- "debugger\n"
- " Enter the debugger, if possible.\n"
- " A continue from the debugger will return to the monitor.\n",
+ "Enter the debugger, if possible. "
+ "A continue from the debugger will return to the monitor.\n",
0,
rtems_monitor_debugger_cmd,
0,
+ &rtems_monitor_commands[19],
},
#endif
- { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, &rtems_registered_commands },
};
@@ -418,6 +407,56 @@ done:
return;
}
+/*
+ * User registered commands.
+ */
+
+int
+rtems_monitor_insert_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ rtems_monitor_command_entry_t *p = rtems_registered_commands.next;
+
+ command->next = 0;
+
+ if (rtems_registered_commands.next)
+ {
+ for (; p->next; p = p->next)
+ {
+ if (STREQ(command->command, p->command))
+ return 0;
+ }
+ p->next = command;
+ }
+ else
+ rtems_registered_commands.next = command;
+
+ return 1;
+}
+
+int
+rtems_monitor_erase_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ rtems_monitor_command_entry_t *p;
+ rtems_monitor_command_entry_t **p_prev = &rtems_registered_commands.next;
+
+ if (rtems_registered_commands.next)
+ {
+ for (p = rtems_registered_commands.next; p->next; p = p->next)
+ {
+ if (STREQ(command->command, p->command))
+ {
+ *p_prev = p->next;
+ return 1;
+ }
+ p_prev = &p->next;
+ }
+ }
+ return 0;
+}
/*
* Main monitor command loop
@@ -435,7 +474,39 @@ rtems_monitor_task(
int argc;
char *argv[64];
boolean verbose = FALSE;
+ struct termios term;
+ /*
+ * Make the stdin stream characte not line based.
+ */
+
+ if (tcgetattr (STDIN_FILENO, &term) < 0)
+ {
+ printf("rtems-monitor: cannot get terminal attributes.\n");
+ }
+ else
+ {
+ /*
+ * No echo, no canonical processing.
+ */
+
+ term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
+
+ /*
+ * No sigint on BREAK, CR-to-NL off, input parity off,
+ * don't strip 8th bit on input, output flow control off
+ */
+
+ term.c_lflag &= ~(INPCK | ISTRIP | IXON);
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+
+ if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
+ {
+ printf("cannot set terminal attributes\n");
+ }
+ }
+
if (monitor_flags & RTEMS_MONITOR_SUSPEND)
(void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
@@ -453,7 +524,11 @@ rtems_monitor_task(
if ((command = rtems_monitor_command_lookup(rtems_monitor_commands,
argc,
argv)) == 0)
+ {
+ /* no command */
+ printf("Unrecognised command; try 'help'\n");
continue;
+ }
command->command_function(argc, argv, command->command_arg, verbose);
diff --git a/c/src/libmisc/monitor/monitor.h b/c/src/libmisc/monitor/monitor.h
index a9584808f3..ef0e099ac7 100644
--- a/c/src/libmisc/monitor/monitor.h
+++ b/c/src/libmisc/monitor/monitor.h
@@ -294,9 +294,9 @@ struct rtems_monitor_command_entry_s {
char *usage; /* usage string for the command */
unsigned32 arguments_required; /* # of required args */
rtems_monitor_command_function_t command_function;
-
/* Some argument for the command */
- unsigned32 command_arg;
+ unsigned32 command_arg;
+ struct rtems_monitor_command_entry_s *next;
};
typedef void *(*rtems_monitor_object_next_fn)(void *, void *, rtems_id *);
@@ -325,6 +325,9 @@ void rtems_monitor_continue_cmd(int, char **, unsigned32, boolean);
void rtems_monitor_debugger_cmd(int, char **, unsigned32, boolean);
void rtems_monitor_node_cmd(int, char **, unsigned32, boolean);
void rtems_monitor_symbols_loadup(void);
+int rtems_monitor_insert_cmd(rtems_monitor_command_entry_t *);
+int rtems_monitor_erase_cmd(rtems_monitor_command_entry_t *);
+
void rtems_monitor_task(rtems_task_argument);
/* server.c */