Changeset b5bf8cd1 in rtems


Ignore:
Timestamp:
Sep 24, 2007, 9:35:10 PM (12 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.9, master
Children:
b1cbb2d
Parents:
41f17ba
Message:

2007-09-24 Joel Sherrill <joel.sherrill@…>

PR 1262/filesystem

  • libcsupport/Makefile.am, libnetworking/libc/herror.c, libnetworking/libc/res_send.c, libnetworking/sys/uio.h, telnetd/Makefile.am, telnetd/README, telnetd/preinstall.am, telnetd/pty.c, telnetd/telnetd.c: Add support for readv() and writev() including documentation and test case.
  • libcsupport/src/readv.c, libcsupport/src/writev.c: New files.
Location:
cpukit
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    r41f17ba rb5bf8cd1  
     12007-09-24      Joel Sherrill <joel.sherrill@oarcorp.com>
     2
     3        PR 1262/filesystem
     4        * libcsupport/Makefile.am, libnetworking/libc/herror.c,
     5        libnetworking/libc/res_send.c, libnetworking/sys/uio.h,
     6        telnetd/Makefile.am, telnetd/README, telnetd/preinstall.am,
     7        telnetd/pty.c, telnetd/telnetd.c: Add support for readv() and
     8        writev() including documentation and test case.
     9        * libcsupport/src/readv.c, libcsupport/src/writev.c: New files.
     10
    1112007-09-21      Joel Sherrill <joel.sherrill@oarcorp.com>
    212
  • cpukit/libcsupport/Makefile.am

    r41f17ba rb5bf8cd1  
    6464    src/chroot.c src/sync.c
    6565
     66## Until sys/uio.h is moved to libcsupport, we have to have networking
     67## enabled to compile these.  Hopefully this is a temporary situation.
     68if LIBNETWORKING
     69SYSTEM_CALL_C_FILES += src/readv.c src/writev.c
     70endif
     71
    6672DIRECTORY_SCAN_C_FILES = src/opendir.c src/closedir.c src/readdir.c \
    6773    src/readdir_r.c src/rewinddir.c src/scandir.c src/seekdir.c \
  • cpukit/libnetworking/libc/herror.c

    r41f17ba rb5bf8cd1  
    7070int     h_errno;
    7171
     72#define HERROR_USE_WRITEV
     73
    7274/*
    7375 * herror --
     
    7880        const char *s;
    7981{
    80 #if 0
     82#if defined(HERROR_USE_WRITEV)
    8183        struct iovec iov[4];
    8284        register struct iovec *v = iov;
     
    98100#else
    99101        /*
    100          * RTEMS: no writev yet
     102         * no writev implementation available
    101103         */
    102104        if (s && *s) {
  • cpukit/libnetworking/libc/res_send.c

    r41f17ba rb5bf8cd1  
    9898#endif
    9999
     100/* RTEMS now has writev */
     101#define USE_WRITEV
     102
    100103#include "res_config.h"
    101104
     
    379382                if (v_circuit) {
    380383                        int truncated;
    381 #if !defined(__rtems__)
     384#if defined(USE_WRITEV)
    382385                        struct iovec iov[2];
    383386#endif
     
    417420                         */
    418421                        putshort((u_short)buflen, (u_char*)&len);
    419 #if !defined(__rtems__)
     422#if defined(USE_WRITEV)
    420423                        iov[0].iov_base = (caddr_t)&len;
    421424                        iov[0].iov_len = INT16SZ;
  • cpukit/libnetworking/sys/uio.h

    r41f17ba rb5bf8cd1  
    4141
    4242/*
    43  * XXX
    44  * iov_base should be a void *.
     43 *  POSIX compliant iovec definition
    4544 */
    4645struct iovec {
    47         char    *iov_base;      /* Base address. */
    48         size_t   iov_len;       /* Length. */
     46  void    *iov_base;  /* pointer to data to be written */
     47  size_t   iov_len;   /* length of this data block */
    4948};
    5049
  • cpukit/telnetd/Makefile.am

    r41f17ba rb5bf8cd1  
    88if LIBSHELL
    99include_rtemsdir = $(includedir)/rtems
    10 include_rtems_HEADERS = pty.h telnetd.h
     10include_rtems_HEADERS = pty.h telnetd.h passwd.h
    1111
    1212project_lib_LIBRARIES = libtelnetd.a
    13 libtelnetd_a_SOURCES = pty.c pty.h telnetd.c telnetd.h icmds.c
     13libtelnetd_a_SOURCES = check_passwd.c des.c icmds.c pty.c telnetd.c
    1414libtelnetd_a_CPPFLAGS = $(AM_CPPFLAGS)
    1515endif
  • cpukit/telnetd/README

    r41f17ba rb5bf8cd1  
    20201.  OOB not yet implemented. Only a reduced negotiation is implemented.
    2121   
    22 2.  If you have tcp/ip inited you can start telnetd daemon.
     222.  If you have tcp/ip initialied you can start telnetd daemon.
    2323    You need register pseudo-terminals driver into device drivers table.
    2424    16 ptyX termios device terminales are created into /dev/.
  • cpukit/telnetd/preinstall.am

    r41f17ba rb5bf8cd1  
    3939PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/telnetd.h
    4040
     41$(PROJECT_INCLUDE)/rtems/passwd.h: passwd.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
     42        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/passwd.h
     43PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/passwd.h
     44
    4145$(PROJECT_LIB)/libtelnetd.a: libtelnetd.a $(PROJECT_LIB)/$(dirstamp)
    4246        $(INSTALL_DATA) $< $(PROJECT_LIB)/libtelnetd.a
  • cpukit/telnetd/pty.c

    r41f17ba rb5bf8cd1  
    88 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    99 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     10 *
     11 *  Till Straumann <strauman@slac.stanford.edu>
     12 *
     13 *   - converted into a loadable module
     14 *   - NAWS support / ioctls for querying/setting the window
     15 *     size added.
     16 *   - don't delete the running task when the connection
     17 *     is closed. Rather let 'read()' return a 0 count so
     18 *     they may cleanup. Some magic hack works around termios
     19 *     limitation.
    1020 *
    1121 *  $Id$
    1222 */
    1323
     24/*
     25                      LICENSE INFORMATION
     26
     27RTEMS is free software; you can redistribute it and/or modify it under
     28terms of the GNU General Public License as published by the
     29Free Software Foundation; either version 2, or (at your option) any
     30later version.  RTEMS is distributed in the hope that it will be useful,
     31but WITHOUT ANY WARRANTY; without even the implied warranty of
     32MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     33General Public License for more details. You should have received
     34a copy of the GNU General Public License along with RTEMS; see
     35file COPYING. If not, write to the Free Software Foundation, 675
     36Mass Ave, Cambridge, MA 02139, USA.
     37
     38As a special exception, including RTEMS header files in a file,
     39instantiating RTEMS generics or templates, or linking other files
     40with RTEMS objects to produce an executable application, does not
     41by itself cause the resulting executable application to be covered
     42by the GNU General Public License. This exception does not
     43however invalidate any other reasons why the executable file might be
     44covered by the GNU Public License.
     45
     46*/
     47
    1448#ifdef HAVE_CONFIG_H
    1549#include "config.h"
    1650#endif
    1751
     52#define DEBUG_WH                (1<<0)
     53#define DEBUG_DETAIL    (1<<1)
     54
     55/* #define DEBUG DEBUG_WH */
     56
     57#ifdef __cplusplus
     58extern "C" {
     59#endif
    1860/*-----------------------------------------*/
    1961#include <termios.h>
     62#include <rtems/termiostypes.h>
     63#include <sys/ttycom.h>
    2064#include <rtems.h>
    2165#include <rtems/libio.h>
     66#include <bsp.h>
     67#include <rtems/bspIo.h>
     68#if 0
    2269#include <rtems/pty.h>
    23 #include <rtems/bspIo.h>
     70#else
     71#define MAX_PTYS 8
     72#endif
     73#include <errno.h>
     74#include <sys/socket.h>
     75#ifdef __cplusplus
     76};
     77#endif
    2478/*-----------------------------------------*/
    2579#include <stdio.h>
     
    46100#define IAC_EOR    239
    47101
    48 typedef struct {
     102#define SB_MAX          16
     103
     104struct pty_tt;
     105typedef struct pty_tt pty_t;
     106
     107struct pty_tt {
    49108 char                     *devname;
    50109 struct rtems_termios_tty *ttyp;
     
    52111 int                       opened;
    53112 int                       socket;
    54 
    55113 int                       last_cr;
    56  int                       iac_mode;   
    57 } pty_t;
    58 
    59 
    60 static int ptys_initted=FALSE;
    61 static pty_t *ptys;
    62 
    63 size_t rtems_pty_maximum_ptys;
    64 
    65 /* This procedure returns the devname for a free pty slot.
    66  * If no slot available (field socket>=0)
    67  * then the socket argument is closed
    68  */
    69 
    70 char *  rtems_pty_get(int socket) {
     114 unsigned                  iac_mode;   
     115 unsigned char             sb_buf[SB_MAX];     
     116 int                       sb_ind;
     117 int                       width;
     118 int                       height;
     119};
     120
     121
     122#ifdef __cplusplus
     123
     124extern "C" {
     125int             printk(char*,...);
     126
     127#endif
     128
     129#if     MAX_PTYS > 5
     130#undef  MAX_PTYS
     131#define MAX_PTYS 5
     132#endif
     133
     134
     135static int   telnet_pty_inited=FALSE;
     136static pty_t telnet_ptys[MAX_PTYS];
     137
     138static rtems_device_major_number pty_major;
     139
     140
     141/* This procedure returns the devname for a pty slot free.
     142 * If not slot availiable (field socket>=0)
     143 *  then the socket argument is closed
     144 */
     145
     146char *  telnet_get_pty(int socket) {
    71147        int ndx;
    72         if (!ptys_initted) return NULL;
    73         for (ndx=0;ndx<rtems_pty_maximum_ptys;ndx++) {
    74                 if (ptys[ndx].socket<0) {
    75                         ptys[ndx].socket=socket;
    76                         return ptys[ndx].devname;
     148        if (telnet_pty_inited) {
     149                for (ndx=0;ndx<MAX_PTYS;ndx++) {
     150                        if (telnet_ptys[ndx].socket<0) {
     151                                struct timeval t;
     152                                /* set a long polling interval to save CPU time */
     153                                t.tv_sec=2;
     154                                t.tv_usec=00000;
     155                                setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
     156                                telnet_ptys[ndx].socket=socket;
     157                                return telnet_ptys[ndx].devname;
     158                        };
    77159                };
    78         };
     160        }
    79161        close(socket);
    80162        return NULL;
     
    100182        buf[1]=mode;
    101183        buf[2]=option;
    102         return write(ptys[minor].socket,buf,sizeof(buf));
    103 }
    104 
    105 int read_pty(int minor) { /* Characters writed in the client side*/
    106          unsigned char value;
    107          int count;
    108          int result;
    109          count=read(ptys[minor].socket,&value,sizeof(value));
     184        return write(telnet_ptys[minor].socket,buf,sizeof(buf));
     185}
     186
     187static int
     188handleSB(pty_t *pty)
     189{
     190        switch (pty->sb_buf[0]) {
     191                case 31:        /* NAWS */
     192                        pty->width  = (pty->sb_buf[1]<<8) + pty->sb_buf[2];
     193                        pty->height = (pty->sb_buf[3]<<8) + pty->sb_buf[4];
     194#if DEBUG & DEBUG_WH
     195                        fprintf(stderr,
     196                                        "Setting width/height to %ix%i\n",
     197                                        pty->width,
     198                                        pty->height);
     199#endif
     200                        break;
     201                default:
     202                        break;
     203        }
     204        return 0;
     205}
     206
     207static int read_pty(int minor) { /* Characters written to the client side*/
     208         unsigned char  value;
     209         unsigned int   omod;
     210         int                    count;
     211         int                    result;
     212         pty_t                  *pty=telnet_ptys+minor;
     213
     214         count=read(pty->socket,&value,sizeof(value));
     215         if (count<0)
     216                return -1;
     217
    110218         if (count<1) {
    111           fclose(stdin);                 
    112           fclose(stdout);               
    113           fclose(stderr);               
    114           /* If you don't read from the socket the system ends the task */
    115           rtems_task_delete(RTEMS_SELF);
     219                        /* Unfortunately, there is no way of passing an EOF
     220                         * condition through the termios driver. Hence, we
     221                         * resort to an ugly hack. Setting cindex>ccount
     222                         * causes the termios driver to return a read count
     223                         * of '0' which is what we want here. We leave
     224                         * 'errno' untouched.
     225                         */
     226                        pty->ttyp->cindex=pty->ttyp->ccount+1;
     227                        return pty->ttyp->termios.c_cc[VEOF];
    116228         };
    117          switch(ptys[minor].iac_mode) {
    118           case IAC_ESC:
    119                ptys[minor].iac_mode=0;
    120                switch(value) {
    121                 case IAC_ESC :
    122                      return IAC_ESC;
    123                 case IAC_DONT:
    124                 case IAC_DO  :
    125                 case IAC_WONT:
    126                 case IAC_WILL:
    127                      ptys[minor].iac_mode=value;
    128                      return -1;
    129                 case IAC_SB  :
    130                      return -100;
    131                 case IAC_GA  :
    132                      return -1;
    133                 case IAC_EL  :
    134                      return 0x03; /* Ctrl-C*/
    135                 case IAC_EC  :
    136                      return '\b';
    137                 case IAC_AYT :
    138                      write(ptys[minor].socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
    139                      return -1;
    140                 case IAC_AO  :
    141                      return -1;
    142                 case IAC_IP  :
    143                      write(ptys[minor].socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
    144                      return -1;
    145                 case IAC_BRK :
    146                      write(ptys[minor].socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
    147                      return -1;
    148                 case IAC_DMARK:
    149                      return -2;
    150                 case IAC_NOP :
    151                      return -1;
    152                 case IAC_SE  :
    153                      return -101;
    154                 case IAC_EOR :
    155                      return -102;
    156                 default      :
    157                      return -1;
    158                };
    159                break;
    160           case IAC_WILL:
    161                ptys[minor].iac_mode=0;
    162                if (value==34){send_iac(minor,IAC_DONT,   34);       /*LINEMODE*/
    163                               send_iac(minor,IAC_DO  ,    1);} else /*ECHO    */
    164                              {send_iac(minor,IAC_DONT,value);};
    165                return -1;
    166           case IAC_DONT:
    167                ptys[minor].iac_mode=0;
    168                return -1;
    169           case IAC_DO  :
    170                ptys[minor].iac_mode=0;
    171                if (value==3) {send_iac(minor,IAC_WILL,    3);} else /* GO AHEAD*/
    172                if (value==1) {                               } else /* ECHO */
    173                              {send_iac(minor,IAC_WONT,value);};
    174                return -1;
    175           case IAC_WONT:
    176                ptys[minor].iac_mode=0;
    177                if (value==1) {send_iac(minor,IAC_WILL,    1);} else /* ECHO */
    178                              {send_iac(minor,IAC_WONT,value);};
    179                return -1;
    180           default:
    181                ptys[minor].iac_mode=0;
    182                if (value==IAC_ESC) {
    183                      ptys[minor].iac_mode=value;
    184                      return -1;
    185                } else {
    186                      result=value; 
    187                      if (ptys[minor].last_cr && ((value=='\n')||(value=='\0'))) result=-1;
    188                      ptys[minor].last_cr=(value=='\r');
    189                      return result;
    190                };
     229
     230         omod=pty->iac_mode;
     231         pty->iac_mode=0;
     232         switch(omod & 0xff) {
     233                         case IAC_ESC:
     234                                         switch(value) {
     235                                                         case IAC_ESC :
     236                                                                         /* in case this is an ESC ESC sequence in SB mode */
     237                                                                         pty->iac_mode = omod>>8;
     238                                                                         return IAC_ESC;
     239                                                         case IAC_DONT:
     240                                                         case IAC_DO  :
     241                                                         case IAC_WONT:
     242                                                         case IAC_WILL:
     243                                                                         pty->iac_mode=value;
     244                                                                         return -1;
     245                                                         case IAC_SB  :
     246#if DEBUG & DEBUG_DETAIL
     247                                                                         printk("SB\n");
     248#endif
     249                                                                         pty->iac_mode=value;
     250                                                                         pty->sb_ind=0;
     251                                                                         return -100;
     252                                                         case IAC_GA  :
     253                                                                         return -1;
     254                                                         case IAC_EL  :
     255                                                                         return 0x03; /* Ctrl-C*/
     256                                                         case IAC_EC  :
     257                                                                         return '\b';
     258                                                         case IAC_AYT :
     259                                                                         write(pty->socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
     260                                                                         return -1;
     261                                                         case IAC_AO  :
     262                                                                         return -1;
     263                                                         case IAC_IP  :
     264                                                                         write(pty->socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
     265                                                                         return -1;
     266                                                         case IAC_BRK :
     267                                                                         write(pty->socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
     268                                                                         return -1;
     269                                                         case IAC_DMARK:
     270                                                                         return -2;
     271                                                         case IAC_NOP :
     272                                                                         return -1;
     273                                                         case IAC_SE  :
     274#if DEBUG & DEBUG_DETAIL
     275                                                                        {
     276                                                                        int i;
     277                                                                        printk("SE");
     278                                                                        for (i=0; i<pty->sb_ind; i++)
     279                                                                                printk(" %02x",pty->sb_buf[i]);
     280                                                                        printk("\n");
     281                                                                        }
     282#endif
     283                                                                        handleSB(pty);
     284                                                         return -101;
     285                                                         case IAC_EOR :
     286                                                                         return -102;
     287                                                         default      :
     288                                                                         return -1;
     289                                         };
     290                                         break;
     291
     292                         case IAC_SB:
     293                                         pty->iac_mode=omod;
     294                                         if (IAC_ESC==value) {
     295                                                pty->iac_mode=(omod<<8)|value;
     296                                         } else {
     297                                                if (pty->sb_ind < SB_MAX)
     298                                                        pty->sb_buf[pty->sb_ind++]=value;
     299                                         }
     300                                         return -1;
     301
     302                         case IAC_WILL:
     303                                         if (value==34){
     304                                                        send_iac(minor,IAC_DONT,   34); /*LINEMODE*/
     305                                                        send_iac(minor,IAC_DO  ,    1); /*ECHO    */
     306                                         } else if (value==31) {
     307                                                        send_iac(minor,IAC_DO  ,   31); /*NAWS    */
     308#if DEBUG & DEBUG_DETAIL
     309                                                        printk("replied DO NAWS\n");
     310#endif
     311                                         } else {
     312                                                        send_iac(minor,IAC_DONT,value);
     313                                         }
     314                                         return -1;
     315                         case IAC_DONT:
     316                                         return -1;
     317                         case IAC_DO  :
     318                                         if (value==3) {
     319                                                        send_iac(minor,IAC_WILL,    3); /* GO AHEAD*/
     320                                         } else if (value==1) {                         
     321                                                        /* ECHO */
     322                                         } else {
     323                                                        send_iac(minor,IAC_WONT,value);
     324                                         };
     325                                         return -1;
     326                         case IAC_WONT:
     327                                         if (value==1) {send_iac(minor,IAC_WILL,    1);} else /* ECHO */
     328                                         {send_iac(minor,IAC_WONT,value);};
     329                                         return -1;
     330                         default:
     331                                         if (value==IAC_ESC) {
     332                                                        pty->iac_mode=value;
     333                                                        return -1;
     334                                         } else {
     335                                                        result=value; 
     336                                                        if ( 0
     337#if 0                                                    /* pass CRLF through - they should use termios to handle it */
     338                                                                 ||     ((value=='\n') && (pty->last_cr))
     339#endif
     340                                                                /* but map telnet CRNUL to CR down here */
     341                                                                 || ((value==0) && pty->last_cr)
     342                                                                ) result=-1;
     343                                                         pty->last_cr=(value=='\r');
     344                                                         return result;
     345                                         };
    191346         };
    192        
     347        /* should never get here but keep compiler happy */
     348        return -1;
    193349}
    194350
     
    205361static int
    206362ptySetAttributes(int minor,const struct termios *t) {
    207         if (minor<rtems_pty_maximum_ptys) {     
    208          ptys[minor].c_cflag=t->c_cflag;       
     363        if (minor<MAX_PTYS) {   
     364         telnet_ptys[minor].c_cflag=t->c_cflag;
    209365        } else {
    210366         return -1;
     
    215371static int
    216372ptyPollInitialize(int major,int minor,void * arg) {
    217         rtems_libio_open_close_args_t * args = arg;
     373        rtems_libio_open_close_args_t * args = (rtems_libio_open_close_args_t*)arg;
    218374        struct termios t;
    219         if (minor<rtems_pty_maximum_ptys) {     
    220          if (ptys[minor].socket<0) return -1;           
    221          ptys[minor].opened=TRUE;
    222          ptys[minor].ttyp=args->iop->data1;
     375        if (minor<MAX_PTYS) {   
     376         if (telnet_ptys[minor].socket<0) return -1;           
     377         telnet_ptys[minor].opened=TRUE;
     378         telnet_ptys[minor].ttyp= (struct rtems_termios_tty *) args->iop->data1;
     379         telnet_ptys[minor].iac_mode=0;
     380         telnet_ptys[minor].sb_ind=0;
     381         telnet_ptys[minor].width=0;
     382         telnet_ptys[minor].height=0;
    223383         t.c_cflag=B9600|CS8;/* termios default */
    224384         return ptySetAttributes(minor,&t);
     
    230390static int
    231391ptyShutdown(int major,int minor,void * arg) {
    232         if (minor<rtems_pty_maximum_ptys) {     
    233          ptys[minor].opened=FALSE;
    234          if (ptys[minor].socket>=0) close(ptys[minor].socket);
    235          ptys[minor].socket=-1;
    236          chown(ptys[minor].devname,2,0);
     392        if (minor<MAX_PTYS) {   
     393         telnet_ptys[minor].opened=FALSE;
     394         if (telnet_ptys[minor].socket>=0) close(telnet_ptys[minor].socket);
     395         telnet_ptys[minor].socket=-1;
     396         chown(telnet_ptys[minor].devname,2,0);
    237397        } else {
    238398         return -1;
     
    246406ptyPollWrite(int minor, const char * buf,int len) {
    247407        int count;
    248         if (minor<rtems_pty_maximum_ptys) {     
    249          if (ptys[minor].socket<0) return -1;           
    250          count=write(ptys[minor].socket,buf,len);
     408        if (minor<MAX_PTYS) {   
     409         if (telnet_ptys[minor].socket<0) return -1;           
     410         count=write(telnet_ptys[minor].socket,buf,len);
    251411        } else {
    252412         count=-1;
     
    258418ptyPollRead(int minor) {
    259419        int result;
    260         if (minor<rtems_pty_maximum_ptys) {     
    261          if (ptys[minor].socket<0) return -1;           
     420        if (minor<MAX_PTYS) {   
     421         if (telnet_ptys[minor].socket<0) return -1;           
    262422         result=read_pty(minor);
    263423         return result;
     
    265425        return -1;
    266426}
     427/*-----------------------------------------------------------*/
     428/*  pty_initialize
     429 *
     430 *  This routine initializes the pty IO driver.
     431 *
     432 *  Input parameters: NONE
     433 *
     434 *  Output parameters:  NONE
     435 *
     436 *  Return values:
     437 */
     438/*-----------------------------------------------------------*/
     439static
     440rtems_device_driver my_pty_initialize(
     441  rtems_device_major_number  major,
     442  rtems_device_minor_number  minor,
     443  void                      *arg
     444)
     445{
     446int ndx;       
     447rtems_status_code status ;
     448
     449        /*
     450         * Set up ptys
     451         */
     452
     453        for (ndx=0;ndx<MAX_PTYS;ndx++) {
     454                telnet_ptys[ndx].devname=(char*)malloc(strlen("/dev/ptyXX")+1);
     455                sprintf(telnet_ptys[ndx].devname,"/dev/pty%X",ndx);
     456                telnet_ptys[ndx].ttyp=NULL;
     457                telnet_ptys[ndx].c_cflag=CS8|B9600;
     458                telnet_ptys[ndx].socket=-1;
     459                telnet_ptys[ndx].opened=FALSE;
     460                telnet_ptys[ndx].sb_ind=0;
     461                telnet_ptys[ndx].width=0;
     462                telnet_ptys[ndx].height=0;
     463
     464        };
     465
     466        /*
     467         * Register the devices
     468         */
     469        for (ndx=0;ndx<MAX_PTYS;ndx++) {
     470                status = rtems_io_register_name(telnet_ptys[ndx].devname, major, ndx);
     471                if (status != RTEMS_SUCCESSFUL)
     472                                rtems_fatal_error_occurred(status);
     473                chmod(telnet_ptys[ndx].devname,0660);
     474                chown(telnet_ptys[ndx].devname,2,0); /* tty,root*/
     475        };
     476        printk("Device: /dev/pty%X../dev/pty%X (%d)pseudo-terminals registered.\n",0,MAX_PTYS-1,MAX_PTYS);
     477
     478        return RTEMS_SUCCESSFUL;
     479}
     480
     481static int pty_do_finalize()
     482{
     483int ndx;
     484rtems_status_code status;
     485
     486                if ( !telnet_pty_inited )
     487                        return 0;
     488
     489                for (ndx=0;ndx<MAX_PTYS;ndx++) {
     490                        if (telnet_ptys[ndx].opened) {
     491                                        fprintf(stderr,"There are still opened PTY devices, unable to proceed\n");
     492                                        return -1;
     493                        }
     494                }
     495                if (RTEMS_SUCCESSFUL != rtems_io_unregister_driver(pty_major)) {
     496                                fprintf(stderr,"Unable to remove this driver\n");
     497                                return -1;
     498                }
     499                for (ndx=0;ndx<MAX_PTYS;ndx++) {
     500                                /* rtems_io_register_name() actually creates a node in the filesystem
     501                                 * (mknod())
     502                                 */
     503                                status = (rtems_status_code)unlink(telnet_ptys[ndx].devname);
     504                                if (status != RTEMS_SUCCESSFUL)
     505                                        perror("removing pty device node from file system");
     506                                else
     507                                        free(telnet_ptys[ndx].devname);
     508                };
     509                fprintf(stderr,"PTY driver unloaded successfully\n");
     510                telnet_pty_inited=FALSE;
     511                return 0;
     512}
     513
     514/*
     515 *  Open entry point
     516 */
     517
     518static
     519rtems_device_driver my_pty_open(
     520  rtems_device_major_number major,
     521  rtems_device_minor_number minor,
     522  void                    * arg
     523)
     524{
     525  rtems_status_code sc ;
     526  sc = rtems_termios_open(major,minor,arg,pty_get_termios_handlers(FALSE));
     527  return sc;
     528}
     529 
     530/*
     531 *  Close entry point
     532 */
     533
     534static
     535rtems_device_driver my_pty_close(
     536  rtems_device_major_number major,
     537  rtems_device_minor_number minor,
     538  void                    * arg
     539)
     540{
     541  return rtems_termios_close(arg);
     542}
     543
     544/*
     545 * read bytes from the pty
     546 */
     547
     548static
     549rtems_device_driver my_pty_read(
     550  rtems_device_major_number major,
     551  rtems_device_minor_number minor,
     552  void                    * arg
     553)
     554{
     555  return rtems_termios_read(arg);
     556}
     557
     558/*
     559 * write bytes to the pty
     560 */
     561
     562static
     563rtems_device_driver my_pty_write(
     564  rtems_device_major_number major,
     565  rtems_device_minor_number minor,
     566  void                    * arg
     567)
     568{
     569  return rtems_termios_write(arg);
     570}
     571
     572/*
     573 *  IO Control entry point
     574 */
     575
     576static
     577rtems_device_driver my_pty_control(
     578  rtems_device_major_number major,
     579  rtems_device_minor_number minor,
     580  void                    * arg
     581)
     582{
     583rtems_libio_ioctl_args_t *args = (rtems_libio_ioctl_args_t*)arg;
     584struct winsize                   *wp = (struct winsize*)args->buffer;
     585pty_t                                    *p=&telnet_ptys[minor];
     586
     587        switch (args->command) {
     588
     589                case TIOCGWINSZ:
     590
     591                        wp->ws_row = p->height;
     592                        wp->ws_col = p->width;
     593                        args->ioctl_return=0;
     594#if DEBUG & DEBUG_WH
     595                        fprintf(stderr,
     596                                        "ioctl(TIOCGWINSZ), returning %ix%i\n",
     597                                        wp->ws_col,
     598                                        wp->ws_row);
     599#endif
     600
     601                        return RTEMS_SUCCESSFUL;
     602
     603                case TIOCSWINSZ:
     604#if DEBUG & DEBUG_WH
     605                        fprintf(stderr,
     606                                        "ioctl(TIOCGWINSZ), setting %ix%i\n",
     607                                        wp->ws_col,
     608                                        wp->ws_row);
     609#endif
     610
     611                        p->height = wp->ws_row;
     612                        p->width  = wp->ws_col;
     613                        args->ioctl_return=0;
     614
     615                        return RTEMS_SUCCESSFUL;
     616
     617                default:
     618
     619                break;
     620  }
     621
     622  return rtems_termios_ioctl(arg);
     623}
     624
     625static rtems_driver_address_table drvPty = {
     626                my_pty_initialize,
     627                my_pty_open,
     628                my_pty_close,
     629                my_pty_read,
     630                my_pty_write,
     631                my_pty_control
     632};
     633
    267634/*-----------------------------------------------------------*/
    268635static const rtems_termios_callbacks pty_poll_callbacks = {
     
    281648}
    282649/*-----------------------------------------------------------*/
    283 static void init_ptys(void) {
    284         int ndx;
    285         ptys = malloc( sizeof(pty_t) * rtems_pty_maximum_ptys );
    286         for (ndx=0;ndx<rtems_pty_maximum_ptys;ndx++) {
    287                 ptys[ndx].devname=malloc(strlen("/dev/ptyXX")+1);
    288                 sprintf(ptys[ndx].devname,"/dev/pty%X",ndx);
    289                 ptys[ndx].ttyp=NULL;
    290                 ptys[ndx].c_cflag=CS8|B9600;
    291                 ptys[ndx].socket=-1;
    292                 ptys[ndx].opened=FALSE;
    293 
    294         };
    295         ptys_initted=TRUE;
    296 }
    297 
    298 
    299 /*-----------------------------------------------------------*/
    300 /*  pty_initialize
    301  *
    302  *  This routine initializes the pty IO driver.
    303  *
    304  *  Input parameters: NONE
    305  *
    306  *  Output parameters:  NONE
    307  *
    308  *  Return values:
    309  */
    310 /*-----------------------------------------------------------*/
    311 rtems_device_driver pty_initialize(
    312   rtems_device_major_number  major,
    313   rtems_device_minor_number  minor,
    314   void                      *arg
    315 )
    316 {
    317   int ndx;     
    318   rtems_status_code status;
    319 
    320   /*
    321    * Set up ptys
    322    */
    323 
    324   init_ptys();
    325 
    326   /*
    327    * Register the devices
    328    */
    329   for (ndx=0;ndx<rtems_pty_maximum_ptys;ndx++) {
    330    status = rtems_io_register_name(ptys[ndx].devname, major, ndx);
    331    if (status != RTEMS_SUCCESSFUL)
    332      rtems_fatal_error_occurred(status);
    333    chmod(ptys[ndx].devname,0660);
    334    chown(ptys[ndx].devname,2,0); /* tty,root*/
    335   };
    336   printk("Device: /dev/pty%X../dev/pty%X (%d)pseudo-terminals registered.\n",
    337       0,rtems_pty_maximum_ptys-1,rtems_pty_maximum_ptys);
    338 
    339   return RTEMS_SUCCESSFUL;
    340 }
    341 
    342 
    343 /*
    344  *  Open entry point
    345  */
    346 
    347 rtems_device_driver pty_open(
    348   rtems_device_major_number major,
    349   rtems_device_minor_number minor,
    350   void                    * arg
    351 )
    352 {
    353   rtems_status_code sc ;
    354   sc = rtems_termios_open(major,minor,arg,pty_get_termios_handlers(FALSE));
    355   return sc;
    356 }
    357  
    358 /*
    359  *  Close entry point
    360  */
    361 
    362 rtems_device_driver pty_close(
    363   rtems_device_major_number major,
    364   rtems_device_minor_number minor,
    365   void                    * arg
    366 )
    367 {
    368   return rtems_termios_close(arg);
    369 }
    370 
    371 /*
    372  * read bytes from the pty
    373  */
    374 
    375 rtems_device_driver pty_read(
    376   rtems_device_major_number major,
    377   rtems_device_minor_number minor,
    378   void                    * arg
    379 )
    380 {
    381   return rtems_termios_read(arg);
    382 }
    383 
    384 /*
    385  * write bytes to the pty
    386  */
    387 
    388 rtems_device_driver pty_write(
    389   rtems_device_major_number major,
    390   rtems_device_minor_number minor,
    391   void                    * arg
    392 )
    393 {
    394   return rtems_termios_write(arg);
    395 }
    396 
    397 /*
    398  *  IO Control entry point
    399  */
    400 
    401 rtems_device_driver pty_control(
    402   rtems_device_major_number major,
    403   rtems_device_minor_number minor,
    404   void                    * arg
    405 )
    406 {
    407   return rtems_termios_ioctl(arg);
    408 }
     650
     651static int pty_do_initialize()
     652{
     653        if ( !telnet_pty_inited ) {
     654                if (RTEMS_SUCCESSFUL==rtems_io_register_driver(0, &drvPty, &pty_major))
     655                        telnet_pty_inited=TRUE;
     656                else
     657                        fprintf(stderr,"WARNING: registering the PTY driver FAILED\n");
     658        }
     659        return telnet_pty_inited;
     660}
     661
     662#ifdef __cplusplus
     663
     664class TelnetPtyIni {
     665public:
     666        TelnetPtyIni() { if (!nest++) {
     667                                                pty_do_initialize();
     668                                }
     669                         };
     670        ~TelnetPtyIni(){ if (!--nest) {
     671                                                pty_do_finalize();
     672                                }
     673                         };
     674private:
     675static int nest;
     676};
     677
     678static TelnetPtyIni onlyInst;
     679int TelnetPtyIni::nest=0;
     680
     681int telnet_pty_initialize()
     682{
     683        return telnet_pty_inited;
     684}
     685
     686int telnet_pty_finalize()
     687{
     688        return telnet_pty_inited;
     689}
     690};
     691#else
     692int telnet_pty_initialize()
     693{
     694        return pty_do_initialize();
     695}
     696
     697int telnet_pty_finalize()
     698{
     699        return pty_do_finalize();
     700}
     701#endif
  • cpukit/telnetd/telnetd.c

    r41f17ba rb5bf8cd1  
    1818 *
    1919 * Sorry but OOB is not still implemented. (This is the first version)
     20 *
     21 * Till Straumann <strauman@slac.stanford.edu>
     22 *  - made the 'shell' interface more generic, i.e. it is now
     23 *    possible to have 'telnetd' run an arbitrary 'shell'
     24 *    program.
    2025 */
     26
     27/*
     28                      LICENSE INFORMATION
     29
     30RTEMS is free software; you can redistribute it and/or modify it under
     31terms of the GNU General Public License as published by the
     32Free Software Foundation; either version 2, or (at your option) any
     33later version.  RTEMS is distributed in the hope that it will be useful,
     34but WITHOUT ANY WARRANTY; without even the implied warranty of
     35MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     36General Public License for more details. You should have received
     37a copy of the GNU General Public License along with RTEMS; see
     38file COPYING. If not, write to the Free Software Foundation, 675
     39Mass Ave, Cambridge, MA 02139, USA.
     40
     41As a special exception, including RTEMS header files in a file,
     42instantiating RTEMS generics or templates, or linking other files
     43with RTEMS objects to produce an executable application, does not
     44by itself cause the resulting executable application to be covered
     45by the GNU General Public License. This exception does not
     46however invalidate any other reasons why the executable file might be
     47covered by the GNU Public License.
     48*/
     49
    2150#ifdef HAVE_CONFIG_H
    2251#include "config.h"
     
    2857#include <rtems/shell.h>
    2958#include <rtems/telnetd.h>
     59#include <rtems/bspIo.h>
    3060#include <sys/socket.h>
    3161#include <netinet/in.h>
     
    3363#include <unistd.h>
    3464#include <stdlib.h>
    35 #include <string.h>     /* memset */
    3665#include <stdio.h>
    37 #include <inttypes.h>
    38 
    39 /* FIXME: This should not be here */
    40 extern void _rtems_telnetd_register_icmds(void);
     66#include <assert.h>
     67#include <string.h>
     68#include <syslog.h>
     69
     70#include <rtems/userenv.h>
     71#include <rtems/error.h>
     72#include <rtems/rtems_bsdnet.h>
     73
     74#define PARANOIA
     75
     76extern char *telnet_get_pty(int socket);
     77extern int   telnet_pty_initialize();
     78extern int   telnet_pty_finalize();
     79
     80struct shell_args {
     81        char    *devname;
     82        void    *arg;
     83        char    peername[16];
     84        char    delete_myself;
     85};
     86
     87typedef union uni_sa {
     88        struct sockaddr_in      sin;
     89        struct sockaddr     sa;
     90} uni_sa;
     91
     92static int sockpeername(int sock, char *buf, int bufsz);
     93
     94static int initialize_telnetd();
     95
     96void * telnetd_dflt_spawn(const char *name, unsigned priority, unsigned stackSize, void (*fn)(void*), void *fnarg);
    4197
    4298/***********************************************************/
    4399rtems_id            telnetd_task_id      =0;
    44 uint32_t            telnetd_stack_size   =16384;
    45 rtems_task_priority telnetd_task_priority=100;
     100uint32_t                    telnetd_stack_size   =32000;
     101rtems_task_priority telnetd_task_priority=0;
     102int                                     telnetd_dont_spawn   =0;
     103void                            (*telnetd_shell)(char *, void*)=0;
     104void                            *telnetd_shell_arg       =0;
     105void *                          (*telnetd_spawn_task)(const char *, unsigned, unsigned, void (*)(void*), void *) = telnetd_dflt_spawn;
     106
     107static char *grab_a_Connection(int des_socket, uni_sa *srv, char *peername, int sz)
     108{
     109char            *rval = 0;
     110#if 0
     111socklen_t       
     112#else
     113/* 4.6 doesn't have socklen_t */
     114uint32_t
     115#endif
     116                        size_adr = sizeof(srv->sin);
     117int                     acp_sock;
     118
     119        acp_sock = accept(des_socket,&srv->sa,&size_adr);
     120
     121        if (acp_sock<0) {
     122                perror("telnetd:accept");
     123                goto bailout;
     124        };
     125
     126        if ( !(rval=telnet_get_pty(acp_sock)) ) {
     127                syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY");
     128                /* NOTE: failing 'do_get_pty()' closed the socket */
     129                goto bailout;
     130        }
     131
     132        if (sockpeername(acp_sock, peername, sz))
     133                strncpy(peername, "<UNKNOWN>", sz);
     134
     135#ifdef PARANOIA
     136        syslog(LOG_DAEMON | LOG_INFO,
     137                        "telnetd: accepted connection from %s on %s",
     138                        peername,
     139                        rval);
     140#endif
     141
     142bailout:
     143
     144        return rval;
     145}
     146
     147
     148static void release_a_Connection(char *devname, char *peername, FILE **pstd, int n)
     149{
     150
     151#ifdef PARANOIA
     152        syslog( LOG_DAEMON | LOG_INFO,
     153                        "telnetd: releasing connection from %s on %s",
     154                        peername,
     155                        devname );
     156#endif
     157
     158        while (--n>=0)
     159                if (pstd[n]) fclose(pstd[n]);
     160
     161}
     162
     163static int sockpeername(int sock, char *buf, int bufsz)
     164{
     165uni_sa  peer;
     166#if 0
     167socklen_t       
     168#else
     169/* 4.6 doesn't have socklen_t */
     170uint32_t
     171#endif
     172                len  = sizeof(peer.sin);
     173
     174int             rval = sock < 0;
     175
     176        if ( !rval)
     177                rval = getpeername(sock, &peer.sa, &len);
     178
     179        if ( !rval )
     180                rval = !inet_ntop( AF_INET, &peer.sin.sin_addr, buf, bufsz );
     181
     182        return rval;
     183}
     184
     185#if 1
     186#define INSIDE_TELNETD
     187#include "check_passwd.c"
     188#else
     189#define check_passwd(arg) 0
     190#endif
     191
     192
     193static void
     194spawned_shell(void *arg);
     195
    46196/***********************************************************/
    47 rtems_task rtems_task_telnetd(rtems_task_argument task_argument) {
    48         int des_socket,
    49             acp_socket;
    50         struct sockaddr_in srv;
    51         char * devname;
    52         int i=1;
    53         socklen_t size_adr;
     197static void
     198rtems_task_telnetd(void *task_argument)
     199{
     200int                                     des_socket;
     201uni_sa                          srv;
     202char                            *devname;
     203char                            peername[16];
     204int                                     i=1;
     205int                                     size_adr;
     206struct shell_args       *arg;
     207
    54208        if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
    55209                perror("telnetd:socket");
     210                telnetd_task_id=0;
    56211                rtems_task_delete(RTEMS_SELF);
    57212        };
    58         setsockopt(des_socket,SOL_SOCKET,0,&i,sizeof(i));
     213        setsockopt(des_socket,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i));
     214
    59215        memset(&srv,0,sizeof(srv));
    60         srv.sin_family=AF_INET;
    61         srv.sin_port=htons(23);
    62         size_adr=sizeof(srv);
    63         if ((bind(des_socket,(struct sockaddr *)&srv,size_adr))<0) {
     216        srv.sin.sin_family=AF_INET;
     217        srv.sin.sin_port=htons(23);
     218        size_adr=sizeof(srv.sin);
     219        if ((bind(des_socket,&srv.sa,size_adr))<0) {
    64220                perror("telnetd:bind");
    65221                close(des_socket);
     222                telnetd_task_id=0;
    66223                rtems_task_delete(RTEMS_SELF);
    67224        };
     
    69226                perror("telnetd:listen");
    70227                close(des_socket);
     228                telnetd_task_id=0;
    71229                rtems_task_delete(RTEMS_SELF);
    72230        };
     231
     232        /* we don't redirect stdio as this probably
     233         * was started from the console anyways..
     234         */
    73235        do {
    74           acp_socket=accept(des_socket,(struct sockaddr*)&srv,&size_adr);
    75           if (acp_socket<0) {
    76                 perror("telnetd:accept");
    77                 break;
    78           };
    79           if ((devname = rtems_pty_get(acp_socket)) ) {
    80            shell_init(&devname[5],
    81                       telnetd_stack_size,
    82                       telnetd_task_priority,
    83                       devname,B9600|CS8,FALSE);
     236          devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername));
     237
     238          if ( !devname ) {
     239                /* if something went wrong, sleep for some time */
     240                sleep(10);
     241                continue;
     242          }
     243          if ( telnetd_dont_spawn ) {
     244                if ( 0 == check_passwd(peername) )
     245                        telnetd_shell(devname, telnetd_shell_arg);
    84246          } else {
    85            close(acp_socket);
    86           };
     247                arg = malloc( sizeof(*arg) );
     248
     249                arg->devname = devname;
     250                arg->arg = telnetd_shell_arg;
     251                strncpy(arg->peername, peername, sizeof(arg->peername));
     252
     253                if ( !telnetd_spawn_task(&devname[5], telnetd_task_priority, telnetd_stack_size, spawned_shell, arg) ) {
     254
     255                        FILE *dummy;
     256
     257                        if ( telnetd_spawn_task != telnetd_dflt_spawn ) {
     258                                fprintf(stderr,"Telnetd: Unable to spawn child task\n");
     259                        }
     260
     261                        /* hmm - the pty driver slot can only be
     262                         * released by opening and subsequently
     263                         * closing the PTY - this also closes
     264                         * the underlying socket. So we mock up
     265                         * a stream...
     266                         */
     267
     268                        if ( !(dummy=fopen(devname,"r+")) )
     269                                perror("Unable to dummy open the pty, losing a slot :-(");
     270                        release_a_Connection(devname, peername, &dummy, 1);
     271                        free(arg);
     272                        sleep(2); /* don't accept connections too fast */
     273                }
     274          }
    87275        } while(1);
     276        /* TODO: how to free the connection semaphore? But then -
     277         *       stopping the daemon is probably only needed during
     278         *       development/debugging.
     279         *       Finalizer code should collect all the connection semaphore
     280         *       counts and eventually clean up...
     281         */
    88282        close(des_socket);
    89         rtems_task_delete(RTEMS_SELF);
     283        telnetd_task_id=0;
    90284}
    91285/***********************************************************/
    92 int rtems_telnetd_initialize(void) {
    93         rtems_status_code sc;
    94        
    95         _rtems_telnetd_register_icmds(); /* stats for tcp/ip */
     286static int initialize_telnetd(void) {
    96287       
    97288        if (telnetd_task_id         ) return RTEMS_RESOURCE_IN_USE;
    98         if (telnetd_stack_size<=0   ) telnetd_stack_size   =16384;
    99         if (telnetd_task_priority<=2) telnetd_task_priority=100;
    100         sc=rtems_task_create(new_rtems_name("tlnd"),
    101                              100,RTEMS_MINIMUM_STACK_SIZE,     
    102                              RTEMS_DEFAULT_MODES,
    103                              RTEMS_DEFAULT_ATTRIBUTES,
    104                              &telnetd_task_id);
    105         if (sc!=RTEMS_SUCCESSFUL) {
    106                 rtems_error(sc,"creating task telnetd");
    107                 return (int)sc;
    108         };
    109         sc=rtems_task_start(telnetd_task_id,
    110                             rtems_task_telnetd,
    111                             (rtems_task_argument)NULL);
    112         if (sc!=RTEMS_SUCCESSFUL) {
    113                 rtems_error(sc,"starting task telnetd");
    114         };
    115         return (int)sc;
    116 }
     289        if (telnetd_stack_size<=0   ) telnetd_stack_size   =32000;
     290
     291        if ( !telnetd_spawn_task("TNTD", telnetd_task_priority, RTEMS_MINIMUM_STACK_SIZE, rtems_task_telnetd, 0) ) {
     292                return -1;     
     293        }
     294        return 0;
     295}
     296
    117297/***********************************************************/
    118 int rtems_telnetd_main(int argc,char * argv[]) {
    119         rtems_status_code sc;
     298int startTelnetd(void (*cmd)(char *, void *), void *arg, int dontSpawn, int stack, int priority)
     299{
     300        rtems_status_code       sc;
     301
     302        printf("This is rtems-telnetd (modified by Till Straumann)\n");
     303        printf("$Id$\n");
     304        printf("Release $Name$\n");
     305
     306        if ( !telnetd_shell && !cmd ) {
     307                fprintf(stderr,"startTelnetd(): setup error - NO SHELL; bailing out\n");
     308                return 1;
     309        }
     310
    120311        if (telnetd_task_id) {
    121                 printf("ERROR:telnetd already started\n");
     312                fprintf(stderr,"ERROR:telnetd already started\n");
    122313                return 1;
    123314        };
    124         if (argc>1) telnetd_stack_size   =str2int(argv[1]);
    125         if (argc>2) telnetd_task_priority=str2int(argv[2]);
    126         sc=rtems_initialize_telnetd();
     315
     316        if ( !telnet_pty_initialize() ) {
     317                fprintf(stderr,"PTY driver probably not properly registered\n");
     318                return 1;
     319        }
     320
     321        if (cmd)
     322                telnetd_shell = cmd;
     323        telnetd_shell_arg     = arg;
     324        telnetd_stack_size    = stack;
     325        if ( !priority ) {
     326                priority = rtems_bsdnet_config.network_task_priority;
     327        }
     328        if ( priority < 2 )
     329                priority=100;
     330        telnetd_task_priority = priority;
     331        telnetd_dont_spawn    = dontSpawn;
     332
     333        sc=initialize_telnetd();
    127334        if (sc!=RTEMS_SUCCESSFUL) return sc;
    128         printf(
    129           "rtems_telnetd() started with stacksize=%" PRIu32
    130              ",priority=%" PRId32 "\n",
    131           telnetd_stack_size,telnetd_task_priority);
     335        printf("rtems_telnetd() started with stacksize=%u,priority=%d\n",
     336                        (unsigned)telnetd_stack_size,(int)telnetd_task_priority);
    132337        return 0;
    133338}
    134 /***********************************************************/
    135 int rtems_telnetd_register(void) {
    136         shell_add_cmd("telnetd","telnet","telnetd [stacksize [tsk_priority]]",main_telnetd);
    137         return 0;
    138 }
    139 /***********************************************************/
     339
     340/* utility wrapper */
     341static void
     342spawned_shell(void *targ)
     343{
     344rtems_status_code       sc;
     345FILE                            *nstd[3]={0};
     346FILE                            *ostd[3]={ stdin, stdout, stderr };
     347int                                     i=0;
     348struct shell_args       *arg = targ;
     349
     350        sc=rtems_libio_set_private_env();
     351
     352        /* newlib hack/workaround. Before we change stdin/out/err we must make
     353         * sure the internal data are initialized (fileno(stdout) has this sideeffect).
     354         * This should probably be done from RTEMS' libc support layer...
     355         * (T.S., newlibc-1.13; 2005/10)
     356         */
     357
     358        fileno(stdout);
     359
     360        if (RTEMS_SUCCESSFUL != sc) {
     361                rtems_error(sc,"rtems_libio_set_private_env");
     362                goto cleanup;
     363        }
     364
     365        /* redirect stdio */
     366        for (i=0; i<3; i++) {
     367                if ( !(nstd[i]=fopen(arg->devname,"r+")) ) {
     368                        perror("unable to open stdio");
     369                        goto cleanup;
     370                }
     371        }
     372
     373        stdin  = nstd[0];
     374        stdout = nstd[1];
     375        stderr = nstd[2];
     376
     377
     378
     379#if 0
     380printk("STDOUT is now %x (%x) (FD %i/%i)\n",stdout,nstd[1],fileno(stdout),fileno(nstd[1]));
     381printf("hello\n");
     382write(fileno(stdout),"hellofd\n",8);
     383#endif
     384
     385        /* call their routine */
     386        if ( 0 == check_passwd(arg->peername) )
     387                telnetd_shell(arg->devname, arg->arg);
     388
     389        stdin  = ostd[0];
     390        stdout = ostd[1];
     391        stderr = ostd[2];
     392
     393cleanup:
     394        release_a_Connection(arg->devname, arg->peername, nstd, i);
     395        free(arg);
     396}
     397
     398struct wrap_delete_args {
     399        void (*t)(void *);
     400        void           *a;
     401};
     402
     403static rtems_task
     404wrap_delete(rtems_task_argument arg)
     405{
     406struct wrap_delete_args     *pwa = (struct wrap_delete_args *)arg;
     407register void              (*t)(void *) = pwa->t;
     408register void               *a   = pwa->a;
     409
     410        /* free argument before calling function (which may never return if
     411         * they choose to delete themselves)
     412         */
     413        free(pwa);
     414        t(a);
     415        rtems_task_delete(RTEMS_SELF);
     416}
     417
     418void *
     419telnetd_dflt_spawn(const char *name, unsigned int priority, unsigned int stackSize, void (*fn)(void *), void* fnarg)
     420{
     421rtems_status_code sc;
     422rtems_id          task_id;
     423char              nm[4] = {'X','X','X','X' };
     424struct wrap_delete_args *pwa = malloc(sizeof(*pwa));
     425
     426                strncpy(nm, name, 4);
     427
     428                if ( !pwa ) {
     429                        perror("Telnetd: no memory\n");
     430                        return 0;
     431                }
     432
     433                pwa->t = fn;
     434                pwa->a = fnarg;
     435
     436                if ((sc=rtems_task_create(
     437                                rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
     438                                (rtems_task_priority)priority,
     439                                stackSize,
     440                                RTEMS_DEFAULT_MODES,
     441                                RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
     442                                &task_id)) ||
     443                        (sc=rtems_task_start(
     444                                task_id,
     445                                wrap_delete,
     446                                (rtems_task_argument)pwa))) {
     447                                        free(pwa);
     448                                        rtems_error(sc,"Telnetd: spawning task failed");
     449                                        return 0;
     450                }
     451        return (void*)task_id;
     452}
     453
     454/* convenience routines for CEXP (retrieve stdio descriptors
     455 * from reent structure)
     456 *
     457 */
     458#ifdef stdin
     459static __inline__ FILE *
     460_stdin(void)  { return stdin; }
     461#undef stdin
     462FILE *stdin(void)  { return _stdin(); }
     463#endif
     464#ifdef stdout
     465static __inline__ FILE *
     466_stdout(void) { return stdout; }
     467#undef stdout
     468FILE *stdout(void) { return _stdout(); }
     469#endif
     470#ifdef stderr
     471static __inline__ FILE *
     472_stderr(void) { return stderr; }
     473#undef stderr
     474FILE *stderr(void) { return _stderr(); }
     475#endif
     476
     477/* MUST NOT USE stdin & friends below here !!!!!!!!!!!!! */
Note: See TracChangeset for help on using the changeset viewer.