From dd74e612f1ffe208ad1e20f28ac4da3f08764879 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 20 Apr 2001 20:35:45 +0000 Subject: 2001-04-20 Correo Fernando-ruiz * Added initial shell functionality. * Makefile.am, configure.in, wrapup/Makefile.am: * shell/.cvsignore, shell/Makefile.am, shell/README, shell/cmds.c, shell/shell.c, shell/shell.h: New files. --- c/src/libmisc/ChangeLog | 6 + c/src/libmisc/Makefile.am | 2 +- c/src/libmisc/configure.in | 1 + c/src/libmisc/shell/.cvsignore | 2 + c/src/libmisc/shell/Makefile.am | 44 ++++ c/src/libmisc/shell/README | 28 +++ c/src/libmisc/shell/cmds.c | 479 +++++++++++++++++++++++++++++++++++++++ c/src/libmisc/shell/shell.c | 470 ++++++++++++++++++++++++++++++++++++++ c/src/libmisc/shell/shell.h | 72 ++++++ c/src/libmisc/wrapup/Makefile.am | 1 + 10 files changed, 1104 insertions(+), 1 deletion(-) create mode 100644 c/src/libmisc/shell/.cvsignore create mode 100644 c/src/libmisc/shell/Makefile.am create mode 100644 c/src/libmisc/shell/README create mode 100644 c/src/libmisc/shell/cmds.c create mode 100644 c/src/libmisc/shell/shell.c create mode 100644 c/src/libmisc/shell/shell.h (limited to 'c/src') diff --git a/c/src/libmisc/ChangeLog b/c/src/libmisc/ChangeLog index ad0a3f6f6c..03d1878f57 100644 --- a/c/src/libmisc/ChangeLog +++ b/c/src/libmisc/ChangeLog @@ -1,3 +1,9 @@ +2001-04-20 Correo Fernando-ruiz + + * Added initial shell functionality. + * Makefile.am, configure.in, wrapup/Makefile.am: + * shell/.cvsignore, shell/Makefile.am, shell/README, + shell/cmds.c, shell/shell.c, shell/shell.h: New files. 2001-04-20 Joel Sherrill * devnull/devnull.c (null_initialize): Added check to diff --git a/c/src/libmisc/Makefile.am b/c/src/libmisc/Makefile.am index 0474afc71a..39f14528ea 100644 --- a/c/src/libmisc/Makefile.am +++ b/c/src/libmisc/Makefile.am @@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 ACLOCAL_AMFLAGS = -I ../../../aclocal -SUBDIRS = devnull dummy dumpbuf stackchk monitor cpuuse rtmonuse untar \ +SUBDIRS = devnull dummy dumpbuf stackchk monitor cpuuse shell rtmonuse untar \ mw-fb wrapup EXTRA_DIST = README diff --git a/c/src/libmisc/configure.in b/c/src/libmisc/configure.in index 28628bb222..664485b1d4 100644 --- a/c/src/libmisc/configure.in +++ b/c/src/libmisc/configure.in @@ -33,6 +33,7 @@ AM_CONDITIONAL(HAS_MP,test "$HAS_MP" = "yes") AC_OUTPUT( Makefile cpuuse/Makefile +shell/Makefile devnull/Makefile dummy/Makefile dumpbuf/Makefile diff --git a/c/src/libmisc/shell/.cvsignore b/c/src/libmisc/shell/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/libmisc/shell/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/libmisc/shell/Makefile.am b/c/src/libmisc/shell/Makefile.am new file mode 100644 index 0000000000..814cf40c44 --- /dev/null +++ b/c/src/libmisc/shell/Makefile.am @@ -0,0 +1,44 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +include_rtemsdir = $(includedir)/rtems + +LIBNAME = libshell-tmp +LIB = $(ARCH)/$(LIBNAME).a + +C_FILES = cmds.c shell.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +include_rtems_HEADERS = shell.h + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../automake/compile.am +include $(top_srcdir)/../../../automake/lib.am + +$(PROJECT_INCLUDE)/rtems: + @$(mkinstalldirs) $@ +$(PROJECT_INCLUDE)/rtems/%.h: %.h + $(INSTALL_DATA) $< $@ + +# +# (OPTIONAL) Add local stuff here using += +# + +$(LIB): $(OBJS) + $(make-library) + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems \ + $(include_rtems_HEADERS:%=$(PROJECT_INCLUDE)/rtems/%) + +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) $(LIB) + +.PRECIOUS: $(LIB) + +EXTRA_DIST = README shell.c cmds.c shell.h + +include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/libmisc/shell/README b/c/src/libmisc/shell/README new file mode 100644 index 0000000000..2d38451cc6 --- /dev/null +++ b/c/src/libmisc/shell/README @@ -0,0 +1,28 @@ +# +# $Id$ +# + +This directory contains a shell user extension +primary features: + + + create a user shell terminal task. + +This code has not been extensively tested. It is provided as a tool +for RTEMS users to open more shell terminal. +Suggestions and comments are appreciated. + +NOTES: + +1. printf() & getchar() works but you can't use + 0,1,2 like fildes. You need to use fileno(stdin),fileno(stdout),... + +2. You only need a termios dev to start a new session, add your new commands + and enjoy it. + + + +FUTURE: + +1. Adding new commands in cmds.c to give file manegement to shell. + +2. Create a telnetd daemon. (pseudo-terminal needed) diff --git a/c/src/libmisc/shell/cmds.c b/c/src/libmisc/shell/cmds.c new file mode 100644 index 0000000000..52a4079bf2 --- /dev/null +++ b/c/src/libmisc/shell/cmds.c @@ -0,0 +1,479 @@ +/* + * Author: Fernando RUIZ CASAS + * + * Work: fernando.ruiz@ctv.es + * Home: correo@fernando-ruiz.com + * + * This file is inspired in rtems_monitor & Chris John MyRightBoot + * + * But I want to make it more user friendly + * A 'monitor' command is added to adapt the call rtems monitor commands + * at my call procedure + * + * MINIX date.c is adapted to run here. Like a exercise only.... + * + * TODO: A lot of improvements of course. + * cat, cp, rm, mv, ... + * hexdump, + * + * More? Say me it, please... + * + * The BSP Specific are not welcome here. + * + * C&S welcome... + * + * $Id$ + */ + +#undef __STRICT_ANSI__ /* fileno() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* ----------------------------------------------- * + - str to int "0xaffe" "0b010010" "0123" "192939" + * ----------------------------------------------- */ +int str2int(char * s) { + int sign=1; + int base=10; + int value=0; + int digit; + if (!s) return 0; + if (*s) { + if (*s=='-') { + sign=-1; + s++; + if (!*s) return 0; + }; + if (*s=='0') { + s++; + switch(*s) { + case 'x': + case 'X':s++; + base=16; + break; + case 'b': + case 'B':s++; + base=2; + break; + default :base=8; + break; + } + }; + while (*s) { + switch(*s) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9':digit=*s-'0'; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F':digit=*s-'A'+10; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f':digit=*s-'a'+10; + break; + default:return value*sign; + }; + if (digit>base) return value*sign; + value=value*base+digit; + s++; + }; + }; + return value*sign; +} +/*----------------------------------------------------------------------------* + * RAM MEMORY COMMANDS + *----------------------------------------------------------------------------*/ + +#define mdump_adr (current_shell_env->mdump_adr) /* static value */ + +int main_mdump(int argc,char * argv[]) { + unsigned char n,m,max=0; + int adr=mdump_adr; + unsigned char * pb; + if (argc>1) adr=str2int(argv[1]); + if (argc>2) max=str2int(argv[2]); + max/=16; + if (!max) max=20; + for (m=0;m1) adr=str2int(argv[1]); + if (argc>2) max=str2int(argv[2]); + max/=16; + if (!max) max=20; + for (m=0;m1) fname=argv[1]; + + if ((dirp = opendir(fname)) == NULL) + { + printf("%s: No such file or directory.\n", fname); + return errno; + } + n=0; + size=0; + while ((dp = readdir(dirp)) != NULL) + { + strcpy(nbuf,fname); + if (nbuf[strlen(nbuf)-1]!='/') strcat(nbuf,"/"); + strcat(nbuf,dp->d_name); /* always the fullpathname. Avoid ftpd problem.*/ + if (stat(nbuf, &stat_buf) == 0) + { /* AWFUL buts works...*/ + strftime(sbuf,sizeof(sbuf)-1,"%b %d %H:%M",gmtime(&stat_buf.st_atime)); + printf("%c%c%c%c%c%c%c%c%c%c %3d rtems rtems %11d %s %s%c\n", + (S_ISLNK(stat_buf.st_mode)?('l'): + (S_ISDIR(stat_buf.st_mode)?('d'):('-'))), + (stat_buf.st_mode & S_IRUSR)?('r'):('-'), + (stat_buf.st_mode & S_IWUSR)?('w'):('-'), + (stat_buf.st_mode & S_IXUSR)?('x'):('-'), + (stat_buf.st_mode & S_IRGRP)?('r'):('-'), + (stat_buf.st_mode & S_IWGRP)?('w'):('-'), + (stat_buf.st_mode & S_IXGRP)?('x'):('-'), + (stat_buf.st_mode & S_IROTH)?('r'):('-'), + (stat_buf.st_mode & S_IWOTH)?('w'):('-'), + (stat_buf.st_mode & S_IXOTH)?('x'):('-'), + (int)stat_buf.st_nlink, + (int)stat_buf.st_size, + sbuf, + dp->d_name, + S_ISDIR(stat_buf.st_mode)?'/':' '); + n++; + size+=stat_buf.st_size; + } + } + printf("%d files %d bytes occupied\n",n,size); + closedir(dirp); + return 0; +} +/*-----------------------------------------------------------*/ +int main_pwd (int argc, char *argv[]) { + char dir[1024]; + getcwd(dir,1024); + printf("%s\n",dir); + return 0; +} +/*-----------------------------------------------------------*/ +int main_chdir (int argc, char *argv[]) { + char *dir; + dir="/"; + if (argc>1) dir=argv[1]; + if (chdir(dir)) { + printf("chdir to '%s' failed:%s\n",dir,strerror(errno)); + return errno; + }; + return 0; +} +/*-----------------------------------------------------------*/ +int main_mkdir (int argc, char *argv[]) { + char *dir; + dir=NULL; + if (argc>1) dir=argv[1]; + if (mkdir(dir,S_IRWXU|S_IRWXG|S_IRWXO)) { + printf("mkdir '%s' failed:%s\n",dir,strerror(errno)); + }; + return errno; +} +/*-----------------------------------------------------------*/ +int main_rmdir (int argc, char *argv[]) +{ + char *dir; + dir=NULL; + if (argc>1) dir=argv[1]; + if (rmdir(dir)) printf("rmdir '%s' failed:%s\n",dir,strerror(errno)); + return errno; +} +/*-----------------------------------------------------------*/ +int main_chroot(int argc,char * argv[]) { + char * new_root="/"; + if (argc==2) new_root=argv[1]; + if (chroot(new_root)<0) { + printf("error %s:chroot(%s);\n",strerror(errno),new_root); + return -1; + }; + return 0; +} +/*-----------------------------------------------------------*/ +/* date - print or set time and date Author: Jan Looyen */ +/* MINIX 1.5 GPL'ed */ + + +#define MIN 60L /* # seconds in a minute */ +#define HOUR (60 * MIN) /* # seconds in an hour */ +#define DAY (24 * HOUR) /* # seconds in a day */ +#define YEAR (365 * DAY) /* # seconds in a year */ + +static int conv(unsigned32 *value,char **ptr,unsigned32 max) +{ + int buf; + *ptr -= 2; + buf = atoi(*ptr); + **ptr = 0; + if (buf < 0 || buf > max) { + fprintf(stderr, "Date: bad conversion\n"); + return 0; + }; + *value=buf; + return 1; +} + +static int set_time(char *t) +{ + rtems_time_of_day tod; + FILE * rtc; + char *tp; + int len; + if (rtems_clock_get(RTEMS_CLOCK_GET_TOD,&tod)!=RTEMS_SUCCESSFUL) + memset(&tod,0,sizeof(tod)); + len = strlen(t); + if (len != 12 && len != 10 && len != 6 && len != 4) return 0; + tp = t; + while (*tp) + if (!isdigit(*tp++)) { + fprintf(stderr, "date: bad conversion\n"); + return 0; + }; + if (len == 6 || len == 12) + if (!conv(&tod.second,&tp, 59)) return 0; + if (!conv(&tod.minute,&tp, 59)) return 0; + if (!conv(&tod.hour,&tp, 23)) return 0; + if (len == 12 || len == 10) { + if (!conv(&tod.year,&tp, 99)) return 0; + tod.year+=1900; + if (tod.yearcommand_function(argc, argv, command->command_arg, 0); + return 0; +} +/*-----------------------------------------------------------*/ +void register_cmds(void) { + rtems_monitor_command_entry_t *command; + extern rtems_monitor_command_entry_t rtems_monitor_commands[]; + /* dir[ectories] topic */ + shell_add_cmd ("ls" ,"dir","ls [dir] # list files in the directory" ,main_ls ); + shell_add_cmd ("chdir" ,"dir","chdir [dir] # change the current directory",main_chdir); + shell_add_cmd ("rmdir" ,"dir","rmdir dir # remove directory" ,main_rmdir); + shell_add_cmd ("mkdir" ,"dir","mkdir dir # make a directory" ,main_mkdir); + shell_add_cmd ("pwd" ,"dir","pwd # print work directory" ,main_pwd ); + shell_add_cmd ("chroot","dir","chroot [dir] # change the root directory" ,main_chroot); + + shell_alias_cmd("ls" ,"dir"); + shell_alias_cmd("chdir" ,"cd"); + + /* misc. topic */ + shell_add_cmd ("date" ,"misc","date [[MMDDYY]hhmm[ss]]" ,main_date); + shell_add_cmd ("reset","misc","reset the BSP" ,main_reset); + shell_add_cmd ("alias","misc","alias old new" ,main_alias); + + /* memory topic */ + shell_add_cmd ("mdump","mem" ,"mdump [adr [size]]" ,main_mdump); + shell_add_cmd ("wdump","mem" ,"wdump [adr [size]]" ,main_mwdump); + shell_add_cmd ("medit","mem" ,"medit adr value [value ...]" ,main_medit); + shell_add_cmd ("mfill","mem" ,"mfill adr size value" ,main_mfill); + shell_add_cmd ("mmove","mem" ,"mmove dst src size" ,main_mmove); +#ifdef MALLOC_STATS /* /rtems/s/src/lib/libc/malloc.c */ + shell_add_cmd ("malloc","mem","mem show memory malloc'ed" ,main_mem); +#endif + /* monitor topic */ + command=rtems_monitor_commands; + while (command) { + shell_add_cmd(command->command,"monitor", + command->usage ,main_monitor); + command=command->next; + }; +} +/*-----------------------------------------------------------*/ diff --git a/c/src/libmisc/shell/shell.c b/c/src/libmisc/shell/shell.c new file mode 100644 index 0000000000..d7c2502d90 --- /dev/null +++ b/c/src/libmisc/shell/shell.c @@ -0,0 +1,470 @@ +/* + * + * Instantatiate a new terminal shell. + * + * Author: + * + * WORK: fernando.ruiz@ctv.es + * HOME: correo@fernando-ruiz.com + * + * Thanks at: + * Chris John + * + * $Id$ + */ + +#undef __STRICT_ANSI__ /* fileno() */ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +/* ----------------------------------------------- * + * This is a stupidity but is cute. + * ----------------------------------------------- */ +rtems_unsigned32 new_rtems_name(char * rtems_name) { + static char b[5]; + sprintf(b,"%-4.4s",rtems_name); + return rtems_build_name(b[0],b[1],b[2],b[3]); +} +/* ************************************************************** + * common linked list of shell commands. + * Because the help report is very long + * I have a topic for each command. + * Help list the topics + * help [topic] list the commands for the topic + * help [command] help for the command + * Can you see help rtems monitor report? + * ************************************************************** */ + +struct shell_topic_tt; +typedef struct shell_topic_tt shell_topic_t; + +struct shell_topic_tt { + char * topic; + shell_topic_t * next; +}; + + +static shell_cmd_t * shell_first_cmd; +static shell_topic_t * shell_first_topic; +/* ----------------------------------------------- * + * Using Chain I can reuse the rtems code. + * I am more comfortable with this, sorry. + * ----------------------------------------------- */ +shell_topic_t * shell_lookup_topic(char * topic) { + shell_topic_t * shell_topic; + shell_topic=shell_first_topic; + while (shell_topic) { + if (!strcmp(shell_topic->topic,topic)) return shell_topic; + shell_topic=shell_topic->next; + }; + return (shell_topic_t *) NULL; +} +/* ----------------------------------------------- */ +shell_topic_t * shell_add_topic(char * topic) { + shell_topic_t * current,*aux; + if (!shell_first_topic) { + aux=malloc(sizeof(shell_topic_t)); + aux->topic=topic; + aux->next=(shell_topic_t*)NULL; + return shell_first_topic=aux; + } else { + current=shell_first_topic; + if (!strcmp(topic,current->topic)) return current; + while (current->next) { + if (!strcmp(topic,current->next->topic)) return current->next; + current=current->next; + }; + aux=malloc(sizeof(shell_topic_t)); + aux->topic=topic; + aux->next=(shell_topic_t*)NULL; + current->next=aux; + return aux; + }; +} +/* ----------------------------------------------- */ +shell_cmd_t * shell_lookup_cmd(char * cmd) { + shell_cmd_t * shell_cmd; + shell_cmd=shell_first_cmd; + while (shell_cmd) { + if (!strcmp(shell_cmd->name,cmd)) return shell_cmd; + shell_cmd=shell_cmd->next; + }; + return (shell_cmd_t *) NULL; +} +/* ----------------------------------------------- */ +shell_cmd_t * shell_add_cmd(char * cmd, + char * topic, + char * usage, + shell_command_t command) { + int shell_help(int argc,char * argv[]); + shell_cmd_t * shell_cmd,*shell_pvt; + if (!shell_first_cmd) { + shell_first_cmd=(shell_cmd_t *) malloc(sizeof(shell_cmd_t)); + shell_first_cmd->name ="help"; + shell_first_cmd->topic ="help"; + shell_first_cmd->usage ="help [topic] # list of usage of commands"; + shell_first_cmd->command=shell_help; + shell_first_cmd->alias =(shell_cmd_t *) NULL; + shell_first_cmd->next =(shell_cmd_t *) NULL; + shell_add_topic(shell_first_cmd->topic); + register_cmds(); + }; + if (!cmd) return (shell_cmd_t *) NULL; + if (!command) return (shell_cmd_t *) NULL; + shell_cmd=(shell_cmd_t *) malloc(sizeof(shell_cmd_t)); + shell_cmd->name =cmd; + shell_cmd->topic =topic; + shell_cmd->usage =usage; + shell_cmd->command=command; + shell_cmd->alias =(shell_cmd_t *) NULL; + shell_cmd->next =(shell_cmd_t *) NULL; + shell_add_topic(shell_cmd->topic); + shell_pvt=shell_first_cmd; + while (shell_pvt->next) shell_pvt=shell_pvt->next; + return shell_pvt->next=shell_cmd; +} +/* ----------------------------------------------- * + * you can make an alias for every command. + * ----------------------------------------------- */ +shell_cmd_t * shell_alias_cmd(char * cmd, char * alias) { + shell_cmd_t * shell_cmd,* shell_aux; + shell_aux=(shell_cmd_t *) NULL; + if (alias) { + if ((shell_aux=shell_lookup_cmd(alias))!=NULL) { + return NULL; + }; + if ((shell_cmd=shell_lookup_cmd(cmd))!=NULL) { + shell_aux=shell_add_cmd(alias,shell_cmd->topic, + shell_cmd->usage,shell_cmd->command); + if (shell_aux) shell_aux->alias=shell_cmd; + }; + }; + return shell_aux; +} +/* ----------------------------------------------- * + * Poor but enough.. + * TODO: Redirection capture. "" evaluate, ... C&S welcome. + * ----------------------------------------------- */ +int shell_make_args(char * cmd, + int * pargc, + char * argv[]) { + int argc=0; + while ((cmd=strtok(cmd," \t\r\n"))!=NULL) { + argv[argc++]=cmd; + cmd=(char*)NULL; + }; + argv[argc]=(char*)NULL; + return *pargc=argc; +} +/* ----------------------------------------------- * + * show the help for one command. + * ----------------------------------------------- */ +int shell_help_cmd(shell_cmd_t * shell_cmd) { + char * pc; + int col,line; + printf("%-10.10s -",shell_cmd->name); + col=12; + line=1; + if (shell_cmd->alias) { + printf("is an for command '%s'",shell_cmd->alias->name); + } else + if (shell_cmd->usage) { + pc=shell_cmd->usage; + while (*pc) { + switch(*pc) { + case '\r':break; + case '\n':putchar('\n'); + col=0; + break; + default :putchar(*pc); + col++; + break; + }; + pc++; + if(col>78) { /* What daring... 78?*/ + if (*pc) { + putchar('\n'); + col=0; + }; + }; + if (!col && *pc) { + printf(" "); + col=12;line++; + }; + }; + }; + puts(""); + return line; +} +/* ----------------------------------------------- * + * show the help. The first command implemented. + * Can you see the header of routine? Known? + * The same with all the commands.... + * ----------------------------------------------- */ +int shell_help(int argc,char * argv[]) { + int col,line,arg; + shell_topic_t *topic; + shell_cmd_t * shell_cmd=shell_first_cmd; + if (argc<2) { + printf("help: TOPIC? The topics are\n"); + topic=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;arg16) { + printf("Press any key to continue...");getchar(); + printf("\n"); + line=0; + }; + topic=shell_lookup_topic(argv[arg]); + if (!topic){ + if ((shell_cmd=shell_lookup_cmd(argv[arg]))==NULL) { + printf("help: topic or cmd '%s' not found. Try alone for a list\n",argv[arg]); + line++; + } else { + line+=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+=shell_help_cmd(shell_cmd); + if (line>16) { + printf("Press any key to continue...");getchar(); + printf("\n"); + line=0; + }; + shell_cmd=shell_cmd->next; + }; + }; + puts(""); + return 0; +} +/* ----------------------------------------------- * + * TODO:Change to bash readline() better. + * ----------------------------------------------- */ +int shell_scanline(char * line,int size,FILE * in,FILE * out) { + int c,col; + col=0; + for (;;) { + line[col]=0; + c=fgetc(in); + switch (c) { + case EOF :return 0; + case '\r':if (out) fputc('\n',out); + return 1; + case '\b':if (col) { + if (out) { + fputc('\b',out); + fputc(' ',out); + fputc('\b',out); + }; + col--; + } else { + if (out) fputc('\a',out); + }; + break; + default :if (!iscntrl(c)) { + if (coldevname; + + stdin =fopen(devname,"r+"); + + if (!stdin) { + fprintf(stderr,"shell:unable to open stdin.%s:%s\n",devname,strerror(errno)); + printk("shell:unable to open stdin.(%s)",strerror(errno)); + rtems_task_delete(RTEMS_SELF); + }; + setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/ + /* make a raw terminal,Linux MANuals */ + if (tcgetattr (fileno(stdin), &term)>=0) { + term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + term.c_oflag &= ~OPOST; + term.c_oflag |= (OPOST|ONLCR); + term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + term.c_cflag = CLOCAL | CREAD |(shell_env->tcflag); + 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",devname); + }; + stdout=fopen(devname,"r+"); + if (!stdout) { + fprintf(stderr,"shell:unable to open stdout.%s:%s\n",devname,strerror(errno)); + }; + stderr=fopen(devname,"r+"); + if (!stderr) { + printf("shell:unable to open stderr.%s:%s\n",devname,strerror(errno)); + }; + /* when the future user environment runs ok + * a freopen() reopens the terminals. Now this don't work + * (sorry but you can't use because FILENO_STDIN!=0. Better fileno(stdin)) + */ + }; + shell_add_cmd(NULL,NULL,NULL,NULL); /* init the chain list*/ + strcpy(cmd,""); + printf("\n" + "RTEMS-SHELL:%s. "__DATE__". 'help' to list commands.\n",devname); + curdir=malloc(1024); + chdir("/"); + for (;;) { + /* Prompt section */ + /* XXX: show_prompt user adjustable */ + getcwd(curdir,1024); + printf("%s [%s] # ",devname,curdir); + /* getcmd section */ + if (!shell_scanline(cmd,sizeof(cmd),stdin,stdout)) { + printf("shell:unable scanline(%s)\n",devname); + break; + }; + /* evaluate cmd section */ + if (!strcmp(cmd,"r")) { /* repeat last command, forced, not automatic */ + strcpy(cmd,last_cmd); + } else + if (strcmp(cmd,"")) { /* only for get a new prompt */ + strcpy(last_cmd,cmd); + }; + /* 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. + */ + if (shell_make_args(cmd,&argc,argv)) { + if ((shell_cmd=shell_lookup_cmd(argv[0]))!=NULL) { + current_shell_env->errorlevel=shell_cmd->command(argc,argv); + } else { + printf("shell:%s command not found\n",argv[0]); + current_shell_env->errorlevel=-1; + }; + }; + /* end exec cmd section */ + }; + free(curdir); + rtems_task_delete(RTEMS_SELF); +} +/* ----------------------------------------------- */ +rtems_status_code shell_init (char * task_name, + rtems_unsigned32 task_stacksize, + rtems_task_priority task_priority, + char * devname, + tcflag_t tcflag) { + rtems_id task_id; + rtems_status_code sc; + shell_env_t * shell_env; + sc=rtems_task_create(new_rtems_name(task_name), + task_priority, + task_stacksize?task_stacksize:RTEMS_MINIMUM_STACK_SIZE, + (RTEMS_DEFAULT_MODES&~RTEMS_ASR_MASK)|RTEMS_ASR, + RTEMS_DEFAULT_ATTRIBUTES, + &task_id); + if (sc!=RTEMS_SUCCESSFUL) { + rtems_error(sc,"creating task %s in shell_init()",task_name); + return sc; + }; + shell_env=malloc(sizeof(shell_env_t)); + if (!shell_env) { + rtems_task_delete(task_id); + sc=RTEMS_NO_MEMORY; + rtems_error(sc,"allocating shell_env %s in shell_init()",task_name); + return sc; + }; + if (global_shell_env.magic!=new_rtems_name("SENV")) { + global_shell_env.magic =new_rtems_name("SENV"); + global_shell_env.devname ="/dev/console"; + global_shell_env.taskname="GLOBAL"; + global_shell_env.tcflag =0; + }; + shell_env->magic =global_shell_env.magic; + shell_env->devname =devname; + shell_env->taskname=task_name; + shell_env->tcflag =tcflag; + return rtems_task_start(task_id,shell_shell,(rtems_task_argument) shell_env); +} +/* ----------------------------------------------- */ + diff --git a/c/src/libmisc/shell/shell.h b/c/src/libmisc/shell/shell.h new file mode 100644 index 0000000000..89c70506c4 --- /dev/null +++ b/c/src/libmisc/shell/shell.h @@ -0,0 +1,72 @@ +/* + * $Id$ + */ + +#ifndef __SHELL_H__ +#define __SHELL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef int (*shell_command_t)(int argc,char * argv[]); + +struct shell_cmd_tt ; +typedef struct shell_cmd_tt shell_cmd_t; + +struct shell_cmd_tt { + char * name; + char * usage; + char * topic; + shell_command_t command; + shell_cmd_t * alias; + shell_cmd_t * next; +}; + +rtems_unsigned32 new_rtems_name(char * rtems_name); +shell_cmd_t * shell_lookup_cmd(char * cmd); +shell_cmd_t * shell_add_cmd(char * cmd, + char * topic, + char * usage, + shell_command_t command); +shell_cmd_t * shell_alias_cmd(char * cmd, char * alias); + +int shell_make_args(char * cmd, + int * pargc, + char * argv[]); + +typedef struct { + rtems_name magic; /* 'S','E','N','V': Shell Environment */ + char * devname; + char * taskname; + tcflag_t tcflag; + /* user extensions */ + int errorlevel; + int mdump_adr; +} shell_env_t; + +int shell_scanline(char * line,int size,FILE * in,FILE * out) ; + +rtems_status_code shell_init(char * task_name , + rtems_unsigned32 task_stacksize,/*0 default*/ + rtems_task_priority task_priority , + char * devname , + tcflag_t tcflag ); + +extern shell_env_t global_shell_env, + * current_shell_env; +/*--------*/ +/* cmds.c */ +/*--------*/ +int str2int(char * s); +void register_cmds(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/libmisc/wrapup/Makefile.am b/c/src/libmisc/wrapup/Makefile.am index 50ca35b059..ed6b42b9fc 100644 --- a/c/src/libmisc/wrapup/Makefile.am +++ b/c/src/libmisc/wrapup/Makefile.am @@ -14,6 +14,7 @@ include $(top_srcdir)/../../../automake/lib.am TMP_LIBS = ../monitor/$(ARCH)/libmonitor-tmp.a \ ../untar/$(ARCH)/libuntar-tmp.a ../stackchk/$(ARCH)/libstackchk-tmp.a \ ../cpuuse/$(ARCH)/libcpuuse-tmp.a ../rtmonuse/$(ARCH)/librtmonuse-tmp.a \ + ../shell/$(ARCH)/libshell-tmp.a \ ../dumpbuf/$(ARCH)/libdumpbuf-tmp.a ../devnull/$(ARCH)/libdevnull-tmp.a \ ../mw-fb/$(ARCH)/libmw-fb-tmp.a -- cgit v1.2.3