forked from Imagelibrary/rtems
2001-04-20 Correo Fernando-ruiz <correo@fernando-ruiz.com>
* 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.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2001-04-20 Correo Fernando-ruiz <correo@fernando-ruiz.com>
|
||||
|
||||
* 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 <joel@OARcorp.com>
|
||||
|
||||
* devnull/devnull.c (null_initialize): Added check to
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
2
c/src/libmisc/shell/.cvsignore
Normal file
2
c/src/libmisc/shell/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
44
c/src/libmisc/shell/Makefile.am
Normal file
44
c/src/libmisc/shell/Makefile.am
Normal file
@@ -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
|
||||
28
c/src/libmisc/shell/README
Normal file
28
c/src/libmisc/shell/README
Normal file
@@ -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)
|
||||
479
c/src/libmisc/shell/cmds.c
Normal file
479
c/src/libmisc/shell/cmds.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
#include <rtems/score/tod.h>
|
||||
|
||||
#include <imfs.h>
|
||||
#include <rtems/shell.h>
|
||||
|
||||
/* ----------------------------------------------- *
|
||||
- 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;m<max;m++) {
|
||||
printf("0x%08X ",adr);
|
||||
pb=(unsigned char*) adr;
|
||||
for (n=0;n<16;n++)
|
||||
printf("%02X%c",pb[n],n==7?'-':' ');
|
||||
for (n=0;n<16;n++) {
|
||||
printf("%c",isprint(pb[n])?pb[n]:'.');
|
||||
};
|
||||
printf("\n");
|
||||
adr+=16;
|
||||
};
|
||||
mdump_adr=adr;
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int main_mwdump(int argc,char * argv[]) {
|
||||
unsigned char n,m,max=0;
|
||||
int adr=mdump_adr;
|
||||
unsigned short * pw;
|
||||
if (argc>1) adr=str2int(argv[1]);
|
||||
if (argc>2) max=str2int(argv[2]);
|
||||
max/=16;
|
||||
if (!max) max=20;
|
||||
for (m=0;m<max;m++) {
|
||||
printf("0x%08X ",adr);
|
||||
pw=(unsigned short*) adr;
|
||||
for (n=0;n<8;n++)
|
||||
printf("%02X %02X%c",pw[n]/0x100,pw[n]%0x100,n==3?'-':' ');
|
||||
for (n=0;n<8;n++) {
|
||||
printf("%c",isprint(pw[n]/0x100)?pw[n]/0x100:'.');
|
||||
printf("%c",isprint(pw[n]%0x100)?pw[n]%0x100:'.');
|
||||
};
|
||||
printf("\n");
|
||||
adr+=16;
|
||||
};
|
||||
mdump_adr=adr;
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int main_medit(int argc,char * argv[]) {
|
||||
unsigned char * pb;
|
||||
int n,i;
|
||||
if (argc<3) {
|
||||
printf("too few arguments\n");
|
||||
return 0;
|
||||
};
|
||||
pb=(unsigned char*)str2int(argv[1]);
|
||||
i=2;
|
||||
n=0;
|
||||
while (i<=argc) {
|
||||
pb[n++]=str2int(argv[i++])%0x100;
|
||||
}
|
||||
mdump_adr=(int)pb;
|
||||
return main_mdump(0,NULL);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int main_mfill(int argc,char * argv[]) {
|
||||
int adr;
|
||||
int size;
|
||||
unsigned char value;
|
||||
if (argc<4) {
|
||||
printf("too few arguments\n");
|
||||
return 0;
|
||||
};
|
||||
adr =str2int(argv[1]);
|
||||
size =str2int(argv[2]);
|
||||
value=str2int(argv[3])%0x100;
|
||||
memset((unsigned char*)adr,size,value);
|
||||
mdump_adr=adr;
|
||||
return main_mdump(0,NULL);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int main_mmove(int argc,char * argv[]) {
|
||||
int src;
|
||||
int dst;
|
||||
int size;
|
||||
if (argc<4) {
|
||||
printf("too few arguments\n");
|
||||
return 0;
|
||||
};
|
||||
dst =str2int(argv[1]);
|
||||
src =str2int(argv[2]);
|
||||
size =str2int(argv[3]);
|
||||
memcpy((unsigned char*)dst,(unsigned char*)src,size);
|
||||
mdump_adr=dst;
|
||||
return main_mdump(0,NULL);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#ifdef MALLOC_STATS /* /rtems/s/src/lib/libc/malloc.c */
|
||||
int main_malloc_dump(int argc,char * argv[]) {
|
||||
void malloc_dump(void);
|
||||
malloc_dump();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------
|
||||
* Reset. Assumes that the watchdog is present.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int main_reset (int argc, char **argv)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
printf ("Waiting for watchdog ... ");
|
||||
tcdrain(fileno(stdout));
|
||||
|
||||
rtems_interrupt_disable (level);
|
||||
for (;;)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------
|
||||
* Alias. make an alias
|
||||
*----------------------------------------------------------------------------*/
|
||||
int main_alias (int argc, char **argv)
|
||||
{
|
||||
if (argc<3) {
|
||||
printf("too few arguments\n");
|
||||
return 1;
|
||||
};
|
||||
if (!shell_alias_cmd(argv[1],argv[2])) {
|
||||
printf("unable to make an alias(%s,%s)\n",argv[1],argv[2]);
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*
|
||||
* Directory commands
|
||||
*-----------------------------------------------------------*/
|
||||
int main_ls(int argc, char *argv[])
|
||||
{
|
||||
char * fname;
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
struct stat stat_buf;
|
||||
char sbuf[256];
|
||||
char nbuf[1024];
|
||||
int n,size;
|
||||
|
||||
fname=".";
|
||||
if (argc>1) 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.year<TOD_BASE_YEAR) tod.year+=100;
|
||||
if (!conv(&tod.day ,&tp, 31)) return 0;
|
||||
if (!conv(&tod.month ,&tp, 12)) return 0;
|
||||
}
|
||||
if (!_TOD_Validate(&tod)) {
|
||||
fprintf(stderr, "Invalid date value\n");
|
||||
} else {
|
||||
rtems_clock_set(&tod);
|
||||
rtems_clock_get(RTEMS_CLOCK_GET_TOD,&tod);
|
||||
rtc=fopen("/dev/rtc","r+");
|
||||
if (rtc) {
|
||||
fwrite(&tod,sizeof(tod),1,rtc);
|
||||
fclose(rtc);
|
||||
};
|
||||
};
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main_date(int argc,char *argv[])
|
||||
{
|
||||
time_t t;
|
||||
if (argc == 2) set_time(argv[1]);
|
||||
time(&t);
|
||||
printf("%s", ctime(&t));
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*
|
||||
* with this you can call at all the rtems monitor commands.
|
||||
* Not all work fine but you can show the rtems status and more.
|
||||
*-----------------------------------------------------------*/
|
||||
int main_monitor(int argc,char * argv[]) {
|
||||
rtems_monitor_command_entry_t *command;
|
||||
extern rtems_monitor_command_entry_t rtems_monitor_commands[];
|
||||
rtems_task_ident(RTEMS_SELF,0,&rtems_monitor_task_id);
|
||||
rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
|
||||
rtems_monitor_default_node = rtems_monitor_node;
|
||||
if ((command=rtems_monitor_command_lookup(rtems_monitor_commands,argc,argv)))
|
||||
command->command_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;
|
||||
};
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
470
c/src/libmisc/shell/shell.c
Normal file
470
c/src/libmisc/shell/shell.c
Normal file
@@ -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 <stdio.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/shell.h>
|
||||
/* ----------------------------------------------- *
|
||||
* 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 <alias> 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;arg<argc;arg++) {
|
||||
if (line>16) {
|
||||
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 <help> 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 (col<size-1) {
|
||||
line[col++]=c;
|
||||
if (out) fputc(c,out);
|
||||
} else {
|
||||
if (out) fputc('\a',out);
|
||||
};
|
||||
} else {
|
||||
if (out) fputc('\a',out);
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
}
|
||||
/* ----------------------------------------------- *
|
||||
* - The shell TASK
|
||||
* Poor but enough..
|
||||
* TODO: Redirection. Tty Signals. ENVVARs. Shell language.
|
||||
* ----------------------------------------------- */
|
||||
shell_env_t global_shell_env ,
|
||||
* current_shell_env=&global_shell_env;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
rtems_task shell_shell(rtems_task_argument task_argument) {
|
||||
|
||||
shell_env_t * shell_env =(shell_env_t*) task_argument;
|
||||
shell_cmd_t * shell_cmd;
|
||||
|
||||
rtems_status_code sc;
|
||||
|
||||
struct termios term;
|
||||
char * devname;
|
||||
char * curdir;
|
||||
|
||||
char cmd[256];
|
||||
char last_cmd[256]; /* to repeat 'r' */
|
||||
int argc;
|
||||
char * argv[128];
|
||||
|
||||
sc=rtems_libio_set_private_env();
|
||||
if (sc!=RTEMS_SUCCESSFUL) {
|
||||
rtems_error(sc,"rtems_libio_set_private_env():");
|
||||
printk("rtems_libio_set_private_env():%d",sc);
|
||||
rtems_task_delete(RTEMS_SELF);
|
||||
};
|
||||
|
||||
sc=rtems_task_variable_add(RTEMS_SELF,(void*)¤t_shell_env,free);
|
||||
if (sc!=RTEMS_SUCCESSFUL) {
|
||||
rtems_error(sc,"rtems_task_variable_add():");
|
||||
printk("rtems_task_variable_add():%d",sc);
|
||||
rtems_task_delete(RTEMS_SELF);
|
||||
};
|
||||
|
||||
current_shell_env=shell_env; /* Set the task var */
|
||||
|
||||
devname=shell_env->devname;
|
||||
|
||||
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);
|
||||
}
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
72
c/src/libmisc/shell/shell.h
Normal file
72
c/src/libmisc/shell/shell.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __SHELL_H__
|
||||
#define __SHELL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
|
||||
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
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user