Notice: We have migrated to GitLab launching 2024-05-01 see here: https://gitlab.rtems.org/

Ticket #1389: login_v1.patch

File login_v1.patch, 41.6 KB (added by Sebastian Huber, on 03/10/09 at 11:46:15)

Patch for CVS HEAD.

  • cpukit/telnetd/check_passwd.c

    RCS file: /usr1/CVS/rtems/cpukit/telnetd/check_passwd.c,v
    retrieving revision 1.2
    diff -u -r1.2 check_passwd.c
     
    11/* $Id: check_passwd.c,v 1.2 2008/10/15 17:37:15 joel Exp $ */
    22
    3 /* Read a password, encrypt it and compare to the encrypted
    4  * password in the TELNETD_PASSWD environment variable.
    5  * No password is required if TELNETD_PASSWD is unset
    6  */
    7 
    8 /*
     3/*
    94 * Authorship
    105 * ----------
    116 * This software was created by
    127 *     Till Straumann <strauman@slac.stanford.edu>, 2003-2007
    138 *         Stanford Linear Accelerator Center, Stanford University.
    14  * 
     9 *
    1510 * Acknowledgement of sponsorship
    1611 * ------------------------------
    1712 * This software was produced by
    1813 *     the Stanford Linear Accelerator Center, Stanford University,
    1914 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
    20  * 
     15 *
    2116 * Government disclaimer of liability
    2217 * ----------------------------------
    2318 * Neither the United States nor the United States Department of Energy,
     
    2621 * completeness, or usefulness of any data, apparatus, product, or process
    2722 * disclosed, or represents that its use would not infringe privately owned
    2823 * rights.
    29  * 
     24 *
    3025 * Stanford disclaimer of liability
    3126 * --------------------------------
    3227 * Stanford University makes no representations or warranties, express or
    3328 * implied, nor assumes any liability for the use of this software.
    34  * 
     29 *
    3530 * Stanford disclaimer of copyright
    3631 * --------------------------------
    3732 * Stanford University, owner of the copyright, hereby disclaims its
    3833 * copyright and all other rights in this software.  Hence, anyone may
    39  * freely use it for any purpose without restriction. 
    40  * 
     34 * freely use it for any purpose without restriction.
     35 *
    4136 * Maintenance of notices
    4237 * ----------------------
    4338 * In the interest of clarity regarding the origin and status of this
     
    4641 * or distributed by the recipient and are to be affixed to any copy of
    4742 * software made or distributed by the recipient that contains a copy or
    4843 * derivative of this software.
    49  * 
     44 *
    5045 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
    51  */
     46 *
     47 * Modified by Sebastian Huber (2009).
     48 */
    5249
    53 #if !defined(INSIDE_TELNETD) && !defined(__rtems__)
    54 #include <crypt.h>
    55 #endif
    5650#include <termios.h>
    5751#include <errno.h>
    5852#include <stdio.h>
     
    6155#include <string.h>
    6256#include <syslog.h>
    6357
    64 #include "passwd.h"
     58#include <rtems/telnetd.h>
    6559
    66 /* rtems has global filedescriptors but per-thread stdio streams... */
    67 #define STDI_FD fileno(stdin)
    68 #define MAXPASSRETRY    3
    69 
    70 extern char *__des_crypt_r(char *, char*, char*, int);
    71 
    72 #if !defined(INSIDE_TELNETD)
    73 #define sockpeername(s,b,sz) (-1)
    74 #endif
    75 
    76 #if defined(INSIDE_TELNETD)
    77 static
    78 #endif
    79 int check_passwd(char *peername)
    80 {
    81   char                  *pw;
    82   int                   rval = -1, tmp, retries;
    83   struct termios        t,told;
    84   int                   restore_flags = 0;
    85   char                  buf[30], cryptbuf[21];
    86   char                  salt[3];
    87 
    88   if ( !(pw=getenv("TELNETD_PASSWD")) || 0 == strlen(pw) )
    89 #ifdef TELNETD_DEFAULT_PASSWD
    90     pw = TELNETD_DEFAULT_PASSWD;
    91 #else
    92     return 0;
    93 #endif
    94 
    95   if ( tcgetattr(STDI_FD, &t) ) {
    96     perror("check_passwd(): tcgetattr");
    97     goto done; 
    98   }
    99   told = t;
    100   t.c_lflag &= ~ECHO;
    101   t.c_lflag &= ~ICANON;
    102   t.c_cc[VTIME] = 255;
    103   t.c_cc[VMIN]  = 0;
    104 
    105   strncpy(salt,pw,2);
    106   salt[2]=0;
    107 
    108   if ( tcsetattr(STDI_FD, TCSANOW, &t) ) {
    109     perror("check_passwd(): tcsetattr");
    110     goto done; 
    111   }
    112   restore_flags = 1;
    113 
    114   /* Here we ask for the password... */
    115   for ( retries = MAXPASSRETRY; retries > 0; retries-- ) {
    116     fflush(stdin);
    117     fprintf(stderr,"Password:");
    118     fflush(stderr);
    119     if ( 0 == fgets(buf,sizeof(buf),stdin) ) {
    120       /* Here comes an ugly hack:
    121        * The termios driver's 'read()' handler
    122        * returns 0 to the c library's fgets if
    123        * it times out. 'fgets' interprets this
    124        * (correctly) as EOF, a condition we want
    125        * to undo since it's not really true since
    126        * we really have a read error (termios bug??)
    127        *
    128        * As a workaround we push something back and
    129        * read it again. This should simply reset the
    130        * EOF condition.
    131        */
    132       if (ungetc('?',stdin) >= 0)
    133         fgetc(stdin);
    134       goto done;
    135     }
    136     fputc('\n',stderr);
    137     tmp = strlen(buf);
    138     while ( tmp > 0 && ('\n' == buf[tmp-1] || '\r' == buf[tmp-1]) ) {
    139       buf[--tmp]=0;
    140     }
    141     if ( !strcmp(__des_crypt_r(buf, salt, cryptbuf, sizeof(cryptbuf)), pw) ) {
    142       rval = 0;
    143       break;
    144     }
    145     fprintf(stderr,"Incorrect Password.\n");
    146     sleep(2);
    147   }
    148 
    149   if ( 0 == retries ) {
    150     syslog( LOG_AUTHPRIV | LOG_WARNING,
    151       "telnetd: %i wrong passwords entered from %s",
    152       MAXPASSRETRY,
    153       peername ? peername : "<UNKNOWN>");
    154   }
     60#include "passwd.h"
    15561
    156 done:
    157   /* what to do if restoring the flags fails?? */
    158   if (restore_flags)
    159     tcsetattr(STDI_FD, TCSANOW, &told);
    160  
    161   if (rval) {
    162     sleep(2);
    163   }
    164   return rval;
    165 }
     62char *__des_crypt_r( const char *, const char *, char *, int);
    16663
    167 #if !defined(INSIDE_TELNETD) && !defined(__rtems__)
    168 int
    169 main(int argc, char **argv)
     64/**
     65 * @brief Standard Telnet login check that uses DES to encrypt the passphrase.
     66 *
     67 * Takes a @a passphrase, encrypts it and compares it to the encrypted
     68 * passphrase in the @c TELNETD_PASSWD environment variable.  No password is
     69 * required if @c TELNETD_PASSWD is unset.  The argument @a user is ignored.
     70 */
     71bool rtems_telnetd_login_check(
     72  const char *user,
     73  const char *passphrase
     74)
    17075{
    171 char *str, *enc=0;
    172 int   ch;
    173 
    174 while ( (ch=getopt(argc, argv, "g:")) > 0 ) {
    175   switch (ch) {
    176     default:
    177       fprintf(stderr,"Unknown option\n");
    178     return(1);
    179 
    180     case 'g':
    181       printf("Generated encrypted password: '%s'\n", (enc=crypt(optarg,"td")));
    182     break;
    183      
    184   }
     76  char *pw = getenv( "TELNETD_PASSWD");
     77  char cryptbuf [21];
     78  char salt [3];
     79
     80  if (pw == NULL || strlen( pw) == 0) {
     81    #ifdef TELNETD_DEFAULT_PASSWD
     82      pw = TELNETD_DEFAULT_PASSWD;
     83    #else
     84      return true;
     85    #endif
     86  }
     87
     88  strncpy( salt, pw, 2);
     89  salt [2] = '\0';
     90
     91  return strcmp(
     92    __des_crypt_r( passphrase, salt, cryptbuf, sizeof( cryptbuf)),
     93    pw
     94  ) == 0;
    18595}
    186 if (argc>optind && !enc) {
    187   enc=argv[optind];
    188 }
    189 if (enc) {
    190   str = malloc(strlen(enc) + 30);
    191   sprintf(str,"TELNETD_PASSWD=%s",enc);
    192   putenv(str);
    193 }
    194 if (check_passwd(-1)) {
    195   fprintf(stderr,"check_passwd() failed\n");
    196 }
    197 return 0;
    198 }
    199 
    200 #endif
  • cpukit/telnetd/telnetd.c

    RCS file: /usr1/CVS/rtems/cpukit/telnetd/telnetd.c,v
    retrieving revision 1.13
    diff -u -r1.13 telnetd.c
     
    55 *
    66 *  Author: 17,may 2001
    77 *
    8  *   WORK: fernando.ruiz@ctv.es 
     8 *   WORK: fernando.ruiz@ctv.es
    99 *   HOME: correo@fernando-ruiz.com
    1010 *
    1111 * After start the net you can start this daemon.
     
    1515 *
    1616 * With register_telnetd() you add a new command in the shell to start
    1717 * this daemon interactively. (Login in /dev/console of course)
    18  * 
     18 *
    1919 * Sorry but OOB is not still implemented. (This is the first version)
    2020 *
    2121 * Till Straumann <strauman@slac.stanford.edu>
     
    2323 *    possible to have 'telnetd' run an arbitrary 'shell'
    2424 *    program.
    2525 *
     26 * Modified by Sebastian Huber (2009).
     27 *
    2628 *  This program is distributed in the hope that it will be useful,
    2729 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2830 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    29  * 
     31 *
    3032 *  $Id: telnetd.c,v 1.13 2008/10/15 17:37:15 joel Exp $
    3133 */
    3234
     
    7375
    7476static int sockpeername(int sock, char *buf, int bufsz);
    7577
    76 static int initialize_telnetd(void);
    77 static int telnetd_askForPassword;
    78 
    79 void * telnetd_dflt_spawn(
     78void *telnetd_dflt_spawn(
    8079  const char *name,
    8180  unsigned priority,
    8281  unsigned stackSize,
     
    8584);
    8685
    8786/***********************************************************/
    88 rtems_id            telnetd_task_id                 = 0;
    89 uint32_t            telnetd_stack_size              = 32000;
    90 rtems_task_priority telnetd_task_priority           = 0;
    91 bool                telnetd_remain_on_caller_stdio  = false;
    92 void                (*telnetd_shell)(char *, void*) = 0;
    93 void                *telnetd_shell_arg              = NULL;
    94 void *              (*telnetd_spawn_task)(
     87static rtems_id telnetd_task_id = RTEMS_ID_NONE;
     88
     89void *(*telnetd_spawn_task)(
    9590  const char *,
    9691  unsigned,
    9792  unsigned,
    9893  void (*)(void*),
    99   void *) = telnetd_dflt_spawn;
     94  void *
     95) = telnetd_dflt_spawn;
    10096
    10197static char *grab_a_Connection(
    10298  int des_socket,
     
    178174  return rval;
    179175}
    180176
    181 #if 1
    182 #define INSIDE_TELNETD
    183 #include "check_passwd.c"
    184 #else
    185 #define check_passwd(arg) 0
    186 #endif
    187 
    188 
    189177static void
    190178spawned_shell(void *arg);
    191179
     
    203191
    204192  if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
    205193    perror("telnetd:socket");
    206     telnetd_task_id=0;
     194    telnetd_task_id = RTEMS_ID_NONE;
    207195    rtems_task_delete(RTEMS_SELF);
    208196  };
    209197  setsockopt(des_socket,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i));
     
    215203  if ((bind(des_socket,&srv.sa,size_adr))<0) {
    216204    perror("telnetd:bind");
    217205    close(des_socket);
    218     telnetd_task_id=0;
     206    telnetd_task_id = RTEMS_ID_NONE;
    219207    rtems_task_delete(RTEMS_SELF);
    220208  };
    221209  if ((listen(des_socket,5))<0) {
    222210    perror("telnetd:listen");
    223211          close(des_socket);
    224     telnetd_task_id=0;
     212    telnetd_task_id = RTEMS_ID_NONE;
    225213    rtems_task_delete(RTEMS_SELF);
    226214  };
    227215
     
    229217   * was started from the console anyways..
    230218   */
    231219  do {
    232     if ( telnetd_remain_on_caller_stdio ) {
    233       char device_name[32];
    234       ttyname_r( 1, device_name, sizeof(device_name) );
    235       if ( !telnetd_askForPassword || (0 == check_passwd(arg->peername)) )
    236         telnetd_shell(device_name, telnetd_shell_arg);
     220    if (rtems_telnetd_config.keep_stdio) {
     221      bool start = true;
     222      char device_name [32];
     223
     224      ttyname_r( 1, device_name, sizeof( device_name));
     225      if (rtems_telnetd_config.login_check != NULL) {
     226        start = rtems_shell_login_prompt(
     227          stdin,
     228          stderr,
     229          device_name,
     230          rtems_telnetd_config.login_check
     231        );
     232      }
     233      if (start) {
     234        rtems_telnetd_config.command( device_name, arg->arg);
     235      } else {
     236        syslog(
     237          LOG_AUTHPRIV | LOG_WARNING,
     238          "telnetd: to many wrong passwords entered from %s",
     239          device_name
     240        );
     241      }
    237242    } else {
    238243      devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername));
    239244
    240245      if ( !devname ) {
    241         /* if something went wrong, sleep for some time */
    242         sleep(10);
    243         continue;
     246        /* if something went wrong, sleep for some time */
     247        sleep(10);
     248        continue;
    244249      }
    245250
    246251      arg = malloc( sizeof(*arg) );
    247252
    248253      arg->devname = devname;
    249       arg->arg = telnetd_shell_arg;
     254      arg->arg = rtems_telnetd_config.arg;
    250255      strncpy(arg->peername, peername, sizeof(arg->peername));
    251256
    252       if ( !telnetd_spawn_task( &devname[5], telnetd_task_priority,
    253                telnetd_stack_size, spawned_shell, arg) ) {
     257      telnetd_task_id = (rtems_id) telnetd_spawn_task(
     258        devname,
     259        rtems_telnetd_config.priority,
     260        rtems_telnetd_config.stack_size,
     261        spawned_shell,
     262        arg
     263      );
     264      if (telnetd_task_id == RTEMS_ID_NONE) {
    254265        FILE *dummy;
    255266
    256267        if ( telnetd_spawn_task != telnetd_dflt_spawn ) {
     
    273284    }
    274285  } while(1);
    275286
    276   /* TODO: how to free the connection semaphore? But then - 
     287  /* TODO: how to free the connection semaphore? But then -
    277288   *       stopping the daemon is probably only needed during
    278289   *       development/debugging.
    279290   *       Finalizer code should collect all the connection semaphore
    280291   *       counts and eventually clean up...
    281292   */
    282293  close(des_socket);
    283   telnetd_task_id=0;
     294  telnetd_task_id = RTEMS_ID_NONE;
    284295}
    285296
    286 /***********************************************************/
    287 static int initialize_telnetd(void) {
    288  
    289   if (telnetd_task_id         ) return RTEMS_RESOURCE_IN_USE;
    290   if (telnetd_stack_size<=0   ) telnetd_stack_size   =32000;
    291 
    292   if ( !telnetd_spawn_task("TNTD", telnetd_task_priority,
    293           RTEMS_MINIMUM_STACK_SIZE, rtems_task_telnetd, 0) ) {
    294     return -1;
     297rtems_status_code rtems_telnetd_initialize( void)
     298{
     299  rtems_status_code sc = RTEMS_SUCCESSFUL;
     300
     301  if (telnetd_task_id != RTEMS_ID_NONE) {
     302    fprintf(stderr, "telnetd already started\n");
     303    return RTEMS_RESOURCE_IN_USE;
    295304  }
    296   return 0;
    297 }
    298305
    299 /***********************************************************/
    300 int rtems_telnetd_initialize(
    301   void               (*cmd)(char *, void *),
    302   void                *arg,
    303   bool                 remainOnCallerSTDIO,
    304   size_t               stack,
    305   rtems_task_priority  priority,
    306   bool                 askForPassword
    307 )
    308 {
    309   rtems_status_code sc;
     306  if (rtems_telnetd_config.command == NULL) {
     307    fprintf(stderr, "telnetd setup with invalid command\n");
     308    return RTEMS_IO_ERROR;
     309  }
    310310
    311 #if 0
    312   printf("This is rtems-telnetd (modified by Till Straumann)\n");
    313   printf("$Id: telnetd.c,v 1.13 2008/10/15 17:37:15 joel Exp $\n");
    314   printf("Release $Name:  $\n");
    315 #endif
     311  if ( !telnet_pty_initialize() ) {
     312    fprintf(stderr, "telnetd cannot initialize PTY driver\n");
     313    return RTEMS_IO_ERROR;
     314  }
    316315
    317   if ( !telnetd_shell && !cmd ) {
    318     fprintf(stderr,"startTelnetd(): setup error - NO SHELL; bailing out\n");
    319     return 1;
     316  /* Check priority */
     317  if (rtems_telnetd_config.priority <= 0) {
     318    rtems_telnetd_config.priority = rtems_bsdnet_config.network_task_priority;
     319  }
     320  if (rtems_telnetd_config.priority < 2) {
     321    rtems_telnetd_config.priority = 100;
    320322  }
    321323
    322   if (telnetd_task_id) {
    323     fprintf(stderr,"ERROR:telnetd already started\n");
    324     return 1;
    325   };
     324  /* Check stack size */
     325  if (rtems_telnetd_config.stack_size <= 0) {
     326    rtems_telnetd_config.stack_size = 32 * 1024;
     327  }
    326328
    327   if ( !telnet_pty_initialize() ) {
    328     fprintf(stderr,"PTY driver probably not properly registered\n");
    329     return 1;
     329  /* Spawn task */
     330  telnetd_task_id = (rtems_id) telnetd_spawn_task(
     331    "TNTD",
     332    rtems_telnetd_config.priority,
     333    RTEMS_MINIMUM_STACK_SIZE,
     334    rtems_task_telnetd,
     335    0
     336  );
     337  if (telnetd_task_id == RTEMS_ID_NONE) {
     338    return RTEMS_IO_ERROR;
    330339  }
    331340
    332   telnetd_askForPassword = askForPassword;
     341  /* Print status */
     342  if (!rtems_telnetd_config.keep_stdio) {
     343    fprintf(
     344      stderr,
     345      "telnetd started with stacksize = %u and priority = %d\n",
     346      (unsigned) rtems_telnetd_config.stack_size,
     347      (unsigned) rtems_telnetd_config.priority
     348    );
     349  }
    333350
    334   if (cmd)
    335     telnetd_shell = cmd;
    336   telnetd_shell_arg     = arg;
    337   telnetd_stack_size    = stack;
    338   if ( !priority ) {
    339     priority = rtems_bsdnet_config.network_task_priority;
    340   }
    341   if ( priority < 2 )
    342     priority = 100;
    343   telnetd_task_priority          = priority;
    344   telnetd_remain_on_caller_stdio = remainOnCallerSTDIO;
    345 
    346   sc = initialize_telnetd();
    347   if (sc != RTEMS_SUCCESSFUL) return sc;
    348 
    349   if ( !telnetd_remain_on_caller_stdio )
    350     fprintf(stderr, "rtems_telnetd() started with stacksize=%u,priority=%d\n",
    351       (unsigned)telnetd_stack_size,(int)telnetd_task_priority);
    352   return 0;
     351  return RTEMS_SUCCESSFUL;
    353352}
    354353
    355354/* utility wrapper */
     
    361360  FILE                *ostd[3]={ stdin, stdout, stderr };
    362361  int                  i=0;
    363362  struct shell_args  *arg = targ;
     363  bool login_failed = false;
     364  bool start = true;
    364365
    365366  sc=rtems_libio_set_private_env();
    366367
     
    397398  #endif
    398399
    399400  /* call their routine */
    400   if ( !telnetd_askForPassword || (0 == check_passwd(arg->peername)) )
    401     telnetd_shell(arg->devname, arg->arg);
     401  if (rtems_telnetd_config.login_check != NULL) {
     402    start = rtems_shell_login_prompt(
     403      stdin,
     404      stderr,
     405      arg->devname,
     406      rtems_telnetd_config.login_check
     407    );
     408    login_failed = !start;
     409  }
     410  if (start) {
     411    rtems_telnetd_config.command( arg->devname, arg->arg);
     412  }
    402413
    403414  stdin  = ostd[0];
    404415  stdout = ostd[1];
    405416  stderr = ostd[2];
    406417
     418  if (login_failed) {
     419    syslog(
     420      LOG_AUTHPRIV | LOG_WARNING,
     421      "telnetd: to many wrong passwords entered from %s",
     422      arg->peername
     423    );
     424  }
     425
    407426cleanup:
    408427  release_a_Connection(arg->devname, arg->peername, nstd, i);
    409428  free(arg);
     
    433452telnetd_dflt_spawn(const char *name, unsigned int priority, unsigned int stackSize, void (*fn)(void *), void* fnarg)
    434453{
    435454  rtems_status_code        sc;
    436   rtems_id                 task_id;
     455  rtems_id                 task_id = RTEMS_ID_NONE;
    437456  char                     nm[4] = {'X','X','X','X' };
    438457  struct wrap_delete_args *pwa = malloc(sizeof(*pwa));
    439458
     
    441460
    442461  if ( !pwa ) {
    443462    perror("Telnetd: no memory\n");
    444     return 0;
     463    return (void *) RTEMS_ID_NONE;
    445464  }
    446465
    447466  pwa->t = fn;
     
    460479      (rtems_task_argument)pwa))) {
    461480        free(pwa);
    462481        rtems_error(sc,"Telnetd: spawning task failed");
    463         return 0;
     482        return (void *) RTEMS_ID_NONE;
    464483  }
    465   return (void*)task_id;
     484  return (void *) task_id;
    466485}
    467486
    468487/* convenience routines for CEXP (retrieve stdio descriptors
  • cpukit/telnetd/telnetd.h

    RCS file: /usr1/CVS/rtems/cpukit/telnetd/telnetd.h,v
    retrieving revision 1.8
    diff -u -r1.8 telnetd.h
     
    33 *  May 2001
    44 *  Reworked by Till Straumann and .h overhauled by Joel Sherrill.
    55 *
     6 *  Modified by Sebastian Huber (2009).
     7 *
    68 *  This program is distributed in the hope that it will be useful,
    79 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    810 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     
    1315#ifndef _RTEMS_TELNETD_H
    1416#define _RTEMS_TELNETD_H
    1517
     18#include <rtems.h>
     19#include <rtems/login.h>
     20
    1621#ifdef __cplusplus
    1722extern "C" {
    18 #endif 
     23#endif
     24
     25bool rtems_telnetd_login_check(
     26  const char *user,
     27  const char *passphrase
     28);
     29
     30/**
     31 * @brief Telnet command type.
     32 */
     33typedef void (*rtems_telnetd_command)(char * /* device name */, void * /* arg */);
     34
     35/**
     36 * @brief Telnet configuration structure.
     37 */
     38typedef struct {
     39  /**
     40   * @brief Function invoked for each Telnet connection.
     41   *
     42   * The first parameter contains the device name.  The second parameter
     43   * contains the argument pointer of this configuration table.
     44   */
     45  rtems_telnetd_command command;
     46
     47  /**
     48   * @brief Argument for command function.
     49   */
     50  void *arg;
     51
     52  /**
     53   * @brief Task priority.
     54   *
     55   * If this parameter is equal to zero, then the priority of network task is
     56   * used or 100 if this priority is less than two.
     57   */
     58  rtems_task_priority priority;
     59
     60  /**
     61   * @brief Task stack size.
     62   */
     63  size_t stack_size;
     64
     65  /**
     66   * @brief Login check function.
     67   *
     68   * Method used for login checks.  Use @c NULL to disable a login check.
     69   */
     70  rtems_login_check login_check;
     71
     72  /**
     73   * @brief Keep standard IO of the caller.
     74   *
     75   * Telnet takes over the standard input, output and error associated with
     76   * task, if this parameter is set to @c true.  In this case, it will @b not
     77   * listen on any sockets.  When this parameter is @c false, Telnet will
     78   * create other tasks for the shell which listen on sockets.
     79   */
     80  bool keep_stdio;
     81} rtems_telnetd_config_table;
    1982
    2083/**
    21  *  This method initializes the telnetd subsystem.
     84 * @brief Telnet configuration.
    2285 *
    23  *  @param[in] cmd is the function which is the "shell" telnetd invokes
    24  *  @param[in] arg is the context pointer to cmd
    25  *  @param[in] remainOnCallerSTDIO is set to TRUE if telnetd takes over the
    26  *    standard in, out and error associated with task.  In this case,
    27  *    it will be NOT be listening on any sockets.  When this parameters
    28  *    is FALSE the telnetd will create other tasks for the shell
    29  *    which listen on sockets.
    30  *  @param[in] stack is stack size of spawned task.
    31  *  @param[in] priority is the initial priority of spawned task(s).  If
    32  *    this parameter is less than 2, then the default priority of 100 is used.
    33  *  @param[in] askForPassword is set to TRUE if telnetd is to ask for a
    34  *    password. This is set to FALSE to invoke "cmd" with no password check.
    35  *    This may be OK if "cmd" includes its own check and indeed the RTEMS Shell
    36  *    uses a login with a user name and password so this is the usual case.
     86 * The application must provide this configuration table.  It is used by
     87 * rtems_telnetd_initialize() to configure the Telnet subsystem.  Do not modify
     88 * the entries after the intialization since it is used internally.
    3789 */
    38 int rtems_telnetd_initialize(
    39   void               (*cmd)(char *, void *),
    40   void                *arg,
    41   bool                 remainOnCallerSTDIO,
    42   size_t               stack,
    43   rtems_task_priority  priority,
    44   bool                 askForPassword
    45 );
     90extern rtems_telnetd_config_table rtems_telnetd_config;
     91
     92/**
     93 * @brief Initializes the Telnet subsystem.
     94 *
     95 * Uses the application provided @ref rtems_telnetd_config configuration table.
     96 */
     97rtems_status_code rtems_telnetd_initialize( void);
    4698
    4799#ifdef __cplusplus
    48100}
    49 #endif 
     101#endif
    50102
    51103#endif
  • cpukit/libmisc/Makefile.am

    RCS file: /usr1/CVS/rtems/cpukit/libmisc/Makefile.am,v
    retrieving revision 1.66
    diff -u -r1.66 Makefile.am
     
    8585    shell/err.c shell/errx.c shell/verr.c shell/vis.c \
    8686    shell/verrx.c shell/vwarn.c shell/vwarnx.c shell/warn.c shell/warnx.c \
    8787    shell/fts.c shell/print_heapinfo.c shell/main_wkspaceinfo.c \
    88     shell/shell_script.c
     88    shell/shell_script.c shell/login_prompt.c shell/login_check.c
    8989if LIBNETWORKING
    9090libshell_a_SOURCES += shell/main_mount_ftp.c shell/main_mount_tftp.c \
    9191    shell/main_ifconfig.c shell/main_route.c shell/main_netstats.c \
  • new file cpukit/libmisc/shell/login.h

    RCS file: cpukit/libmisc/shell/login.h
    diff -N cpukit/libmisc/shell/login.h
    - +  
     1/**
     2 * @file
     3 *
     4 * @author Sebastian Huber <sebastian.huber@embedded-brains.de>
     5 *
     6 * @brief Login types and functions.
     7 */
     8
     9/*
     10 * Copyright (c) 2009
     11 * Embedded Brains GmbH
     12 * Obere Lagerstr. 30
     13 * D-82178 Puchheim
     14 * Germany
     15 * rtems@embedded-brains.de
     16 *
     17 * Based on work from Chris Johns, Fernando Ruiz and Till Straumann.
     18 *
     19 * The license and distribution terms for this file may be
     20 * found in the file LICENSE in this distribution or at
     21 * http://www.rtems.com/license/LICENSE.
     22 */
     23
     24#ifndef RTEMS_LOGIN_H
     25#define RTEMS_LOGIN_H
     26
     27#include <stdio.h>
     28
     29#include <rtems.h>
     30
     31#ifdef __cplusplus
     32extern "C" {
     33#endif /* __cplusplus */
     34
     35typedef bool (*rtems_login_check)(
     36  const char * /* user */,
     37  const char * /* passphrase */
     38);
     39
     40bool rtems_shell_login_prompt(
     41  FILE *in,
     42  FILE *out,
     43  const char *device,
     44  rtems_login_check check
     45);
     46
     47bool rtems_shell_login_check(
     48  const char *user,
     49  const char *passphrase
     50);
     51
     52#ifdef __cplusplus
     53}
     54#endif /* __cplusplus */
     55
     56#endif /* RTEMS_LOGIN_H */
  • new file cpukit/libmisc/shell/login_check.c

    RCS file: cpukit/libmisc/shell/login_check.c
    diff -N cpukit/libmisc/shell/login_check.c
    - +  
     1/**
     2 * @file
     3 *
     4 * @author Sebastian Huber <sebastian.huber@embedded-brains.de>
     5 *
     6 * @brief Shell login check function.
     7 */
     8
     9/*
     10 * Copyright (c) 2009
     11 * Embedded Brains GmbH
     12 * Obere Lagerstr. 30
     13 * D-82178 Puchheim
     14 * Germany
     15 * rtems@embedded-brains.de
     16 *
     17 * Based on work from Chris Johns, Fernando Ruiz and Till Straumann.
     18 *
     19 * The license and distribution terms for this file may be
     20 * found in the file LICENSE in this distribution or at
     21 * http://www.rtems.com/license/LICENSE.
     22 */
     23
     24#include <sys/types.h>
     25#include <unistd.h>
     26#include <pwd.h>
     27
     28#include <rtems/login.h>
     29#include <rtems/shell.h>
     30#include <rtems/userenv.h>
     31
     32bool rtems_shell_login_check(
     33  const char *user,
     34  const char *passphrase
     35)
     36{
     37  struct passwd *pw = getpwnam( user);
     38
     39  /* Valid user? */
     40  if (pw != NULL && strcmp( pw->pw_passwd, "!") != 0) {
     41    setuid( pw->pw_uid);
     42    setgid( pw->pw_gid);
     43    rtems_current_user_env->euid = 0;
     44    rtems_current_user_env->egid = 0;
     45    chown( rtems_current_shell_env->devname, pw->pw_uid, 0);
     46    rtems_current_user_env->euid = pw->pw_uid;
     47    rtems_current_user_env->egid = pw->pw_gid;
     48    if (strcmp( pw->pw_passwd, "*") == 0) {
     49      /* TODO: /etc/shadow */
     50      return true;
     51    } else {
     52      /* TODO: crypt() */
     53      return true;
     54    }
     55  }
     56
     57  return false;
     58}
  • new file cpukit/libmisc/shell/login_prompt.c

    RCS file: cpukit/libmisc/shell/login_prompt.c
    diff -N cpukit/libmisc/shell/login_prompt.c
    - +  
     1/**
     2 * @file
     3 *
     4 * @author Sebastian Huber <sebastian.huber@embedded-brains.de>
     5 *
     6 * @brief Shell login prompt functions.
     7 */
     8
     9/*
     10 * Copyright (c) 2009
     11 * Embedded Brains GmbH
     12 * Obere Lagerstr. 30
     13 * D-82178 Puchheim
     14 * Germany
     15 * rtems@embedded-brains.de
     16 *
     17 * Based on work from Chris Johns, Fernando Ruiz and Till Straumann.
     18 *
     19 * The license and distribution terms for this file may be
     20 * found in the file LICENSE in this distribution or at
     21 * http://www.rtems.com/license/LICENSE.
     22 */
     23
     24#include <stdio.h>
     25#include <termios.h>
     26#include <unistd.h>
     27#include <ctype.h>
     28
     29#include <rtems/login.h>
     30
     31static int rtems_shell_discard( int c, FILE *stream)
     32{
     33  return c;
     34}
     35
     36static void rtems_shell_get_text(
     37  FILE *in,
     38  FILE *out,
     39  char *line,
     40  size_t size
     41)
     42{
     43  int fd_in = fileno( in);
     44  int (*put)( int, FILE *) =
     45    out != NULL && isatty( fd_in)
     46      ? fputc
     47      : rtems_shell_discard;
     48  size_t i = 0;
     49
     50  if (size < 1) {
     51    return;
     52  }
     53
     54  tcdrain( fd_in);
     55  if (out != NULL){
     56    tcdrain( fileno( out));
     57  }
     58
     59  while (true) {
     60    int c = fgetc( in);
     61
     62    switch (c) {
     63      case EOF:
     64        /* Here comes an ugly hack: The Termios driver's read() handler returns
     65         * 0 to the C library's fgets() if it times out.  fgets() interprets
     66         * this (correctly) as EOF, a condition we want to undo since it's not
     67         * really true since we really have a read error (Termios bug?).
     68         *
     69         * As a workaround we push something back and read it again.  This
     70         * should simply reset the EOF condition.
     71         */
     72        if (ungetc( '?', in) == '?') {
     73          fgetc( in);
     74        }
     75        break;
     76      case '\n':
     77      case '\r':
     78        put( '\n', out);
     79        line [i] = '\0';
     80        return;
     81      case  127:
     82      case '\b':
     83        if (i > 0) {
     84          put( '\b', out);
     85          put( ' ', out);
     86          put( '\b', out);
     87          --i;
     88        } else {
     89          put( '\a', out);
     90        }
     91        break;
     92      default:
     93        if (!iscntrl( c)) {
     94          if (i < size - 1) {
     95            line [i] = (char) c;
     96            ++i;
     97            put( c, out);
     98          } else {
     99            put( '\a', out);
     100          }
     101        } else {
     102          put( '\a', out);
     103        }
     104        break;
     105    }
     106  }
     107}
     108
     109bool rtems_shell_login_prompt(
     110  FILE *in,
     111  FILE *out,
     112  const char *device,
     113  rtems_login_check check
     114)
     115{
     116  int fd_in = fileno( in);
     117  struct termios termios_previous;
     118  bool restore_termios = false;
     119  int i = 0;
     120  bool result = false;
     121
     122  if (tcgetattr( fd_in, &termios_previous) == 0) {
     123    struct termios termios_new = termios_previous;
     124
     125    termios_new.c_lflag &= ~ECHO;
     126    termios_new.c_lflag &= ~ICANON;
     127    termios_new.c_cc [VTIME] = 255;
     128    termios_new.c_cc [VMIN] = 0;
     129
     130    restore_termios = tcsetattr( fd_in, TCSANOW, &termios_new) == 0;
     131  }
     132
     133  for (i = 0; i < 3; ++i) {
     134    char user [32];
     135    char passphrase [128];
     136
     137    fprintf( out, "%s login: ", device);
     138    fflush( out);
     139    rtems_shell_get_text( in, out, user, sizeof( user));
     140
     141    fflush( in);
     142    fprintf( out, "Password: ");
     143    fflush( out);
     144    rtems_shell_get_text( in, NULL, passphrase, sizeof( passphrase));
     145    fputc( '\n', out);
     146
     147    result = check( user, passphrase);
     148    if (result) {
     149      break;
     150    }
     151
     152    fprintf( out, "Login incorrect\n\n");
     153    sleep( 2);
     154  }
     155
     156  if (restore_termios) {
     157    /* What to do if restoring the flags fails? */
     158    tcsetattr( fd_in, TCSANOW, &termios_previous);
     159  }
     160
     161  return result;
     162}
  • cpukit/libmisc/shell/shell.c

    RCS file: /usr1/CVS/rtems/cpukit/libmisc/shell/shell.c,v
    retrieving revision 1.41
    diff -u -r1.41 shell.c
     
    77 *   WORK: fernando.ruiz@ctv.es
    88 *   HOME: correo@fernando-ruiz.com
    99 *
     10 *  Modified by Sebastian Huber (2009).
     11 *
    1012 *  The license and distribution terms for this file may be
    1113 *  found in the file LICENSE in this distribution or at
    1214 *  http://www.rtems.com/license/LICENSE.
     
    4042#include <errno.h>
    4143#include <pwd.h>
    4244
    43 rtems_shell_env_t  rtems_global_shell_env = {
     45rtems_shell_env_t rtems_global_shell_env = {
    4446  .magic         = rtems_build_name('S', 'E', 'N', 'V'),
    4547  .devname       = CONSOLE_DEVICE_NAME,
    4648  .taskname      = "SHGL",
     
    5355  .output        = NULL,
    5456  .output_append = false,
    5557  .wake_on_end   = RTEMS_ID_NONE,
    56   .login         = true
     58  .login_check   = NULL
    5759};
    5860
    5961rtems_shell_env_t *rtems_current_shell_env = &rtems_global_shell_env;
     
    118120  int          up;
    119121  int          cmd = -1;
    120122  int          inserting = 1;
    121  
     123
    122124  output = (out && isatty(fileno(in)));
    123125
    124126  col = last_col = 0;
    125  
     127
    126128  tcdrain(fileno(in));
    127129  if (out)
    128130    tcdrain(fileno(out));
    129131
    130132  if (output && prompt)
    131133    fprintf(out, "\r%s", prompt);
    132  
     134
    133135  line[0] = 0;
    134136  new_line[0] = 0;
    135  
     137
    136138  for (;;) {
    137    
     139
    138140    if (output)
    139141      fflush(out);
    140142
     
    142144
    143145    if (extended_key == EOF)
    144146      return -2;
    145    
     147
    146148    c = extended_key & RTEMS_SHELL_KEYS_NORMAL_MASK;
    147    
     149
    148150    /*
    149151     * Make the extended_key usable as a boolean.
    150152     */
    151153    extended_key &= ~RTEMS_SHELL_KEYS_NORMAL_MASK;
    152    
     154
    153155    up = 0;
    154    
     156
    155157    if (extended_key)
    156158    {
    157159      switch (c)
     
    199201
    200202          /* drop through */
    201203        case RTEMS_SHELL_KEYS_DARROW:
    202          
     204
    203205        {
    204206          int last_cmd = cmd;
    205207          int clen = strlen (line);
    206208
    207209          if (prompt)
    208210            clen += strlen(prompt);
    209          
     211
    210212          if (up) {
    211213            cmd++;
    212214          } else {
     
    226228            memcpy (line, new_line, size);
    227229          else
    228230            memcpy (line, cmds[cmd], size);
    229          
     231
    230232          col = strlen (line);
    231          
     233
    232234          if (output) {
    233235            fprintf(out,"\r%*c", clen, ' ');
    234236            fprintf(out,"\r%s%s", prompt, line);
     
    271273          }
    272274          col = 0;
    273275          break;
    274          
     276
    275277        case 5:/*Control-e*/
    276278          if (output)
    277279            fprintf(out,line + col);
     
    290292            line[col] = '\0';
    291293          }
    292294          break;
    293          
     295
    294296        case 0x04:/*Control-d*/
    295297          if (strlen(line))
    296298            break;
     
    298300          if (output)
    299301            fputc('\n', out);
    300302          return -2;
    301        
     303
    302304        case '\f':
    303305          if (output) {
    304306            int end;
     
    334336           */
    335337          if (output)
    336338            fprintf(out,"\n");
    337          
     339
    338340          /*
    339341           * Only process the command if we have a command and it is not
    340342           * repeated in the history.
     
    378380  return -2;
    379381}
    380382
    381 int rtems_shell_scanline(
    382   char *line,
    383   int   size,
    384   FILE *in,
    385   FILE *out
    386 )
    387 {
    388   int c;
    389   int col;
    390   int doEcho;
    391 
    392   doEcho = (out && isatty(fileno(in)));
    393 
    394   col = 0;
    395   if (*line) {
    396     col = strlen(line);
    397     if (doEcho) fprintf(out,"%s",line);
    398   }
    399   tcdrain(fileno(in));
    400   if (out)
    401     tcdrain(fileno(out));
    402   for (;;) {
    403     line[col] = 0;
    404     c = fgetc(in);
    405     switch (c) {
    406       case EOF:
    407         return 0;
    408       case '\n':
    409       case '\r':
    410         if (doEcho)
    411           fputc('\n',out);
    412         return 1;
    413       case  127:
    414       case '\b':
    415         if (col) {
    416           if (doEcho) {
    417             fputc('\b',out);
    418             fputc(' ',out);
    419             fputc('\b',out);
    420           }
    421           col--;
    422         } else {
    423           if (doEcho) fputc('\a',out);
    424         }
    425         break;
    426      default:
    427        if (!iscntrl(c)) {
    428          if (col<size-1) {
    429             line[col++] = c;
    430             if (doEcho) fputc(c,out);
    431           } else {
    432             if (doEcho) fputc('\a',out);
    433           }
    434        } else {
    435         if (doEcho)
    436           if (c=='\a') fputc('\a',out);
    437        }
    438        break;
    439      }
    440   }
    441 }
    442  
    443383/* ----------------------------------------------- *
    444384 * - The shell TASK
    445385 * Poor but enough..
     
    473413  }
    474414}
    475415
    476 int rtems_shell_login(FILE * in,FILE * out) {
     416static bool rtems_shell_login(FILE * in,FILE * out) {
    477417  FILE          *fd;
    478418  int            c;
    479419  time_t         t;
     
    584524    }
    585525  }
    586526
    587   times=0;
    588   strcpy(name,"");
    589   strcpy(pass,"");
    590   for (;;) {
    591     times++;
    592     if (times>3) break;
    593     if (out) fprintf(out,"\nlogin: ");
    594     if (!rtems_shell_scanline(name,sizeof(name),in,out )) break;
    595     if (out) fprintf(out,"Password: ");
    596     if (!rtems_shell_scanline(pass,sizeof(pass),in,NULL)) break;
    597     if (out) fprintf(out,"\n");
    598     if ((passwd=getpwnam(name))) {
    599       if (strcmp(passwd->pw_passwd,"!")) { /* valid user */
    600         setuid(passwd->pw_uid);
    601         setgid(passwd->pw_gid);
    602         rtems_current_user_env->euid =
    603         rtems_current_user_env->egid = 0;
    604         chown(rtems_current_shell_env->devname,passwd->pw_uid,0);
    605         rtems_current_user_env->euid = passwd->pw_uid;
    606         rtems_current_user_env->egid = passwd->pw_gid;
    607         if (!strcmp(passwd->pw_passwd,"*")) {
    608           /* /etc/shadow */
    609           return 0;
    610         } else {
    611           /* crypt() */
    612           return 0;
    613         }
    614       }
    615     }
    616     if (out)
    617       fprintf(out,"Login incorrect\n");
    618     strcpy(name,"");
    619     strcpy(pass,"");
    620   }
    621   return -1;
     527  return rtems_shell_login_prompt(
     528    in,
     529    out,
     530    rtems_current_shell_env->devname,
     531    rtems_current_shell_env->login_check
     532  );
    622533}
    623534
    624535#if defined(SHELL_DEBUG)
     
    686597
    687598  shell_env =
    688599  rtems_current_shell_env = rtems_shell_init_env( shell_env_arg );
    689  
     600
    690601  /*
    691602   * @todo chrisj
    692603   * Remove the use of task variables. Change to have a single
     
    711622
    712623  fileno(stdout);
    713624
    714   /* fprintf( stderr, 
     625  /* fprintf( stderr,
    715626     "-%s-%s-\n", shell_env->input, shell_env->output );
    716627  */
    717628
     
    732643      stdoutToClose = output;
    733644    }
    734645  }
    735  
     646
    736647  if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) {
    737648    FILE *input = fopen(shell_env_arg->input, "r");
    738649    if (!input) {
     
    772683  setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
    773684
    774685  rtems_shell_initialize_command_set();
    775  
     686
    776687  /*
    777688   * Allocate the command line buffers.
    778689   */
     
    780691  if (!cmd_argv) {
    781692    fprintf(stderr, "no memory for command line buffers\n" );
    782693  }
    783  
     694
    784695  cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE);
    785696  if (!cmds[0]) {
    786697    fprintf(stderr, "no memory for command line buffers\n" );
     
    793704    for (cmd = 1; cmd < cmd_count; cmd++) {
    794705      cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE;
    795706    }
    796    
     707
    797708    do {
    798709      /* Set again root user and root filesystem, side effect of set_priv..*/
    799710      sc = rtems_libio_set_private_env();
     
    808719       *  loop when the connection is dropped during login and
    809720       *  keep on trucking.
    810721       */
    811       if (shell_env->login) {
    812         result = rtems_shell_login(stdin,stdout) == 0;
     722      if (shell_env->login_check != NULL) {
     723        result = rtems_shell_login(stdin,stdout);
    813724      } else {
    814725        result = true;
    815726      }
     
    829740          chdir(shell_env->cwd);
    830741        else
    831742          chdir("/"); /* XXX: chdir to getpwent homedir */
    832        
     743
    833744        shell_env->exit_shell = false;
    834745
    835746        for (;;) {
    836747          int cmd;
    837          
     748
    838749          /* Prompt section */
    839750          if (prompt) {
    840751            rtems_shell_get_prompt(shell_env, prompt,
    841752                                   RTEMS_SHELL_PROMPT_SIZE);
    842753          }
    843        
     754
    844755          /* getcmd section */
    845756          cmd = rtems_shell_line_editor(cmds, cmd_count,
    846757                                        RTEMS_SHELL_CMD_SIZE, prompt,
     
    848759
    849760          if (cmd == -1)
    850761            continue; /* empty line */
    851          
     762
    852763          if (cmd == -2)
    853764            break; /*EOF*/
    854765
     
    856767
    857768          if (shell_env->echo)
    858769            fprintf(stdout, "%d: %s\n", line, cmds[cmd]);
    859          
     770
    860771          /* evaluate cmd section */
    861772          c = cmds[cmd];
    862773          while (*c) {
     
    944855  const char          *devname,
    945856  bool                 forever,
    946857  bool                 wait,
    947   const char*          input,
    948   const char*          output,
     858  const char          *input,
     859  const char          *output,
    949860  bool                 output_append,
    950861  rtems_id             wake_on_end,
    951862  bool                 echo,
    952   bool                 login
     863  rtems_login_check    login_check
    953864)
    954865{
    955866  rtems_id           task_id;
     
    991902  shell_env->output        = strdup (output);
    992903  shell_env->output_append = output_append;
    993904  shell_env->wake_on_end   = wake_on_end;
    994   shell_env->login         = login;
     905  shell_env->login_check   = login_check;
    995906
    996907  getcwd(shell_env->cwd, sizeof(shell_env->cwd));
    997908
     
    1017928  const char          *devname,
    1018929  bool                 forever,
    1019930  bool                 wait,
    1020   bool                 login
     931  rtems_login_check    login_check
    1021932)
    1022933{
    1023934  rtems_id to_wake = RTEMS_ID_NONE;
     
    1037948    false,                   /* output_append */
    1038949    to_wake,                 /* wake_on_end */
    1039950    false,                   /* echo */
    1040     login                    /* login */
     951    login_check              /* login check */
    1041952  );
    1042953}
    1043954
     
    1060971    if (sc != RTEMS_SUCCESSFUL)
    1061972      return sc;
    1062973  }
    1063  
     974
    1064975  sc = rtems_shell_run(
    1065976    task_name,       /* task_name */
    1066977    task_stacksize,  /* task_stacksize */
     
    1073984    output_append,   /* output_append */
    1074985    current_task,    /* wake_on_end */
    1075986    echo,            /* echo */
    1076     false            /* login */
     987    NULL             /* login check */
    1077988  );
    1078989  if (sc != RTEMS_SUCCESSFUL)
    1079990    return sc;
  • cpukit/libmisc/shell/shell.h

    RCS file: /usr1/CVS/rtems/cpukit/libmisc/shell/shell.h,v
    retrieving revision 1.23
    diff -u -r1.23 shell.h
     
    2424#include <termios.h>
    2525#include <rtems/fs.h>
    2626#include <rtems/libio.h>
     27#include <rtems/login.h>
    2728
    2829#ifdef __cplusplus
    2930extern "C" {
     
    99100
    100101int rtems_shell_make_args(
    101102  char  *commandLine,
    102   int   *argc_p, 
    103   char **argv_p, 
     103  int   *argc_p,
     104  char **argv_p,
    104105  int    max_args
    105106);
    106107
    107 int rtems_shell_scanline(
    108   char *line,
    109   int   size,
    110   FILE *in,
    111   FILE *out
    112 );
    113 
    114108int rtems_shell_cat_file(
    115109  FILE *out,
    116110  const char *name
     
    135129 * @param task_priority The priority the shell runs at.
    136130 * @param forever Repeat logins.
    137131 * @param wait Caller should block until shell exits.
    138  * @param login Demand user login.
     132 * @param login_check User login check function, NULL disables login checks.
    139133 *
    140134 */
    141135rtems_status_code rtems_shell_init(
     
    145139  const char          *devname,
    146140  bool                 forever,
    147141  bool                 wait,
    148   bool                 login
     142  rtems_login_check    login_check
    149143);
    150144
    151145/**
     
    179173int rtems_shell_str2int(const char * s);
    180174
    181175typedef struct  {
    182   rtems_name  magic; /* 'S','E','N','V': Shell Environment */
    183   const char *devname;
    184   const char *taskname;
     176  rtems_name         magic; /* 'S','E','N','V': Shell Environment */
     177  const char        *devname;
     178  const char        *taskname;
    185179  /* user extensions */
    186   bool        exit_shell; /* logout */
    187   bool        forever   ; /* repeat login */
    188   int         errorlevel;
    189   bool        echo;
    190   char        cwd[256];
    191   const char* input;
    192   const char* output;
    193   bool        output_append;
    194   rtems_id    wake_on_end;
    195   bool        login;
     180  bool               exit_shell; /* logout */
     181  bool               forever; /* repeat login */
     182  int                errorlevel;
     183  bool               echo;
     184  char               cwd[256];
     185  const char        *input;
     186  const char        *output;
     187  bool               output_append;
     188  rtems_id           wake_on_end;
     189  rtems_login_check  login_check;
    196190} rtems_shell_env_t;
    197191
    198192bool rtems_shell_main_loop(
     
    210204 * all possible file systems being included it would force the
    211205 * networking stack into the applcation and this may not be
    212206 * required.
    213  */ 
     207 */
    214208struct rtems_shell_filesystems_tt;
    215209typedef struct rtems_shell_filesystems_tt rtems_shell_filesystems_t;
    216210