Index: cpukit/telnetd/telnetd.c
===================================================================
--- cpukit/telnetd/telnetd.c	(revision 1fae7b43d751ca803b12f63d4dfc074f0de8e613)
+++ cpukit/telnetd/telnetd.c	(revision 8a775c27fc62ddb08f7705e20de34b55434dfdb1)
@@ -6,5 +6,5 @@
  *  Author: 17,may 2001
  *
- *   WORK: fernando.ruiz@ctv.es 
+ *   WORK: fernando.ruiz@ctv.es
  *   HOME: correo@fernando-ruiz.com
  *
@@ -16,5 +16,5 @@
  * With register_telnetd() you add a new command in the shell to start
  * this daemon interactively. (Login in /dev/console of course)
- * 
+ *
  * Sorry but OOB is not still implemented. (This is the first version)
  *
@@ -24,9 +24,18 @@
  *    program.
  *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * 
- *  $Id$
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
  */
 
@@ -74,8 +83,5 @@
 static int sockpeername(int sock, char *buf, int bufsz);
 
-static int initialize_telnetd(void);
-static int telnetd_askForPassword;
-
-void * telnetd_dflt_spawn(
+void *telnetd_dflt_spawn(
   const char *name,
   unsigned priority,
@@ -86,16 +92,13 @@
 
 /***********************************************************/
-rtems_id            telnetd_task_id                 = 0;
-uint32_t            telnetd_stack_size              = 32000;
-rtems_task_priority telnetd_task_priority           = 0;
-bool                telnetd_remain_on_caller_stdio  = false;
-void                (*telnetd_shell)(char *, void*) = 0;
-void                *telnetd_shell_arg              = NULL;
-void *              (*telnetd_spawn_task)(
+static rtems_id telnetd_task_id = RTEMS_ID_NONE;
+
+void *(*telnetd_spawn_task)(
   const char *,
   unsigned,
   unsigned,
   void (*)(void*),
-  void *) = telnetd_dflt_spawn;
+  void *
+) = telnetd_dflt_spawn;
 
 static char *grab_a_Connection(
@@ -179,12 +182,4 @@
 }
 
-#if 1
-#define INSIDE_TELNETD
-#include "check_passwd.c"
-#else
-#define check_passwd(arg) 0
-#endif
-
-
 static void
 spawned_shell(void *arg);
@@ -204,5 +199,5 @@
   if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
     perror("telnetd:socket");
-    telnetd_task_id=0;
+    telnetd_task_id = RTEMS_ID_NONE;
     rtems_task_delete(RTEMS_SELF);
   };
@@ -216,5 +211,5 @@
     perror("telnetd:bind");
     close(des_socket);
-    telnetd_task_id=0;
+    telnetd_task_id = RTEMS_ID_NONE;
     rtems_task_delete(RTEMS_SELF);
   };
@@ -222,5 +217,5 @@
     perror("telnetd:listen");
           close(des_socket);
-    telnetd_task_id=0;
+    telnetd_task_id = RTEMS_ID_NONE;
     rtems_task_delete(RTEMS_SELF);
   };
@@ -230,16 +225,33 @@
    */
   do {
-    if ( telnetd_remain_on_caller_stdio ) {
-      char device_name[32];
-      ttyname_r( 1, device_name, sizeof(device_name) );
-      if ( !telnetd_askForPassword || (0 == check_passwd(arg->peername)) )
-	telnetd_shell(device_name, telnetd_shell_arg);
+    if (rtems_telnetd_config.keep_stdio) {
+      bool start = true;
+      char device_name [32];
+
+      ttyname_r( 1, device_name, sizeof( device_name));
+      if (rtems_telnetd_config.login_check != NULL) {
+        start = rtems_shell_login_prompt(
+          stdin,
+          stderr,
+          device_name,
+          rtems_telnetd_config.login_check
+        );
+      }
+      if (start) {
+        rtems_telnetd_config.command( device_name, arg->arg);
+      } else {
+        syslog(
+          LOG_AUTHPRIV | LOG_WARNING,
+          "telnetd: to many wrong passwords entered from %s",
+          device_name
+        );
+      }
     } else {
       devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername));
 
       if ( !devname ) {
-	/* if something went wrong, sleep for some time */
-	sleep(10);
-	continue;
+        /* if something went wrong, sleep for some time */
+        sleep(10);
+        continue;
       }
 
@@ -247,9 +259,15 @@
 
       arg->devname = devname;
-      arg->arg = telnetd_shell_arg;
+      arg->arg = rtems_telnetd_config.arg;
       strncpy(arg->peername, peername, sizeof(arg->peername));
 
-      if ( !telnetd_spawn_task( &devname[5], telnetd_task_priority,
-               telnetd_stack_size, spawned_shell, arg) ) {
+      telnetd_task_id = (rtems_id) telnetd_spawn_task(
+        devname,
+        rtems_telnetd_config.priority,
+        rtems_telnetd_config.stack_size,
+        spawned_shell,
+        arg
+      );
+      if (telnetd_task_id == RTEMS_ID_NONE) {
         FILE *dummy;
 
@@ -274,5 +292,5 @@
   } while(1);
 
-  /* TODO: how to free the connection semaphore? But then - 
+  /* TODO: how to free the connection semaphore? But then -
    *       stopping the daemon is probably only needed during
    *       development/debugging.
@@ -281,74 +299,62 @@
    */
   close(des_socket);
-  telnetd_task_id=0;
-}
-
-/***********************************************************/
-static int initialize_telnetd(void) {
-  
-  if (telnetd_task_id         ) return RTEMS_RESOURCE_IN_USE;
-  if (telnetd_stack_size<=0   ) telnetd_stack_size   =32000;
-
-  if ( !telnetd_spawn_task("TNTD", telnetd_task_priority,
-          RTEMS_MINIMUM_STACK_SIZE, rtems_task_telnetd, 0) ) {
-    return -1;
-  }
-  return 0;
-}
-
-/***********************************************************/
-int rtems_telnetd_initialize(
-  void               (*cmd)(char *, void *),
-  void                *arg,
-  bool                 remainOnCallerSTDIO,
-  size_t               stack,
-  rtems_task_priority  priority,
-  bool                 askForPassword
-)
-{
-  rtems_status_code sc;
-
-#if 0
-  printf("This is rtems-telnetd (modified by Till Straumann)\n");
-  printf("$Id$\n");
-  printf("Release $Name$\n");
-#endif
-
-  if ( !telnetd_shell && !cmd ) {
-    fprintf(stderr,"startTelnetd(): setup error - NO SHELL; bailing out\n");
-    return 1;
-  }
-
-  if (telnetd_task_id) {
-    fprintf(stderr,"ERROR:telnetd already started\n");
-    return 1;
-  };
+  telnetd_task_id = RTEMS_ID_NONE;
+}
+
+rtems_status_code rtems_telnetd_initialize( void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (telnetd_task_id != RTEMS_ID_NONE) {
+    fprintf(stderr, "telnetd already started\n");
+    return RTEMS_RESOURCE_IN_USE;
+  }
+
+  if (rtems_telnetd_config.command == NULL) {
+    fprintf(stderr, "telnetd setup with invalid command\n");
+    return RTEMS_IO_ERROR;
+  }
 
   if ( !telnet_pty_initialize() ) {
-    fprintf(stderr,"PTY driver probably not properly registered\n");
-    return 1;
-  }
-
-  telnetd_askForPassword = askForPassword;
-
-  if (cmd)
-    telnetd_shell = cmd;
-  telnetd_shell_arg     = arg;
-  telnetd_stack_size    = stack;
-  if ( !priority ) {
-    priority = rtems_bsdnet_config.network_task_priority;
-  }
-  if ( priority < 2 )
-    priority = 100;
-  telnetd_task_priority          = priority;
-  telnetd_remain_on_caller_stdio = remainOnCallerSTDIO;
-
-  sc = initialize_telnetd();
-  if (sc != RTEMS_SUCCESSFUL) return sc;
-
-  if ( !telnetd_remain_on_caller_stdio )
-    fprintf(stderr, "rtems_telnetd() started with stacksize=%u,priority=%d\n",
-      (unsigned)telnetd_stack_size,(int)telnetd_task_priority);
-  return 0;
+    fprintf(stderr, "telnetd cannot initialize PTY driver\n");
+    return RTEMS_IO_ERROR;
+  }
+
+  /* Check priority */
+  if (rtems_telnetd_config.priority <= 0) {
+    rtems_telnetd_config.priority = rtems_bsdnet_config.network_task_priority;
+  }
+  if (rtems_telnetd_config.priority < 2) {
+    rtems_telnetd_config.priority = 100;
+  }
+
+  /* Check stack size */
+  if (rtems_telnetd_config.stack_size <= 0) {
+    rtems_telnetd_config.stack_size = 32 * 1024;
+  }
+
+  /* Spawn task */
+  telnetd_task_id = (rtems_id) telnetd_spawn_task(
+    "TNTD",
+    rtems_telnetd_config.priority,
+    RTEMS_MINIMUM_STACK_SIZE,
+    rtems_task_telnetd,
+    0
+  );
+  if (telnetd_task_id == RTEMS_ID_NONE) {
+    return RTEMS_IO_ERROR;
+  }
+
+  /* Print status */
+  if (!rtems_telnetd_config.keep_stdio) {
+    fprintf(
+      stderr,
+      "telnetd started with stacksize = %u and priority = %d\n",
+      (unsigned) rtems_telnetd_config.stack_size,
+      (unsigned) rtems_telnetd_config.priority
+    );
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
@@ -362,4 +368,6 @@
   int                  i=0;
   struct shell_args  *arg = targ;
+  bool login_failed = false;
+  bool start = true;
 
   sc=rtems_libio_set_private_env();
@@ -398,10 +406,28 @@
 
   /* call their routine */
-  if ( !telnetd_askForPassword || (0 == check_passwd(arg->peername)) )
-    telnetd_shell(arg->devname, arg->arg);
+  if (rtems_telnetd_config.login_check != NULL) {
+    start = rtems_shell_login_prompt(
+      stdin,
+      stderr,
+      arg->devname,
+      rtems_telnetd_config.login_check
+    );
+    login_failed = !start;
+  }
+  if (start) {
+    rtems_telnetd_config.command( arg->devname, arg->arg);
+  }
 
   stdin  = ostd[0];
   stdout = ostd[1];
   stderr = ostd[2];
+
+  if (login_failed) {
+    syslog(
+      LOG_AUTHPRIV | LOG_WARNING,
+      "telnetd: to many wrong passwords entered from %s",
+      arg->peername
+    );
+  }
 
 cleanup:
@@ -434,5 +460,5 @@
 {
   rtems_status_code        sc;
-  rtems_id                 task_id;
+  rtems_id                 task_id = RTEMS_ID_NONE;
   char                     nm[4] = {'X','X','X','X' };
   struct wrap_delete_args *pwa = malloc(sizeof(*pwa));
@@ -442,5 +468,5 @@
   if ( !pwa ) {
     perror("Telnetd: no memory\n");
-    return 0;
+    return (void *) RTEMS_ID_NONE;
   }
 
@@ -461,7 +487,7 @@
         free(pwa);
         rtems_error(sc,"Telnetd: spawning task failed");
-        return 0;
-  }
-  return (void*)task_id;
+        return (void *) RTEMS_ID_NONE;
+  }
+  return (void *) task_id;
 }
 
