source: rtems/cpukit/libmisc/shell/shell.c @ 9a77af8

4.104.115
Last change on this file since 9a77af8 was bab5c5fa, checked in by Joel Sherrill <joel.sherrill@…>, on 03/12/10 at 16:26:16

2010-03-12 Joel Sherrill <joel.sherrill@…>

  • ftpd/ftpd.c, httpd/asp.c, httpd/ejparse.c, httpd/emfdb.c, httpd/misc.c, httpd/um.c, httpd/webs.c, httpd/websuemf.c, libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_misc.c, libfs/src/nfsclient/src/nfs.c, libmisc/capture/capture-cli.c, libmisc/monitor/mon-network.c, libmisc/shell/hexdump-odsyntax.c, libmisc/shell/main_ifconfig.c, libmisc/shell/shell.c, libmisc/shell/shell_makeargs.c, libmisc/uuid/parse.c, libnetworking/libc/gethostbydns.c, libnetworking/libc/gethostbyht.c, libnetworking/libc/gethostnamadr.c, libnetworking/libc/getnetnamadr.c, libnetworking/libc/inet_addr.c, libnetworking/libc/inet_network.c, libnetworking/libc/res_debug.c, libnetworking/libc/res_init.c, libnetworking/libc/res_query.c, libnetworking/rtems/rtems_mii_ioctl.c, score/src/objectgetnameasstring.c: Readdress use of ctype methods per recommendation from D.J. Delorie on the newlib mailing list. We should pass an unsigned char into these methods.
  • Property mode set to 100644
File size: 24.9 KB
Line 
1/*
2 *
3 *  Instantatiate a new terminal shell.
4 *
5 *  Author:
6 *
7 *   WORK: fernando.ruiz@ctv.es
8 *   HOME: correo@fernando-ruiz.com
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 <time.h>
23
24#include <rtems.h>
25#include <rtems/error.h>
26#include <rtems/libio.h>
27#include <rtems/libio_.h>
28#include <rtems/system.h>
29#include <rtems/shell.h>
30#include <rtems/shellconfig.h>
31#include <rtems/console.h>
32#include "internal.h"
33
34#include <termios.h>
35#include <string.h>
36#include <stdlib.h>
37#include <ctype.h>
38#include <sys/stat.h>
39#include <unistd.h>
40#include <errno.h>
41#include <pwd.h>
42
43rtems_shell_env_t rtems_global_shell_env = {
44  .magic         = rtems_build_name('S', 'E', 'N', 'V'),
45  .devname       = CONSOLE_DEVICE_NAME,
46  .taskname      = "SHGL",
47  .exit_shell    = false,
48  .forever       = true,
49  .errorlevel    = -1,
50  .echo          = false,
51  .cwd           = "/",
52  .input         = NULL,
53  .output        = NULL,
54  .output_append = false,
55  .wake_on_end   = RTEMS_ID_NONE,
56  .login_check   = NULL
57};
58
59rtems_shell_env_t *rtems_current_shell_env = &rtems_global_shell_env;
60
61/*
62 *  Initialize the shell user/process environment information
63 */
64rtems_shell_env_t *rtems_shell_init_env(
65  rtems_shell_env_t *shell_env_p
66)
67{
68  rtems_shell_env_t *shell_env;
69
70  shell_env = malloc(sizeof(rtems_shell_env_t));
71  if ( !shell_env )
72    return NULL;
73  if ( !shell_env_p ) {
74    *shell_env = rtems_global_shell_env;
75  } else {
76    *shell_env = *shell_env_p;
77  }
78  shell_env->taskname = NULL;
79
80  return shell_env;
81}
82
83/*
84 *  Completely free a shell_env_t and all associated memory
85 */
86void rtems_shell_env_free(
87  void *ptr
88)
89{
90  rtems_shell_env_t *shell_env;
91  shell_env = (rtems_shell_env_t *) ptr;
92
93  if ( !ptr )
94    return;
95
96  if ( shell_env->input )
97    free((void *)shell_env->input);
98  if ( shell_env->output )
99    free((void *)shell_env->output);
100  free( ptr );
101}
102
103/*
104 *  Get a line of user input with modest features
105 */
106int rtems_shell_line_editor(
107  char       *cmds[],
108  int         count,
109  int         size,
110  const char *prompt,
111  FILE       *in,
112  FILE       *out
113)
114{
115  unsigned int extended_key;
116  int          c;
117  int          col;
118  int          last_col;
119  int          output;
120  char         line[size];
121  char         new_line[size];
122  int          up;
123  int          cmd = -1;
124  int          inserting = 1;
125
126  output = (out && isatty(fileno(in)));
127
128  col = last_col = 0;
129
130  tcdrain(fileno(in));
131  if (out)
132    tcdrain(fileno(out));
133
134  if (output && prompt)
135    fprintf(out, "\r%s", prompt);
136
137  line[0] = 0;
138  new_line[0] = 0;
139
140  for (;;) {
141
142    if (output)
143      fflush(out);
144
145    extended_key = rtems_shell_getchar(in);
146
147    if (extended_key == EOF)
148      return -2;
149
150    c = extended_key & RTEMS_SHELL_KEYS_NORMAL_MASK;
151
152    /*
153     * Make the extended_key usable as a boolean.
154     */
155    extended_key &= ~RTEMS_SHELL_KEYS_NORMAL_MASK;
156
157    up = 0;
158
159    if (extended_key)
160    {
161      switch (c)
162      {
163        case RTEMS_SHELL_KEYS_END:
164          if (output)
165            fprintf(out, "%s", line + col);
166          col = (int) strlen (line);
167          break;
168
169        case RTEMS_SHELL_KEYS_HOME:
170          if (output) {
171            if (prompt)
172              fprintf(out,"\r%s", prompt);
173          }
174          col = 0;
175          break;
176
177        case RTEMS_SHELL_KEYS_LARROW:
178          if (col > 0)
179          {
180            col--;
181            if (output)
182              fputc('\b', out);
183          }
184          break;
185
186          case RTEMS_SHELL_KEYS_RARROW:
187            if ((col < size) && (line[col] != '\0'))
188            {
189              if (output)
190                fprintf(out, "%c", line[col]);
191              col++;
192            }
193            break;
194
195        case RTEMS_SHELL_KEYS_UARROW:
196          if ((cmd >= (count - 1)) || (strlen(cmds[cmd + 1]) == 0)) {
197            if (output)
198              fputc('\x7', out);
199            break;
200          }
201
202          up = 1;
203
204          /* drop through */
205        case RTEMS_SHELL_KEYS_DARROW:
206
207        {
208          int last_cmd = cmd;
209          int clen = strlen (line);
210
211          if (prompt)
212            clen += strlen(prompt);
213
214          if (up) {
215            cmd++;
216          } else {
217            if (cmd < 0) {
218              if (output)
219                fprintf(out, "\x7");
220              break;
221            }
222            else
223              cmd--;
224          }
225
226          if ((last_cmd < 0) || (strcmp(cmds[last_cmd], line) != 0))
227            memcpy (new_line, line, size);
228
229          if (cmd < 0)
230            memcpy (line, new_line, size);
231          else
232            memcpy (line, cmds[cmd], size);
233
234          col = strlen (line);
235
236          if (output) {
237            fprintf(out,"\r%*c", clen, ' ');
238            fprintf(out,"\r%s%s", prompt, line);
239          }
240        }
241        break;
242
243        case RTEMS_SHELL_KEYS_DEL:
244          if (line[col] != '\0')
245          {
246            int end;
247            int bs;
248            strcpy (&line[col], &line[col + 1]);
249            if (output) {
250              fprintf(out,"\r%s%s ", prompt, line);
251              end = (int) strlen (line);
252              for (bs = 0; bs < ((end - col) + 1); bs++)
253                fputc('\b', out);
254            }
255          }
256          break;
257
258        case RTEMS_SHELL_KEYS_INS:
259          inserting = inserting ? 0 : 1;
260          break;
261      }
262    }
263    else
264    {
265      switch (c)
266      {
267        case 1:/*Control-a*/
268          if (output) {
269            if (prompt)
270              fprintf(out,"\r%s", prompt);
271          }
272          col = 0;
273          break;
274
275        case 5:/*Control-e*/
276          if (output)
277            fprintf(out, "%s", line + col);
278          col = (int) strlen (line);
279          break;
280
281        case 11:/*Control-k*/
282          if (line[col]) {
283            if (output) {
284              int end = strlen(line);
285              int bs;
286              fprintf(out,"%*c", end - col, ' ');
287              for (bs = 0; bs < (end - col); bs++)
288                fputc('\b', out);
289            }
290            line[col] = '\0';
291          }
292          break;
293
294        case 0x04:/*Control-d*/
295          if (strlen(line))
296            break;
297        case EOF:
298          if (output)
299            fputc('\n', out);
300          return -2;
301
302        case '\f':
303          if (output) {
304            int end;
305            int bs;
306            fputc('\f',out);
307            fprintf(out,"\r%s%s", prompt, line);
308            end = (int) strlen (line);
309            for (bs = 0; bs < (end - col); bs++)
310              fputc('\b', out);
311          }
312          break;
313
314        case '\b':
315        case '\x7f':
316          if (col > 0)
317          {
318            int bs;
319            col--;
320            strcpy (line + col, line + col + 1);
321            if (output) {
322              fprintf(out,"\b%s \b", line + col);
323              for (bs = 0; bs < ((int) strlen (line) - col); bs++)
324                fputc('\b', out);
325            }
326          }
327          break;
328
329        case '\n':
330        case '\r':
331        {
332          /*
333           * Process the command.
334           */
335          if (output)
336            fprintf(out,"\n");
337
338          /*
339           * Only process the command if we have a command and it is not
340           * repeated in the history.
341           */
342          if (strlen(line) == 0) {
343            cmd = -1;
344          } else {
345            if ((cmd < 0) || (strcmp(line, cmds[cmd]) != 0)) {
346              if (count > 1)
347                memmove(cmds[1], cmds[0], (count - 1) * size);
348              memmove (cmds[0], line, size);
349              cmd = 0;
350            }
351          }
352        }
353        return cmd;
354
355        default:
356          if ((col < (size - 1)) && (c >= ' ') && (c <= '~')) {
357            int end = strlen (line);
358            if (inserting && (col < end) && (end < size)) {
359              int ch, bs;
360              for (ch = end + 1; ch > col; ch--)
361                line[ch] = line[ch - 1];
362              if (output) {
363                fprintf(out, "%s", line + col);
364                for (bs = 0; bs < (end - col + 1); bs++)
365                  fputc('\b', out);
366              }
367            }
368            line[col++] = c;
369            if (col > end)
370              line[col] = '\0';
371            if (output)
372              fputc(c, out);
373          }
374          break;
375      }
376    }
377  }
378  return -2;
379}
380
381/* ----------------------------------------------- *
382 * - The shell TASK
383 * Poor but enough..
384 * TODO: Redirection. Tty Signals. ENVVARs. Shell language.
385 * ----------------------------------------------- */
386
387void rtems_shell_init_issue(void)
388{
389  static bool issue_inited=false;
390  struct stat buf;
391
392  if (issue_inited)
393    return;
394  issue_inited = true;
395
396  /* dummy call to init /etc dir */
397  getpwnam("root");
398
399  if (stat("/etc/issue",&buf)) {
400    rtems_shell_write_file("/etc/issue",
401                           "\n"
402                           "Welcome to @V\\n"
403                           "Login into @S\\n");
404  }
405
406  if (stat("/etc/issue.net",&buf)) {
407     rtems_shell_write_file("/etc/issue.net",
408                           "\n"
409                            "Welcome to %v\n"
410                            "running on %m\n");
411  }
412}
413
414static bool rtems_shell_login(FILE * in,FILE * out) {
415  FILE          *fd;
416  int            c;
417  time_t         t;
418
419  rtems_shell_init_issue();
420  setuid(0);
421  setgid(0);
422  rtems_current_user_env->euid =
423  rtems_current_user_env->egid =0;
424
425  if (out) {
426    if ((rtems_current_shell_env->devname[5]!='p')||
427        (rtems_current_shell_env->devname[6]!='t')||
428        (rtems_current_shell_env->devname[7]!='y')) {
429      fd = fopen("/etc/issue","r");
430      if (fd) {
431        while ((c=fgetc(fd))!=EOF) {
432          if (c=='@')  {
433            switch(c=fgetc(fd)) {
434              case 'L':
435                fprintf(out,"%s",rtems_current_shell_env->devname);
436                break;
437              case 'B':
438                fprintf(out,"0");
439                break;
440              case 'T':
441              case 'D':
442                time(&t);
443                fprintf(out,"%s",ctime(&t));
444                break;
445              case 'S':
446                fprintf(out,"RTEMS");
447                break;
448              case 'V':
449                fprintf(out,"%s\n%s",_RTEMS_version, _Copyright_Notice);
450                break;
451              case '@':
452                fprintf(out,"@");
453                break;
454              default :
455                fprintf(out,"@%c",c);
456                break;
457            }
458          } else if (c=='\\')  {
459            switch(c=fgetc(fd)) {
460              case '\\': fprintf(out,"\\"); break;
461              case 'b':  fprintf(out,"\b"); break;
462              case 'f':  fprintf(out,"\f"); break;
463              case 'n':  fprintf(out,"\n"); break;
464              case 'r':  fprintf(out,"\r"); break;
465              case 's':  fprintf(out," ");  break;
466              case 't':  fprintf(out,"\t"); break;
467              case '@':  fprintf(out,"@");  break;
468            }
469          } else {
470            fputc(c,out);
471          }
472        }
473        fclose(fd);
474      }
475    } else {
476      fd = fopen("/etc/issue.net","r");
477      if (fd) {
478        while ((c=fgetc(fd))!=EOF) {
479          if (c=='%')  {
480            switch(c=fgetc(fd)) {
481              case 't':
482                fprintf(out,"%s",rtems_current_shell_env->devname);
483                break;
484              case 'h':
485                fprintf(out,"0");
486                break;
487              case 'D':
488                fprintf(out," ");
489                break;
490              case 'd':
491                time(&t);
492                fprintf(out,"%s",ctime(&t));
493                break;
494              case 's':
495                fprintf(out,"RTEMS");
496                break;
497              case 'm':
498                fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
499                break;
500              case 'r':
501                fprintf(out,_RTEMS_version);
502                break;
503              case 'v':
504                fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
505                break;
506              case '%':fprintf(out,"%%");
507                break;
508              default:
509                fprintf(out,"%%%c",c);
510                break;
511            }
512          } else {
513            fputc(c,out);
514          }
515        }
516        fclose(fd);
517      }
518    }
519  }
520
521  return rtems_shell_login_prompt(
522    in,
523    out,
524    rtems_current_shell_env->devname,
525    rtems_current_shell_env->login_check
526  );
527}
528
529#if defined(SHELL_DEBUG)
530void rtems_shell_print_env(
531  rtems_shell_env_t * shell_env
532)
533{
534  if ( !shell_env ) {
535    printk( "shell_env is NULL\n" );
536    return;
537  }
538  printk( "shell_env=%p\n"
539    "shell_env->magic=0x%08x\t"
540    "shell_env->devname=%s\n"
541    "shell_env->taskname=%s\t"
542    "shell_env->exit_shell=%d\t"
543    "shell_env->forever=%d\n",
544    shell_env->magic,
545    shell_env->devname,
546    ((shell_env->taskname) ? shell_env->taskname : "NOT SET"),
547    shell_env->exit_shell,
548    shell_env->forever
549  );
550}
551#endif
552
553rtems_task rtems_shell_task(rtems_task_argument task_argument)
554{
555  rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
556  rtems_id           wake_on_end = shell_env->wake_on_end;
557  rtems_shell_main_loop( shell_env );
558  if (wake_on_end != RTEMS_INVALID_ID)
559    rtems_event_send (wake_on_end, RTEMS_EVENT_1);
560  rtems_task_delete( RTEMS_SELF );
561}
562
563#define RTEMS_SHELL_MAXIMUM_ARGUMENTS (128)
564#define RTEMS_SHELL_CMD_SIZE          (128)
565#define RTEMS_SHELL_CMD_COUNT         (32)
566#define RTEMS_SHELL_PROMPT_SIZE       (128)
567
568bool rtems_shell_main_loop(
569  rtems_shell_env_t *shell_env_arg
570)
571{
572  rtems_shell_env_t *shell_env;
573  rtems_shell_cmd_t *shell_cmd;
574  rtems_status_code  sc;
575  struct termios     term;
576  struct termios     previous_term;
577  char              *prompt = NULL;
578  int                cmd;
579  int                cmd_count = 1; /* assume a script and so only 1 command line */
580  char              *cmds[RTEMS_SHELL_CMD_COUNT];
581  char              *cmd_argv;
582  int                argc;
583  char              *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
584  bool               result = true;
585  bool               input_file = false;
586  int                line = 0;
587  FILE              *stdinToClose = NULL;
588  FILE              *stdoutToClose = NULL;
589
590  rtems_shell_initialize_command_set();
591
592  shell_env =
593  rtems_current_shell_env = rtems_shell_init_env( shell_env_arg );
594
595  /*
596   * @todo chrisj
597   * Remove the use of task variables. Change to have a single
598   * allocation per shell and then set into a notepad register
599   * in the TCB. Provide a function to return the pointer.
600   * Task variables are a virus to embedded systems software.
601   */
602  sc = rtems_task_variable_add(
603    RTEMS_SELF,
604    (void*)&rtems_current_shell_env,
605    rtems_shell_env_free
606  );
607  if (sc != RTEMS_SUCCESSFUL) {
608    rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
609    return false;
610  }
611
612  setuid(0);
613  setgid(0);
614
615  rtems_current_user_env->euid = rtems_current_user_env->egid = 0;
616
617  fileno(stdout);
618
619  /* fprintf( stderr,
620     "-%s-%s-\n", shell_env->input, shell_env->output );
621  */
622
623  if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) {
624    if (strcmp(shell_env->output, "stderr") == 0) {
625      stdout = stderr;
626    } else if (strcmp(shell_env->output, "/dev/null") == 0) {
627      fclose (stdout);
628    } else {
629      FILE *output = fopen(shell_env_arg->output,
630                           shell_env_arg->output_append ? "a" : "w");
631      if (!output) {
632        fprintf(stderr, "shell: open output %s failed: %s\n",
633                shell_env_arg->output, strerror(errno));
634        return false;
635      }
636      stdout = output;
637      stdoutToClose = output;
638    }
639  }
640
641  if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) {
642    FILE *input = fopen(shell_env_arg->input, "r");
643    if (!input) {
644      fprintf(stderr, "shell: open input %s failed: %s\n",
645              shell_env_arg->input, strerror(errno));
646      return false;
647    }
648    stdin = input;
649    stdinToClose = input;
650    shell_env->forever = false;
651    input_file =true;
652  }
653  else {
654    /* make a raw terminal,Linux Manuals */
655    if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
656      term = previous_term;
657      term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
658      term.c_oflag &= ~OPOST;
659      term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
660      term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
661      term.c_cflag  |= CLOCAL | CREAD;
662      term.c_cc[VMIN]  = 1;
663      term.c_cc[VTIME] = 0;
664      if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
665        fprintf(stderr,
666                "shell:cannot set terminal attributes(%s)\n",shell_env->devname);
667      }
668    }
669    cmd_count = RTEMS_SHELL_CMD_COUNT;
670    prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
671    if (!prompt)
672        fprintf(stderr,
673                "shell:cannot allocate prompt memory\n");
674  }
675
676  setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
677  setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
678
679  rtems_shell_initialize_command_set();
680
681  /*
682   * Allocate the command line buffers.
683   */
684  cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE);
685  if (!cmd_argv) {
686    fprintf(stderr, "no memory for command line buffers\n" );
687  }
688
689  cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE);
690  if (!cmds[0]) {
691    fprintf(stderr, "no memory for command line buffers\n" );
692  }
693
694  if (cmd_argv && cmds[0]) {
695
696    memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
697
698    for (cmd = 1; cmd < cmd_count; cmd++) {
699      cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE;
700    }
701
702    do {
703      /* Set again root user and root filesystem, side effect of set_priv..*/
704      sc = rtems_libio_set_private_env();
705      if (sc != RTEMS_SUCCESSFUL) {
706        rtems_error(sc,"rtems_libio_set_private_env():");
707        result = false;
708        break;
709      }
710
711      /*
712       *  By using result here, we can fall to the bottom of the
713       *  loop when the connection is dropped during login and
714       *  keep on trucking.
715       */
716      if (shell_env->login_check != NULL) {
717        result = rtems_shell_login(stdin,stdout);
718      } else {
719        result = true;
720      }
721
722      if (result)  {
723        const char *c;
724        memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
725        if (!input_file) {
726          rtems_shell_cat_file(stdout,"/etc/motd");
727          fprintf(stdout, "\n"
728                  "RTEMS SHELL (Ver.1.0-FRC):%s. " \
729                  __DATE__". 'help' to list commands.\n",
730                  shell_env->devname);
731        }
732
733        if (input_file)
734          chdir(shell_env->cwd);
735        else
736          chdir("/"); /* XXX: chdir to getpwent homedir */
737
738        shell_env->exit_shell = false;
739
740        for (;;) {
741          int cmd;
742
743          /* Prompt section */
744          if (prompt) {
745            rtems_shell_get_prompt(shell_env, prompt,
746                                   RTEMS_SHELL_PROMPT_SIZE);
747          }
748
749          /* getcmd section */
750          cmd = rtems_shell_line_editor(cmds, cmd_count,
751                                        RTEMS_SHELL_CMD_SIZE, prompt,
752                                        stdin, stdout);
753
754          if (cmd == -1)
755            continue; /* empty line */
756
757          if (cmd == -2)
758            break; /*EOF*/
759
760          line++;
761
762          if (shell_env->echo)
763            fprintf(stdout, "%d: %s\n", line, cmds[cmd]);
764
765          /* evaluate cmd section */
766          c = cmds[cmd];
767          while (*c) {
768            if (!isblank((unsigned char)*c))
769              break;
770            c++;
771          }
772
773          if (*c == '\0')   /* empty line */
774            continue;
775
776          if (*c == '#') {  /* comment character */
777            cmds[cmd][0] = 0;
778            continue;
779          }
780
781          if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) {
782            fprintf(stdout, "Shell exiting\n" );
783            break;
784          } else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */
785            fprintf(stdout, "System shutting down at user request\n" );
786            exit(0);
787          }
788
789          /* exec cmd section */
790          /* TODO:
791           *  To avoid user crash catch the signals.
792           *  Open a new stdio files with posibility of redirection *
793           *  Run in a new shell task background. (unix &)
794           *  Resuming. A little bash.
795           */
796          memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE);
797          if (!rtems_shell_make_args(cmd_argv, &argc, argv,
798                                     RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
799            shell_cmd = rtems_shell_lookup_cmd(argv[0]);
800            if ( argv[0] == NULL ) {
801              shell_env->errorlevel = -1;
802            } else if ( shell_cmd == NULL ) {
803              shell_env->errorlevel = rtems_shell_script_file(argc, argv);
804            } else {
805              shell_env->errorlevel = shell_cmd->command(argc, argv);
806            }
807          }
808
809          /* end exec cmd section */
810          if (shell_env->exit_shell)
811            break;
812        }
813
814        fflush( stdout );
815        fflush( stderr );
816      }
817    } while (result && shell_env->forever);
818
819  }
820
821  if (cmds[0])
822    free (cmds[0]);
823  if (cmd_argv)
824    free (cmd_argv);
825  if (prompt)
826    free (prompt);
827
828  if (stdinToClose) {
829    fclose( stdinToClose );
830  } else {
831    if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) {
832      fprintf(
833        stderr,
834        "shell: cannot reset terminal attributes (%s)\n",
835        shell_env->devname
836      );
837    }
838  }
839  if ( stdoutToClose )
840    fclose( stdoutToClose );
841  return result;
842}
843
844/* ----------------------------------------------- */
845static rtems_status_code rtems_shell_run (
846  const char *task_name,
847  size_t task_stacksize,
848  rtems_task_priority task_priority,
849  const char *devname,
850  bool forever,
851  bool wait,
852  const char *input,
853  const char *output,
854  bool output_append,
855  rtems_id wake_on_end,
856  bool echo,
857  rtems_shell_login_check_t login_check
858)
859{
860  rtems_id           task_id;
861  rtems_status_code  sc;
862  rtems_shell_env_t *shell_env;
863  rtems_name         name;
864
865  if ( task_name && strlen(task_name) >= 4)
866    name = rtems_build_name(
867      task_name[0], task_name[1], task_name[2], task_name[3]);
868  else
869    name = rtems_build_name( 'S', 'E', 'N', 'V' );
870
871  sc = rtems_task_create(
872    name,
873    task_priority,
874    task_stacksize,
875    RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
876    RTEMS_LOCAL | RTEMS_FLOATING_POINT,
877    &task_id
878  );
879  if (sc != RTEMS_SUCCESSFUL) {
880    rtems_error(sc,"creating task %s in shell_init()",task_name);
881    return sc;
882  }
883
884  shell_env = rtems_shell_init_env( NULL );
885  if ( !shell_env )  {
886   rtems_error(RTEMS_NO_MEMORY,
887               "allocating shell_env %s in shell_init()",task_name);
888   return RTEMS_NO_MEMORY;
889  }
890  shell_env->devname       = devname;
891  shell_env->taskname      = task_name;
892  shell_env->exit_shell    = false;
893  shell_env->forever       = forever;
894  shell_env->echo          = echo;
895  shell_env->input         = strdup (input);
896  shell_env->output        = strdup (output);
897  shell_env->output_append = output_append;
898  shell_env->wake_on_end   = wake_on_end;
899  shell_env->login_check   = login_check;
900
901  getcwd(shell_env->cwd, sizeof(shell_env->cwd));
902
903  sc = rtems_task_start(task_id, rtems_shell_task,
904                          (rtems_task_argument) shell_env);
905  if (sc != RTEMS_SUCCESSFUL) {
906    rtems_error(sc,"starting task %s in shell_init()",task_name);
907    return sc;
908  }
909
910  if (wait) {
911    rtems_event_set out;
912    sc = rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT, 0, &out);
913  }
914
915  return 0;
916}
917
918rtems_status_code rtems_shell_init(
919  const char *task_name,
920  size_t task_stacksize,
921  rtems_task_priority task_priority,
922  const char *devname,
923  bool forever,
924  bool wait,
925  rtems_shell_login_check_t login_check
926)
927{
928  rtems_id to_wake = RTEMS_ID_NONE;
929
930  if ( wait )
931    to_wake = rtems_task_self();
932
933  return rtems_shell_run(
934    task_name,               /* task_name */
935    task_stacksize,          /* task_stacksize */
936    task_priority,           /* task_priority */
937    devname,                 /* devname */
938    forever,                 /* forever */
939    wait,                    /* wait */
940    "stdin",                 /* input */
941    "stdout",                /* output */
942    false,                   /* output_append */
943    to_wake,                 /* wake_on_end */
944    false,                   /* echo */
945    login_check              /* login check */
946  );
947}
948
949rtems_status_code   rtems_shell_script (
950  const char          *task_name,
951  size_t               task_stacksize,
952  rtems_task_priority  task_priority,
953  const char*          input,
954  const char*          output,
955  bool                 output_append,
956  bool                 wait,
957  bool                 echo
958)
959{
960  rtems_id          current_task = RTEMS_INVALID_ID;
961  rtems_status_code sc;
962
963  if (wait) {
964    sc = rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &current_task);
965    if (sc != RTEMS_SUCCESSFUL)
966      return sc;
967  }
968
969  sc = rtems_shell_run(
970    task_name,       /* task_name */
971    task_stacksize,  /* task_stacksize */
972    task_priority,   /* task_priority */
973    NULL,            /* devname */
974    0,               /* forever */
975    wait,            /* wait */
976    input,           /* input */
977    output,          /* output */
978    output_append,   /* output_append */
979    current_task,    /* wake_on_end */
980    echo,            /* echo */
981    NULL             /* login check */
982  );
983  if (sc != RTEMS_SUCCESSFUL)
984    return sc;
985
986  return sc;
987}
Note: See TracBrowser for help on using the repository browser.