/* * Shell Script Invocation * * Pseudo-code from Chris Johns, implemented and debugged * by Joel Sherrill. * * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. * * $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #define __need_getopt_newlib #include #include #include #include #include "internal.h" static void rtems_shell_joel_usage(void) { printf( "joel [args] where args may be:\n" " -o FILE output file (default=stdout)\n" " -p PRIORITY task priority\n" " -s SIZE task stack size\n" " -t NAME task name\n" ); } static int findOnPATH( const char *userScriptName, char *scriptFile ) { int sc; /* * If the user script name starts with a / assume it is a fully * qualified path name and just use it. */ if ( userScriptName[0] == '/' ) { strcpy( scriptFile, userScriptName ); } else { /* * For now, the provided name is just turned into a fully * qualified path name and used. There is no attempt to * search along a path for it. */ /* XXX should use strncat but what is the limit? */ getcwd( scriptFile, PATH_MAX ); strcat( scriptFile, "/" ); strcat( scriptFile, ( (userScriptName[0] == '.' && userScriptName[1] == '/') ? &userScriptName[2] : userScriptName) ); } sc = access( scriptFile, R_OK ); if ( sc ) { return -1; } return 0; #if 0 /* * Does the command (argv[0]) contain a path ?, i.e. starts with * '.' or contains a '/'? */ /* TODO: Add concept of PATH */ if (!contains_path) { /* check PATH environment variable */ for (path_part = PATH; path_part; skip to ':') { } if (not found) return -1; } #endif } int rtems_shell_main_joel( int argc, char **argv ); int rtems_shell_main_joel( int argc, char **argv ) { unsigned long tmp; int option; int sc; int verbose = 0; char *taskName = "JOEL"; uint32_t stackSize = RTEMS_MINIMUM_STACK_SIZE * 10; rtems_task_priority taskPriority = 20; char *outputFile = "stdout"; rtems_status_code result; char scriptFile[PATH_MAX]; struct getopt_data getopt_reent; memset(&getopt_reent, 0, sizeof(getopt_data)); while ( (option = getopt_r( argc, argv, "o:p:s:t:v", &getopt_reent)) != -1 ) { switch ((char)option) { case 'o': outputFile = getopt_reent.optarg; break; case 'p': { const char *s = getopt_reent.optarg; if ( rtems_string_to_unsigned_long( s, &tmp, NULL, 0) ) { printf( "Task Priority argument (%s) is not a number\n", s ); return -1; } taskPriority = (rtems_task_priority) tmp; break; } case 's': { const char *s = getopt_reent.optarg; if ( rtems_string_to_unsigned_long( s, &tmp, NULL, 0) ) { printf( "Stack size argument (%s) is not a number\n", s ); return -1; } stackSize = (uint32_t) tmp; break; } case 't': taskName = getopt_reent.optarg; break; case 'v': verbose = 1; break; case '?': default: rtems_shell_joel_usage(); return -1; } } if ( verbose ) { fprintf( stderr, "outputFile: %s\n" "taskPriority: %" PRId32 "\n" "stackSize: %" PRId32 "\n" "taskName: %s\n", outputFile, taskPriority, stackSize, taskName ); } /* * Verify there is a script name past the end of the arguments. * Preincrement to skip program name. */ if ( getopt_reent.optind >= argc ) { fprintf( stderr, "Shell: No script to execute\n" ); return -1; } /* * Find script on the path. * * NOTE: It is terrible that this is done twice but it * seems to be the most expedient thing. */ sc = findOnPATH( argv[getopt_reent.optind], scriptFile ); if ( sc ) { fprintf( stderr, "%s: command not found\n", argv[0] ); return -1; } /* fprintf( stderr, "SCRIPT: -%s-\n", scriptFile ); */ /* * I assume that argv[optind...] will have the arguments to * the shell script. But that remains to be implemented. */ /* * Run the script */ result = rtems_shell_script( taskName, /* the name of the task */ stackSize, /* stack size */ taskPriority, /* task priority */ scriptFile, /* the script file */ outputFile, /* where to redirect the script */ 0, /* run once and exit */ 1, /* we will wait */ verbose /* do we echo */ ); if (result) return -1; return 0; } rtems_shell_cmd_t rtems_shell_JOEL_Command = { "joel", /* name */ "joel [args] SCRIPT", /* usage */ "misc", /* topic */ rtems_shell_main_joel, /* command */ NULL, /* alias */ NULL /* next */ }; /* * This is a helper function which takes a command as arguments * which has not been located as a built-in command and attempts * to find something in the filesystem with the same name that * appears to be a shell script. */ int rtems_shell_script_file( int argc __attribute__((unused)), char *argv[] ) { #define FIRST_LINE_LENGTH 128 #define SCRIPT_ARGV_LIMIT 32 char scriptFile[PATH_MAX]; char *scriptHead; char scriptHeadBuffer[FIRST_LINE_LENGTH]; int sc; FILE *script; size_t length; int scriptArgc; char *scriptArgv[SCRIPT_ARGV_LIMIT]; /* * Clear argv pointer array */ for ( scriptArgc=0 ; scriptArgc