static int rtems_shell_main_time( int argc, char *argv[] ) { rtems_shell_cmd_t* shell_cmd; int errorlevel = 0; struct timespec start; struct timespec end; struct timespec period; rtems_status_code sc; argc--; sc = rtems_clock_get_uptime(&start); if (sc != RTEMS_SUCCESSFUL) printf("error: cannot read time\n"); if (argc) { shell_cmd = rtems_shell_lookup_cmd(argv[1]); if ( argv[1] == NULL ) { errorlevel = -1; } else if ( shell_cmd == NULL ) { errorlevel = rtems_shell_script_file(argc, &argv[1]); } else { errorlevel = shell_cmd->command(argc, &argv[1]); } } sc = rtems_clock_get_uptime(&end); if (sc != RTEMS_SUCCESSFUL) printf("error: cannot read time\n"); period.tv_sec = end.tv_sec - start.tv_sec; period.tv_nsec = end.tv_nsec - start.tv_nsec; if (period.tv_nsec < 0) { --period.tv_sec; period.tv_nsec += 1000000000UL; } printf("time: %" PRIdtime_t ":%02" PRIdtime_t ":%02" PRIdtime_t ".%03li\n", period.tv_sec / 3600, period.tv_sec / 60, period.tv_sec % 60, period.tv_nsec / 1000000); return errorlevel; }
bool rtems_shell_main_loop( rtems_shell_env_t *shell_env_arg ) { rtems_shell_env_t *shell_env; rtems_shell_cmd_t *shell_cmd; rtems_status_code sc; struct termios term; struct termios previous_term; char *prompt = NULL; int cmd; int cmd_count = 1; /* assume a script and so only 1 command line */ char *cmds[RTEMS_SHELL_CMD_COUNT]; char *cmd_argv; int argc; char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS]; bool result = true; bool input_file = false; int line = 0; FILE *stdinToClose = NULL; FILE *stdoutToClose = NULL; rtems_shell_initialize_command_set(); shell_env = rtems_current_shell_env = rtems_shell_init_env( shell_env_arg ); /* * @todo chrisj * Remove the use of task variables. Change to have a single * allocation per shell and then set into a notepad register * in the TCB. Provide a function to return the pointer. * Task variables are a virus to embedded systems software. */ sc = rtems_task_variable_add( RTEMS_SELF, (void*)&rtems_current_shell_env, rtems_shell_env_free ); if (sc != RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_task_variable_add(current_shell_env):"); return false; } setuid(0); setgid(0); rtems_current_user_env->euid = rtems_current_user_env->egid = 0; fileno(stdout); /* fprintf( stderr, "-%s-%s-\n", shell_env->input, shell_env->output ); */ if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) { if (strcmp(shell_env->output, "stderr") == 0) { stdout = stderr; } else if (strcmp(shell_env->output, "/dev/null") == 0) { fclose (stdout); } else { FILE *output = fopen(shell_env_arg->output, shell_env_arg->output_append ? "a" : "w"); if (!output) { fprintf(stderr, "shell: open output %s failed: %s\n", shell_env_arg->output, strerror(errno)); return false; } stdout = output; stdoutToClose = output; } } if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) { FILE *input = fopen(shell_env_arg->input, "r"); if (!input) { fprintf(stderr, "shell: open input %s failed: %s\n", shell_env_arg->input, strerror(errno)); return false; } stdin = input; stdinToClose = input; shell_env->forever = false; input_file =true; } else { /* make a raw terminal,Linux Manuals */ if (tcgetattr(fileno(stdin), &previous_term) >= 0) { term = previous_term; term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); term.c_oflag &= ~OPOST; term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); term.c_cflag |= CLOCAL | CREAD; term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) { fprintf(stderr, "shell:cannot set terminal attributes(%s)\n",shell_env->devname); } } cmd_count = RTEMS_SHELL_CMD_COUNT; prompt = malloc(RTEMS_SHELL_PROMPT_SIZE); if (!prompt) fprintf(stderr, "shell:cannot allocate prompt memory\n"); } setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/ setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/ rtems_shell_initialize_command_set(); /* * Allocate the command line buffers. */ cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE); if (!cmd_argv) { fprintf(stderr, "no memory for command line buffers\n" ); } cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE); if (!cmds[0]) { fprintf(stderr, "no memory for command line buffers\n" ); } if (cmd_argv && cmds[0]) { memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); for (cmd = 1; cmd < cmd_count; cmd++) { cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE; } do { /* Set again root user and root filesystem, side effect of set_priv..*/ sc = rtems_libio_set_private_env(); if (sc != RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_libio_set_private_env():"); result = false; break; } /* * By using result here, we can fall to the bottom of the * loop when the connection is dropped during login and * keep on trucking. */ if (shell_env->login_check != NULL) { result = rtems_shell_login(stdin,stdout); } else { result = true; } if (result) { const char *c; memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); if (!input_file) { rtems_shell_cat_file(stdout,"/etc/motd"); fprintf(stdout, "\n" "RTEMS SHELL (Ver.1.0-FRC):%s. " \ __DATE__". 'help' to list commands.\n", shell_env->devname); } if (input_file) chdir(shell_env->cwd); else chdir("/"); /* XXX: chdir to getpwent homedir */ shell_env->exit_shell = false; for (;;) { int cmd; /* Prompt section */ if (prompt) { rtems_shell_get_prompt(shell_env, prompt, RTEMS_SHELL_PROMPT_SIZE); } /* getcmd section */ cmd = rtems_shell_line_editor(cmds, cmd_count, RTEMS_SHELL_CMD_SIZE, prompt, stdin, stdout); if (cmd == -1) continue; /* empty line */ if (cmd == -2) break; /*EOF*/ line++; if (shell_env->echo) fprintf(stdout, "%d: %s\n", line, cmds[cmd]); /* evaluate cmd section */ c = cmds[cmd]; while (*c) { if (!isblank((unsigned char)*c)) break; c++; } if (*c == '\0') /* empty line */ continue; if (*c == '#') { /* comment character */ cmds[cmd][0] = 0; continue; } if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) { fprintf(stdout, "Shell exiting\n" ); break; } else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */ fprintf(stdout, "System shutting down at user request\n" ); exit(0); } /* exec cmd section */ /* TODO: * To avoid user crash catch the signals. * Open a new stdio files with posibility of redirection * * Run in a new shell task background. (unix &) * Resuming. A little bash. */ memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE); if (!rtems_shell_make_args(cmd_argv, &argc, argv, RTEMS_SHELL_MAXIMUM_ARGUMENTS)) { shell_cmd = rtems_shell_lookup_cmd(argv[0]); if ( argv[0] == NULL ) { shell_env->errorlevel = -1; } else if ( shell_cmd == NULL ) { shell_env->errorlevel = rtems_shell_script_file(argc, argv); } else { shell_env->errorlevel = shell_cmd->command(argc, argv); } } /* end exec cmd section */ if (shell_env->exit_shell) break; } fflush( stdout ); fflush( stderr ); } } while (result && shell_env->forever); } if (cmds[0]) free (cmds[0]); if (cmd_argv) free (cmd_argv); if (prompt) free (prompt); if (stdinToClose) { fclose( stdinToClose ); } else { if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) { fprintf( stderr, "shell: cannot reset terminal attributes (%s)\n", shell_env->devname ); } } if ( stdoutToClose ) fclose( stdoutToClose ); return result; }
/* * show the help. The first command implemented. * Can you see the header of routine? Known? * The same with all the commands.... */ static int rtems_shell_help( int argc, char * argv[] ) { int col,line,lines,arg; char* lines_env; rtems_shell_topic_t *topic; rtems_shell_cmd_t * shell_cmd = rtems_shell_first_cmd; lines_env = getenv("SHELL_LINES"); if (lines_env) lines = strtol(lines_env, 0, 0); else lines = 16; if (argc<2) { printf("help: ('r' repeat last cmd - 'e' edit last cmd)\n" " TOPIC? The topics are\n"); topic = rtems_shell_first_topic; col = 0; while (topic) { if (!col){ col = printf(" %s",topic->topic); } else { if ((col+strlen(topic->topic)+2)>78){ printf("\n"); col = printf(" %s",topic->topic); } else { col+= printf(", %s",topic->topic); } } topic = topic->next; } printf("\n"); return 1; } line = 0; for (arg = 1;arg<argc;arg++) { if (lines && (line > lines)) { printf("Press any key to continue...");getchar(); printf("\n"); line = 0; } topic = rtems_shell_lookup_topic(argv[arg]); if (!topic){ if ((shell_cmd = rtems_shell_lookup_cmd(argv[arg])) == NULL) { printf("help: topic or cmd '%s' not found. Try <help> alone for a list\n", argv[arg]); line++; } else { line+= rtems_shell_help_cmd(shell_cmd); } continue; } printf("help: list for the topic '%s'\n",argv[arg]); line++; while (shell_cmd) { if (!strcmp(topic->topic,shell_cmd->topic)) line+= rtems_shell_help_cmd(shell_cmd); if (lines && (line > lines)) { printf("Press any key to continue..."); getchar(); printf("\n"); line = 0; } shell_cmd = shell_cmd->next; } } puts(""); return 0; }