source: rtems/cpukit/libmisc/shell/shell.c @ 42836e3

4.104.115
Last change on this file since 42836e3 was 13c37ad, checked in by Joel Sherrill <joel.sherrill@…>, on 11/23/09 at 21:56:50

2009-11-23 Joel Sherrill <joel.sherrill@…>

  • libmisc/shell/shell.c: Always duplicate the environment passed to us because we will delete it when the shell exits. If we do not duplicate it, we could end up freeing memory which was not allocated from the heap or double freeing it.
  • 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,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          else {
241            if (output)
242              fputc('\x7', out);
243          }
244        }
245        break;
246
247        case RTEMS_SHELL_KEYS_DEL:
248          if (line[col] != '\0')
249          {
250            int end;
251            int bs;
252            strcpy (&line[col], &line[col + 1]);
253            if (output) {
254              fprintf(out,"\r%s%s ", prompt, line);
255              end = (int) strlen (line);
256              for (bs = 0; bs < ((end - col) + 1); bs++)
257                fputc('\b', out);
258            }
259          }
260          break;
261
262        case RTEMS_SHELL_KEYS_INS:
263          inserting = inserting ? 0 : 1;
264          break;
265      }
266    }
267    else
268    {
269      switch (c)
270      {
271        case 1:/*Control-a*/
272          if (output) {
273            if (prompt)
274              fprintf(out,"\r%s", prompt);
275          }
276          col = 0;
277          break;
278
279        case 5:/*Control-e*/
280          if (output)
281            fprintf(out,line + col);
282          col = (int) strlen (line);
283          break;
284
285        case 11:/*Control-k*/
286          if (line[col]) {
287            if (output) {
288              int end = strlen(line);
289              int bs;
290              fprintf(out,"%*c", end - col, ' ');
291              for (bs = 0; bs < (end - col); bs++)
292                fputc('\b', out);
293            }
294            line[col] = '\0';
295          }
296          break;
297
298        case 0x04:/*Control-d*/
299          if (strlen(line))
300            break;
301        case EOF:
302          if (output)
303            fputc('\n', out);
304          return -2;
305
306        case '\f':
307          if (output) {
308            int end;
309            int bs;
310            fputc('\f',out);
311            fprintf(out,"\r%s%s", prompt, line);
312            end = (int) strlen (line);
313            for (bs = 0; bs < (end - col); bs++)
314              fputc('\b', out);
315          }
316          break;
317
318        case '\b':
319        case '\x7f':
320          if (col > 0)
321          {
322            int bs;
323            col--;
324            strcpy (line + col, line + col + 1);
325            if (output) {
326              fprintf(out,"\b%s \b", line + col);
327              for (bs = 0; bs < ((int) strlen (line) - col); bs++)
328                fputc('\b', out);
329            }
330          }
331          break;
332
333        case '\n':
334        case '\r':
335        {
336          /*
337           * Process the command.
338           */
339          if (output)
340            fprintf(out,"\n");
341
342          /*
343           * Only process the command if we have a command and it is not
344           * repeated in the history.
345           */
346          if (strlen(line) == 0) {
347            cmd = -1;
348          } else {
349            if ((cmd < 0) || (strcmp(line, cmds[cmd]) != 0)) {
350              if (count > 1)
351                memmove(cmds[1], cmds[0], (count - 1) * size);
352              memmove (cmds[0], line, size);
353              cmd = 0;
354            }
355          }
356        }
357        return cmd;
358
359        default:
360          if ((col < (size - 1)) && (c >= ' ') && (c <= '~')) {
361            int end = strlen (line);
362            if (inserting && (col < end) && (end < size)) {
363              int ch, bs;
364              for (ch = end + 1; ch > col; ch--)
365                line[ch] = line[ch - 1];
366              if (output) {
367                fprintf(out, line + col);
368                for (bs = 0; bs < (end - col + 1); bs++)
369                  fputc('\b', out);
370              }
371            }
372            line[col++] = c;
373            if (col > end)
374              line[col] = '\0';
375            if (output)
376              fputc(c, out);
377          }
378          break;
379      }
380    }
381  }
382  return -2;
383}
384
385/* ----------------------------------------------- *
386 * - The shell TASK
387 * Poor but enough..
388 * TODO: Redirection. Tty Signals. ENVVARs. Shell language.
389 * ----------------------------------------------- */
390
391void rtems_shell_init_issue(void)
392{
393  static bool issue_inited=false;
394  struct stat buf;
395
396  if (issue_inited)
397    return;
398  issue_inited = true;
399
400  /* dummy call to init /etc dir */
401  getpwnam("root");
402
403  if (stat("/etc/issue",&buf)) {
404    rtems_shell_write_file("/etc/issue",
405                           "\n"
406                           "Welcome to @V\\n"
407                           "Login into @S\\n");
408  }
409
410  if (stat("/etc/issue.net",&buf)) {
411     rtems_shell_write_file("/etc/issue.net",
412                           "\n"
413                            "Welcome to %v\n"
414                            "running on %m\n");
415  }
416}
417
418static bool rtems_shell_login(FILE * in,FILE * out) {
419  FILE          *fd;
420  int            c;
421  time_t         t;
422
423  rtems_shell_init_issue();
424  setuid(0);
425  setgid(0);
426  rtems_current_user_env->euid =
427  rtems_current_user_env->egid =0;
428
429  if (out) {
430    if ((rtems_current_shell_env->devname[5]!='p')||
431        (rtems_current_shell_env->devname[6]!='t')||
432        (rtems_current_shell_env->devname[7]!='y')) {
433      fd = fopen("/etc/issue","r");
434      if (fd) {
435        while ((c=fgetc(fd))!=EOF) {
436          if (c=='@')  {
437            switch(c=fgetc(fd)) {
438              case 'L':
439                fprintf(out,"%s",rtems_current_shell_env->devname);
440                break;
441              case 'B':
442                fprintf(out,"0");
443                break;
444              case 'T':
445              case 'D':
446                time(&t);
447                fprintf(out,"%s",ctime(&t));
448                break;
449              case 'S':
450                fprintf(out,"RTEMS");
451                break;
452              case 'V':
453                fprintf(out,"%s\n%s",_RTEMS_version, _Copyright_Notice);
454                break;
455              case '@':
456                fprintf(out,"@");
457                break;
458              default :
459                fprintf(out,"@%c",c);
460                break;
461            }
462          } else if (c=='\\')  {
463            switch(c=fgetc(fd)) {
464              case '\\': fprintf(out,"\\"); break;
465              case 'b':  fprintf(out,"\b"); break;
466              case 'f':  fprintf(out,"\f"); break;
467              case 'n':  fprintf(out,"\n"); break;
468              case 'r':  fprintf(out,"\r"); break;
469              case 's':  fprintf(out," ");  break;
470              case 't':  fprintf(out,"\t"); break;
471              case '@':  fprintf(out,"@");  break;
472            }
473          } else {
474            fputc(c,out);
475          }
476        }
477        fclose(fd);
478      }
479    } else {
480      fd = fopen("/etc/issue.net","r");
481      if (fd) {
482        while ((c=fgetc(fd))!=EOF) {
483          if (c=='%')  {
484            switch(c=fgetc(fd)) {
485              case 't':
486                fprintf(out,"%s",rtems_current_shell_env->devname);
487                break;
488              case 'h':
489                fprintf(out,"0");
490                break;
491              case 'D':
492                fprintf(out," ");
493                break;
494              case 'd':
495                time(&t);
496                fprintf(out,"%s",ctime(&t));
497                break;
498              case 's':
499                fprintf(out,"RTEMS");
500                break;
501              case 'm':
502                fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
503                break;
504              case 'r':
505                fprintf(out,_RTEMS_version);
506                break;
507              case 'v':
508                fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
509                break;
510              case '%':fprintf(out,"%%");
511                break;
512              default:
513                fprintf(out,"%%%c",c);
514                break;
515            }
516          } else {
517            fputc(c,out);
518          }
519        }
520        fclose(fd);
521      }
522    }
523  }
524
525  return rtems_shell_login_prompt(
526    in,
527    out,
528    rtems_current_shell_env->devname,
529    rtems_current_shell_env->login_check
530  );
531}
532
533#if defined(SHELL_DEBUG)
534void rtems_shell_print_env(
535  rtems_shell_env_t * shell_env
536)
537{
538  if ( !shell_env ) {
539    printk( "shell_env is NULL\n" );
540    return;
541  }
542  printk( "shell_env=%p\n"
543    "shell_env->magic=0x%08x\t"
544    "shell_env->devname=%s\n"
545    "shell_env->taskname=%s\t"
546    "shell_env->exit_shell=%d\t"
547    "shell_env->forever=%d\n",
548    shell_env->magic,
549    shell_env->devname,
550    ((shell_env->taskname) ? shell_env->taskname : "NOT SET"),
551    shell_env->exit_shell,
552    shell_env->forever
553  );
554}
555#endif
556
557rtems_task rtems_shell_task(rtems_task_argument task_argument)
558{
559  rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
560  rtems_id           wake_on_end = shell_env->wake_on_end;
561  rtems_shell_main_loop( shell_env );
562  if (wake_on_end != RTEMS_INVALID_ID)
563    rtems_event_send (wake_on_end, RTEMS_EVENT_1);
564  rtems_task_delete( RTEMS_SELF );
565}
566
567#define RTEMS_SHELL_MAXIMUM_ARGUMENTS (128)
568#define RTEMS_SHELL_CMD_SIZE          (128)
569#define RTEMS_SHELL_CMD_COUNT         (32)
570#define RTEMS_SHELL_PROMPT_SIZE       (128)
571
572bool rtems_shell_main_loop(
573  rtems_shell_env_t *shell_env_arg
574)
575{
576  rtems_shell_env_t *shell_env;
577  rtems_shell_cmd_t *shell_cmd;
578  rtems_status_code  sc;
579  struct termios     term;
580  struct termios     previous_term;
581  char              *prompt = NULL;
582  int                cmd;
583  int                cmd_count = 1; /* assume a script and so only 1 command line */
584  char              *cmds[RTEMS_SHELL_CMD_COUNT];
585  char              *cmd_argv;
586  int                argc;
587  char              *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
588  bool               result = true;
589  bool               input_file = false;
590  int                line = 0;
591  FILE              *stdinToClose = NULL;
592  FILE              *stdoutToClose = NULL;
593
594  rtems_shell_initialize_command_set();
595
596  shell_env =
597  rtems_current_shell_env = rtems_shell_init_env( shell_env_arg );
598
599  /*
600   * @todo chrisj
601   * Remove the use of task variables. Change to have a single
602   * allocation per shell and then set into a notepad register
603   * in the TCB. Provide a function to return the pointer.
604   * Task variables are a virus to embedded systems software.
605   */
606  sc = rtems_task_variable_add(
607    RTEMS_SELF,
608    (void*)&rtems_current_shell_env,
609    rtems_shell_env_free
610  );
611  if (sc != RTEMS_SUCCESSFUL) {
612    rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
613    return false;
614  }
615
616  setuid(0);
617  setgid(0);
618
619  rtems_current_user_env->euid = rtems_current_user_env->egid = 0;
620
621  fileno(stdout);
622
623  /* fprintf( stderr,
624     "-%s-%s-\n", shell_env->input, shell_env->output );
625  */
626
627  if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) {
628    if (strcmp(shell_env->output, "stderr") == 0) {
629      stdout = stderr;
630    } else if (strcmp(shell_env->output, "/dev/null") == 0) {
631      fclose (stdout);
632    } else {
633      FILE *output = fopen(shell_env_arg->output,
634                           shell_env_arg->output_append ? "a" : "w");
635      if (!output) {
636        fprintf(stderr, "shell: open output %s failed: %s\n",
637                shell_env_arg->output, strerror(errno));
638        return false;
639      }
640      stdout = output;
641      stdoutToClose = output;
642    }
643  }
644
645  if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) {
646    FILE *input = fopen(shell_env_arg->input, "r");
647    if (!input) {
648      fprintf(stderr, "shell: open input %s failed: %s\n",
649              shell_env_arg->input, strerror(errno));
650      return false;
651    }
652    stdin = input;
653    stdinToClose = input;
654    shell_env->forever = false;
655    input_file =true;
656  }
657  else {
658    /* make a raw terminal,Linux Manuals */
659    if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
660      term = previous_term;
661      term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
662      term.c_oflag &= ~OPOST;
663      term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
664      term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
665      term.c_cflag  |= CLOCAL | CREAD;
666      term.c_cc[VMIN]  = 1;
667      term.c_cc[VTIME] = 0;
668      if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
669        fprintf(stderr,
670                "shell:cannot set terminal attributes(%s)\n",shell_env->devname);
671      }
672    }
673    cmd_count = RTEMS_SHELL_CMD_COUNT;
674    prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
675    if (!prompt)
676        fprintf(stderr,
677                "shell:cannot allocate prompt memory\n");
678  }
679
680  setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
681  setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
682
683  rtems_shell_initialize_command_set();
684
685  /*
686   * Allocate the command line buffers.
687   */
688  cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE);
689  if (!cmd_argv) {
690    fprintf(stderr, "no memory for command line buffers\n" );
691  }
692
693  cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE);
694  if (!cmds[0]) {
695    fprintf(stderr, "no memory for command line buffers\n" );
696  }
697
698  if (cmd_argv && cmds[0]) {
699
700    memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
701
702    for (cmd = 1; cmd < cmd_count; cmd++) {
703      cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE;
704    }
705
706    do {
707      /* Set again root user and root filesystem, side effect of set_priv..*/
708      sc = rtems_libio_set_private_env();
709      if (sc != RTEMS_SUCCESSFUL) {
710        rtems_error(sc,"rtems_libio_set_private_env():");
711        result = false;
712        break;
713      }
714
715      /*
716       *  By using result here, we can fall to the bottom of the
717       *  loop when the connection is dropped during login and
718       *  keep on trucking.
719       */
720      if (shell_env->login_check != NULL) {
721        result = rtems_shell_login(stdin,stdout);
722      } else {
723        result = true;
724      }
725
726      if (result)  {
727        const char *c;
728        memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
729        if (!input_file) {
730          rtems_shell_cat_file(stdout,"/etc/motd");
731          fprintf(stdout, "\n"
732                  "RTEMS SHELL (Ver.1.0-FRC):%s. " \
733                  __DATE__". 'help' to list commands.\n",
734                  shell_env->devname);
735        }
736
737        if (input_file)
738          chdir(shell_env->cwd);
739        else
740          chdir("/"); /* XXX: chdir to getpwent homedir */
741
742        shell_env->exit_shell = false;
743
744        for (;;) {
745          int cmd;
746
747          /* Prompt section */
748          if (prompt) {
749            rtems_shell_get_prompt(shell_env, prompt,
750                                   RTEMS_SHELL_PROMPT_SIZE);
751          }
752
753          /* getcmd section */
754          cmd = rtems_shell_line_editor(cmds, cmd_count,
755                                        RTEMS_SHELL_CMD_SIZE, prompt,
756                                        stdin, stdout);
757
758          if (cmd == -1)
759            continue; /* empty line */
760
761          if (cmd == -2)
762            break; /*EOF*/
763
764          line++;
765
766          if (shell_env->echo)
767            fprintf(stdout, "%d: %s\n", line, cmds[cmd]);
768
769          /* evaluate cmd section */
770          c = cmds[cmd];
771          while (*c) {
772            if (!isblank(*c))
773              break;
774            c++;
775          }
776
777          if (*c == '\0')   /* empty line */
778            continue;
779
780          if (*c == '#') {  /* comment character */
781            cmds[cmd][0] = 0;
782            continue;
783          }
784
785          if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) {
786            fprintf(stdout, "Shell exiting\n" );
787            break;
788          } else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */
789            fprintf(stdout, "System shutting down at user request\n" );
790            exit(0);
791          }
792
793          /* exec cmd section */
794          /* TODO:
795           *  To avoid user crash catch the signals.
796           *  Open a new stdio files with posibility of redirection *
797           *  Run in a new shell task background. (unix &)
798           *  Resuming. A little bash.
799           */
800          memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE);
801          if (!rtems_shell_make_args(cmd_argv, &argc, argv,
802                                     RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
803            shell_cmd = rtems_shell_lookup_cmd(argv[0]);
804            if ( argv[0] == NULL ) {
805              shell_env->errorlevel = -1;
806            } else if ( shell_cmd == NULL ) {
807              shell_env->errorlevel = rtems_shell_script_file(argc, argv);
808            } else {
809              shell_env->errorlevel = shell_cmd->command(argc, argv);
810            }
811          }
812
813          /* end exec cmd section */
814          if (shell_env->exit_shell)
815            break;
816        }
817
818        fflush( stdout );
819        fflush( stderr );
820      }
821    } while (result && shell_env->forever);
822
823  }
824
825  if (cmds[0])
826    free (cmds[0]);
827  if (cmd_argv)
828    free (cmd_argv);
829  if (prompt)
830    free (prompt);
831
832  if (stdinToClose) {
833    fclose( stdinToClose );
834  } else {
835    if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) {
836      fprintf(
837        stderr,
838        "shell: cannot reset terminal attributes (%s)\n",
839        shell_env->devname
840      );
841    }
842  }
843  if ( stdoutToClose )
844    fclose( stdoutToClose );
845  return result;
846}
847
848/* ----------------------------------------------- */
849static rtems_status_code rtems_shell_run (
850  const char *task_name,
851  size_t task_stacksize,
852  rtems_task_priority task_priority,
853  const char *devname,
854  bool forever,
855  bool wait,
856  const char *input,
857  const char *output,
858  bool output_append,
859  rtems_id wake_on_end,
860  bool echo,
861  rtems_shell_login_check_t login_check
862)
863{
864  rtems_id           task_id;
865  rtems_status_code  sc;
866  rtems_shell_env_t *shell_env;
867  rtems_name         name;
868
869  if ( task_name && strlen(task_name) >= 4)
870    name = rtems_build_name(
871      task_name[0], task_name[1], task_name[2], task_name[3]);
872  else
873    name = rtems_build_name( 'S', 'E', 'N', 'V' );
874
875  sc = rtems_task_create(
876    name,
877    task_priority,
878    task_stacksize,
879    RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
880    RTEMS_LOCAL | RTEMS_FLOATING_POINT,
881    &task_id
882  );
883  if (sc != RTEMS_SUCCESSFUL) {
884    rtems_error(sc,"creating task %s in shell_init()",task_name);
885    return sc;
886  }
887
888  shell_env = rtems_shell_init_env( NULL );
889  if ( !shell_env )  {
890   rtems_error(RTEMS_NO_MEMORY,
891               "allocating shell_env %s in shell_init()",task_name);
892   return RTEMS_NO_MEMORY;
893  }
894  shell_env->devname       = devname;
895  shell_env->taskname      = task_name;
896  shell_env->exit_shell    = false;
897  shell_env->forever       = forever;
898  shell_env->echo          = echo;
899  shell_env->input         = strdup (input);
900  shell_env->output        = strdup (output);
901  shell_env->output_append = output_append;
902  shell_env->wake_on_end   = wake_on_end;
903  shell_env->login_check   = login_check;
904
905  getcwd(shell_env->cwd, sizeof(shell_env->cwd));
906
907  sc = rtems_task_start(task_id, rtems_shell_task,
908                          (rtems_task_argument) shell_env);
909  if (sc != RTEMS_SUCCESSFUL) {
910    rtems_error(sc,"starting task %s in shell_init()",task_name);
911    return sc;
912  }
913
914  if (wait) {
915    rtems_event_set out;
916    sc = rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT, 0, &out);
917  }
918
919  return 0;
920}
921
922rtems_status_code rtems_shell_init(
923  const char *task_name,
924  size_t task_stacksize,
925  rtems_task_priority task_priority,
926  const char *devname,
927  bool forever,
928  bool wait,
929  rtems_shell_login_check_t login_check
930)
931{
932  rtems_id to_wake = RTEMS_ID_NONE;
933
934  if ( wait )
935    to_wake = rtems_task_self();
936
937  return rtems_shell_run(
938    task_name,               /* task_name */
939    task_stacksize,          /* task_stacksize */
940    task_priority,           /* task_priority */
941    devname,                 /* devname */
942    forever,                 /* forever */
943    wait,                    /* wait */
944    "stdin",                 /* input */
945    "stdout",                /* output */
946    false,                   /* output_append */
947    to_wake,                 /* wake_on_end */
948    false,                   /* echo */
949    login_check              /* login check */
950  );
951}
952
953rtems_status_code   rtems_shell_script (
954  const char          *task_name,
955  size_t               task_stacksize,
956  rtems_task_priority  task_priority,
957  const char*          input,
958  const char*          output,
959  bool                 output_append,
960  bool                 wait,
961  bool                 echo
962)
963{
964  rtems_id          current_task = RTEMS_INVALID_ID;
965  rtems_status_code sc;
966
967  if (wait) {
968    sc = rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &current_task);
969    if (sc != RTEMS_SUCCESSFUL)
970      return sc;
971  }
972
973  sc = rtems_shell_run(
974    task_name,       /* task_name */
975    task_stacksize,  /* task_stacksize */
976    task_priority,   /* task_priority */
977    NULL,            /* devname */
978    0,               /* forever */
979    wait,            /* wait */
980    input,           /* input */
981    output,          /* output */
982    output_append,   /* output_append */
983    current_task,    /* wake_on_end */
984    echo,            /* echo */
985    NULL             /* login check */
986  );
987  if (sc != RTEMS_SUCCESSFUL)
988    return sc;
989
990  return sc;
991}
Note: See TracBrowser for help on using the repository browser.