[ofa-general] [PATCH] opensm & osm_console: modified console framework to support multiple connections

Timothy A. Meier meier3 at llnl.gov
Mon Oct 15 16:52:49 PDT 2007


Sasha,
  This patch is setting up for adding Remote/Secure Console capability 
using SSL/TSL (we need at LLNL).

  Its a big patch because I changed to an abstract server model, instead 
of the original
single connection and synchronous model.  There is no significant 
functional difference (yet).

========
 From cb69c1e2c8ea526bcb1e81d079bfa787eda09ba8 Mon Sep 17 00:00:00 2001
From: Tim Meier <meier3 at llnl.gov>
Date: Mon, 15 Oct 2007 16:08:10 -0700
Subject: [PATCH] opensm & osm_console: modified console framework to 
support multiple connections

Provided an abstract console service that supports the current 
connection types
(local, loopback, socket) as well as supporting the addition of a secure
connection type.

* A server implementation supports multiple connections, and reduces the
posibility of an inadvertant denial of service (currently vulnerable).

* An IO abstraction (CIO) is employed to facilitate the future 
implementation
of a secure socket (SSL / TSL) connection, while maintaining backward
compatibility.

Signed-off-by: Tim Meier <meier3 at llnl.gov>
---
 opensm/include/opensm/osm_console.h |   35 +-
 opensm/opensm/main.c                |   77 ++-
 opensm/opensm/osm_console.c         | 1500 
+++++++++++++++++++++++++----------
 3 files changed, 1177 insertions(+), 435 deletions(-)

diff --git a/opensm/include/opensm/osm_console.h 
b/opensm/include/opensm/osm_console.h
index 33e41e7..75111a4 100644
--- a/opensm/include/opensm/osm_console.h
+++ b/opensm/include/opensm/osm_console.h
@@ -49,6 +49,14 @@
 #define OSM_DEFAULT_CONSOLE      OSM_DISABLE_CONSOLE
 #define OSM_DEFAULT_CONSOLE_PORT 10000
 #define OSM_DAEMON_NAME          "opensm"
+#define OSM_QUIT_CMD             "quit"
+#define OSM_LOOP_PERIOD_SEC      2
+
+#define CIO_BUFSIZE          1024
+#define CIO_INFO_SIZE         128
+#define CIO_NOTE_SIZE          64
+#define CIO_MAX_CONNECTS        5
+#define CIO_CONNECTION_PORT 10000
 
 #ifdef __cplusplus
 #  define BEGIN_C_DECLS extern "C" {
@@ -59,10 +67,29 @@
 #endif                /* __cplusplus */
 
 BEGIN_C_DECLS
-void osm_console_init(osm_subn_opt_t * opt, osm_opensm_t * p_osm);
-void osm_console(osm_opensm_t * p_osm);
-void osm_console_prompt(FILE * out);
-void osm_console_close_socket(osm_opensm_t * p_osm);
+
+/* TODO move when fully implemented */
+typedef struct _CIO_t
+{
+  int  fd;  // file descriptor (socket)
+  FILE *out;
+  FILE *err;
+  FILE *in;
+  struct pollfd *pfd;
+} CIO_t;
+
+int osm_console_server(osm_subn_opt_t *p_opt, osm_opensm_t *p_osm);
+void osm_console_server_init(osm_subn_opt_t *opt, osm_opensm_t *p_osm);
+void osm_console_server_destroy(osm_opensm_t *p_osm);
+int is_console_enabled(osm_subn_opt_t *p_opt);
+
+/* TODO move along with other IO abstraction code */
+int cio_printf( CIO_t *cio, const char *format, ...);
+int cio_flush( CIO_t *cio);
+int cio_getline( char **lineptr, size_t *n, CIO_t *cio);
+int cio_open( CIO_t *cio);
+int cio_close( CIO_t *cio);
+int cio_poll(CIO_t *cio, int timeout);
 
 END_C_DECLS
 #endif                /* _OSM_CONSOLE_H_ */
diff --git a/opensm/opensm/main.c b/opensm/opensm/main.c
index 0250551..b744157 100644
--- a/opensm/opensm/main.c
+++ b/opensm/opensm/main.c
@@ -229,11 +229,13 @@ void show_usage(void)
            "          SMPs.\n"
            "          Without -maxsmps, OpenSM defaults to a maximum of\n"
            "          4 outstanding SMPs.\n\n");
-    printf("-console [off|local"
 #ifdef ENABLE_OSM_CONSOLE_SOCKET
-           "|socket|loopback"
+  printf("-console [%s|%s|%s|%s]", OSM_DISABLE_CONSOLE, OSM_LOCAL_CONSOLE,
+         OSM_REMOTE_CONSOLE, OSM_LOOPBACK_CONSOLE);
+#else
+  printf("-console [%s|%s]", OSM_DISABLE_CONSOLE, OSM_LOCAL_CONSOLE);
 #endif
-           "]\n          This option activates the OpenSM console 
(default off).\n\n");
+    printf("]\n          This option activates the OpenSM console 
(default off).\n\n");
 #ifdef ENABLE_OSM_CONSOLE_SOCKET
     printf("-console-port <port>\n"
            "          Specify an alternate telnet port for the console 
(default %d).\n\n",
@@ -566,6 +568,45 @@ static int daemonize(osm_opensm_t * osm)
     return 0;
 }
 
+/* simple server to provide an interface to support
+ *  interactive (and non-interactive) commands 
+ *   loop here until an exit signal is received
+ *
+ * currently just support a command console
+ */
+void osm_opensm_server(osm_subn_opt_t *p_opt, osm_opensm_t *p_osm)
+{
+  if(is_console_enabled(p_opt))
+    osm_console_server_init(p_opt, p_osm);
+
+  /*
+   Sit here forever - dwelling or running the server
+   */
+  while (!osm_exit_flag)
+  {
+    if(is_console_enabled(p_opt))
+      osm_console_server(p_opt, p_osm);
+    else
+      cl_thread_suspend( 10000);
+
+    if (osm_usr1_flag)
+    {
+      osm_usr1_flag = 0;
+      osm_log_reopen_file(&(p_osm->log));
+    }
+    if (osm_hup_flag)
+    {
+      osm_hup_flag = 0;
+      /* a HUP signal should only start a new heavy sweep */
+      p_osm->subn.force_immediate_heavy_sweep = TRUE;
+      osm_opensm_sweep(p_osm);
+    }
+  }
+ 
+  if(is_console_enabled(p_opt))
+    osm_console_server_destroy(p_osm);
+}
+
 /**********************************************************************
  **********************************************************************/
 int main(int argc, char *argv[])
@@ -1034,34 +1075,8 @@ int main(int argc, char *argv[])
                 osm_exit_flag = 1;
         }
     } else {
-        osm_console_init(&opt, &osm);
-
-        /*
-           Sit here forever
-         */
-        while (!osm_exit_flag) {
-            if (strcmp(opt.console, OSM_LOCAL_CONSOLE) == 0
-#ifdef ENABLE_OSM_CONSOLE_SOCKET
-                || strcmp(opt.console, OSM_REMOTE_CONSOLE) == 0
-                || strcmp(opt.console, OSM_LOOPBACK_CONSOLE) == 0
-#endif
-                )
-                osm_console(&osm);
-            else
-                cl_thread_suspend(10000);
-
-            if (osm_usr1_flag) {
-                osm_usr1_flag = 0;
-                osm_log_reopen_file(&osm.log);
-            }
-            if (osm_hup_flag) {
-                osm_hup_flag = 0;
-                /* a HUP signal should only start a new heavy sweep */
-                osm.subn.force_immediate_heavy_sweep = TRUE;
-                osm_opensm_sweep(&osm);
-            }
-        }
-        osm_console_close_socket(&osm);
+    // start a server that runs indefinately
+    osm_opensm_server(&opt, &osm);
     }
 
 #if 0
diff --git a/opensm/opensm/osm_console.c b/opensm/opensm/osm_console.c
index c6e02ab..9d62774 100644
--- a/opensm/opensm/osm_console.c
+++ b/opensm/opensm/osm_console.c
@@ -38,15 +38,16 @@
 #define _GNU_SOURCE        /* for getline */
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <sys/poll.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netdb.h>
 #ifdef ENABLE_OSM_CONSOLE_SOCKET
 #include <tcpd.h>
-#endif
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#endif
 #include <unistd.h>
 #include <errno.h>
 #include <ctype.h>
@@ -57,20 +58,113 @@
 #include <complib/cl_passivelock.h>
 #include <opensm/osm_perfmgr.h>
 
+typedef struct _LoopCmd
+{
+  int    on;
+  int    running;
+  int    delay_s;
+  void (*loop_function)(osm_opensm_t *p_osm, CIO_t *out);
+  cl_thread_t  loopThread; // a specific thread for each looping cmd
+} LoopCmd;
+
+// unique attributes for each connection
+typedef struct _osm_console_thread_t
+{
+  int used;
+  unsigned short int port;
+  int authorized;
+  int state;
+  char name[CIO_INFO_SIZE];
+  char in_buff[CIO_BUFSIZE];
+  char out_buff[CIO_BUFSIZE];
+  char client_type[CIO_NOTE_SIZE];  // maps to option->console 
(off|local|socket)
+  char client_ip[CIO_NOTE_SIZE];
+  char client_hn[CIO_INFO_SIZE];
+  unsigned int thread_num;  // a unique ever increasing number 
+  osm_opensm_t *p_osm;     // the global opensm singleton (protect with 
lock)
+  CIO_t io;                // the io streams for the connection
+  LoopCmd loop_command;
+  cl_thread_t  consoleThread; // a specific thread each console connection
+  struct timeval connect_time;
+} osm_console_thread_t;
+
 struct command {
-    char *name;
-    void (*help_function) (FILE * out, int detail);
-    void (*parse_function) (char **p_last, osm_opensm_t * p_osm,
-                FILE * out);
+  char *name;
+  void (*help_function)(CIO_t *out, int detail);
+  void (*parse_function)(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out);
 };
 
-struct {
-    int on;
-    int delay_s;
-    time_t previous;
-    void (*loop_function) (osm_opensm_t * p_osm, FILE * out);
-} loop_command = {
-on: 0, delay_s: 2, loop_function:NULL};
+/* connection pool for remote clients - currently only consoles */
+static osm_console_thread_t ConsoleThreadPool[CIO_MAX_CONNECTS];
+static cl_plock_t ThreadLock;
+static volatile unsigned int cio_thread_counter = 0;
+static struct timeval ServerTime;
+
+/**********************************************************************
+ * convenience function
+ **********************************************************************/
+CIO_t* getCIO(osm_console_thread_t *oct)
+{
+  return &oct->io;
+}
+
+/**********************************************************************
+ * thread pool primitive: counts the number currently in use
+ **********************************************************************/
+int num_console_threads(void)
+{
+  // count them up
+
+  int i;
+  int num = 0;
+ 
+  cl_plock_acquire(&ThreadLock);
+  for(i = 0; i <  CIO_MAX_CONNECTS; ++i)
+  {
+    if(ConsoleThreadPool[i].used != 0)
+      num++;
+  }
+  cl_plock_release(&ThreadLock);
+ 
+  return num;
+}
+
+/**********************************************************************
+ * thread pool primitive: the current value reflects the number of
+ * connection attempts made since program execution.
+ **********************************************************************/
+unsigned int get_console_thread_counter(void)
+{
+  return cio_thread_counter;
+}
+
+int is_loopback(char* str)
+{
+  // convenience - checks if socket based connection
+ if(str)
+   return (strcmp(str, OSM_LOOPBACK_CONSOLE) == 0);
+return 0;
+}
+
+int is_remote(char* str)
+{
+  // convenience - checks if socket based connection
+ if(str)
+   return (strcmp(str, OSM_REMOTE_CONSOLE) == 0)
+       || is_loopback(str);
+return 0;
+}
+
+int is_console_enabled(osm_subn_opt_t *p_opt)
+{
+  // checks for a variety of types of consoles - default is off or 0
+ if(p_opt)
+   return ((strcmp(p_opt->console, OSM_LOCAL_CONSOLE) == 0)
+       || (strcmp(p_opt->console, OSM_LOOPBACK_CONSOLE) == 0)
+       || (strcmp(p_opt->console, OSM_REMOTE_CONSOLE) == 0));
+return 0;
+}
+
 
 static const struct command console_cmds[];
 
@@ -79,114 +173,103 @@ static inline char *next_token(char **p_last)
     return strtok_r(NULL, " \t\n\r", p_last);
 }
 
-static void help_command(FILE * out, int detail)
+static void help_command(CIO_t *out, int detail)
 {
     int i;
 
-    fprintf(out, "Supported commands and syntax:\n");
-    fprintf(out, "help [<command>]\n");
+    cio_printf(out, "Supported commands and syntax:\n");
+    cio_printf(out, "help [<command>]\n");
     /* skip help command */
     for (i = 1; console_cmds[i].name; i++)
         console_cmds[i].help_function(out, 0);
 }
 
-static void help_quit(FILE * out, int detail)
+static void help_quit(CIO_t *out, int detail)
 {
-    fprintf(out, "quit (not valid in local mode; use ctl-c)\n");
+    cio_printf(out, "%s -- stops the console\n", OSM_QUIT_CMD);
+  if (detail) {
+    cio_printf(out, "  OpenSM will continue, to kill; \n");
+    cio_printf(out, "    use ctrl-C in local mode or\n");
+    cio_printf(out, "    kill the process\n");
+  }
 }
 
-static void help_loglevel(FILE * out, int detail)
+
+static void help_loglevel(CIO_t *out, int detail)
 {
-    fprintf(out, "loglevel [<log-level>]\n");
+    cio_printf(out, "loglevel [<log-level>]\n");
     if (detail) {
-        fprintf(out, "   log-level is OR'ed from the following\n");
-        fprintf(out, "   OSM_LOG_NONE             0x%02X\n",
-            OSM_LOG_NONE);
-        fprintf(out, "   OSM_LOG_ERROR            0x%02X\n",
-            OSM_LOG_ERROR);
-        fprintf(out, "   OSM_LOG_INFO             0x%02X\n",
-            OSM_LOG_INFO);
-        fprintf(out, "   OSM_LOG_VERBOSE          0x%02X\n",
-            OSM_LOG_VERBOSE);
-        fprintf(out, "   OSM_LOG_DEBUG            0x%02X\n",
-            OSM_LOG_DEBUG);
-        fprintf(out, "   OSM_LOG_FUNCS            0x%02X\n",
-            OSM_LOG_FUNCS);
-        fprintf(out, "   OSM_LOG_FRAMES           0x%02X\n",
-            OSM_LOG_FRAMES);
-        fprintf(out, "   OSM_LOG_ROUTING          0x%02X\n",
-            OSM_LOG_ROUTING);
-        fprintf(out, "   OSM_LOG_SYS              0x%02X\n",
-            OSM_LOG_SYS);
-        fprintf(out, "\n");
-        fprintf(out, "   OSM_LOG_DEFAULT_LEVEL    0x%02X\n",
-            OSM_LOG_DEFAULT_LEVEL);
+        cio_printf(out, "   log-level is OR'ed from the following\n");
+        cio_printf(out, "   OSM_LOG_NONE             0x%02X\n", 
OSM_LOG_NONE);
+        cio_printf(out, "   OSM_LOG_ERROR            0x%02X\n", 
OSM_LOG_ERROR);
+        cio_printf(out, "   OSM_LOG_INFO             0x%02X\n", 
OSM_LOG_INFO);
+        cio_printf(out, "   OSM_LOG_VERBOSE          0x%02X\n", 
OSM_LOG_VERBOSE);
+        cio_printf(out, "   OSM_LOG_DEBUG            0x%02X\n", 
OSM_LOG_DEBUG);
+        cio_printf(out, "   OSM_LOG_FUNCS            0x%02X\n", 
OSM_LOG_FUNCS);
+        cio_printf(out, "   OSM_LOG_FRAMES           0x%02X\n", 
OSM_LOG_FRAMES);
+        cio_printf(out, "   OSM_LOG_ROUTING          0x%02X\n", 
OSM_LOG_ROUTING);
+        cio_printf(out, "   OSM_LOG_SYS              0x%02X\n", 
OSM_LOG_SYS);
+        cio_printf(out, "\n");
+        cio_printf(out, "   OSM_LOG_DEFAULT_LEVEL    0x%02X\n", 
OSM_LOG_DEFAULT_LEVEL);
     }
 }
 
-static void help_priority(FILE * out, int detail)
+static void help_priority(CIO_t *out, int detail)
 {
-    fprintf(out, "priority [<sm-priority>]\n");
+    cio_printf(out, "priority [<sm-priority>]\n");
 }
 
-static void help_resweep(FILE * out, int detail)
+static void help_resweep(CIO_t *out, int detail)
 {
-    fprintf(out, "resweep [heavy|light]\n");
+    cio_printf(out, "resweep [heavy|light]\n");
 }
 
-static void help_status(FILE * out, int detail)
+static void help_status(CIO_t *out, int detail)
 {
-    fprintf(out, "status [loop]\n");
+    cio_printf(out, "status [loop]\n");
     if (detail) {
-        fprintf(out, "   loop -- type \"q<ret>\" to quit\n");
+        cio_printf(out, "   loop -- type \"q<ret>\" to quit\n");
     }
 }
 
-static void help_logflush(FILE * out, int detail)
+static void help_logflush(CIO_t *out, int detail)
 {
-    fprintf(out, "logflush -- flush the opensm.log file\n");
+    cio_printf(out, "logflush -- flush the opensm.log file\n");
 }
 
-static void help_querylid(FILE * out, int detail)
+static void help_querylid(CIO_t *out, int detail)
 {
-    fprintf(out,
-        "querylid lid -- print internal information about the lid 
specified\n");
+    cio_printf(out,
+    "querylid lid -- print internal information about the lid 
specified\n");
 }
 
-static void help_portstatus(FILE * out, int detail)
+static void help_portstatus(CIO_t *out, int detail)
 {
-    fprintf(out, "portstatus [ca|switch|router]\n");
+    cio_printf(out, "portstatus [ca|switch|router]\n");
     if (detail) {
-        fprintf(out, "summarize port status\n");
-        fprintf(out,
-            "   [ca|switch|router] -- limit the results to the node 
type specified\n");
+        cio_printf(out, "summarize port status\n");
+        cio_printf(out, "   [ca|switch|router] -- limit the results to 
the node type specified\n");
     }
 
 }
 
 #ifdef ENABLE_OSM_PERF_MGR
-static void help_perfmgr(FILE * out, int detail)
+static void help_perfmgr(CIO_t *out, int detail)
 {
-    fprintf(out,
-        "perfmgr 
[enable|disable|clear_counters|dump_counters|sweep_time[seconds]]\n");
+    cio_printf(out, "perfmgr 
[enable|disable|clear_counters|dump_counters|sweep_time[seconds]]\n");
     if (detail) {
-        fprintf(out,
-            "perfmgr -- print the performance manager state\n");
-        fprintf(out,
-            "   [enable|disable] -- change the perfmgr state\n");
-        fprintf(out,
-            "   [sweep_time] -- change the perfmgr sweep time (requires 
[seconds] option)\n");
-        fprintf(out,
-            "   [clear_counters] -- clear the counters stored\n");
-        fprintf(out,
-            "   [dump_counters [mach]] -- dump the counters (optionally 
in [mach]ine readable format)\n");
+        cio_printf(out, "perfmgr -- print the performance manager 
state\n");
+        cio_printf(out, "   [enable|disable] -- change the perfmgr 
state\n");
+        cio_printf(out, "   [sweep_time] -- change the perfmgr sweep 
time (requires [seconds] option)\n");
+        cio_printf(out, "   [clear_counters] -- clear the counters 
stored\n");
+        cio_printf(out, "   [dump_counters [mach]] -- dump the counters 
(optionally in [mach]ine readable format)\n");
     }
 }
 #endif                /* ENABLE_OSM_PERF_MGR */
 
 /* more help routines go here */
 
-static void help_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void help_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
     char *p_cmd;
     int i, found = 0;
@@ -203,21 +286,21 @@ static void help_parse(char **p_last, osm_opensm_t 
* p_osm, FILE * out)
             }
         }
         if (!found) {
-            fprintf(out, "%s : Command not found\n\n", p_cmd);
+            cio_printf(out, "%s : Command not found\n\n", p_cmd);
             help_command(out, 0);
         }
     }
 }
 
-static void loglevel_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void loglevel_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
+  osm_opensm_t *p_osm = p_oct->p_osm;
     char *p_cmd;
     int level;
 
     p_cmd = next_token(p_last);
     if (!p_cmd)
-        fprintf(out, "Current log level is 0x%x\n",
-            osm_log_get_level(&p_osm->log));
+        cio_printf(out, "Current log level is 0x%x\n", 
osm_log_get_level(&p_osm->log));
     else {
         /* Handle x, 0x, and decimal specification of log level */
         if (!strncmp(p_cmd, "x", 1)) {
@@ -231,31 +314,29 @@ static void loglevel_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
                 level = strtol(p_cmd, NULL, 10);
         }
         if ((level >= 0) && (level < 256)) {
-            fprintf(out, "Setting log level to 0x%x\n", level);
+            cio_printf(out, "Setting log level to 0x%x\n", level);
             osm_log_set_level(&p_osm->log, level);
         } else
-            fprintf(out, "Invalid log level 0x%x\n", level);
+            cio_printf(out, "Invalid log level 0x%x\n", level);
     }
 }
 
-static void priority_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void priority_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
+  osm_opensm_t *p_osm = p_oct->p_osm;
     char *p_cmd;
     int priority;
 
     p_cmd = next_token(p_last);
     if (!p_cmd)
-        fprintf(out, "Current sm-priority is %d\n",
-            p_osm->subn.opt.sm_priority);
+        cio_printf(out, "Current sm-priority is %d\n", 
p_osm->subn.opt.sm_priority);
     else {
         priority = strtol(p_cmd, NULL, 0);
         if (0 > priority || 15 < priority)
-            fprintf(out,
-                "Invalid sm-priority %d; must be between 0 and 15\n",
-                priority);
+            cio_printf(out, "Invalid sm-priority %d; must be between 0 
and 15\n", priority);
         else {
-            fprintf(out, "Setting sm-priority to %d\n", priority);
-            p_osm->subn.opt.sm_priority = (uint8_t) priority;
+            cio_printf(out, "Setting sm-priority to %d\n", priority);
+            p_osm->subn.opt.sm_priority = (uint8_t)priority;
             /* Does the SM state machine need a kick now ? */
         }
     }
@@ -371,24 +452,23 @@ static char *sm_state_mgr_str(osm_sm_state_t state)
     }
 }
 
-static void print_status(osm_opensm_t * p_osm, FILE * out)
+static void print_status(osm_opensm_t *p_osm, CIO_t *out)
 {
     if (out) {
-        fprintf(out, "   OpenSM Version     : %s\n", OSM_VERSION);
-        fprintf(out, "   SM State/Mgr State : %s/%s\n",
+        cio_printf(out, "   OpenSM Version     : %s\n", OSM_VERSION);
+        cio_printf(out, "   SM State/Mgr State : %s/%s\n",
             sm_state_str(p_osm->subn.sm_state),
             sm_state_mgr_str(p_osm->sm.state_mgr.state));
-        fprintf(out, "   SA State           : %s\n",
+        cio_printf(out, "   SA State           : %s\n",
             sa_state_str(p_osm->sa.state));
-        fprintf(out, "   Routing Engine     : %s\n",
-            p_osm->routing_engine.name ? p_osm->routing_engine.
-            name : "null (min-hop)");
+        cio_printf(out, "   Routing Engine     : %s\n",
+            p_osm->routing_engine.name ? p_osm->routing_engine.name : 
"null (min-hop)");
 #ifdef ENABLE_OSM_PERF_MGR
-        fprintf(out, "\n   PerfMgr state/sweep state : %s/%s\n",
+        cio_printf(out, "\n   PerfMgr state/sweep state : %s/%s\n",
             osm_perfmgr_get_state_str(&(p_osm->perfmgr)),
             osm_perfmgr_get_sweep_state_str(&(p_osm->perfmgr)));
 #endif
-        fprintf(out, "\n   MAD stats\n"
+        cio_printf(out, "\n   MAD stats\n"
             "   ---------\n"
             "   QP0 MADs outstanding           : %d\n"
             "   QP0 MADs outstanding (on wire) : %d\n"
@@ -412,7 +492,7 @@ static void print_status(osm_opensm_t * p_osm, FILE 
* out)
             p_osm->stats.sa_mads_sent,
             p_osm->stats.sa_mads_rcvd_unknown,
             p_osm->stats.sa_mads_ignored);
-        fprintf(out, "\n   Subnet flags\n"
+        cio_printf(out, "\n   Subnet flags\n"
             "   ------------\n"
             "   Ignore existing lfts           : %d\n"
             "   Subnet Init errors             : %d\n"
@@ -426,32 +506,24 @@ static void print_status(osm_opensm_t * p_osm, 
FILE * out)
             p_osm->subn.moved_to_master_state,
             p_osm->subn.first_time_master_sweep,
             p_osm->subn.coming_out_of_standby);
-        fprintf(out, "\n");
-    }
-}
-
-static int loop_command_check_time(void)
-{
-    time_t cur = time(NULL);
-    if ((loop_command.previous + loop_command.delay_s) < cur) {
-        loop_command.previous = cur;
-        return (1);
+        cio_printf(out, "\n");
     }
-    return (0);
 }
 
-static void status_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void status_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
+  osm_opensm_t *p_osm = p_oct->p_osm;
     char *p_cmd;
 
     p_cmd = next_token(p_last);
     if (p_cmd) {
         if (strcmp(p_cmd, "loop") == 0) {
-            fprintf(out, "Looping on status command...\n");
-            fflush(out);
-            loop_command.on = 1;
-            loop_command.previous = time(NULL);
-            loop_command.loop_function = print_status;
+            cio_printf(out, "Looping on status command...\n");
+            cio_flush(out);
+      p_oct->loop_command.on = 1;
+      p_oct->loop_command.delay_s = OSM_LOOP_PERIOD_SEC;
+      p_oct->loop_command.running = 0;
+      p_oct->loop_command.loop_function = print_status;
         } else {
             help_status(out, 1);
             return;
@@ -460,14 +532,15 @@ static void status_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
     print_status(p_osm, out);
 }
 
-static void resweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void resweep_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
+  osm_opensm_t *p_osm = p_oct->p_osm;
     char *p_cmd;
 
     p_cmd = next_token(p_last);
     if (!p_cmd ||
         (strcmp(p_cmd, "heavy") != 0 && strcmp(p_cmd, "light") != 0)) {
-        fprintf(out, "Invalid resweep command\n");
+        cio_printf(out, "Invalid resweep command\n");
         help_resweep(out, 1);
     } else {
         if (strcmp(p_cmd, "heavy") == 0) {
@@ -477,20 +550,21 @@ static void resweep_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
     }
 }
 
-static void logflush_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void logflush_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
-    fflush(p_osm->log.out_port);
+    fflush(p_oct->p_osm->log.out_port);
 }
 
-static void querylid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void querylid_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
-    int p = 0;
-    uint16_t lid = 0;
+  osm_opensm_t *p_osm = p_oct->p_osm;
+    int         p = 0;
+    uint16_t    lid = 0;
     osm_port_t *p_port = NULL;
     char *p_cmd = next_token(p_last);
 
     if (!p_cmd) {
-        fprintf(out, "no LID specified\n");
+        cio_printf(out, "no LID specified\n");
         help_querylid(out, 1);
         return;
     }
@@ -503,8 +577,8 @@ static void querylid_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
     if (!p_port)
         goto invalid_lid;
 
-    fprintf(out, "Query results for LID %d\n", lid);
-    fprintf(out,
+    cio_printf(out, "Query results for LID %d\n", lid);
+    cio_printf(out,
         "   GUID                : 0x%016" PRIx64 "\n"
         "   Node Desc           : %s\n"
         "   Node Type           : %s\n"
@@ -518,20 +592,19 @@ static void querylid_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
         p = 0;
     else
         p = 1;
-    for ( /* see above */ ; p < p_port->p_node->physp_tbl_size; p++) {
-        fprintf(out,
+    for (/* see above */; p < p_port->p_node->physp_tbl_size; p++) {
+        cio_printf(out,
             "   Port %d health       : %s\n",
             p,
-            p_port->p_node->physp_table[p].
-            healthy ? "OK" : "ERROR");
+            p_port->p_node->physp_table[p].healthy ? "OK" : "ERROR");
     }
 
     cl_plock_release(&p_osm->lock);
     return;
 
-      invalid_lid:
+invalid_lid:
     cl_plock_release(&p_osm->lock);
-    fprintf(out, "Invalid lid %d\n", lid);
+    cio_printf(out, "Invalid lid %d\n", lid);
     return;
 }
 
@@ -564,11 +637,11 @@ __tag_port_report(port_report_t ** head, uint64_t 
node_guid,
         *head = rep;
 }
 
-static void __print_port_report(FILE * out, port_report_t * head)
+static void __print_port_report(CIO_t *out, port_report_t *head)
 {
     port_report_t *item = head;
     while (item != NULL) {
-        fprintf(out, "      0x%016" PRIx64 " %d (%s)\n",
+        cio_printf(out, "      0x%016"PRIx64" %d (%s)\n",
             item->node_guid, item->port_num, item->print_desc);
         port_report_t *next = item->next;
         free(item);
@@ -689,10 +762,11 @@ static void __get_stats(cl_map_item_t * const 
p_map_item, void *context)
     }
 }
 
-static void portstatus_parse(char **p_last, osm_opensm_t * p_osm, FILE 
* out)
+static void portstatus_parse(char **p_last, osm_console_thread_t 
*p_oct, CIO_t *out)
 {
-    fabric_stats_t fs;
-    struct timeval before, after;
+  osm_opensm_t *p_osm = p_oct->p_osm;
+    fabric_stats_t  fs;
+    struct timeval  before, after;
     char *p_cmd;
 
     memset(&fs, 0, sizeof(fs));
@@ -706,7 +780,7 @@ static void portstatus_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
         } else if (strcmp(p_cmd, "router") == 0) {
             fs.node_type_lim = IB_NODE_TYPE_ROUTER;
         } else {
-            fprintf(out, "Node type not understood\n");
+            cio_printf(out, "Node type not understood\n");
             help_portstatus(out, 1);
             return;
         }
@@ -723,58 +797,56 @@ static void portstatus_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
     gettimeofday(&after, NULL);
 
     /* report the stats */
-    fprintf(out, "\"%s\" port status:\n",
-        fs.node_type_lim ? ib_get_node_type_str(fs.
-                            node_type_lim) : "ALL");
-    fprintf(out,
-        "   %" PRIu64 " port(s) scanned on %" PRIu64
-        " nodes in %lu us\n", fs.total_ports, fs.total_nodes,
-        after.tv_usec - before.tv_usec);
+    cio_printf(out, "\"%s\" port status:\n",
+        fs.node_type_lim ?  ib_get_node_type_str(fs.node_type_lim) : 
"ALL");
+    cio_printf(out, "   %"PRIu64" port(s) scanned on %"PRIu64" nodes in 
%lu us\n",
+        fs.total_ports, fs.total_nodes, after.tv_usec - before.tv_usec);
 
     if (fs.ports_down)
-        fprintf(out, "   %" PRIu64 " down\n", fs.ports_down);
+        cio_printf(out, "   %"PRIu64" down\n", fs.ports_down);
     if (fs.ports_active)
-        fprintf(out, "   %" PRIu64 " active\n", fs.ports_active);
+        cio_printf(out, "   %"PRIu64" active\n", fs.ports_active);
     if (fs.ports_1X)
-        fprintf(out, "   %" PRIu64 " at 1X\n", fs.ports_1X);
+        cio_printf(out, "   %"PRIu64" at 1X\n", fs.ports_1X);
     if (fs.ports_4X)
-        fprintf(out, "   %" PRIu64 " at 4X\n", fs.ports_4X);
+        cio_printf(out, "   %"PRIu64" at 4X\n", fs.ports_4X);
     if (fs.ports_8X)
-        fprintf(out, "   %" PRIu64 " at 8X\n", fs.ports_8X);
+        cio_printf(out, "   %"PRIu64" at 8X\n", fs.ports_8X);
     if (fs.ports_12X)
-        fprintf(out, "   %" PRIu64 " at 12X\n", fs.ports_12X);
+        cio_printf(out, "   %"PRIu64" at 12X\n", fs.ports_12X);
 
     if (fs.ports_sdr)
-        fprintf(out, "   %" PRIu64 " at 2.5 Gbps\n", fs.ports_sdr);
+        cio_printf(out, "   %"PRIu64" at 2.5 Gbps\n", fs.ports_sdr);
     if (fs.ports_ddr)
-        fprintf(out, "   %" PRIu64 " at 5.0 Gbps\n", fs.ports_ddr);
+        cio_printf(out, "   %"PRIu64" at 5.0 Gbps\n", fs.ports_ddr);
     if (fs.ports_qdr)
-        fprintf(out, "   %" PRIu64 " at 10.0 Gbps\n", fs.ports_qdr);
+        cio_printf(out, "   %"PRIu64" at 10.0 Gbps\n", fs.ports_qdr);
 
     if (fs.ports_disabled + fs.ports_reduced_speed + fs.ports_reduced_width
-        > 0) {
-        fprintf(out, "\nPossible issues:\n");
+            > 0) {
+        cio_printf(out, "\nPossible issues:\n");
     }
     if (fs.ports_disabled) {
-        fprintf(out, "   %" PRIu64 " disabled\n", fs.ports_disabled);
+        cio_printf(out, "   %"PRIu64" disabled\n", fs.ports_disabled);
         __print_port_report(out, fs.disabled_ports);
     }
     if (fs.ports_reduced_speed) {
-        fprintf(out, "   %" PRIu64 " with reduced speed\n",
+        cio_printf(out, "   %"PRIu64" with reduced speed\n",
             fs.ports_reduced_speed);
         __print_port_report(out, fs.reduced_speed_ports);
     }
     if (fs.ports_reduced_width) {
-        fprintf(out, "   %" PRIu64 " with reduced width\n",
+        cio_printf(out, "   %"PRIu64" with reduced width\n",
             fs.ports_reduced_width);
         __print_port_report(out, fs.reduced_width_ports);
     }
-    fprintf(out, "\n");
+    cio_printf(out, "\n");
 }
 
 #ifdef ENABLE_OSM_PERF_MGR
-static void perfmgr_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void perfmgr_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
+  osm_opensm_t *p_osm = p_oct->p_osm;
     char *p_cmd;
 
     p_cmd = next_token(p_last);
@@ -803,309 +875,937 @@ static void perfmgr_parse(char **p_last, 
osm_opensm_t * p_osm, FILE * out)
                 osm_perfmgr_set_sweep_time_s(&(p_osm->perfmgr),
                                  time_s);
             } else {
-                fprintf(out,
+                cio_printf(out,
                     "sweep_time requires a time period (in seconds) to 
be specified\n");
             }
         } else {
-            fprintf(out, "\"%s\" option not found\n", p_cmd);
+            cio_printf(out, "\"%s\" option not found\n", p_cmd);
         }
     } else {
-        fprintf(out, "Performance Manager status:\n"
+        cio_printf(out, "Performance Manager status:\n"
             "state                   : %s\n"
             "sweep state             : %s\n"
             "sweep time              : %us\n"
-            "outstanding queries/max : %d/%u\n"
-            "loaded event plugin     : %s\n",
+            "outstanding queries/max : %d/%u\n",
             osm_perfmgr_get_state_str(&(p_osm->perfmgr)),
             osm_perfmgr_get_sweep_state_str(&(p_osm->perfmgr)),
             osm_perfmgr_get_sweep_time_s(&(p_osm->perfmgr)),
             p_osm->perfmgr.outstanding_queries,
-            p_osm->perfmgr.max_outstanding_queries,
-            p_osm->perfmgr.event_plugin ?
-            p_osm->perfmgr.event_plugin->plugin_name : "NONE");
+            p_osm->perfmgr.max_outstanding_queries);
     }
 }
 #endif                /* ENABLE_OSM_PERF_MGR */
 
-/* This is public to be able to close it on exit */
-void osm_console_close_socket(osm_opensm_t * p_osm)
+static void help_version(CIO_t *out, int detail)
 {
-    if (p_osm->console.socket > 0) {
-        close(p_osm->console.in_fd);
-        p_osm->console.in_fd = -1;
-        p_osm->console.out_fd = -1;
-        p_osm->console.in = NULL;
-        p_osm->console.out = NULL;
-    }
+  cio_printf(out, "version -- print the OSM version\n");
 }
 
-static void quit_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+static void version_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
 {
-    osm_console_close_socket(p_osm);
+  cio_printf(out, "%s build %s %s\n", OSM_VERSION, __DATE__, __TIME__);
 }
 
-static void help_version(FILE * out, int detail)
+/**********************************************************************
+ * thread pool primitive: returns the thread structure to the pool, and
+ * makes it available
+ **********************************************************************/
+int free_console_thread(osm_console_thread_t *oct)
 {
-    fprintf(out, "version -- print the OSM version\n");
+  // just clear the used flag, mark as available
+  oct->used = 0;
+  return 1;
+}
+
+/**********************************************************************
+ * Cleans up the thread that was established for a connection.
+ *   The connection should already be closed.  This method releases
+ *   any resources and destroy the thread (done automagically??)
+ *
+ * refer to:  osm_console_thread and osm_console_thread_init
+**********************************************************************/
+int osm_console_thread_destroy(osm_console_thread_t *oct)
+{ 
+  free_console_thread(oct);
+ 
+  // there are a few end cases that might need this (e.g. not 
completely init)
+  cio_close(getCIO(oct));
+ 
+  return 0;
 }
 
-static void version_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
+
+/**********************************************************************
+ * Gracefully shut down the console connection, release resources
+ *   refer to:  osm_console_init
+ **********************************************************************/
+void osm_console_destroy(osm_console_thread_t *p_oct)
+{
+  osm_opensm_t *p_osm = p_oct->p_osm;
+  CIO_t *out = getCIO(p_oct);
+
+  osm_log(&(p_osm->log), OSM_LOG_INFO,
+      "osm_console_destroy: Console connection being closed:  %s (%s) 
s#%d\n", p_oct->client_hn,
+           p_oct->client_ip, out->fd);
+  fflush(p_osm->log.out_port);
+  cio_printf(out, "Closing this connection from osm_console_destroy\n");
+ 
+  cio_close(out);
+  }
+
+/**********************************************************************
+ * thread pool primitive: kills and disconnects connections.  If the
+ * argument is a current thread, it will NOT be cleared (will be skipped)
+ **********************************************************************/
+int kill_console_thread_pool(osm_console_thread_t* p_oct, osm_opensm_t 
*p_osm)
+{
+  // kill everything but my connection if p_oct is in the list
+  int i;
+  osm_console_thread_t* oct;
+  CIO_t *p_out = getCIO(p_oct);
+  CIO_t *out   = getCIO(p_oct);
+
+  // brute force this, don't use locks because don't want to get deadlocked
+//  cl_plock_acquire(&ThreadLock);
+  for(i = 0; i <  CIO_MAX_CONNECTS; ++i)
+  {
+    oct = &ConsoleThreadPool[i];
+    if((oct) && (oct->used) && (p_oct != oct))
+    {
+      cio_printf(p_out, " killing thread: %s\n", oct->name);
+      out = getCIO(oct);
+     
+      // disconnect gracefully??
+      osm_log(&(p_osm->log), OSM_LOG_INFO,
+          "kill_console_thread_pool: %d (s#%d)\n", i, out->fd);
+     
+      // return all the console resources
+      osm_console_destroy(oct);
+     
+      // return all the thread and connection resources
+      osm_console_thread_destroy(oct);
+    }
+  }
+//  cl_plock_release(&ThreadLock);
+  return i;
+}
+
+/**********************************************************************
+ * releases all of the resources used by all of the connections, by
+ * closing sockets, freeing threads, etc..
+ *
+ * a good method for handling a kill signal
+ **********************************************************************/
+int free_console_threads(osm_opensm_t *p_osm)
 {
-    fprintf(out, "%s build %s %s\n", OSM_VERSION, __DATE__, __TIME__);
+  // just make sure everything is gone
+  int rtnval =  kill_console_thread_pool(NULL, p_osm);
+  return rtnval;
 }
 
+
+/**********************************************************************
+ * thread pool primitive: clears and initializes all the threads.  If the
+ * argument is a current thread, it will NOT be cleared (will be skipped)
+ **********************************************************************/
+int print_console_thread_pool(osm_console_thread_t* p_oct, osm_opensm_t 
*p_osm, CIO_t *out)
+{
+  // show whats in use, and whats available
+
+  int i;
+  osm_console_thread_t* oct;
+
+  char *t_string = ctime(&(ServerTime.tv_sec));
+  t_string[strlen(t_string)-1]=0;     
+  cio_printf(out, "OSM Server - Up since: %s, Users: %d, * = this 
connection\n", t_string, num_console_threads());
+
+  // (careful not to double lock .. num_console_threads() 
+  cl_plock_acquire(&ThreadLock);
+
+  for(i = 0; i <  CIO_MAX_CONNECTS; ++i)
+  {
+    oct = &ConsoleThreadPool[i];
+    if((oct) && (oct->used))
+    {
+      if(p_oct == oct)
+        cio_printf(out, "*");
+      else
+        cio_printf(out, " ");
+      cio_printf(out,  "Thread:  %s [%d]\n", oct->name, oct->thread_num);
+      cio_printf(out, "  User:   %s, (%s)\n", oct->client_hn, 
oct->client_ip);
+      t_string = ctime(&(oct->connect_time.tv_sec));
+      t_string[strlen(t_string)-1]=0;     
+      cio_printf(out, "  Since:  %s\n", t_string);
+      cio_printf(out, "  Port:   %d\n", oct->port);
+      cio_printf(out, "  Socket: %d\n", oct->io.fd);
+      cio_printf(out, "  State:  %d\n", oct->state);
+    }
+  }
+  cl_plock_release(&ThreadLock);
+  return i;
+}
+
+/* close and free up resources used by socket */
+static void osm_console_deinit_socket(osm_opensm_t *p_osm)
+{
+  if (p_osm->console.socket > 0)
+  {
+    osm_log(&(p_osm->log), OSM_LOG_INFO,
+    "osm_console: Closing the primary (listening) socket connection 
(%d)\n", p_osm->console.in_fd);
+
+    close(p_osm->console.in_fd);
+    p_osm->console.in_fd = -1;
+    p_osm->console.out_fd = -1;
+    p_osm->console.in = NULL;
+    p_osm->console.out = NULL;
+  }
+}
+
+/* do everything necessary to gracefully turn off the console */
+void osm_console_server_destroy(osm_opensm_t *p_osm)
+{
+  /* make sure consoles are closed before stopping the main listener 
socket */
+  free_console_threads(p_osm);
+ 
+  cl_plock_destroy(&ThreadLock);
+ 
+  /* close the socket, listening for connections */
+  osm_console_deinit_socket(p_osm);
+}
+
+/* turns off the console, signature needs to match the parse_funciton() */
+static void quit_parse(char **p_last, osm_console_thread_t *p_oct, 
CIO_t *out)
+{
+  // set the "done" flag used by the isDone() method
+  p_oct->authorized = 0;  // temporarily use this as the done flag
+
+  // do other necessary things to clean up and turn off
+}
+
+
 /* more parse routines go here */
 
 static const struct command console_cmds[] = {
-    {"help", &help_command, &help_parse},
-    {"quit", &help_quit, &quit_parse},
-    {"loglevel", &help_loglevel, &loglevel_parse},
-    {"priority", &help_priority, &priority_parse},
-    {"resweep", &help_resweep, &resweep_parse},
-    {"status", &help_status, &status_parse},
-    {"logflush", &help_logflush, &logflush_parse},
-    {"querylid", &help_querylid, &querylid_parse},
-    {"portstatus", &help_portstatus, &portstatus_parse},
-    {"version", &help_version, &version_parse},
+    { "help",    &help_command,        &help_parse},
+    { OSM_QUIT_CMD,    &help_quit,        &quit_parse},
+    { "loglevel",    &help_loglevel,        &loglevel_parse},
+    { "priority",    &help_priority,        &priority_parse},
+    { "resweep",    &help_resweep,        &resweep_parse},
+    { "status",    &help_status,        &status_parse},
+    { "logflush",    &help_logflush,        &logflush_parse},
+    { "querylid",   &help_querylid,         &querylid_parse},
+    { "portstatus", &help_portstatus,       &portstatus_parse},
+  { "version", &help_version,       &version_parse},
 #ifdef ENABLE_OSM_PERF_MGR
     {"perfmgr", &help_perfmgr, &perfmgr_parse},
 #endif                /* ENABLE_OSM_PERF_MGR */
     {NULL, NULL, NULL}    /* end of array */
 };
 
-static void parse_cmd_line(char *line, osm_opensm_t * p_osm)
-{
-    char *p_cmd, *p_last;
-    int i, found = 0;
-    FILE *out = p_osm->console.out;
-
-    while (isspace(*line))
-        line++;
-    if (!*line)
-        return;
 
-    /* find first token which is the command */
-    p_cmd = strtok_r(line, " \t\n\r", &p_last);
-    if (p_cmd) {
-        for (i = 0; console_cmds[i].name; i++) {
-            if (loop_command.on) {
-                if (!strcmp(p_cmd, "q")) {
-                    loop_command.on = 0;
-                }
-                found = 1;
-                break;
-            }
-            if (!strcmp(p_cmd, console_cmds[i].name)) {
-                found = 1;
-                console_cmds[i].parse_function(&p_last, p_osm,
-                                   out);
-                break;
-            }
-        }
-        if (!found) {
-            fprintf(out, "%s : Command not found\n\n", p_cmd);
-            help_command(out, 0);
-        }
-    } else {
-        fprintf(out, "Error parsing command line: `%s'\n", line);
-    }
-    if (loop_command.on) {
-        fprintf(out, "use \"q<ret>\" to quit loop\n");
-        fflush(out);
-    }
+static void parse_cmd_line(char *line, osm_console_thread_t *oct)
+{
+  char *p_cmd, *p_last;
+  int i, found = 0;
+  CIO_t *out = getCIO(oct);
+ 
+  while (isspace(*line))
+    line++;
+  if (!*line)
+    return;
+
+  /* find first token which is the command */
+  p_cmd = strtok_r(line, " \t\n\r", &p_last);
+  if (p_cmd) {
+    for (i = 0; console_cmds[i].name; i++) {
+      if (oct->loop_command.on ) {
+        if (!strcmp(p_cmd, "q")) {
+          oct->loop_command.on = 0;
+        }
+        found = 1;
+        break;
+      }
+      if (!strcmp(p_cmd, console_cmds[i].name)) {
+        found = 1;
+        console_cmds[i].parse_function(&p_last, oct, out);
+        break;
+      }
+    }
+    if (!found) {
+      cio_printf(out, "%s : Command not found\n\n", p_cmd);
+      help_command(out, 0);
+    }
+  } else {
+    cio_printf(out, "Error parsing command line: `%s'\n", line);
+  }
 }
 
-void osm_console_prompt(FILE * out)
+void osm_console_prompt(CIO_t *out, int loop_prompt)
 {
     if (out) {
-        fprintf(out, "OpenSM %s", OSM_COMMAND_PROMPT);
-        fflush(out);
+      if(loop_prompt)
+        cio_printf(out, "use \"q<ret>\" to quit loop\n");
+      else
+      cio_printf(out, "OpenSM %s", OSM_COMMAND_PROMPT);
+        cio_flush(out);
     }
 }
 
-void osm_console_init(osm_subn_opt_t * opt, osm_opensm_t * p_osm)
+/* open and setup socket connection */
+static void osm_console_init_socket(osm_opensm_t *p_osm, uint16_t 
console_port, char* console_type)
 {
-    p_osm->console.socket = -1;
-    /* set up the file descriptors for the console */
-    if (strcmp(opt->console, OSM_LOCAL_CONSOLE) == 0) {
-        p_osm->console.in = stdin;
-        p_osm->console.out = stdout;
-        p_osm->console.in_fd = fileno(stdin);
-        p_osm->console.out_fd = fileno(stdout);
-
-        osm_console_prompt(p_osm->console.out);
 #ifdef ENABLE_OSM_CONSOLE_SOCKET
-    } else if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0
-           || strcmp(opt->console, OSM_LOOPBACK_CONSOLE) == 0) {
-        struct sockaddr_in sin;
-        int optval = 1;
-
-        if ((p_osm->console.socket =
-             socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-            osm_log(&(p_osm->log), OSM_LOG_ERROR,
-                "osm_console_init: ERR 4B01: Failed to open console 
socket: %s\n",
-                strerror(errno));
-            return;
-        }
-        setsockopt(p_osm->console.socket, SOL_SOCKET, SO_REUSEADDR,
-               &optval, sizeof(optval));
-        sin.sin_family = AF_INET;
-        sin.sin_port = htons(opt->console_port);
-        if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0)
-            sin.sin_addr.s_addr = htonl(INADDR_ANY);
-        else
-            sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-        if (bind(p_osm->console.socket, &sin, sizeof(sin)) < 0) {
-            osm_log(&(p_osm->log), OSM_LOG_ERROR,
-                "osm_console_init: ERR 4B02: Failed to bind console 
socket: %s\n",
-                strerror(errno));
-            return;
-        }
-        if (listen(p_osm->console.socket, 1) < 0) {
-            osm_log(&(p_osm->log), OSM_LOG_ERROR,
-                "osm_console_init: ERR 4B03: Failed to listen on 
socket: %s\n",
-                strerror(errno));
-            return;
-        }
 
-        signal(SIGPIPE, SIG_IGN);    /* protect ourselves from closed 
pipes */
-        p_osm->console.in = NULL;
-        p_osm->console.out = NULL;
-        p_osm->console.in_fd = -1;
-        p_osm->console.out_fd = -1;
-        osm_log(&(p_osm->log), OSM_LOG_INFO,
-            "osm_console_init: Console listening on port %d\n",
-            opt->console_port);
+  struct sockaddr_in sin;
+  int optval = 1;
+ 
+  osm_log(&(p_osm->log), OSM_LOG_INFO, "osm_console_init_socket: 
Initializing the socket: %d\n", console_port);
+ 
+  if ((p_osm->console.socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+  {
+    osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_init_socket: ERR 
4B01: Failed to open console socket: %s\n", strerror(errno));
+    return;
+  }
+  setsockopt(p_osm->console.socket, SOL_SOCKET, SO_REUSEADDR, &optval, 
sizeof(optval));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(console_port);
+
+  // loopback or ...
+  if(is_loopback(console_type))
+    sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  else
+    sin.sin_addr.s_addr = htonl(INADDR_ANY);
+  if (bind(p_osm->console.socket, &sin, sizeof(sin))< 0)
+  {
+    osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_init_socket: ERR 
4B02: Failed to bind console socket: %s\n", strerror(errno));
+    return;
+  }
+  if (listen(p_osm->console.socket, 2)< 0)
+  {
+    osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_init_socket: ERR 
4B03: Failed to listen on socket: %s\n", strerror(errno));
+    return;
+  }
+
+  signal(SIGPIPE, SIG_IGN); /* protect ourselves from closed pipes */
+  p_osm->console.in = NULL;
+  p_osm->console.out = NULL;
+  p_osm->console.in_fd = -1;
+  p_osm->console.out_fd = -1;
+  osm_log(&(p_osm->log), OSM_LOG_INFO, "osm_console_init_socket: 
Console listening on port %d\n", console_port);
 #endif
-    }
 }
 
-#ifdef ENABLE_OSM_CONSOLE_SOCKET
-static void handle_osm_connection(osm_opensm_t * p_osm, int new_fd,
-                  char *client_ip, char *client_hn)
+/**********************************************************************
+ * thread pool primitive: gets the next available thread structure from
+ * the pool.
+ *
+ * refer to free_console_thread()
+ **********************************************************************/
+osm_console_thread_t* new_console_thread(void)
 {
-    char *p_line;
-    size_t len;
-    ssize_t n;
-
-    if (p_osm->console.in_fd >= 0) {
-        FILE *file = fdopen(new_fd, "w+");
-
-        fprintf(file, "OpenSM Console connection already in use\n"
-            "   kill other session (y/n)? ");
-        fflush(file);
-        p_line = NULL;
-        n = getline(&p_line, &len, file);
-        if (n > 0 && (p_line[0] == 'y' || p_line[0] == 'Y')) {
-            osm_console_close_socket(p_osm);
-        } else {
-            close(new_fd);
-            return;
-        }
-    }
-    p_osm->console.in_fd = new_fd;
-    p_osm->console.out_fd = p_osm->console.in_fd;
-    p_osm->console.in = fdopen(p_osm->console.in_fd, "w+");
-    p_osm->console.out = p_osm->console.in;
-    osm_console_prompt(p_osm->console.out);
-    osm_log(&(p_osm->log), OSM_LOG_INFO,
-        "osm_console_init: Console connection accepted: %s (%s)\n",
-        client_hn, client_ip);
+  // return the next available thread from the pool
+  //  just iterate through..
+
+  int i;
+  osm_console_thread_t* next = NULL;
+ 
+  cl_plock_acquire(&ThreadLock);
+  for(i = 0; i <  CIO_MAX_CONNECTS; ++i)
+  {
+    next = &ConsoleThreadPool[i];
+    if(next->used == 0)
+      break;
+  }
+ 
+  if(i >= CIO_MAX_CONNECTS)
+    next = NULL;  // full
+  else
+  {
+    // immediately mark this as NOT available
+    next->used = 1;
+    next->thread_num = ++cio_thread_counter;
+    gettimeofday(&(next->connect_time), NULL);   
+  }
+  cl_plock_release(&ThreadLock);
+ 
+  return next;
 }
 
-static int connection_ok(char *client_ip, char *client_hn)
+/**********************************************************************
+ * thread pool primitive: clears and initializes all the threads.  If the
+ * argument is a current thread, it will NOT be cleared (will be skipped)
+ **********************************************************************/
+int init_console_thread_pool(osm_console_thread_t* p_oct, 
osm_subn_opt_t *opt, osm_opensm_t *p_osm)
 {
-    return (hosts_ctl
-        (OSM_DAEMON_NAME, client_hn, client_ip, "STRING_UNKNOWN"));
+  // initialize
+
+  int i;
+  osm_console_thread_t* oct;
+ 
+  cl_plock_acquire(&ThreadLock);
+  for(i = 0; i <  CIO_MAX_CONNECTS; ++i)
+  {
+    oct = &ConsoleThreadPool[i];
+    if(p_oct == NULL || p_oct != oct)
+    {
+      oct->used        = 0;
+      oct->thread_num  = -1;
+      oct->authorized  = 0;
+      oct->port        = CIO_CONNECTION_PORT;
+      oct->io.fd       = -1;
+      oct->state       = 0;
+      oct->p_osm       = p_osm;
+      if(opt != NULL)
+      {
+        oct->port      = opt->console_port;
+        strncpy(oct->name, opt->console, CIO_INFO_SIZE);
+      }
+    }
+  }
+  cl_plock_release(&ThreadLock);
+  return i;
 }
-#endif
 
-void osm_console(osm_opensm_t * p_osm)
+void osm_console_server_init(osm_subn_opt_t *opt, osm_opensm_t *p_osm)
 {
-    struct pollfd pollfd[2];
-    char *p_line;
-    size_t len;
-    ssize_t n;
-    struct pollfd *fds;
-    nfds_t nfds;
-
-    pollfd[0].fd = p_osm->console.socket;
-    pollfd[0].events = POLLIN;
-    pollfd[0].revents = 0;
-
-    pollfd[1].fd = p_osm->console.in_fd;
-    pollfd[1].events = POLLIN;
-    pollfd[1].revents = 0;
-
-    fds = p_osm->console.socket < 0 ? &pollfd[1] : pollfd;
-    nfds = p_osm->console.socket < 0 || pollfd[1].fd < 0 ? 1 : 2;
-
-    if (loop_command.on && loop_command_check_time() &&
-        loop_command.loop_function) {
-        if (p_osm->console.out) {
-            loop_command.loop_function(p_osm, p_osm->console.out);
-            fflush(p_osm->console.out);
-        } else {
-            loop_command.on = 0;
-        }
-    }
+  int status = 0;
+
+  cl_plock_construct(&ThreadLock);
+  status = cl_plock_init(&ThreadLock);
+  if (status != IB_SUCCESS)
+    osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_server_init: 
lock initialization error\n");
+ 
+  init_console_thread_pool(NULL, opt, p_osm);
+ 
+  gettimeofday(&ServerTime, NULL);  // start time
+ 
+  p_osm->console.socket = -1;
+
+  /* set up the file descriptors for the console */
+  if (strcmp(opt->console, OSM_LOCAL_CONSOLE)== 0)
+  {
+    p_osm->console.in = stdin;
+    p_osm->console.out = stdout;
+    p_osm->console.in_fd = fileno(stdin);
+    p_osm->console.out_fd = fileno(stdout);
+  }
+  else if (is_remote(opt->console))
+  {
+    osm_console_init_socket(p_osm, opt->console_port, opt->console);
+  }
+  // TODO - other types of "console" connections here
+}
 
-    if (poll(fds, nfds, 1000) <= 0)
-        return;
+/**********************************************************************
+ * Main Loop Thread.
+ *
+ * Continuously loop on this command until turned off
+ **********************************************************************/
+void osm_loop_thread(void *p_ptr)
+{
+  osm_console_thread_t *oct = ( osm_console_thread_t * ) p_ptr;
+  CIO_t *p_io = getCIO(oct);
+ 
+  oct->loop_command.running = 1;
+  while (oct->loop_command.on && oct->loop_command.loop_function)
+  {
+    if (p_io->out)
+    {
+      // dwell here
+      cl_thread_suspend(oct->loop_command.delay_s * 1000);
+      oct->loop_command.loop_function(oct->p_osm, p_io);
+     
+      // send the cmd prompt
+      osm_console_prompt(p_io, oct->loop_command.on);    
+      cio_flush(p_io);
+    }
+    else
+    {
+      oct->loop_command.on = 0;
+    }
+  }
+  oct->loop_command.running = 0;
+  return;
+}
 
+/**********************************************************************
+ * Do authentication & authorization check
+ **********************************************************************/
+static int is_authorized(osm_console_thread_t *p_oct)
+{
 #ifdef ENABLE_OSM_CONSOLE_SOCKET
-    if (pollfd[0].revents & POLLIN) {
-        int new_fd = 0;
-        struct sockaddr_in sin;
-        socklen_t len = sizeof(sin);
-        char client_ip[64];
-        char client_hn[128];
-        struct hostent *hent;
-        if ((new_fd = accept(p_osm->console.socket, &sin, &len)) < 0) {
-            osm_log(&(p_osm->log), OSM_LOG_ERROR,
-                "osm_console: ERR 4B04: Failed to accept console 
socket: %s\n",
-                strerror(errno));
-            p_osm->console.in_fd = -1;
-            return;
-        }
-        if (inet_ntop
-            (AF_INET, &sin.sin_addr, client_ip,
-             sizeof(client_ip)) == NULL) {
-            snprintf(client_ip, 64, "STRING_UNKNOWN");
-        }
-        if ((hent = gethostbyaddr((const char *)&sin.sin_addr,
-                      sizeof(struct in_addr),
-                      AF_INET)) == NULL) {
-            snprintf(client_hn, 128, "STRING_UNKNOWN");
-        } else {
-            snprintf(client_hn, 128, "%s", hent->h_name);
-        }
-        if (connection_ok(client_ip, client_hn)) {
-            handle_osm_connection(p_osm, new_fd, client_ip,
-                          client_hn);
-        } else {
-            osm_log(&(p_osm->log), OSM_LOG_ERROR,
-                "osm_console: ERR 4B05: Console connection denied: %s 
(%s)\n",
-                client_hn, client_ip);
-            close(new_fd);
-        }
-        return;
-    }
+  ////  oct->authorized = pam_authorize(pTs);
+  p_oct->authorized = !is_remote(p_oct->client_type) ||
+                       hosts_ctl(OSM_DAEMON_NAME, p_oct->client_hn, 
p_oct->client_ip, "STRING_UNKNOWN");
+#else
+  p_oct->authorized = 1;
 #endif
+  return p_oct->authorized;
+}
 
-    if (pollfd[1].revents & POLLIN) {
-        p_line = NULL;
-        /* Get input line */
-        n = getline(&p_line, &len, p_osm->console.in);
-        if (n > 0) {
-            /* Parse and act on input */
-            parse_cmd_line(p_line, p_osm);
-            if (!loop_command.on) {
-                osm_console_prompt(p_osm->console.out);
-            }
-        } else
-            osm_console_close_socket(p_osm);
-        if (p_line)
-            free(p_line);
-    }
+/*
+ * determine if the connection should be closed
+ */
+static int is_done(osm_console_thread_t *oct)
+{
+  int done = 0;  // set to 1 when finished
+ 
+  /* Look for a condition that signals the connection should be closed */
+  if (!(oct->authorized) || !strcmp(oct->in_buff, OSM_QUIT_CMD) || 
osm_exit_flag)
+  {
+    done = 1;
+  }
+  return (done);
+}
+
+/*
+ * handle basic output to the client
+ *
+ * this includes results from a command, error information
+ * or any appropriate feedback
+ */
+static int output(osm_console_thread_t *oct)
+{
+  CIO_t *out = getCIO(oct);
+ 
+  // send the output buffer to the client
+  cio_printf(out, oct->out_buff);
+  cio_flush(out);
+ 
+  // clear the output buffer??
+  oct->out_buff[0] = 0;
+
+  // send the cmd prompt
+  if(!oct->loop_command.on)
+    osm_console_prompt(out, 0);
+ 
+  return (is_done(oct));
+}
+
+/*
+ * handle basic input from the socket
+ */
+static int input(osm_console_thread_t *oct)
+{
+  char *p_line = NULL;
+  size_t len;
+  ssize_t n;
+  CIO_t *p_io = getCIO(oct);
+ 
+  // if we are in a loop command, the don't block
+  if(oct->loop_command.on && !cio_poll(p_io, 1000))
+    return 0;
+
+  /* Get input line */
+  n = cio_getline(&p_line, &len, p_io);
+  if (n > 0)
+  {
+    // got something, so copy it to the input buffer
+    sprintf(oct->in_buff, "%s", p_line);     
+
+    if(p_line)
+     free(p_line);
+  }
+ 
+ return (0);
+}
+
+/*
+ * process the command in the input buffer -
+ *    take action, produce results, copy to output buffer
+ */
+static int commands(osm_console_thread_t *oct)
+{
+  osm_opensm_t *p_osm = oct->p_osm;
+  
+   ib_api_status_t status = IB_INSUFFICIENT_RESOURCES;
+
+   parse_cmd_line(oct->in_buff, oct);
+  
+   /* if parsed and executed then clear the input buffer
+    */
+   oct->in_buff[0] = 0;
+  
+   /* special case, only allow one loop command
+    */
+   if(!oct->loop_command.running && oct->loop_command.on && 
oct->loop_command.loop_function)
+   {
+     status = cl_thread_init(&oct->loop_command.loopThread, 
osm_loop_thread, oct, "Loop command");   
+     if (status != IB_SUCCESS)
+     {
+       // something bad
+       osm_log(&(p_osm->log), OSM_LOG_ERROR,
+           "commands: Couldn't create a thread for the loop command!\n");
+       return -1;
+     }
+   }
+   return (0);
+}
+
+/**********************************************************************
+ * Initialization and configuration of the console connection.
+ * (security & authorization, plus some bookkeeping)
+ *
+ * returns 1 if okay
+ *         0 if not authorized
+ *        -1 if too many connections
+ *        -2 if error??
+ **********************************************************************/
+int osm_console_init(osm_console_thread_t *p_oct)
+{
+  // the first opportunity to do thread specific actions
+ 
+  int status = 0; // not authorized
+  int max_connects_exceeded = (num_console_threads() >= CIO_MAX_CONNECTS);
+
+  osm_opensm_t *p_osm = p_oct->p_osm;
+  CIO_t *p_io = getCIO(p_oct);
+
+  // check for authorization
+  if(is_authorized(p_oct))
+  {
+    // check for available connections (too many?)
+    if (!max_connects_exceeded)
+     {
+       cio_open(p_io);
+
+       osm_log(&(p_osm->log), OSM_LOG_INFO, "osm_console_init: Console 
connection accepted: %s (%s) s#%d\n", p_oct->client_hn,
+           p_oct->client_ip, p_io->fd);
+       status = 1;
+     }
+     else
+     {
+       osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_init: ERR 
4B06: No available connections: %s (%s) t#%d\n", p_oct->client_hn,
+           p_oct->client_ip, num_console_threads());
+       status = -1;
+     }   
+  }
+  else
+  {
+    osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_init: ERR 4B05: 
Console connection denied: %s (%s)\n", p_oct->client_hn,
+        p_oct->client_ip);
+    status = 0;   
+  }
+ 
+  fflush(p_osm->log.out_port);
+  return status;
+}
+
+/**********************************************************************
+ * The console I/O and command loop
+ *   refer to:  osm_console_init and osm_console_destroy
+ **********************************************************************/
+void osm_console(osm_console_thread_t *oct)
+{
+  cl_thread_suspend(100);  // wait for other threads to initialize
+ 
+  // provide feedback from the server (probably from a previous command)
+  while(!output(oct))
+  {
+    // read the socket
+    input(oct);
+   
+    // process or act on the input
+    commands(oct);
+  }
+  // final methods??
 }
+
+/**********************************************************************
+ * Main Console Thread.
+ *
+ * Finish setting up the connection ( secure & authorized) and misc config
+ *
+ * Loop continuously in the osm_console method.
+ *
+ * Clean up, and gracefully exit when done
+ **********************************************************************/
+void osm_console_thread(void *p_ptr)
+{
+  osm_console_thread_t *p_oct = ( osm_console_thread_t * ) p_ptr;
+ 
+  /* Finish setting up the connection (secure & authorized) and misc 
config */
+  if(osm_console_init(p_oct) == 1)
+  {
+    // do all i/o and commands until done
+    osm_console(p_oct);
+   
+    // done, so close down the console gracefully
+    osm_console_destroy(p_oct);
+  } 
+ 
+  // nothing left to do but destroy our own thread, return to pool
+  osm_console_thread_destroy(p_oct);
+  return; 
+}
+
+/* Prepare to launch the console by encapsulating all the necessary 
data in a thread
+ * safe data structure.
+ *
+ * Support for single (local) or multiple (socket) threads.
+ *
+ * initialize the console data structure for a thread, and then..
+ *   if socket
+ *      create the thread
+ *   else
+ *      run inline
+ *
+ * refer to:  osm_console_thread and osm_console_thread_destroy
+ *
+ */
+int osm_console_thread_init(int socket, struct sockaddr_in *sin, 
osm_subn_opt_t *p_opt, osm_opensm_t *p_osm)
+{
+  static int n_local = 0;
+  osm_console_thread_t *oct;        // see free_console_thread() !!
+  ib_api_status_t status = IB_INSUFFICIENT_RESOURCES;
+
+  // have we used up all available connections?
+  if ((!is_remote(p_opt->console) && n_local) || ((oct = 
new_console_thread())== NULL))
+  {
+    if(n_local)
+      cl_thread_suspend( 100000);  // denied, dwell here before trying 
again.
+    else
+      osm_log(&(p_osm->log), OSM_LOG_ERROR,
+          "osm_console_thread_init: Maximum number of connections 
exceeded, connection denied (%d)\n",
+          num_console_threads());
+    return status;
+  }
+ 
+  if(!is_remote(p_opt->console))
+      n_local++;  // only one local connection...
+
+  /* fill in the osm_console_thread_t structure (can't be NULL) */
+  oct->authorized = 0;
+  oct->state = 0;
+  oct->p_osm = p_osm;
+  oct->io.fd = socket;
+  oct->port = p_opt->console_port;
+  snprintf(oct->client_type, CIO_NOTE_SIZE, p_opt->console);
+ 
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+  /* get then name and ip of the client (console connection) */
+  if(is_remote(oct->client_type))
+  {
+    /* get the clients ip address */
+    if (inet_ntop(AF_INET, &sin->sin_addr, oct->client_ip, 
sizeof(oct->client_ip))== NULL)
+    {
+      snprintf(oct->client_ip, CIO_NOTE_SIZE, "STRING_UNKNOWN");
+    }
+   
+    /* get the clients host name */
+    struct hostent *hent;
+    if ((hent = gethostbyaddr((const char *)&sin->sin_addr, 
sizeof(struct in_addr), AF_INET)) == NULL)
+    {
+      snprintf(oct->client_hn, CIO_INFO_SIZE, "STRING_UNKNOWN");
+    }
+    else
+    {
+      snprintf(oct->client_hn, CIO_INFO_SIZE, "%s", hent->h_name);
+    }   
+  } 
+  else
+#endif   
+  {
+    if(gethostname(oct->client_hn, CIO_INFO_SIZE))
+    {
+      snprintf(oct->client_hn, CIO_INFO_SIZE, "localhost");
+      snprintf(oct->client_ip, CIO_NOTE_SIZE, "localhost");
+    }
+    else
+      snprintf(oct->client_ip, CIO_NOTE_SIZE, oct->client_hn);   
+  }
+   
+
+  // create a name for the thread, based on the connection
+  snprintf(oct->name, CIO_INFO_SIZE, "%s %d", OSM_CONSOLE_NAME, 
oct->io.fd);
+
+  // ***** Finally, create a new thread for this connection ******
+  status = cl_thread_init(&oct->consoleThread, osm_console_thread, oct, 
oct->name);   
+  if (status != IB_SUCCESS)
+  {
+    // something bad
+    osm_log(&(p_osm->log), OSM_LOG_ERROR,
+        "osm_console_thread_init: Couldn't create a thread for the 
socket!\n");
+
+    // free up the thread, wasn't actually used   
+    osm_console_thread_destroy(oct);
+    return -1;
+  }
+  return 0;
+}
+
+
+/* Multi-threaded service to handle zero or more osm_consoles
+ *
+ * Typically the OSM runs as a daemon process, with zero
+ *   consoles.  Occationally it is necessary to remotely connect
+ *   to the OSM through a console connection.
+ *
+ * Allow one Master remote console and many Slaves.
+ *
+ * Provide a mechanism to release and assume Master role.
+ *
+ */
+int osm_console_server(osm_subn_opt_t *p_opt, osm_opensm_t *p_osm)
+{
+  struct sockaddr_in sin;
+  int s = 0;
+
+  /* don't enter this code section, if the exit flag is true */
+  if (!osm_exit_flag)
+  {
+    // handle IO from local or remote console
+    // blocks here until a client tries to connect
+
+    /*
+     * this version is supposed to block
+     *
+     * the block is released when a connection occurs, which causes a new
+     * thread to be spawned to handle the connection.  The new thread 
cleans
+     * up after itself.
+     *
+     * return only happens after a successful connection has been 
established,
+     * and needs to be prepared for another connection.
+     */
+#ifdef ENABLE_OSM_CONSOLE_SOCKET
+    socklen_t len = sizeof(sin);
+    if (is_remote(p_opt->console) && ((s = 
accept(p_osm->console.socket, &sin, &len)) < 0))
+    {
+      // kill sig can cause this... which would be normal during a shutdown
+      osm_log(&(p_osm->log), OSM_LOG_ERROR, "osm_console_server: not 
accepting socket connections\n");
+      return -1;
+    }
+    else
+#endif
+      // create a thread to handle the i/o on this connection
+      osm_console_thread_init(s, &sin, p_opt, p_osm);
+  }
+  else
+    free_console_threads(p_osm);  // clean up
+  return s;
+}
+
+
+/**********************************************************************
+ * Function Name:
+ *             cio_vprintf
+ *
+ * This routine formats a message and uses a Stream IO abstraction to 
determine
+ * how and where to write the message out (stdout, socket, ssl, etc.)
+ *
+ * Side Effects:
+ *             Unknown, uses vsprintf and variable arguments.  Possible 
stack problems.
+ *
+ * cio         pointer to the Connection IO data structure - an IO 
Stream abstraction
+ *
+ * format      A string literal that describes the desired text and 
formatting.  See printf().
+ *
+ * args        A variable argument list, of the type available between 
a va_start() and
+ *             va_end() block.
+ *
+ * Always returns 0
+ 
******************************************************************************/
+
+ int cio_vprintf( CIO_t *cio, const char *format, va_list args)
+ {
+   char msg_buffer[CIO_BUFSIZE];
+
+   // create the formatted string and place it in the local string buffer
+   vsprintf(msg_buffer, format, args);
+  
+   // send it out the proper I/O channel
+   fprintf(cio->out, msg_buffer);
+
+   return 0;
+ }
+
+/******************************************************************************
+ * Function Name:
+ *             cio_printf
+ *
+ * This is an abstract form of the standard fprintf() routine.  It can 
be used
+ * in an identical manner, with the exception of the first argument 
that needs
+ * to be the Connection IO abstraction, rather than a FILE.
+ *
+ * Side Effects:
+ *             Unknown, uses vsprintf and variable arguments.  Possible 
stack problems.
+ *
+ * cio         pointer to the Connection IO data structure - an IO 
Stream abstraction
+ *
+ * format      A string literal that describes the desired text and 
formatting.  See printf().
+ *
+ * args        A variable argument list, of the type available between 
a va_start() and
+ *             va_end() block.
+ *
+ * Always returns 0, from cio_vprintf()
+ 
******************************************************************************/
+
+ int cio_printf( CIO_t *cio, const char *format, ...)
+ {
+   int returnval = 0;
+   va_list args;
+  
+   // Sink Filter or Message Filter.  Does it get printed??
+   if(1)
+   {
+     va_start(args, format);
+     returnval = cio_vprintf(cio, format, args);
+     va_end(args);
+   }
+   return returnval;
+ }
+
+ int cio_flush( CIO_t *cio)
+ {
+   int returnval = fflush(cio->out);
+  
+   return returnval;
+ }
+
+ int cio_getline( char **lineptr, size_t *n, CIO_t *cio)
+ {
+   int returnval = getline(lineptr, n, cio->in);
+  
+   return returnval;
+ }
+
+ int cio_open( CIO_t *cio)
+ {
+   // returns zero, if opened fine, -1 otherwise
+  
+   struct pollfd *pd = (struct pollfd* )malloc(sizeof(struct pollfd));
+   if (pd == NULL)
+     return -1;  // should not happen
+  
+   cio->in = fdopen(cio->fd, "w+");
+   cio->out = cio->in;
+   cio->err = cio->in;
+  
+   cio->pfd = pd;
+   cio->pfd[0].fd = cio->fd;
+   cio->pfd[0].events = POLLIN;
+   cio->pfd[0].revents = 0;
+  
+   return (cio->in == NULL) ? -1 : 0;
+ }
+
+ int cio_close( CIO_t *cio)
+ {
+   int rtnval = -1;
+   if(cio && (cio->fd > 0))
+   {
+     free(cio->pfd);
+     rtnval = close(cio->fd);
+   }
+   cio->fd = 0;
+   return rtnval;
+ }
+
+ /* return true if input available */
+ int cio_poll(CIO_t *cio, int timeout)
+ {
+   // if timeout is less than 1, return true, alw
+   if(timeout < 1)
+     return 1;
+   return (poll(cio->pfd, 1, timeout) > 0);
+ }    
-- 
1.5.1


========

-- 
Timothy A. Meier
Computer Scientist
ICCD/High Performance Computing
925.422.3341
meier3 at llnl.gov

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 0001-opensm-osm_console-modified-console-framework-to.patch
URL: <http://lists.openfabrics.org/pipermail/general/attachments/20071015/e48aebb7/attachment.ksh>


More information about the general mailing list