source: rtems/cpukit/libmisc/shell/shell_script.c @ 9a9851dd

4.104.114.9
Last change on this file since 9a9851dd was 9a9851dd, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 2, 2008 at 2:26:24 PM

2008-07-02 Joel Sherrill <joel.sherrill@…>

  • libmisc/shell/shell_script.c: Remove unused function.
  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 *  Shell Script Invocation
3 *
4 *  Pseudo-code from Chris Johns, implemented and debugged
5 *  by Joel Sherrill.
6 *
7 *  COPYRIGHT (c) 1989-2008.
8 *  On-Line Applications Research Corporation (OAR).
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *  http://www.rtems.com/license/LICENSE.
13 *
14 *  $Id$
15 */
16
17#ifdef HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <stdio.h>
22#include <unistd.h>
23#include <string.h>
24#include <errno.h>
25#include <inttypes.h>
26#include <sys/types.h>
27#include <unistd.h>
28#include <getopt.h>
29
30#include <rtems.h>
31#include <rtems/shell.h>
32#include "internal.h"
33
34static void rtems_shell_joel_usage()
35{
36  printf(
37    "joel [args] where args may be:\n"
38    "  -o FILE     output file (default=stdout)\n"
39    "  -p PRIORITY task priority\n"
40    "  -s SIZE     task stack size\n"
41    "  -t NAME     task name\n"
42  );
43}
44
45static int findOnPATH(
46  const char *userScriptName,
47  char       *scriptFile
48)
49{
50  /*
51   *  If the user script name starts with a / assume it is a fully
52   *  qualified path name and just use it.
53   */
54  if ( userScriptName[0] == '/' ) {
55    strcpy( scriptFile, userScriptName );
56    return 0;
57  }
58
59  /*
60   *  For now, the provided name is just turned into a fully
61   *  qualified path name and used.  There is no attempt to
62   *  search along a path for it.
63   */
64
65  getcwd( scriptFile, PATH_MAX );
66  /* XXX should use strncat but what is the limit? */
67  strcat( scriptFile, "/" );
68  strcat( scriptFile, userScriptName );
69  return 0;
70
71#if 0
72   /*
73    * Does the command (argv[0]) contain a path ?, i.e. starts with
74    * '.' or contains a '/'?
75    */
76   /* TODO: Add concept of PATH */
77   if (!contains_path) {
78     /* check PATH environment variable */
79     for (path_part = PATH; path_part; skip to ':')
80     {
81     }
82     if (not found)
83       return -1;
84   }
85#endif
86}
87
88int rtems_shell_main_joel(
89  int    argc,
90  char **argv
91)
92{
93  int                  option;
94  int                  sc;
95  int                  verbose = 0;
96  char                *taskName = "JOEL";
97  uint32_t             stackSize = RTEMS_MINIMUM_STACK_SIZE * 10;
98  rtems_task_priority  taskPriority = 20;
99  char                *outputFile = "stdout";
100  rtems_status_code    result;
101  char                 scriptFile[PATH_MAX];
102  struct getopt_data   getopt_reent;
103
104  memset(&getopt_reent, 0, sizeof(getopt_data)); 
105  while ( (option = getopt_r( argc, argv, "o:p:s:t:v", &getopt_reent)) != -1 ) {
106    switch ((char)option) {
107      case 'o':
108        outputFile = getopt_reent.optarg;
109        break;
110      case 'p':
111        taskPriority = rtems_shell_str2int(getopt_reent.optarg);
112        break;
113      case 's':
114        stackSize = rtems_shell_str2int(getopt_reent.optarg);
115        break;
116      case 't':
117        taskName = getopt_reent.optarg;
118        break;
119      case 'v': 
120        verbose = 1;
121        break;
122      case '?': 
123      default:
124        rtems_shell_joel_usage();
125        return -1;
126    }
127  }
128
129  if ( verbose ) {
130    fprintf( stderr, 
131      "outputFile: %s\n"
132      "taskPriority: %" PRId32 "\n"
133      "stackSize: %" PRId32 "\n"
134      "taskName: %s\n",
135      outputFile,
136      taskPriority,
137      stackSize,
138      taskName
139   );
140  }
141
142  /*
143   *  Verify there is a script name past the end of the arguments.
144   *  Preincrement to skip program name.
145   */
146  if ( getopt_reent.optind >= argc ) {
147    fprintf( stderr, "Shell: No script to execute\n" );
148    return -1;
149  } 
150 
151  /*
152   *  Find script on the path. 
153   *
154   *  NOTE: It is terrible that this is done twice but it
155   *        seems to be the most expedient thing.
156   */
157  sc = findOnPATH( argv[getopt_reent.optind], scriptFile );
158  if ( sc ) {
159    fprintf( stderr, "%s not found on PATH\n", argv[0] );
160    return -1;
161  }
162
163  /* fprintf( stderr, "SCRIPT: -%s-\n", scriptFile ); */
164
165  /*
166   *  I assume that argv[optind...] will have the arguments to
167   *  the shell script.  But that remains to be implemented.
168   */
169
170  /*
171   * Run the script
172   */
173  result = rtems_shell_script(
174    taskName,        /* the name of the task */
175    stackSize,       /* stack size */
176    taskPriority,    /* task priority */
177    scriptFile,      /* the script file */
178    outputFile,      /* where to redirect the script */
179    0,               /* run once and exit */
180    1,               /* we will wait */
181    verbose          /* do we echo */
182  );
183  if (result)
184    return -1;
185  return 0;
186}
187     
188rtems_shell_cmd_t rtems_shell_JOEL_Command = {
189  "joel",                        /* name */
190  "joel [args] SCRIPT",          /* usage */
191  "misc",                        /* topic */
192  rtems_shell_main_joel,         /* command */
193  NULL,                          /* alias */
194  NULL                           /* next */
195};
196
197/*
198 *  This is a helper function which takes a command as arguments
199 *  which has not been located as a built-in command and attempts
200 *  to find something in the filesystem with the same name that
201 *  appears to be a shell script.
202 */
203int rtems_shell_script_file(
204  int   argc,
205  char *argv[]
206)
207{
208  #define FIRST_LINE_LENGTH 128
209  #define SCRIPT_ARGV_LIMIT 32
210  char    scriptFile[PATH_MAX];
211  char   *scriptHead;
212  char    scriptHeadBuffer[FIRST_LINE_LENGTH];
213  int     sc;
214  FILE   *script;
215  size_t  length;
216  int     scriptArgc;
217  char   *scriptArgv[SCRIPT_ARGV_LIMIT];
218
219  /*
220   *  Clear argv pointer array
221   */
222  for ( scriptArgc=0 ; scriptArgc<SCRIPT_ARGV_LIMIT ; scriptArgc++ )
223    scriptArgv[scriptArgc] = NULL;
224
225  /*
226   *  Find argv[0] on the path
227   */
228  sc = findOnPATH( argv[0], scriptFile );
229  if ( sc ) {
230    fprintf( stderr, "%s not found on PATH\n", argv[0] );
231    return -1;
232  }
233
234  /*
235   *  Open the file so we can see if it looks like a script.
236   */
237  script = fopen( scriptFile, "r" );
238  if ( !script ) {
239    fprintf( stderr, "%s: Unable to open %s\n", argv[0], scriptFile );
240    return -1;
241  }
242
243  /*
244   *  Is the script OK to run?
245   *  Verify the current user has permission to execute it.
246   *
247   *  NOTE: May not work on all file systems
248   */
249  sc = access( scriptFile, X_OK );
250  if ( sc ) {
251    fprintf( stderr, "Unable to execute %s\n", scriptFile );
252    fclose( script );
253    return -1;
254  }
255
256  /*
257   *  Try to read the first line from the potential script file
258   */
259  scriptHead = fgets(scriptHeadBuffer, FIRST_LINE_LENGTH, script);
260  if ( !scriptHead ) {
261    fprintf(
262      stderr, "%s: Unable to read first line of %s\n", argv[0], scriptFile );
263    fclose( script );
264    return -1;
265  }
266
267  fclose(script);
268
269  length = strnlen(scriptHead, FIRST_LINE_LENGTH);
270  scriptHead[length - 1] = '\0';
271
272  /* fprintf( stderr, "FIRST LINE: -%s-\n", scriptHead ); */
273   
274  /*
275   *  Verify the name of the "shell" is joel.  This means
276   *  the line starts with "#! joel".
277   */
278  if (strncmp("#! joel", scriptHead, 7) != 0) {
279    fprintf( stderr, "%s: Not a joel script %s\n", argv[0], scriptFile );
280    return -1;
281  }
282
283  /*
284   * Do not worry about search path further.  We have found the
285   * script, it is executable, and we have successfully read the
286   * first line and found out it is a script.
287   */
288
289  /*
290   * Check for arguments in fist line of the script.  This changes
291   * how the shell task is run.
292   */
293
294  sc = rtems_shell_make_args(
295    &scriptHead[3],
296    &scriptArgc,
297    scriptArgv,
298    SCRIPT_ARGV_LIMIT - 1
299  );
300  if ( sc ) {
301    fprintf(
302      stderr, "%s: Error parsing joel arguments %s\n", argv[0], scriptFile );
303    return -1;
304  }
305
306  scriptArgv[ scriptArgc++ ] = scriptFile;
307
308  /*
309   *  TODO: How do we pass arguments from here to the script?
310   *        At this point, it doesn't matter because we don't
311   *        have any way for a shell script to access them.
312   */
313  return rtems_shell_main_joel( scriptArgc, scriptArgv );
314
315  return 0;
316}
317
Note: See TracBrowser for help on using the repository browser.