From f421fee4651720bb84f69b4584cebd6129adc5f4 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 15 Sep 2009 21:11:42 +0000 Subject: 2009-09-15 Joel Sherrill * .cvsignore, ChangeLog, Makefile, README, commands.adb, commands.ads, config.h, main.adb, rtems_shell.ads, shell_init.c: New files. --- shell/.cvsignore | 5 ++ shell/ChangeLog | 8 +++ shell/Makefile | 35 ++++++++++++ shell/README | 11 ++++ shell/commands.adb | 35 ++++++++++++ shell/commands.ads | 21 +++++++ shell/config.h | 13 +++++ shell/main.adb | 21 +++++++ shell/rtems_shell.ads | 43 ++++++++++++++ shell/shell_init.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 344 insertions(+) create mode 100644 shell/.cvsignore create mode 100644 shell/ChangeLog create mode 100644 shell/Makefile create mode 100644 shell/README create mode 100644 shell/commands.adb create mode 100644 shell/commands.ads create mode 100644 shell/config.h create mode 100644 shell/main.adb create mode 100644 shell/rtems_shell.ads create mode 100644 shell/shell_init.c diff --git a/shell/.cvsignore b/shell/.cvsignore new file mode 100644 index 0000000..cf1b678 --- /dev/null +++ b/shell/.cvsignore @@ -0,0 +1,5 @@ +b~hello.adb +b~hello.ads +b~hello.ali +hello +hello.ali diff --git a/shell/ChangeLog b/shell/ChangeLog new file mode 100644 index 0000000..7c8e66f --- /dev/null +++ b/shell/ChangeLog @@ -0,0 +1,8 @@ +2009-09-15 Joel Sherrill + + * .cvsignore, ChangeLog, Makefile, README, commands.adb, commands.ads, + config.h, main.adb, rtems_shell.ads, shell_init.c: New files. + +2009-09-13 Cynthia Cicalese + + * Created example. diff --git a/shell/Makefile b/shell/Makefile new file mode 100644 index 0000000..43ccc72 --- /dev/null +++ b/shell/Makefile @@ -0,0 +1,35 @@ +# +# $Id$ +# + +PROGRAM=shell + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +LINKARGS += -ltelnetd + +# stack size for the first Ada thread +CFLAGS +=-DGNAT_MAIN_STACKSPACE=100 + +# initialize the network stack -- assumes existence of networkconfig.h +CFLAGS +=-DMAIN_USE_NETWORKING=1 + +# Should we prompt for command line arguments? +# DEFINES +=-DMAIN_USE_REQUIRES_COMMAND_LINE + +# If you want to hard-code the command line, define this to a string +# DEFINES += -DMAIN_COMMAND_LINE="ARGS" + +# Do we have extra configuration? +DEFINES += -DHAS_EXTRA_CONFIGURATION + +# Some tests need to be able to do a gethostbyname +NEED_ROOTFS_FOR_HOST_INFO=yes + +EXTRA_OBJS=shell_init.o + +include ../Makefile.shared + +shell_init.o: shell_init.c diff --git a/shell/README b/shell/README new file mode 100644 index 0000000..8c097e3 --- /dev/null +++ b/shell/README @@ -0,0 +1,11 @@ +# +# $Id$ +# + +This directory contains an example of using an Ada application +with the RTEMS Shell and telnetd. It demonstrates how to +add your own custom commands to the RTEMS Shell. + +See the README.Makefiles in the top directory for instructions +on building for most BSPs. + diff --git a/shell/commands.adb b/shell/commands.adb new file mode 100644 index 0000000..d7971ce --- /dev/null +++ b/shell/commands.adb @@ -0,0 +1,35 @@ +-- +-- $Id$ +-- + +with Ada.Text_IO; use Ada.Text_IO; + +package body Commands is + + function Prompt return String is begin + return "RTEMS> "; + end Prompt; + + function C_Prompt return chars_ptr is + begin + return New_String (Prompt); + end C_Prompt; + + function Command_Test_Arguments + (ArgC : Argument_Count_Type; + ArgV : Argument_Vector_Type) + return int + is + Arguments : Argument_Array (1 .. ArgC); + Count : Argument_Count_Type := 1; + begin + Arguments := Argument_Vector_Package.Value (ArgV, ArgC); + loop + exit when Count > ArgC; + Put_Line (Value (Arguments (Count))); + Count := Count + 1; + end loop; + return 0; + end Command_Test_Arguments; + +end Commands; diff --git a/shell/commands.ads b/shell/commands.ads new file mode 100644 index 0000000..ce47730 --- /dev/null +++ b/shell/commands.ads @@ -0,0 +1,21 @@ +-- +-- $Id$ +-- + +with Interfaces.C; use Interfaces.C; +with Interfaces.C.Strings; use Interfaces.C.Strings; +with RTEMS_Shell; use RTEMS_Shell; + +package Commands is + + function Prompt return String; + function C_Prompt return chars_ptr; + pragma Convention (C, C_Prompt); + + function Command_Test_Arguments + (ArgC : Argument_Count_Type; + ArgV : Argument_Vector_Type) + return int; + pragma Convention (C, Command_Test_Arguments); + +end Commands; diff --git a/shell/config.h b/shell/config.h new file mode 100644 index 0000000..0461f88 --- /dev/null +++ b/shell/config.h @@ -0,0 +1,13 @@ +/* + * Extra configuration for telnet/shell + * + * $Id$ + */ + +#define CONFIGURE_MAXIMUM_PTYS 8 + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define ADA_APPLICATION_NEEDS_EXTRA_MEMORY 256 + +#define CONFIGURE_MAXIMUM_DRIVERS 10 diff --git a/shell/main.adb b/shell/main.adb new file mode 100644 index 0000000..a4ae014 --- /dev/null +++ b/shell/main.adb @@ -0,0 +1,21 @@ +-- +-- $Id$ +-- + +with Interfaces.C.Strings; use Interfaces.C.Strings; +with Commands; use Commands; +with RTEMS_Shell; use RTEMS_Shell; + +procedure Main is +begin + RTEMS_Shell_Add_Command + (New_String ("args"), + New_String ("test"), + New_String ("Test passing arguments"), + Command_Test_Arguments'Access); + Set_RTEMS_Shell_Prompt_Function (C_Prompt'Access); + Initialize_Telnet_Daemon; + loop + Invoke_RTEMS_Shell; + end loop; +end Main; diff --git a/shell/rtems_shell.ads b/shell/rtems_shell.ads new file mode 100644 index 0000000..8f7b5d6 --- /dev/null +++ b/shell/rtems_shell.ads @@ -0,0 +1,43 @@ +-- +-- $Id$ +-- + +with Interfaces.C; use Interfaces.C; +with Interfaces.C.Strings; use Interfaces.C.Strings; +with Interfaces.C.Pointers; + +package RTEMS_Shell is + + type Argument_Array is array (ptrdiff_t range <>) of aliased chars_ptr; + + package Argument_Vector_Package is + new Pointers (Index => ptrdiff_t, + Element => chars_ptr, + Element_Array => Argument_Array, + Default_Terminator => Null_Ptr); + + subtype Argument_Count_Type is ptrdiff_t; + subtype Argument_Vector_Type is Argument_Vector_Package.Pointer; + + type Command_Function_Type is access function (ArgC : Argument_Count_Type; + ArgV : Argument_Vector_Type) return int; + pragma Convention (C, Command_Function_Type); + + procedure RTEMS_Shell_Add_Command(Name : chars_ptr; Category : chars_ptr; + Help : chars_ptr; Command_Function : Command_Function_Type); + pragma Import (C, RTEMS_Shell_Add_Command, "rtems_shell_add_cmd"); + + type Prompt_Function_Type is access function return chars_ptr; + pragma Convention (C, Prompt_Function_Type); + + procedure Set_RTEMS_Shell_Prompt_Function( + Prompt_Function : Prompt_Function_Type); + pragma Import (C, Set_RTEMS_Shell_Prompt_Function, "set_prompt_function"); + + procedure Invoke_RTEMS_Shell; + pragma Import (C, Invoke_RTEMS_Shell, "invoke_rtems_shell"); + + procedure Initialize_Telnet_Daemon; + pragma Import (C, Initialize_Telnet_Daemon, "init_telnet_daemon"); + +end RTEMS_Shell; diff --git a/shell/shell_init.c b/shell/shell_init.c new file mode 100644 index 0000000..32d7bbe --- /dev/null +++ b/shell/shell_init.c @@ -0,0 +1,152 @@ +/* + * This is a derived from the init.c file in the telnetd demo. + * + * $Id$ + */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include "../networkconfig.h" + +// I'm not sure why this is necessary +#include +const rtems_bdbuf_config rtems_bdbuf_configuration; + +typedef char * (* prompt_function_t)(void); + +static prompt_function_t prompt_function = NULL; + +extern void set_prompt_function(prompt_function_t f) +{ + prompt_function = f; +} + +extern char * get_prompt(void); +void rtems_shell_get_prompt( + rtems_shell_env_t *shell_env, + char *prompt, + size_t size +) +{ + char curdir[256]; + + if (prompt_function == NULL) + { + getcwd(curdir,sizeof(curdir)); + snprintf(prompt, size - 1, "%s%s[%s] %c ", + ((shell_env->taskname) ? shell_env->taskname : ""), + ((shell_env->taskname) ? " " : ""), + curdir, + geteuid()?'$':'#'); + + } + else + snprintf(prompt, size - 1, prompt_function()); +} + +/* + * If true, listen on socket(s). + * If false, remain on console. + */ +/* #define REMAIN_ON_CONSOLE */ +bool remain_on_console = false; + +#include + +#define SHELL_HELP_MSG \ + "Starting rtemsShell via telnetd -- default account is rtems w/no password\n" + +#define CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING +#define CONFIGURE_SHELL_COMMANDS_ALL + +#define CONFIGURE_SHELL_COMMANDS_INIT +#include + + +static void rtemsShell( + char *pty_name, + void *cmd_arg +) +{ + rtems_shell_env_t env = rtems_global_shell_env; + + env.devname = pty_name; + env.taskname = "TLNT"; + env.login_check = rtems_shell_login_check; + + if ( !remain_on_console ) + printk("============== Starting Shell ==============\n"); + + rtems_shell_main_loop( &env ); + + if ( !remain_on_console ) + printk("============== Exiting Shell ==============\n"); +} + +#define SHELL_ENTRY rtemsShell + +/* + * Telnet demon configuration + */ +rtems_telnetd_config_table rtems_telnetd_config = { + .command = SHELL_ENTRY, + .arg = NULL, + .priority = 1, /* We feel important today */ + .stack_size = 20 * RTEMS_MINIMUM_STACK_SIZE, /* Shell needs a large stack */ + .login_check = NULL, /* Shell asks for user and password */ + .keep_stdio = false +}; + +/* + * Initialization Aid + */ +void init_telnet_daemon(void) +{ + fprintf(stderr, "\n\n*** Telnetd Server Test ***\n\r" ); + + fprintf(stderr, "============== Initializing Network ==============\n"); + rtems_bsdnet_initialize_network (); + + fprintf(stderr, "============== Add Route ==============\n"); + rtems_bsdnet_show_inet_routes (); + + fprintf(stderr, "============== Start Telnetd ==============\n"); + + printk( SHELL_HELP_MSG ); + + #if defined(REMAIN_ON_CONSOLE) + remain_on_console = true; + #endif + + rtems_global_shell_env.login_check = rtems_shell_login_check; + rtems_telnetd_config.keep_stdio = remain_on_console; + + rtems_telnetd_initialize(); +} + + +#include +#include +#include + +/* Helper for Ada */ +void invoke_rtems_shell(void) +{ + rtemsShell("console", NULL); +} + -- cgit v1.2.3