summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2001-05-24 21:58:39 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2001-05-24 21:58:39 +0000
commitb2712e35b948d7ab37cf6ef46bcdfea678506444 (patch)
treee7575dbae5f5861131ac9cf03cdea1bfc7447269
parent2000-05-24 Fernando Ruiz Casas <fernando.ruiz@ctv.es> (diff)
downloadrtems-b2712e35b948d7ab37cf6ef46bcdfea678506444.tar.bz2
2000-05-24 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
* monitor/mon-prmisc.c: Correct print line. * shell/Makefile.am: Added new file telnetd.c. * shell/telnetd.c, shell/telnetd.h, shell/pty.c: New files. * shell/shell.c, shell/cmds.c, shell/shell.h: Numerous improvments: - The shell_init has a new parameter 'forever' because in /dev/console you need that this process runs forever but in tcp/ip not. (respawn?) - A new task for every session opened trought tcp/ip telnet client. (the chargen,daytime and more are possible of implementation but I ask me if they are necesary) - Exit from the session delete the task and when the client fails too. - More cmds have been implemented. (very reduced version of these) umask, chmod, id, whoami, rm, cat, ... - A reduced line edit has been implemented. Ctrl-C abort the input, Ctrl-d in the first position gives EOF (logout). '\b' and DEL makes the rubout operation. I think that readline() for every session spents a lot of resources.
-rw-r--r--c/src/libmisc/ChangeLog21
-rw-r--r--c/src/libmisc/monitor/mon-prmisc.c4
-rw-r--r--c/src/libmisc/shell/Makefile.am6
-rw-r--r--c/src/libmisc/shell/README8
-rw-r--r--c/src/libmisc/shell/cmds.c123
-rw-r--r--c/src/libmisc/shell/pty.c406
-rw-r--r--c/src/libmisc/shell/shell.c242
-rw-r--r--c/src/libmisc/shell/shell.h42
-rw-r--r--c/src/libmisc/shell/telnetd.c107
-rw-r--r--c/src/libmisc/shell/telnetd.h20
-rw-r--r--c/src/libnetworking/rtems_servers/telnetd.c107
-rw-r--r--c/src/libnetworking/rtems_servers/telnetd.h20
-rw-r--r--cpukit/libmisc/ChangeLog21
-rw-r--r--cpukit/libmisc/monitor/mon-prmisc.c4
-rw-r--r--cpukit/libmisc/shell/Makefile.am6
-rw-r--r--cpukit/libmisc/shell/README8
-rw-r--r--cpukit/libmisc/shell/cmds.c123
-rw-r--r--cpukit/libmisc/shell/shell.c242
-rw-r--r--cpukit/libmisc/shell/shell.h42
19 files changed, 1396 insertions, 156 deletions
diff --git a/c/src/libmisc/ChangeLog b/c/src/libmisc/ChangeLog
index 6815f6cdfa..670f2b0ccd 100644
--- a/c/src/libmisc/ChangeLog
+++ b/c/src/libmisc/ChangeLog
@@ -1,3 +1,24 @@
+2000-05-24 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
+
+ * monitor/mon-prmisc.c: Correct print line.
+ * shell/Makefile.am: Added new file telnetd.c.
+ * shell/telnetd.c, shell/telnetd.h, shell/pty.c: New files.
+ * shell/shell.c, shell/cmds.c, shell/shell.h: Numerous improvments:
+ - The shell_init has a new parameter 'forever' because in
+ /dev/console you need that this process runs forever but in
+ tcp/ip not. (respawn?)
+ - A new task for every session opened trought tcp/ip telnet client.
+ (the chargen,daytime and more are possible of implementation but
+ I ask me if they are necesary)
+ - Exit from the session delete the task and when the client fails too.
+ - More cmds have been implemented. (very reduced version of these)
+ umask, chmod, id, whoami, rm, cat, ...
+ - A reduced line edit has been implemented.
+ Ctrl-C abort the input,
+ Ctrl-d in the first position gives EOF (logout).
+ '\b' and DEL makes the rubout operation.
+ I think that readline() for every session spents a lot of resources.
+
2001-04-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* shell/cmds.c, shell/shell.c: Remove fileno-hacks.
diff --git a/c/src/libmisc/monitor/mon-prmisc.c b/c/src/libmisc/monitor/mon-prmisc.c
index ce9aa9a554..5081b16584 100644
--- a/c/src/libmisc/monitor/mon-prmisc.c
+++ b/c/src/libmisc/monitor/mon-prmisc.c
@@ -108,8 +108,8 @@ rtems_monitor_dump_name(rtems_name name)
for (i=0; i<sizeof(u.c); i++)
length += rtems_monitor_dump_char(u.c[i]);
#else
- for (i=sizeof(u.c)-1; i ; i--)
- length += rtems_monitor_dump_char(u.c[i]);
+ for (i=0; i<sizeof(u.c); i++)
+ length += rtems_monitor_dump_char(u.c[sizeof(u.c)-1-i]);
#endif
return length;
}
diff --git a/c/src/libmisc/shell/Makefile.am b/c/src/libmisc/shell/Makefile.am
index 814cf40c44..94e5350c82 100644
--- a/c/src/libmisc/shell/Makefile.am
+++ b/c/src/libmisc/shell/Makefile.am
@@ -9,10 +9,10 @@ include_rtemsdir = $(includedir)/rtems
LIBNAME = libshell-tmp
LIB = $(ARCH)/$(LIBNAME).a
-C_FILES = cmds.c shell.c
+C_FILES = cmds.c shell.c pty.c telnetd.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
-include_rtems_HEADERS = shell.h
+include_rtems_HEADERS = shell.h telnetd.h
OBJS = $(C_O_FILES)
@@ -39,6 +39,6 @@ all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) $(LIB)
.PRECIOUS: $(LIB)
-EXTRA_DIST = README shell.c cmds.c shell.h
+EXTRA_DIST = README shell.c cmds.c pty.c telnetd.c shell.h telnetd.h
include $(top_srcdir)/../../../automake/local.am
diff --git a/c/src/libmisc/shell/README b/c/src/libmisc/shell/README
index 2d38451cc6..d0064d4fde 100644
--- a/c/src/libmisc/shell/README
+++ b/c/src/libmisc/shell/README
@@ -19,10 +19,12 @@ NOTES:
2. You only need a termios dev to start a new session, add your new commands
and enjoy it.
-
+3. If you have tcp/ip inited you can start telnetd daemon.
+ You need register pseudo-terminals driver into device drivers table.
+ 16 ptyX termios device terminales are created into /dev/.
+ Calling rtems_initialize_telnetd() starts the daemon.
+ 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
index c1c670f997..32402aa1e7 100644
--- a/c/src/libmisc/shell/cmds.c
+++ b/c/src/libmisc/shell/cmds.c
@@ -13,7 +13,7 @@
* MINIX date.c is adapted to run here. Like a exercise only....
*
* TODO: A lot of improvements of course.
- * cat, cp, rm, mv, ...
+ * cp, mv, ...
* hexdump,
*
* More? Say me it, please...
@@ -34,6 +34,8 @@
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
#include <errno.h>
#include <sys/types.h>
#include <stddef.h>
@@ -257,6 +259,10 @@ int main_ls(int argc, char *argv[])
DIR *dirp;
struct dirent *dp;
struct stat stat_buf;
+ struct passwd * pwd;
+ struct group * grp;
+ char * user;
+ char * group;
char sbuf[256];
char nbuf[1024];
int n,size;
@@ -279,7 +285,11 @@ int main_ls(int argc, char *argv[])
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",
+ pwd=getpwuid(stat_buf.st_uid);
+ user=pwd?pwd->pw_name:"nouser";
+ grp=getgrgid(stat_buf.st_gid);
+ group=grp?grp->gr_name:"nogrp";
+ printf("%c%c%c%c%c%c%c%c%c%c %3d %6.6s %6.6s %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'):('-'),
@@ -292,6 +302,7 @@ int main_ls(int argc, char *argv[])
(stat_buf.st_mode & S_IWOTH)?('w'):('-'),
(stat_buf.st_mode & S_IXOTH)?('x'):('-'),
(int)stat_buf.st_nlink,
+ user,group,
(int)stat_buf.st_size,
sbuf,
dp->d_name,
@@ -352,6 +363,28 @@ int main_chroot(int argc,char * argv[]) {
return 0;
}
/*-----------------------------------------------------------*/
+int main_cat (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) cat_file(stdout,argv[n++]);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_rm (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) {
+ if (unlink(argv[n])) {
+ printf("error %s:rm %s\n",strerror(errno),argv[n]);
+ return -1;
+ };
+ n++;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
/* date - print or set time and date Author: Jan Looyen */
/* MINIX 1.5 GPL'ed */
@@ -424,6 +457,67 @@ int main_date(int argc,char *argv[])
printf("%s", ctime(&t));
return 0;
}
+/*-----------------------------------------------------------*/
+int main_logoff(int argc,char *argv[])
+{
+ printf("logoff from the system...");
+ current_shell_env->exit_shell=TRUE;
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_tty (int argc,char *argv[])
+{
+ printf("%s\n",ttyname(fileno(stdin)));
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_whoami(int argc,char *argv[])
+{
+ struct passwd * pwd;
+ pwd=getpwuid(getuid());
+ printf("%s\n",pwd?pwd->pw_name:"nobody");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_id (int argc,char *argv[])
+{
+ struct passwd * pwd;
+ struct group * grp;
+ pwd=getpwuid(getuid());
+ grp=getgrgid(getgid());
+ printf("uid=%d(%s),gid=%d(%s),",
+ getuid(),pwd?pwd->pw_name:"",
+ getgid(),grp?grp->gr_name:"");
+ pwd=getpwuid(geteuid());
+ grp=getgrgid(getegid());
+ printf("euid=%d(%s),egid=%d(%s)\n",
+ geteuid(),pwd?pwd->pw_name:"",
+ getegid(),grp?grp->gr_name:"");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_umask(int argc,char *argv[])
+{
+ mode_t msk=umask(0);
+ if (argc == 2) msk=str2int(argv[1]);
+ umask(msk);
+ msk=umask(0);
+ printf("0%o\n",msk);
+ umask(msk);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_chmod(int argc,char *argv[])
+{
+ int n;
+ mode_t mode;
+ if (argc > 2){
+ mode=str2int(argv[1])&0777;
+ n=2;
+ while (n<argc) chmod(argv[n++],mode);
+ };
+ 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.
@@ -442,6 +536,14 @@ int main_monitor(int argc,char * argv[]) {
void register_cmds(void) {
rtems_monitor_command_entry_t *command;
extern rtems_monitor_command_entry_t rtems_monitor_commands[];
+ /* monitor topic */
+ command=rtems_monitor_commands;
+ while (command) {
+ if (strcmp("exit",command->command)) /*Exclude EXIT (alias quit)*/
+ shell_add_cmd(command->command,"monitor",
+ command->usage ,main_monitor);
+ command=command->next;
+ };
/* 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);
@@ -449,14 +551,24 @@ void register_cmds(void) {
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_add_cmd ("cat" ,"dir","cat n1 [n2 [n3...]]# show the ascii contents",main_cat );
+ shell_add_cmd ("rm" ,"dir","rm n1 [n2 [n3...]]# remove files" ,main_rm );
+ shell_add_cmd ("chmod" ,"dir","chmod 0777 n1 n2... #change filemode" ,main_chmod);
shell_alias_cmd("ls" ,"dir");
shell_alias_cmd("chdir" ,"cd");
/* misc. topic */
+ shell_add_cmd ("logoff","misc","logoff from the system" ,main_logoff);
+ shell_alias_cmd("logoff","exit");
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);
+ shell_add_cmd ("tty" ,"misc","show ttyname" ,main_tty );
+ shell_add_cmd ("whoami","misc","show current user" ,main_whoami);
+ shell_add_cmd ("id" ,"misc","show uid,gid,euid,egid" ,main_id );
+ shell_add_cmd ("umask" ,"misc","umask [new_umask]" ,main_umask );
+
/* memory topic */
shell_add_cmd ("mdump","mem" ,"mdump [adr [size]]" ,main_mdump);
@@ -467,12 +579,5 @@ void register_cmds(void) {
#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/pty.c b/c/src/libmisc/shell/pty.c
new file mode 100644
index 0000000000..d6077a566a
--- /dev/null
+++ b/c/src/libmisc/shell/pty.c
@@ -0,0 +1,406 @@
+/*
+ * /dev/ptyXX (A first version for pseudo-terminals)
+ *
+ * Author: Fernando RUIZ CASAS (fernando.ruiz@ctv.es)
+ * May 2001
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+/*-----------------------------------------*/
+#include <termios.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <bsp.h>
+/*-----------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+/*-----------------------------------------*/
+#define IAC_ESC 255
+#define IAC_DONT 254
+#define IAC_DO 253
+#define IAC_WONT 252
+#define IAC_WILL 251
+#define IAC_SB 250
+#define IAC_GA 249
+#define IAC_EL 248
+#define IAC_EC 247
+#define IAC_AYT 246
+#define IAC_AO 245
+#define IAC_IP 244
+#define IAC_BRK 243
+#define IAC_DMARK 242
+#define IAC_NOP 241
+#define IAC_SE 240
+#define IAC_EOR 239
+
+struct pty_tt;
+typedef struct pty_tt pty_t;
+
+struct pty_tt {
+ char *devname;
+ struct rtems_termios_tty *ttyp;
+ tcflag_t c_cflag;
+ int opened;
+ int socket;
+
+ int last_cr;
+ int iac_mode;
+};
+
+#define MAX_PTYS 16
+
+pty_t ptys[MAX_PTYS];
+
+/* This procedure returns the devname for a pty slot free.
+ * If not slot availiable (field socket>=0)
+ * then the socket argument is closed
+ */
+
+char * get_pty(int socket) {
+ int ndx;
+ for (ndx=0;ndx<MAX_PTYS;ndx++) {
+ if (ptys[ndx].socket<0) {
+ ptys[ndx].socket=socket;
+ return ptys[ndx].devname;
+ };
+ };
+ close(socket);
+ return NULL;
+}
+
+
+/*-----------------------------------------------------------*/
+/*
+ * The NVT terminal is negociated in PollRead and PollWrite
+ * with every BYTE sendded or received.
+ * A litle status machine in the pty_read_byte(int minor)
+ *
+ */
+const char IAC_AYT_RSP[]="\r\nAYT? Yes, RTEMS-SHELL is here\r\n";
+const char IAC_BRK_RSP[]="<*Break*>";
+const char IAC_IP_RSP []="<*Interupt*>";
+
+
+static
+int send_iac(int minor,unsigned char mode,unsigned char option) {
+ unsigned char buf[3];
+ buf[0]=IAC_ESC;
+ buf[1]=mode;
+ buf[2]=option;
+ return write(ptys[minor].socket,buf,sizeof(buf));
+}
+
+int read_pty(int minor) { /* Characters writed in the client side*/
+ unsigned char value;
+ int count;
+ int result;
+ count=read(ptys[minor].socket,&value,sizeof(value));
+ if (count<1) {
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ switch(ptys[minor].iac_mode) {
+ case IAC_ESC:
+ ptys[minor].iac_mode=0;
+ switch(value) {
+ case IAC_ESC :
+ return IAC_ESC;
+ case IAC_DONT:
+ case IAC_DO :
+ case IAC_WONT:
+ case IAC_WILL:
+ ptys[minor].iac_mode=value;
+ return -1;
+ case IAC_SB :
+ return -100;
+ case IAC_GA :
+ return -1;
+ case IAC_EL :
+ return 0x03; /* Ctrl-C*/
+ case IAC_EC :
+ return '\b';
+ case IAC_AYT :
+ write(ptys[minor].socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
+ return -1;
+ case IAC_AO :
+ return -1;
+ case IAC_IP :
+ write(ptys[minor].socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
+ return -1;
+ case IAC_BRK :
+ write(ptys[minor].socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
+ return -1;
+ case IAC_DMARK:
+ return -2;
+ case IAC_NOP :
+ return -1;
+ case IAC_SE :
+ return -101;
+ case IAC_EOR :
+ return -102;
+ default :
+ return -1;
+ };
+ break;
+ case IAC_WILL:
+ ptys[minor].iac_mode=0;
+ if (value==34){send_iac(minor,IAC_DONT, 34); /*LINEMODE*/
+ send_iac(minor,IAC_DO , 1);} else /*ECHO */
+ {send_iac(minor,IAC_DONT,value);};
+ return -1;
+ case IAC_DONT:
+ ptys[minor].iac_mode=0;
+ return -1;
+ case IAC_DO :
+ ptys[minor].iac_mode=0;
+ if (value==3) {send_iac(minor,IAC_WILL, 3);} else /* GO AHEAD*/
+ if (value==1) { } else /* ECHO */
+ {send_iac(minor,IAC_WONT,value);};
+ return -1;
+ case IAC_WONT:
+ ptys[minor].iac_mode=0;
+ if (value==1) {send_iac(minor,IAC_WILL, 1);} else /* ECHO */
+ {send_iac(minor,IAC_WONT,value);};
+ return -1;
+ default:
+ ptys[minor].iac_mode=0;
+ if (value==IAC_ESC) {
+ ptys[minor].iac_mode=value;
+ return -1;
+ } else {
+ result=value;
+ if ((value=='\n') && (ptys[minor].last_cr)) result=-1;
+ ptys[minor].last_cr=(value=='\r');
+ return result;
+ };
+ };
+
+}
+
+/*-----------------------------------------------------------*/
+static int ptySetAttributes(int minor,const struct termios *t);
+static int ptyPollInitialize(int major,int minor,void * arg) ;
+static int ptyShutdown(int major,int minor,void * arg) ;
+static int ptyPollWrite(int minor, const char * buf,int len) ;
+static int ptyPollRead(int minor) ;
+const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;
+/*-----------------------------------------------------------*/
+/* Set the 'Hardware' */
+/*-----------------------------------------------------------*/
+static int
+ptySetAttributes(int minor,const struct termios *t) {
+ if (minor<MAX_PTYS) {
+ ptys[minor].c_cflag=t->c_cflag;
+ } else {
+ return -1;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+static int
+ptyPollInitialize(int major,int minor,void * arg) {
+ rtems_libio_open_close_args_t * args = arg;
+ struct termios t;
+ if (minor<MAX_PTYS) {
+ if (ptys[minor].socket<0) return -1;
+ ptys[minor].opened=TRUE;
+ ptys[minor].ttyp=args->iop->data1;
+ t.c_cflag=B9600|CS8;/* termios default */
+ return ptySetAttributes(minor,&t);
+ } else {
+ return -1;
+ };
+}
+/*-----------------------------------------------------------*/
+static int
+ptyShutdown(int major,int minor,void * arg) {
+ if (minor<MAX_PTYS) {
+ ptys[minor].opened=FALSE;
+ if (ptys[minor].socket>=0) close(ptys[minor].socket);
+ ptys[minor].socket=-1;
+ chown(ptys[minor].devname,2,0);
+ } else {
+ return -1;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+/* Write Characters into pty device */
+/*-----------------------------------------------------------*/
+static int
+ptyPollWrite(int minor, const char * buf,int len) {
+ int count;
+ if (minor<MAX_PTYS) {
+ if (ptys[minor].socket<0) return -1;
+ count=write(ptys[minor].socket,buf,len);
+ } else {
+ count=-1;
+ };
+ return count;
+}
+/*-----------------------------------------------------------*/
+static void
+ptyStopRemoteTX(int minor) {
+}
+/*-----------------------------------------------------------*/
+static void
+ptyStartRemoteTX(int minor) {
+}
+/*-----------------------------------------------------------*/
+static int
+ptyPollRead(int minor) {
+ int result;
+ if (minor<MAX_PTYS) {
+ if (ptys[minor].socket<0) return -1;
+ result=read_pty(minor);
+ return result;
+ };
+ return -1;
+}
+/*-----------------------------------------------------------*/
+static const rtems_termios_callbacks pty_poll_callbacks = {
+ ptyPollInitialize, /* FirstOpen*/
+ ptyShutdown, /* LastClose*/
+ ptyPollRead, /* PollRead */
+ ptyPollWrite, /* Write */
+ ptySetAttributes, /* setAttributes */
+ NULL, /* stopRemoteTX */
+ NULL, /* StartRemoteTX */
+ 0 /* outputUsesInterrupts */
+};
+/*-----------------------------------------------------------*/
+const rtems_termios_callbacks * pty_get_termios_handlers(int polled) {
+ return &pty_poll_callbacks;
+}
+/*-----------------------------------------------------------*/
+void init_ptys(void) {
+ int ndx;
+ for (ndx=0;ndx<MAX_PTYS;ndx++) {
+ ptys[ndx].devname=malloc(strlen("/dev/ptyXX")+1);
+ sprintf(ptys[ndx].devname,"/dev/pty%X",ndx);
+ ptys[ndx].ttyp=NULL;
+ ptys[ndx].c_cflag=CS8|B9600;
+ ptys[ndx].socket=-1;
+ ptys[ndx].opened=FALSE;
+
+ };
+}
+
+
+/*-----------------------------------------------------------*/
+/* pty_initialize
+ *
+ * This routine initializes the pty IO driver.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+/*-----------------------------------------------------------*/
+rtems_device_driver pty_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ int ndx;
+ rtems_status_code status ;
+
+ /*
+ * Set up ptys
+ */
+
+ init_ptys();
+
+ /*
+ * Register the devices
+ */
+ for (ndx=0;ndx<MAX_PTYS;ndx++) {
+ status = rtems_io_register_name(ptys[ndx].devname, major, ndx);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ chmod(ptys[ndx].devname,0660);
+ chown(ptys[ndx].devname,2,0);
+ };
+ printk("Device: /dev/pty%X../dev/pty%X (%d)pseudo-terminals registered.\n",0,MAX_PTYS-1,MAX_PTYS);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver pty_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_status_code sc ;
+ sc = rtems_termios_open(major,minor,arg,pty_get_termios_handlers(FALSE));
+ return sc;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver pty_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_close(arg);
+}
+
+/*
+ * read bytes from the pty
+ */
+
+rtems_device_driver pty_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_read(arg);
+}
+
+/*
+ * write bytes to the pty
+ */
+
+rtems_device_driver pty_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_write(arg);
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver pty_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl(arg);
+}
diff --git a/c/src/libmisc/shell/shell.c b/c/src/libmisc/shell/shell.c
index d79fd9d321..2efd1831e0 100644
--- a/c/src/libmisc/shell/shell.c
+++ b/c/src/libmisc/shell/shell.c
@@ -12,6 +12,9 @@
*
* $Id$
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <stdio.h>
@@ -19,6 +22,8 @@
#include <rtems/error.h>
#include <rtems/libio.h>
#include <rtems/libio_.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
#include <termios.h>
#include <string.h>
@@ -26,8 +31,8 @@
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
+#include <pwd.h>
-#include <rtems/shell.h>
/* ----------------------------------------------- *
* This is a stupidity but is cute.
* ----------------------------------------------- */
@@ -275,13 +280,21 @@ int shell_help(int argc,char * argv[]) {
int shell_scanline(char * line,int size,FILE * in,FILE * out) {
int c,col;
col=0;
+ tcdrain(fileno(out));
for (;;) {
line[col]=0;
c=fgetc(in);
switch (c) {
+ case 0x04:/*Control-d*/
+ if (col) break;
case EOF :return 0;
+ case '\n':break;
+ case '\f':if (out) fputc('\f',out);
+ case 0x03:/*Control-C*/
+ line[0]=0;
case '\r':if (out) fputc('\n',out);
return 1;
+ case 127:
case '\b':if (col) {
if (out) {
fputc('\b',out);
@@ -301,7 +314,8 @@ int shell_scanline(char * line,int size,FILE * in,FILE * out) {
if (out) fputc('\a',out);
};
} else {
- if (out) fputc('\a',out);
+ if (out)
+ if (c=='\a') fputc('\a',out);
};
break;
};
@@ -317,6 +331,101 @@ shell_env_t global_shell_env ,
extern char **environ;
+void cat_file(FILE * out,char * name) {
+ FILE * fd;
+ int c;
+ if (out) {
+ fd=fopen(name,"r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) fputc(c,out);
+ fclose(fd);
+ };
+ };
+}
+
+int shell_login(FILE * in,FILE * out) {
+ FILE * fd;
+ int c;
+ time_t t;
+ int times;
+ char name[128];
+ char pass[128];
+ struct passwd * passwd;
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ if (out) {
+ if((current_shell_env->devname[5]!='p')||
+ (current_shell_env->devname[6]!='t')||
+ (current_shell_env->devname[7]!='y')) {
+ cat_file(out,"/etc/issue");
+ } else {
+ fd=fopen("/etc/issue.net","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='%') {
+ switch(c=fgetc(fd)) {
+ case 't':fprintf(out,"%s",current_shell_env->devname);
+ break;
+ case 'h':fprintf(out,"0");
+ break;
+ case 'D':fprintf(out," ");
+ break;
+ case 'd':time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 's':fprintf(out,"RTEMS");
+ break;
+ case 'm':fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
+ break;
+ case 'r':fprintf(out,_RTEMS_version);
+ break;
+ case 'v':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '%':fprintf(out,"%%");
+ break;
+ default :fprintf(out,"%%%c",c);
+ break;
+ };
+ } else {
+ fputc(c,out);
+ };
+ };
+ fclose(fd);
+ }
+ };
+ };
+ times=0;
+ for (;;) {
+ times++;
+ if (times>3) break;
+ if (out) fprintf(out,"\nlogin: ");
+ if (!shell_scanline(name,sizeof(name),in,out )) break;
+ if (out) fprintf(out,"Password: ");
+ if (!shell_scanline(pass,sizeof(pass),in,NULL)) break;
+ if (out) fprintf(out,"\n");
+ if ((passwd=getpwnam(name))) {
+ setuid(passwd->pw_uid);
+ setgid(passwd->pw_gid);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ chown(current_shell_env->devname,passwd->pw_uid,0);
+ rtems_current_user_env->euid=passwd->pw_uid;
+ rtems_current_user_env->egid=passwd->pw_gid;
+ if (!strcmp(passwd->pw_passwd,"*")) {
+ /* /etc/shadow */
+ return 0;
+ } else {
+ /* crypt() */
+ return 0;
+ };
+ };
+ if (out) fprintf(out,"Login incorrect\n");
+ };
+ return -1;
+}
+
rtems_task shell_shell(rtems_task_argument task_argument) {
shell_env_t * shell_env =(shell_env_t*) task_argument;
@@ -326,36 +435,38 @@ rtems_task shell_shell(rtems_task_argument task_argument) {
struct termios term;
char * devname;
- char * curdir;
+ char curdir[256];
char cmd[256];
char last_cmd[256]; /* to repeat 'r' */
int argc;
char * argv[128];
- sc=rtems_libio_set_private_env();
+ sc=rtems_task_variable_add(RTEMS_SELF,(void*)&current_shell_env,free);
if (sc!=RTEMS_SUCCESSFUL) {
- rtems_error(sc,"rtems_libio_set_private_env():");
- printk("rtems_libio_set_private_env():%d",sc);
+ rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
rtems_task_delete(RTEMS_SELF);
};
- sc=rtems_task_variable_add(RTEMS_SELF,(void*)&current_shell_env,free);
+ current_shell_env=shell_env;
+
+ sc=rtems_libio_set_private_env();
if (sc!=RTEMS_SUCCESSFUL) {
- rtems_error(sc,"rtems_task_variable_add():");
- printk("rtems_task_variable_add():%d",sc);
+ rtems_error(sc,"rtems_libio_set_private_env():");
rtems_task_delete(RTEMS_SELF);
};
- current_shell_env=shell_env; /* Set the task var */
devname=shell_env->devname;
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
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*/
@@ -363,7 +474,7 @@ rtems_task shell_shell(rtems_task_argument task_argument) {
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_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
term.c_cflag = CLOCAL | CREAD |(shell_env->tcflag);
term.c_cc[VMIN] = 1;
@@ -385,46 +496,53 @@ rtems_task shell_shell(rtems_task_argument task_argument) {
*/
};
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;
+ do {
+ if (!shell_login(stdin,stdout)) {
+ cat_file(stdout,"/etc/motd");
+ strcpy(last_cmd,"");
+ strcpy(cmd,"");
+ printf("\n"
+ "RTEMS SHELL (Version 1.0-FRC):%s. "__DATE__". 'help' to list commands.\n",devname);
+ chdir("/");
+ shell_env->exit_shell=FALSE;
+ for (;;) {
+ /* Prompt section */
+ /* XXX: show_prompt user adjustable */
+ getcwd(curdir,sizeof(curdir));
+ printf("%s [%s] %c ",shell_env->taskname,curdir,geteuid()?'$':'#');
+ /* getcmd section */
+ if (!shell_scanline(cmd,sizeof(cmd),stdin,stdout)) break; /*EOF*/
+ /* 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) {
+ shell_env->errorlevel=shell_cmd->command(argc,argv);
+ } else {
+ printf("shell:%s command not found\n",argv[0]);
+ shell_env->errorlevel=-1;
+ };
};
+ /* end exec cmd section */
+ if (shell_env->exit_shell) break;
};
- /* end exec cmd section */
+ printf("\nGoodbye from RTEMS SHELL :-(\n");
};
- free(curdir);
+ } while (shell_env->forever);
+ fclose(stdin );
+ fclose(stdout);
+ fclose(stderr);
rtems_task_delete(RTEMS_SELF);
}
/* ----------------------------------------------- */
@@ -432,14 +550,15 @@ rtems_status_code shell_init (char * task_name,
rtems_unsigned32 task_stacksize,
rtems_task_priority task_priority,
char * devname,
- tcflag_t tcflag) {
+ tcflag_t tcflag,
+ int forever) {
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_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&task_id);
if (sc!=RTEMS_SUCCESSFUL) {
@@ -454,16 +573,19 @@ rtems_status_code shell_init (char * 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;
+ global_shell_env.magic =new_rtems_name("SENV");
+ global_shell_env.devname ="/dev/console";
+ global_shell_env.taskname ="GLOBAL";
+ global_shell_env.tcflag =0;
+ global_shell_env.exit_shell=0;
+ global_shell_env.forever =TRUE;
};
- shell_env->magic =global_shell_env.magic;
- shell_env->devname =devname;
- shell_env->taskname=task_name;
- shell_env->tcflag =tcflag;
+ shell_env->magic =global_shell_env.magic;
+ shell_env->devname =devname;
+ shell_env->taskname =task_name;
+ shell_env->tcflag =tcflag;
+ shell_env->exit_shell=FALSE;
+ shell_env->forever =forever;
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
index 89c70506c4..3b9522f10a 100644
--- a/c/src/libmisc/shell/shell.h
+++ b/c/src/libmisc/shell/shell.h
@@ -45,21 +45,61 @@ typedef struct {
char * taskname;
tcflag_t tcflag;
/* user extensions */
+ int exit_shell; /* logout */
+ int forever ; /* repeat login */
int errorlevel;
int mdump_adr;
} shell_env_t;
int shell_scanline(char * line,int size,FILE * in,FILE * out) ;
+void cat_file(FILE * out,char *name);
rtems_status_code shell_init(char * task_name ,
rtems_unsigned32 task_stacksize,/*0 default*/
rtems_task_priority task_priority ,
char * devname ,
- tcflag_t tcflag );
+ tcflag_t tcflag ,
+ int forever );
extern shell_env_t global_shell_env,
* current_shell_env;
/*--------*/
+/* pty.c */
+/*--------*/
+
+char * get_pty(int socket);
+
+
+rtems_device_driver pty_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+rtems_device_driver pty_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+
+
+#define PTY_DRIVER_TABLE_ENTRY \
+ { pty_initialize , pty_open , pty_close , \
+ pty_read , pty_write , pty_control }
+/*--------*/
/* cmds.c */
/*--------*/
int str2int(char * s);
diff --git a/c/src/libmisc/shell/telnetd.c b/c/src/libmisc/shell/telnetd.c
new file mode 100644
index 0000000000..6a643f7d25
--- /dev/null
+++ b/c/src/libmisc/shell/telnetd.c
@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/shell.h>
+#include <rtems/telnetd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+/***********************************************************/
+rtems_id telnetd_task_id =0;
+rtems_unsigned32 telnetd_stack_size =16384;
+rtems_task_priority telnetd_task_priority=100;
+/***********************************************************/
+rtems_task rtems_task_telnetd(rtems_task_argument task_argument) {
+ int des_socket,
+ acp_socket;
+ struct sockaddr_in srv;
+ char * devname;
+ int i=1;
+ int size_adr;
+ if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
+ perror("socket");
+ rtems_task_delete(RTEMS_SELF);
+ };
+ setsockopt(des_socket,SOL_SOCKET,0,&i,sizeof(i));
+ memset(&srv,0,sizeof(srv));
+ srv.sin_family=AF_INET;
+ srv.sin_port=htons(23);
+ size_adr=sizeof(srv);
+ if ((bind(des_socket,(struct sockaddr *)&srv,size_adr))<0) {
+ perror("bind");
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ if ((listen(des_socket,5))<0) {
+ perror("listen");
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ do {
+ acp_socket=accept(des_socket,(struct sockaddr*)&srv,&size_adr);
+ if (acp_socket<0) {
+ perror("accept");
+ break;
+ };
+ if (devname = get_pty(acp_socket) ) {
+ shell_init(&devname[5],
+ telnetd_stack_size,
+ telnetd_task_priority,
+ devname,B9600|CS8,FALSE);
+ } else {
+ close(acp_socket);
+ };
+ } while(1);
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+}
+/***********************************************************/
+int rtems_initialize_telnetd(void) {
+ rtems_status_code sc;
+ if (telnetd_task_id ) return RTEMS_RESOURCE_IN_USE;
+ if (telnetd_stack_size<=0 ) telnetd_stack_size =16384;
+ if (telnetd_task_priority<=2) telnetd_task_priority=100;
+ sc=rtems_task_create(new_rtems_name("TLND"),
+ 100,RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &telnetd_task_id);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"creating task telnetd");
+ return (int)sc;
+ };
+ sc=rtems_task_start(telnetd_task_id,
+ rtems_task_telnetd,
+ (rtems_task_argument)NULL);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"starting task telnetd");
+ };
+ return (int)sc;
+}
+/***********************************************************/
+int main_telnetd(int argc,char * argv[]) {
+ rtems_status_code sc;
+ if (telnetd_task_id) {
+ printf("ERROR:telnetd already started\n");
+ return 1;
+ };
+ if (argc>1) telnetd_stack_size =str2int(argv[1]);
+ if (argc>2) telnetd_task_priority=str2int(argv[2]);
+ sc=rtems_initialize_telnetd();
+ if (sc!=RTEMS_SUCCESSFUL) return sc;
+ printf("rtems_telnetd() started with stacksize=%u,priority=%d\n",
+ telnetd_stack_size,telnetd_task_priority);
+ return 0;
+}
+/***********************************************************/
+int register_telnetd(void) {
+ shell_add_cmd("telnetd","telnet","telnetd [stacksize [tsk_priority]]",main_telnetd);
+ return 0;
+}
+/***********************************************************/
diff --git a/c/src/libmisc/shell/telnetd.h b/c/src/libmisc/shell/telnetd.h
new file mode 100644
index 0000000000..fa710151bf
--- /dev/null
+++ b/c/src/libmisc/shell/telnetd.h
@@ -0,0 +1,20 @@
+/*
+ * $Id$
+ */
+
+#ifndef __TELNETD_H
+#define __TELNETD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int rtems_initialize_telnetd(void);
+int main_telnetd(int argc,char * argv[]);
+int register_telnetd(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/c/src/libnetworking/rtems_servers/telnetd.c b/c/src/libnetworking/rtems_servers/telnetd.c
new file mode 100644
index 0000000000..6a643f7d25
--- /dev/null
+++ b/c/src/libnetworking/rtems_servers/telnetd.c
@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/shell.h>
+#include <rtems/telnetd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+/***********************************************************/
+rtems_id telnetd_task_id =0;
+rtems_unsigned32 telnetd_stack_size =16384;
+rtems_task_priority telnetd_task_priority=100;
+/***********************************************************/
+rtems_task rtems_task_telnetd(rtems_task_argument task_argument) {
+ int des_socket,
+ acp_socket;
+ struct sockaddr_in srv;
+ char * devname;
+ int i=1;
+ int size_adr;
+ if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
+ perror("socket");
+ rtems_task_delete(RTEMS_SELF);
+ };
+ setsockopt(des_socket,SOL_SOCKET,0,&i,sizeof(i));
+ memset(&srv,0,sizeof(srv));
+ srv.sin_family=AF_INET;
+ srv.sin_port=htons(23);
+ size_adr=sizeof(srv);
+ if ((bind(des_socket,(struct sockaddr *)&srv,size_adr))<0) {
+ perror("bind");
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ if ((listen(des_socket,5))<0) {
+ perror("listen");
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ do {
+ acp_socket=accept(des_socket,(struct sockaddr*)&srv,&size_adr);
+ if (acp_socket<0) {
+ perror("accept");
+ break;
+ };
+ if (devname = get_pty(acp_socket) ) {
+ shell_init(&devname[5],
+ telnetd_stack_size,
+ telnetd_task_priority,
+ devname,B9600|CS8,FALSE);
+ } else {
+ close(acp_socket);
+ };
+ } while(1);
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+}
+/***********************************************************/
+int rtems_initialize_telnetd(void) {
+ rtems_status_code sc;
+ if (telnetd_task_id ) return RTEMS_RESOURCE_IN_USE;
+ if (telnetd_stack_size<=0 ) telnetd_stack_size =16384;
+ if (telnetd_task_priority<=2) telnetd_task_priority=100;
+ sc=rtems_task_create(new_rtems_name("TLND"),
+ 100,RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &telnetd_task_id);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"creating task telnetd");
+ return (int)sc;
+ };
+ sc=rtems_task_start(telnetd_task_id,
+ rtems_task_telnetd,
+ (rtems_task_argument)NULL);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"starting task telnetd");
+ };
+ return (int)sc;
+}
+/***********************************************************/
+int main_telnetd(int argc,char * argv[]) {
+ rtems_status_code sc;
+ if (telnetd_task_id) {
+ printf("ERROR:telnetd already started\n");
+ return 1;
+ };
+ if (argc>1) telnetd_stack_size =str2int(argv[1]);
+ if (argc>2) telnetd_task_priority=str2int(argv[2]);
+ sc=rtems_initialize_telnetd();
+ if (sc!=RTEMS_SUCCESSFUL) return sc;
+ printf("rtems_telnetd() started with stacksize=%u,priority=%d\n",
+ telnetd_stack_size,telnetd_task_priority);
+ return 0;
+}
+/***********************************************************/
+int register_telnetd(void) {
+ shell_add_cmd("telnetd","telnet","telnetd [stacksize [tsk_priority]]",main_telnetd);
+ return 0;
+}
+/***********************************************************/
diff --git a/c/src/libnetworking/rtems_servers/telnetd.h b/c/src/libnetworking/rtems_servers/telnetd.h
new file mode 100644
index 0000000000..fa710151bf
--- /dev/null
+++ b/c/src/libnetworking/rtems_servers/telnetd.h
@@ -0,0 +1,20 @@
+/*
+ * $Id$
+ */
+
+#ifndef __TELNETD_H
+#define __TELNETD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int rtems_initialize_telnetd(void);
+int main_telnetd(int argc,char * argv[]);
+int register_telnetd(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/ChangeLog b/cpukit/libmisc/ChangeLog
index 6815f6cdfa..670f2b0ccd 100644
--- a/cpukit/libmisc/ChangeLog
+++ b/cpukit/libmisc/ChangeLog
@@ -1,3 +1,24 @@
+2000-05-24 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
+
+ * monitor/mon-prmisc.c: Correct print line.
+ * shell/Makefile.am: Added new file telnetd.c.
+ * shell/telnetd.c, shell/telnetd.h, shell/pty.c: New files.
+ * shell/shell.c, shell/cmds.c, shell/shell.h: Numerous improvments:
+ - The shell_init has a new parameter 'forever' because in
+ /dev/console you need that this process runs forever but in
+ tcp/ip not. (respawn?)
+ - A new task for every session opened trought tcp/ip telnet client.
+ (the chargen,daytime and more are possible of implementation but
+ I ask me if they are necesary)
+ - Exit from the session delete the task and when the client fails too.
+ - More cmds have been implemented. (very reduced version of these)
+ umask, chmod, id, whoami, rm, cat, ...
+ - A reduced line edit has been implemented.
+ Ctrl-C abort the input,
+ Ctrl-d in the first position gives EOF (logout).
+ '\b' and DEL makes the rubout operation.
+ I think that readline() for every session spents a lot of resources.
+
2001-04-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* shell/cmds.c, shell/shell.c: Remove fileno-hacks.
diff --git a/cpukit/libmisc/monitor/mon-prmisc.c b/cpukit/libmisc/monitor/mon-prmisc.c
index ce9aa9a554..5081b16584 100644
--- a/cpukit/libmisc/monitor/mon-prmisc.c
+++ b/cpukit/libmisc/monitor/mon-prmisc.c
@@ -108,8 +108,8 @@ rtems_monitor_dump_name(rtems_name name)
for (i=0; i<sizeof(u.c); i++)
length += rtems_monitor_dump_char(u.c[i]);
#else
- for (i=sizeof(u.c)-1; i ; i--)
- length += rtems_monitor_dump_char(u.c[i]);
+ for (i=0; i<sizeof(u.c); i++)
+ length += rtems_monitor_dump_char(u.c[sizeof(u.c)-1-i]);
#endif
return length;
}
diff --git a/cpukit/libmisc/shell/Makefile.am b/cpukit/libmisc/shell/Makefile.am
index 814cf40c44..94e5350c82 100644
--- a/cpukit/libmisc/shell/Makefile.am
+++ b/cpukit/libmisc/shell/Makefile.am
@@ -9,10 +9,10 @@ include_rtemsdir = $(includedir)/rtems
LIBNAME = libshell-tmp
LIB = $(ARCH)/$(LIBNAME).a
-C_FILES = cmds.c shell.c
+C_FILES = cmds.c shell.c pty.c telnetd.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
-include_rtems_HEADERS = shell.h
+include_rtems_HEADERS = shell.h telnetd.h
OBJS = $(C_O_FILES)
@@ -39,6 +39,6 @@ all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) $(LIB)
.PRECIOUS: $(LIB)
-EXTRA_DIST = README shell.c cmds.c shell.h
+EXTRA_DIST = README shell.c cmds.c pty.c telnetd.c shell.h telnetd.h
include $(top_srcdir)/../../../automake/local.am
diff --git a/cpukit/libmisc/shell/README b/cpukit/libmisc/shell/README
index 2d38451cc6..d0064d4fde 100644
--- a/cpukit/libmisc/shell/README
+++ b/cpukit/libmisc/shell/README
@@ -19,10 +19,12 @@ NOTES:
2. You only need a termios dev to start a new session, add your new commands
and enjoy it.
-
+3. If you have tcp/ip inited you can start telnetd daemon.
+ You need register pseudo-terminals driver into device drivers table.
+ 16 ptyX termios device terminales are created into /dev/.
+ Calling rtems_initialize_telnetd() starts the daemon.
+ 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/cpukit/libmisc/shell/cmds.c b/cpukit/libmisc/shell/cmds.c
index c1c670f997..32402aa1e7 100644
--- a/cpukit/libmisc/shell/cmds.c
+++ b/cpukit/libmisc/shell/cmds.c
@@ -13,7 +13,7 @@
* MINIX date.c is adapted to run here. Like a exercise only....
*
* TODO: A lot of improvements of course.
- * cat, cp, rm, mv, ...
+ * cp, mv, ...
* hexdump,
*
* More? Say me it, please...
@@ -34,6 +34,8 @@
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
#include <errno.h>
#include <sys/types.h>
#include <stddef.h>
@@ -257,6 +259,10 @@ int main_ls(int argc, char *argv[])
DIR *dirp;
struct dirent *dp;
struct stat stat_buf;
+ struct passwd * pwd;
+ struct group * grp;
+ char * user;
+ char * group;
char sbuf[256];
char nbuf[1024];
int n,size;
@@ -279,7 +285,11 @@ int main_ls(int argc, char *argv[])
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",
+ pwd=getpwuid(stat_buf.st_uid);
+ user=pwd?pwd->pw_name:"nouser";
+ grp=getgrgid(stat_buf.st_gid);
+ group=grp?grp->gr_name:"nogrp";
+ printf("%c%c%c%c%c%c%c%c%c%c %3d %6.6s %6.6s %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'):('-'),
@@ -292,6 +302,7 @@ int main_ls(int argc, char *argv[])
(stat_buf.st_mode & S_IWOTH)?('w'):('-'),
(stat_buf.st_mode & S_IXOTH)?('x'):('-'),
(int)stat_buf.st_nlink,
+ user,group,
(int)stat_buf.st_size,
sbuf,
dp->d_name,
@@ -352,6 +363,28 @@ int main_chroot(int argc,char * argv[]) {
return 0;
}
/*-----------------------------------------------------------*/
+int main_cat (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) cat_file(stdout,argv[n++]);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_rm (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) {
+ if (unlink(argv[n])) {
+ printf("error %s:rm %s\n",strerror(errno),argv[n]);
+ return -1;
+ };
+ n++;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
/* date - print or set time and date Author: Jan Looyen */
/* MINIX 1.5 GPL'ed */
@@ -424,6 +457,67 @@ int main_date(int argc,char *argv[])
printf("%s", ctime(&t));
return 0;
}
+/*-----------------------------------------------------------*/
+int main_logoff(int argc,char *argv[])
+{
+ printf("logoff from the system...");
+ current_shell_env->exit_shell=TRUE;
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_tty (int argc,char *argv[])
+{
+ printf("%s\n",ttyname(fileno(stdin)));
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_whoami(int argc,char *argv[])
+{
+ struct passwd * pwd;
+ pwd=getpwuid(getuid());
+ printf("%s\n",pwd?pwd->pw_name:"nobody");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_id (int argc,char *argv[])
+{
+ struct passwd * pwd;
+ struct group * grp;
+ pwd=getpwuid(getuid());
+ grp=getgrgid(getgid());
+ printf("uid=%d(%s),gid=%d(%s),",
+ getuid(),pwd?pwd->pw_name:"",
+ getgid(),grp?grp->gr_name:"");
+ pwd=getpwuid(geteuid());
+ grp=getgrgid(getegid());
+ printf("euid=%d(%s),egid=%d(%s)\n",
+ geteuid(),pwd?pwd->pw_name:"",
+ getegid(),grp?grp->gr_name:"");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_umask(int argc,char *argv[])
+{
+ mode_t msk=umask(0);
+ if (argc == 2) msk=str2int(argv[1]);
+ umask(msk);
+ msk=umask(0);
+ printf("0%o\n",msk);
+ umask(msk);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_chmod(int argc,char *argv[])
+{
+ int n;
+ mode_t mode;
+ if (argc > 2){
+ mode=str2int(argv[1])&0777;
+ n=2;
+ while (n<argc) chmod(argv[n++],mode);
+ };
+ 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.
@@ -442,6 +536,14 @@ int main_monitor(int argc,char * argv[]) {
void register_cmds(void) {
rtems_monitor_command_entry_t *command;
extern rtems_monitor_command_entry_t rtems_monitor_commands[];
+ /* monitor topic */
+ command=rtems_monitor_commands;
+ while (command) {
+ if (strcmp("exit",command->command)) /*Exclude EXIT (alias quit)*/
+ shell_add_cmd(command->command,"monitor",
+ command->usage ,main_monitor);
+ command=command->next;
+ };
/* 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);
@@ -449,14 +551,24 @@ void register_cmds(void) {
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_add_cmd ("cat" ,"dir","cat n1 [n2 [n3...]]# show the ascii contents",main_cat );
+ shell_add_cmd ("rm" ,"dir","rm n1 [n2 [n3...]]# remove files" ,main_rm );
+ shell_add_cmd ("chmod" ,"dir","chmod 0777 n1 n2... #change filemode" ,main_chmod);
shell_alias_cmd("ls" ,"dir");
shell_alias_cmd("chdir" ,"cd");
/* misc. topic */
+ shell_add_cmd ("logoff","misc","logoff from the system" ,main_logoff);
+ shell_alias_cmd("logoff","exit");
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);
+ shell_add_cmd ("tty" ,"misc","show ttyname" ,main_tty );
+ shell_add_cmd ("whoami","misc","show current user" ,main_whoami);
+ shell_add_cmd ("id" ,"misc","show uid,gid,euid,egid" ,main_id );
+ shell_add_cmd ("umask" ,"misc","umask [new_umask]" ,main_umask );
+
/* memory topic */
shell_add_cmd ("mdump","mem" ,"mdump [adr [size]]" ,main_mdump);
@@ -467,12 +579,5 @@ void register_cmds(void) {
#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/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
index d79fd9d321..2efd1831e0 100644
--- a/cpukit/libmisc/shell/shell.c
+++ b/cpukit/libmisc/shell/shell.c
@@ -12,6 +12,9 @@
*
* $Id$
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <stdio.h>
@@ -19,6 +22,8 @@
#include <rtems/error.h>
#include <rtems/libio.h>
#include <rtems/libio_.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
#include <termios.h>
#include <string.h>
@@ -26,8 +31,8 @@
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
+#include <pwd.h>
-#include <rtems/shell.h>
/* ----------------------------------------------- *
* This is a stupidity but is cute.
* ----------------------------------------------- */
@@ -275,13 +280,21 @@ int shell_help(int argc,char * argv[]) {
int shell_scanline(char * line,int size,FILE * in,FILE * out) {
int c,col;
col=0;
+ tcdrain(fileno(out));
for (;;) {
line[col]=0;
c=fgetc(in);
switch (c) {
+ case 0x04:/*Control-d*/
+ if (col) break;
case EOF :return 0;
+ case '\n':break;
+ case '\f':if (out) fputc('\f',out);
+ case 0x03:/*Control-C*/
+ line[0]=0;
case '\r':if (out) fputc('\n',out);
return 1;
+ case 127:
case '\b':if (col) {
if (out) {
fputc('\b',out);
@@ -301,7 +314,8 @@ int shell_scanline(char * line,int size,FILE * in,FILE * out) {
if (out) fputc('\a',out);
};
} else {
- if (out) fputc('\a',out);
+ if (out)
+ if (c=='\a') fputc('\a',out);
};
break;
};
@@ -317,6 +331,101 @@ shell_env_t global_shell_env ,
extern char **environ;
+void cat_file(FILE * out,char * name) {
+ FILE * fd;
+ int c;
+ if (out) {
+ fd=fopen(name,"r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) fputc(c,out);
+ fclose(fd);
+ };
+ };
+}
+
+int shell_login(FILE * in,FILE * out) {
+ FILE * fd;
+ int c;
+ time_t t;
+ int times;
+ char name[128];
+ char pass[128];
+ struct passwd * passwd;
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ if (out) {
+ if((current_shell_env->devname[5]!='p')||
+ (current_shell_env->devname[6]!='t')||
+ (current_shell_env->devname[7]!='y')) {
+ cat_file(out,"/etc/issue");
+ } else {
+ fd=fopen("/etc/issue.net","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='%') {
+ switch(c=fgetc(fd)) {
+ case 't':fprintf(out,"%s",current_shell_env->devname);
+ break;
+ case 'h':fprintf(out,"0");
+ break;
+ case 'D':fprintf(out," ");
+ break;
+ case 'd':time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 's':fprintf(out,"RTEMS");
+ break;
+ case 'm':fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
+ break;
+ case 'r':fprintf(out,_RTEMS_version);
+ break;
+ case 'v':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '%':fprintf(out,"%%");
+ break;
+ default :fprintf(out,"%%%c",c);
+ break;
+ };
+ } else {
+ fputc(c,out);
+ };
+ };
+ fclose(fd);
+ }
+ };
+ };
+ times=0;
+ for (;;) {
+ times++;
+ if (times>3) break;
+ if (out) fprintf(out,"\nlogin: ");
+ if (!shell_scanline(name,sizeof(name),in,out )) break;
+ if (out) fprintf(out,"Password: ");
+ if (!shell_scanline(pass,sizeof(pass),in,NULL)) break;
+ if (out) fprintf(out,"\n");
+ if ((passwd=getpwnam(name))) {
+ setuid(passwd->pw_uid);
+ setgid(passwd->pw_gid);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ chown(current_shell_env->devname,passwd->pw_uid,0);
+ rtems_current_user_env->euid=passwd->pw_uid;
+ rtems_current_user_env->egid=passwd->pw_gid;
+ if (!strcmp(passwd->pw_passwd,"*")) {
+ /* /etc/shadow */
+ return 0;
+ } else {
+ /* crypt() */
+ return 0;
+ };
+ };
+ if (out) fprintf(out,"Login incorrect\n");
+ };
+ return -1;
+}
+
rtems_task shell_shell(rtems_task_argument task_argument) {
shell_env_t * shell_env =(shell_env_t*) task_argument;
@@ -326,36 +435,38 @@ rtems_task shell_shell(rtems_task_argument task_argument) {
struct termios term;
char * devname;
- char * curdir;
+ char curdir[256];
char cmd[256];
char last_cmd[256]; /* to repeat 'r' */
int argc;
char * argv[128];
- sc=rtems_libio_set_private_env();
+ sc=rtems_task_variable_add(RTEMS_SELF,(void*)&current_shell_env,free);
if (sc!=RTEMS_SUCCESSFUL) {
- rtems_error(sc,"rtems_libio_set_private_env():");
- printk("rtems_libio_set_private_env():%d",sc);
+ rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
rtems_task_delete(RTEMS_SELF);
};
- sc=rtems_task_variable_add(RTEMS_SELF,(void*)&current_shell_env,free);
+ current_shell_env=shell_env;
+
+ sc=rtems_libio_set_private_env();
if (sc!=RTEMS_SUCCESSFUL) {
- rtems_error(sc,"rtems_task_variable_add():");
- printk("rtems_task_variable_add():%d",sc);
+ rtems_error(sc,"rtems_libio_set_private_env():");
rtems_task_delete(RTEMS_SELF);
};
- current_shell_env=shell_env; /* Set the task var */
devname=shell_env->devname;
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
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*/
@@ -363,7 +474,7 @@ rtems_task shell_shell(rtems_task_argument task_argument) {
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_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
term.c_cflag = CLOCAL | CREAD |(shell_env->tcflag);
term.c_cc[VMIN] = 1;
@@ -385,46 +496,53 @@ rtems_task shell_shell(rtems_task_argument task_argument) {
*/
};
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;
+ do {
+ if (!shell_login(stdin,stdout)) {
+ cat_file(stdout,"/etc/motd");
+ strcpy(last_cmd,"");
+ strcpy(cmd,"");
+ printf("\n"
+ "RTEMS SHELL (Version 1.0-FRC):%s. "__DATE__". 'help' to list commands.\n",devname);
+ chdir("/");
+ shell_env->exit_shell=FALSE;
+ for (;;) {
+ /* Prompt section */
+ /* XXX: show_prompt user adjustable */
+ getcwd(curdir,sizeof(curdir));
+ printf("%s [%s] %c ",shell_env->taskname,curdir,geteuid()?'$':'#');
+ /* getcmd section */
+ if (!shell_scanline(cmd,sizeof(cmd),stdin,stdout)) break; /*EOF*/
+ /* 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) {
+ shell_env->errorlevel=shell_cmd->command(argc,argv);
+ } else {
+ printf("shell:%s command not found\n",argv[0]);
+ shell_env->errorlevel=-1;
+ };
};
+ /* end exec cmd section */
+ if (shell_env->exit_shell) break;
};
- /* end exec cmd section */
+ printf("\nGoodbye from RTEMS SHELL :-(\n");
};
- free(curdir);
+ } while (shell_env->forever);
+ fclose(stdin );
+ fclose(stdout);
+ fclose(stderr);
rtems_task_delete(RTEMS_SELF);
}
/* ----------------------------------------------- */
@@ -432,14 +550,15 @@ rtems_status_code shell_init (char * task_name,
rtems_unsigned32 task_stacksize,
rtems_task_priority task_priority,
char * devname,
- tcflag_t tcflag) {
+ tcflag_t tcflag,
+ int forever) {
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_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&task_id);
if (sc!=RTEMS_SUCCESSFUL) {
@@ -454,16 +573,19 @@ rtems_status_code shell_init (char * 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;
+ global_shell_env.magic =new_rtems_name("SENV");
+ global_shell_env.devname ="/dev/console";
+ global_shell_env.taskname ="GLOBAL";
+ global_shell_env.tcflag =0;
+ global_shell_env.exit_shell=0;
+ global_shell_env.forever =TRUE;
};
- shell_env->magic =global_shell_env.magic;
- shell_env->devname =devname;
- shell_env->taskname=task_name;
- shell_env->tcflag =tcflag;
+ shell_env->magic =global_shell_env.magic;
+ shell_env->devname =devname;
+ shell_env->taskname =task_name;
+ shell_env->tcflag =tcflag;
+ shell_env->exit_shell=FALSE;
+ shell_env->forever =forever;
return rtems_task_start(task_id,shell_shell,(rtems_task_argument) shell_env);
}
/* ----------------------------------------------- */
-
diff --git a/cpukit/libmisc/shell/shell.h b/cpukit/libmisc/shell/shell.h
index 89c70506c4..3b9522f10a 100644
--- a/cpukit/libmisc/shell/shell.h
+++ b/cpukit/libmisc/shell/shell.h
@@ -45,21 +45,61 @@ typedef struct {
char * taskname;
tcflag_t tcflag;
/* user extensions */
+ int exit_shell; /* logout */
+ int forever ; /* repeat login */
int errorlevel;
int mdump_adr;
} shell_env_t;
int shell_scanline(char * line,int size,FILE * in,FILE * out) ;
+void cat_file(FILE * out,char *name);
rtems_status_code shell_init(char * task_name ,
rtems_unsigned32 task_stacksize,/*0 default*/
rtems_task_priority task_priority ,
char * devname ,
- tcflag_t tcflag );
+ tcflag_t tcflag ,
+ int forever );
extern shell_env_t global_shell_env,
* current_shell_env;
/*--------*/
+/* pty.c */
+/*--------*/
+
+char * get_pty(int socket);
+
+
+rtems_device_driver pty_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+rtems_device_driver pty_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+
+
+#define PTY_DRIVER_TABLE_ENTRY \
+ { pty_initialize , pty_open , pty_close , \
+ pty_read , pty_write , pty_control }
+/*--------*/
/* cmds.c */
/*--------*/
int str2int(char * s);