diff options
Diffstat (limited to 'c/src')
-rw-r--r-- | c/src/libmisc/ChangeLog | 21 | ||||
-rw-r--r-- | c/src/libmisc/monitor/mon-prmisc.c | 4 | ||||
-rw-r--r-- | c/src/libmisc/shell/Makefile.am | 6 | ||||
-rw-r--r-- | c/src/libmisc/shell/README | 8 | ||||
-rw-r--r-- | c/src/libmisc/shell/cmds.c | 123 | ||||
-rw-r--r-- | c/src/libmisc/shell/pty.c | 406 | ||||
-rw-r--r-- | c/src/libmisc/shell/shell.c | 242 | ||||
-rw-r--r-- | c/src/libmisc/shell/shell.h | 42 | ||||
-rw-r--r-- | c/src/libmisc/shell/telnetd.c | 107 | ||||
-rw-r--r-- | c/src/libmisc/shell/telnetd.h | 20 | ||||
-rw-r--r-- | c/src/libnetworking/rtems_servers/telnetd.c | 107 | ||||
-rw-r--r-- | c/src/libnetworking/rtems_servers/telnetd.h | 20 |
12 files changed, 1028 insertions, 78 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*)¤t_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*)¤t_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 |