## root/source/sockc.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following definitions.

1. main
2. parse_comline
3. d_initialize
4. d_socloc_activate
5. do_comm
6. d_term
7. d_socloc_term
8. d_status
9. d_client_log_on
10. d_client_log_off
11. d_client_log_status
12. d_server_log_on
13. d_server_log_off
14. d_server_log_status
15. d_socloc_log_on
16. d_socloc_log_off
17. d_socloc_log_status
18. d_connect
19. d_socloc_connect
20. d_socloc_list
21. d_socloc_config_list
22. d_socloc_get
23. d_socloc_find
24. d_socloc_service_name
25. d_service_name
26. d_socloc_version
27. d_version
28. d_client_version
29. d_socloc_config_find
30. d_socloc_status
31. d_socloc_client_update
32. d_socloc_client_update_file
33. d_send
34. d_socloc_add
35. d_socloc_config_add
36. d_socloc_delete
37. d_socloc_config_delete
38. d_socloc_on
39. d_socloc_off
40. d_socloc_dump
41. d_socloc_config_dump
42. d_socloc_trans_num
43. d_socloc_connect_num
44. d_trans_num
45. d_connect_num
46. d_display_list
47. d_display_config_list
48. d_sr
49. get_token
50. d_display_connect_status
51. d_header
52. d_out
53. is_connected
54. term_app

    /* sockc - A command line for any command string connection oriented
       socket server or QNX message passing server. Rick Smereka,
       Copyright (C) 2000-2006.

       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2 of the License, or
       (at your option) any later version.

       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.  See the
       GNU General Public License for more details.

       You should have received a copy of the GNU General Public License
       along with this program; if not, get a copy via the Internet at
       http://gnu.org/copyleft/gpl.html or write to the Free Software
       Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       MA 02111-1307 USA

       You can contact the author via email at rsmereka@future-lab.com

       Original Windows 32bit version Feb/2000, Rick Smereka

       Re-compiled after re-structuring the definition of the common
       send and repy codes. Apr/2000, Rick Smereka

       Changed function 'main' to return an 'init'. Changed function
       'main' to use 'scanf' instead of 'gets' to acquire command
       from user. Fixed bug in functions 'd_socloc_list' and
       'd_socloc_config_list' that 'free'ed allocated memory too
       soon. Added two command line switches. Program syntax now is:

          sockc [-s] [-l log_file]

       Where '-s' will not connect to or use 'socloc' and '-l'
       will specify a client log file name. Added the commands
       'SOCLOC.ON' and 'SOCLOC.OFF' to turn the 'socloc' interface
       on or off while the program is running. Changed the method
       of obtaining the command line from 'scanf' back to 'gets' after
       I realized that 'scanf' will stop parsing when it detects a
       space. May/2000, Rick Smereka

       Re-compiled after adding the new 'clib' module 'ip.c'.
       Jul/2000, Rick Smereka

       Corrected some minor messages and documentation. Jul/2001,
       Rick Smereka

       Modified for use by both socket and QNX message passing servers.
       Ported to QNX V4.23a. Since the 'socloc' interface does not exist
       with QNX message passing server, the '-s' switch does not exist
       for this variant. QNX message passing syntax is:

          sockc [-l log_file]

       Oct/2001, Rick Smereka

       Ported to Debian Linux. Jan/2003, Rick Smereka

       Modified for the updated 'socloc' API ('sloc.c') and generic client
       IPC API ('ipclient.c'). Added support for the commands 'socloc.trans.num',
       'socloc.connect.num', 'trans.num' and 'connect.num'. May/2003,
       Rick Smereka

       Added function 'term_api' which performs an orderly shutdown of
       any sockets in use (TCP) and terminates all API's in use.
       Jun/2003, Rick Smereka

       Code cleanup and changed all logging calls to use the
       'logman' API. Dec/2004, Rick Smereka

       Re-compile after changing the 'socloc' API.
       Jan/2005, Rick Smereka

       Re-compile after modifications to low level TCP socket communication
       module (ipcomm.c). Feb/2006, Rick Smereka */

    #include "stdhead.h"
    #include "flsocket.h"
    #include "ipclient.h"                 /* IPC high level routines */
    #ifdef IPC_TCP
    #include "ip.h"
    #include "ipcomm.h"                   /* TCP low level routines */
    #include "socloc.h"                   /* socket locate defines */
    #include "sloc.h"                     /* 'socloc' client API */
    #include "sconnect.h"                 /* parse connect string */
    #endif

    #define VERSION "1.14.01-2006.02.23"  /* version ID */
    #define APNAME "sockc"

    /* default log file definition */

    #define SOCKC_LOG_FILE "sockc.log"

    /* client/server return/reply codes */

    #define SC_OK SOCKET_RC_OK
    #define SC_VC_ERROR SOCKET_RC_VC_ERROR
    #define SC_NO_SERVER 1
    #define SC_MEMORY_FAIL 2

    /* send messages */

    #define SC_SEND_TERM SOCKET_SEND_TERM
    #define SC_SEND_STATUS SOCKET_SEND_STATUS
    #define SC_SEND_LOG_OFF SOCKET_SEND_LOG_OFF
    #define SC_SEND_LOG_ON SOCKET_SEND_LOG_ON
    #define SC_SEND_LOG_STATUS SOCKET_SEND_LOG_STATUS
    #define SC_SEND_SERVICE_NAME SOCKET_SEND_SERVICE_NAME
    #define SC_SEND_VERSION SOCKET_SEND_VERSION
    #define SC_SEND_TRANS_NUM SOCKET_SEND_TRANS_NUM
    #define SC_SEND_CONNECT_NUM SOCKET_SEND_CONNECT_NUM

    /* command line codes */

    #define SCOM_TERM 1
    #define SCOM_STATUS 2
    #define SCOM_CLIENT_LOG_OFF 3
    #define SCOM_CLIENT_LOG_ON 4
    #define SCOM_CLIENT_LOG_STATUS 5
    #define SCOM_SERVER_LOG_OFF 6
    #define SCOM_SERVER_LOG_ON 7
    #define SCOM_SERVER_LOG_STATUS 8
    #define SCOM_CONNECT 9
    #define SCOM_SOCLOC_LIST 10
    #define SCOM_SOCLOC_CONFIG_LIST 11
    #define SCOM_SOCLOC_GET 12
    #define SCOM_SOCLOC_LOG_ON 13
    #define SCOM_SOCLOC_LOG_OFF 14
    #define SCOM_SOCLOC_LOG_STATUS 15
    #define SCOM_SOCLOC_CONNECT 16
    #define SCOM_SOCLOC_FIND 17
    #define SCOM_SOCLOC_SERVICE_NAME 18
    #define SCOM_SERVICE_NAME 19
    #define SCOM_SOCLOC_VERSION 20
    #define SCOM_VERSION 21
    #define SCOM_SOCLOC_CONFIG_FIND 22
    #define SCOM_SOCLOC_STATUS 23
    #define SCOM_SOCLOC_CLIENT_LIST 24
    #define SCOM_SOCLOC_CLIENT_UPDATE 25
    #define SCOM_SOCLOC_CLIENT_UPDATE_FILE 26
    #define SCOM_SEND 27
    #define SCOM_SOCLOC_ADD 28
    #define SCOM_SOCLOC_CONFIG_ADD 29
    #define SCOM_SOCLOC_DELETE 30
    #define SCOM_SOCLOC_CONFIG_DELETE 31
    #define SCOM_SOCLOC_DUMP 32
    #define SCOM_SOCLOC_CONFIG_DUMP 33
    #define SCOM_SOCLOC_TERM 34
    #define SCOM_CLIENT_VERSION 35
    #define SCOM_SOCLOC_ON 36
    #define SCOM_SOCLOC_OFF 37
    #define SCOM_SOCLOC_TRANS_NUM 38
    #define SCOM_SOCLOC_CONNECT_NUM 39
    #define SCOM_TRANS_NUM 40
    #define SCOM_CONNECT_NUM 41
    #define SCOM_NOT_FOUND -1
    #define SCOM_OFF -2
    #define SCOM_MAXCOM 41

    /* maximum size of socket send/receive buffer */

    #define SC_MAXCOMMAND 32767

    /* global data */

    #ifdef IPC_TCP
    #ifdef OS_WIN32
    WSADATA wsaData;
    #endif

    int serverport = 0;                  /* socket server TCP port */
    char serverservice[128];             /* socket server service name */
    int sk_port = 0;                     /* 'socloc' server TCP port */
    char sk_host[128];                   /* 'socloc' server host name */
    int sk_flag = TRUE;                  /* 'socloc' on/off flag */
    #else
    int sk_flag = FALSE;
    #endif

    char serverhost[128];                /* server host name */
    char d_log_file[128];                /* name of client log */

    int main(int, char **);
    int parse_comline(int, char **);
    int d_initialize(void);
    int d_socloc_activate(void);
    void d_term(char *);
    void d_socloc_term(char *);
    void d_status(void);
    void d_client_log_on(char *);
    void d_client_log_off(void);
    void d_client_log_status(void);
    void d_server_log_on(char *);
    void d_server_log_off(void);
    void d_server_log_status(void);
    void d_socloc_log_on(char *);
    void d_socloc_log_off(void);
    void d_socloc_log_status(void);
    void d_connect(char *);
    void d_socloc_connect(char *);
    void d_socloc_list(void);
    void d_socloc_config_list(void);
    void d_socloc_get(void);
    void d_socloc_find(char *);
    void d_socloc_service_name(void);
    void d_service_name(void);
    void d_socloc_version(void);
    void d_version(void);
    void d_client_version(void);
    void d_socloc_config_find(char *);
    void d_socloc_status(void);
    void d_socloc_client_update(void);
    void d_socloc_client_update_file(void);
    void d_send(char *);
    void d_socloc_add(char *);
    void d_socloc_config_add(char *);
    void d_socloc_delete(char *);
    void d_socloc_config_delete(char *);
    void d_socloc_on(void);
    void d_socloc_off(void);
    void d_socloc_dump(void);
    void d_socloc_config_dump(void);
    void d_socloc_trans_num(void);
    void d_socloc_connect_num(void);
    void d_trans_num(void);
    void d_connect_num(void);
    int get_token(char *);
    void d_display_connect_status(void);
    void d_header(char *);
    void d_out(char *,...);
    int is_connected(void);
    void term_app(void);

    #ifdef IPC_TCP
    int d_sr(int, char *, char *);
    void d_display_list(char *);
    void d_display_config_list(char *);
    #else
    int d_sr(int, char *, char *, int);
    #endif

    int main(int argc, char **argv)
    {
       char *comm;
       int done = FALSE;

       /* set default log file name */

       strcpy(d_log_file, SOCKC_LOG_FILE);

       /* parse any command line parameters */

       if (argc > 1)
          if (!parse_comline(argc, argv))
             return(0);

       /* allocate command line buffer */

       if ((comm = malloc(BUFSIZE + 1)) == NULL)
          {
          printf("%s:insufficient memory to run program\n", APNAME);
          return(0);
          }

       /* build logo string based on platform */

    #ifndef OS_UNIX
       /* non-Unix */

       printf("%s for %s Version %s\n", APNAME, PLATFORM_STRING, VERSION);
    #else
       /* Unix */

       printf("%s for %s Version %s\n", APNAME, SUB_PLATFORM_STRING, VERSION);
    #endif

       printf("By Rick Smereka, Copyright (c) 2000-2006\n");

       /* initialize */

       if (!d_initialize())
          {
          free(comm);
          term_app();
          return(0);
          }

       printf("%s comes with ABSOLUTELY NO WARRANTY\n", APNAME);
       printf("This is free software, and you are welcome to redistribute it\n");
       printf("under certain conditions; see 'gpl.txt' for information.\n");
       (void)flag_2_logic_string(sk_flag, comm);
    #ifdef IPC_TCP
       printf("%s:socloc interface is %s\n", APNAME, comm);
    #endif

       /* interpret loop */

       while(!done)
          {
          d_display_connect_status();
          printf(">");
          get_rec(stdin, comm);

          if (!do_comm(comm))
             done = TRUE;
          }

       free(comm);
       term_app();
       printf("exit %s\n", APNAME);
       return(0);
    }

    int parse_comline(int c_count, char **c_parm)
    {
       /* Parse the command line for parameters. Function
          returns 'TRUE' if no error was detected, 'FALSE'
          otherwise. */

       char mname[] = "sockc:parse_comline";
       int parms = 1, done = FALSE;

       while(!done)
          {
          if (c_parm[parms][0] == SWITCH_CHAR)
             {
             switch(toupper(c_parm[parms][1]))
                {
                case 'L':
                   if (strlen(c_parm[parms]) > 2)
                      printf("%s:extraneous input with log file switch, "
                             "ignoring\n", mname);

                   parms++;

                   if (parms >= c_count)
                      {
                      printf("%s:log file switch with no file name, "
                             "program abort\n", mname);
                      return(FALSE);
                      }

                   strcpy(d_log_file, c_parm[parms]);
                   parms++;
                   break;

    #ifdef IPC_TCP
                case 'S':
                   sk_flag = FALSE;
                   parms++;
                   break;
    #endif

                default:
                   printf("%s:unknown switch[%s], program abort\n",
                          mname, c_parm[parms]);
                   return(FALSE);
                };
             }
          else
             {
             printf("%s:unknown parameter[%s], program abort\n",
                    mname, c_parm[parms]);
             return(FALSE);
             }

          if (parms >= c_count)
             done = TRUE;
          }

       return(TRUE);
    }

    int d_initialize(void)
    {
       /* Initialize communication, form connection to
          'socloc' server and update the config list if
          'socloc' is turned on (TCP only). Function returns 'TRUE'
          upon success, 'FALSE' otherwise. */

       char mname[] = "d_initialize";
       char *thelist, mes[128];
       int ret;

       logman("%s:enter", mname);

       /* startup WinSock (if Windoze) */

    #ifdef OS_WIN32
       if (WSAStartup(WINSOCK_VERSION, &wsaData))
          {
          d_out("%s:unable to start WinSock. "
                "Program abort", mname);
          return(FALSE);
          }
    #endif

    #ifdef IPC_TCP
       if (sk_flag)
          if (!d_socloc_activate())
             {
             d_out("%s:socloc failure, program abort", mname);
             return(FALSE);
             }
    #endif

       serverhost[0] = EOS;

    #ifdef IPC_TCP
       serverservice[0] = EOS;
       serverport = 0;
    #endif
       logman("%s:exit[TRUE]", mname);
       return(TRUE);
    }

    int d_socloc_activate(void)
    {
       /* Initialize the 'socloc' interface and connect to a
          'socloc' server. Function returns 'TRUE' upon
          success, 'FALSE' otherwise. If the function fails,
          the global 'socloc' flag will be forced down. */

       char mname[] = "d_socloc_activate";
       char *thelist, mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies only to TCP IPC method", mname);
       return(FALSE);
    #else
       /* attempt to connect to a 'socloc' server */

       if ((ret = sloc_initialize()) != SL_OK)
          {
          sl_code_string(ret, mes);
          d_out("%s:bad rc[%s] from 'sloc_initialize'", mname, mes);
          sk_flag = FALSE;
          return(FALSE);
          }

       /* get config list from 'socloc' server and update
          the client list with it */

       if ((thelist = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[thelist]", mname);
          sk_flag = FALSE;
          sloc_term_api();
          return(FALSE);
          }

       if ((ret = sloc_config_get_list(thelist)) != SL_OK)
          {
          free(thelist);
          sl_code_string(ret, mes);
          d_out("%s:bad rc[%s] from 'sloc_config_get_list'", mname, mes);
          sk_flag = FALSE;
          sloc_term_api();
          return(FALSE);
          }

       if ((ret = sl_config_put_list(thelist)) != SL_OK)
          {
          sl_code_string(ret, mes);
          d_out("%s:bad rc[%s] from 'sl_config_put_list'",
                        mname, mes);
          free(thelist);
          sk_flag = FALSE;
          sloc_term_api();
          return(FALSE);
          }

       free(thelist);
       sk_flag = TRUE;
       return(TRUE);
    #endif
    }

    int do_comm(char *comm)
    {
       /* Dispatch a 'sockc' command. */

       char mname[] = "do_comm";
       char *keywrd;                 /* command keyword */
       int token;                    /* keyword token */
       int nwords;                   /* number of words */
       int len;                      /* length of command */

       logman("%s:enter", mname);
       len = strlen(comm);

       if (!len)
          {
          d_out("empty command");
          return(TRUE);
          }

       if ((keywrd = malloc(SC_MAXCOMMAND + 1)) == NULL)
          {
          d_out("%s:alloc fail[keywrd]", mname);
          return(TRUE);
          }

       if (!word(comm, keywrd, 1))
          {
          d_out("%s:error while retreving keyword, line skipped", mname);
          free(keywrd);
          return(TRUE);
          }

       nwords = words(comm);

       if ((token = get_token(keywrd)) == SCOM_NOT_FOUND)
          {
          d_out("%s:unknown keyword[%s]", mname, keywrd);
          free(keywrd);
          return(TRUE);
          }

       /* process command */

       switch(token)
          {
          case SCOM_TERM:
             d_term(comm);
             break;

          case SCOM_SOCLOC_TERM:
             d_socloc_term(comm);
             break;

          case SCOM_STATUS:
             d_status();
             break;

          case SCOM_CLIENT_LOG_ON:
             d_client_log_on(comm);
             break;

          case SCOM_CLIENT_LOG_OFF:
             d_client_log_off();
             break;

          case SCOM_CLIENT_LOG_STATUS:
             d_client_log_status();
             break;

          case SCOM_SERVER_LOG_ON:
             d_server_log_on(comm);
             break;

          case SCOM_SERVER_LOG_OFF:
             d_server_log_off();
             break;

          case SCOM_SERVER_LOG_STATUS:
             d_server_log_status();
             break;

          case SCOM_CONNECT:
             d_connect(comm);
             break;

          case SCOM_SOCLOC_LIST:
             d_socloc_list();
             break;

          case SCOM_SOCLOC_CONFIG_LIST:
             d_socloc_config_list();
             break;

          case SCOM_SOCLOC_GET:
             d_socloc_get();
             break;

          case SCOM_SOCLOC_LOG_ON:
             d_socloc_log_on(comm);
             break;

          case SCOM_SOCLOC_LOG_OFF:
             d_socloc_log_off();
             break;

          case SCOM_SOCLOC_LOG_STATUS:
             d_socloc_log_status();
             break;

          case SCOM_SOCLOC_CONNECT:
             d_socloc_connect(comm);
             break;

          case SCOM_SOCLOC_FIND:
             d_socloc_find(comm);
             break;

          case SCOM_SOCLOC_SERVICE_NAME:
             d_socloc_service_name();
             break;

          case SCOM_SERVICE_NAME:
             d_service_name();
             break;

          case SCOM_SOCLOC_VERSION:
             d_socloc_version();
             break;

          case SCOM_VERSION:
             d_version();
             break;

          case SCOM_SOCLOC_CONFIG_FIND:
             d_socloc_config_find(comm);
             break;

          case SCOM_SOCLOC_STATUS:
             d_socloc_status();
             break;

          case SCOM_SOCLOC_CLIENT_LIST:
    #ifdef IPC_TCP
             sl_config_list();
    #else
             d_out("%s:applies to TCP IPC method only", mname);
    #endif
             break;

          case SCOM_SOCLOC_CLIENT_UPDATE:
             d_socloc_client_update();
             break;

          case SCOM_SOCLOC_CLIENT_UPDATE_FILE:
             d_socloc_client_update_file();
             break;

          case SCOM_SEND:
             d_send(comm);
             break;

          case SCOM_SOCLOC_ADD:
             d_socloc_add(comm);
             break;

          case SCOM_SOCLOC_CONFIG_ADD:
             d_socloc_config_add(comm);
             break;

          case SCOM_SOCLOC_DELETE:
             d_socloc_delete(comm);
             break;

          case SCOM_SOCLOC_CONFIG_DELETE:
             d_socloc_config_delete(comm);
             break;

          case SCOM_SOCLOC_DUMP:
             d_socloc_dump();
             break;

          case SCOM_SOCLOC_CONFIG_DUMP:
             d_socloc_config_dump();
             break;

          case SCOM_CLIENT_VERSION:
             d_client_version();
             break;

          case SCOM_SOCLOC_TRANS_NUM:
             d_socloc_trans_num();
             break;

          case SCOM_SOCLOC_CONNECT_NUM:
             d_socloc_connect_num();
             break;

          case SCOM_TRANS_NUM:
             d_trans_num();
             break;

          case SCOM_CONNECT_NUM:
             d_connect_num();
             break;

          case SCOM_SOCLOC_ON:
             d_socloc_on();
             break;

          case SCOM_SOCLOC_OFF:
             d_socloc_off();
             break;

          case SCOM_OFF:
             return(FALSE);
             break;

          default:
             d_out("%s:command not found", mname);
             free(keywrd);
             return(TRUE);
          };

       free(keywrd);
       logman("%s:exit 'TRUE'", mname);
       return(TRUE);
    }

    void d_term(char *comm)
    {
       /* Terminate a socket server. Syntax:

             term passwd

          Where 'passwd' is the termination password. */

       char mname[] = "d_term";
       char passwd[128], parm[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

       if (command_words(comm) < 2)
          {
          d_out("%s:no password,access denied", mname);
          return;
          }

       if (!command_word(comm, passwd, 2))
          {
          d_out("%s:error getting password", mname);
          return;
          }

       if (words(passwd) > 1)
          sprintf(parm, "'%s'", passwd);
       else
          strcpy(parm, passwd);

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_TERM, parm, passwd);
    #else
       ret = d_sr(SC_SEND_TERM, parm, passwd, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, passwd);

       logman("%s:normal exit", mname);
    }

    void d_socloc_term(char *comm)
    {
       /* Terminate a 'socloc' server. Syntax:

             socloc.term passwd

          Where 'passwd' is the termination password. */

       char mname[] = "d_socloc_term";
       char passwd[128], mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       if (command_words(comm) < 2)
          {
          d_out("%s:no password,access denied", mname);
          return;
          }

       if (!command_word(comm, passwd, 2))
          {
          d_out("%s:error getting password", mname);
          return;
          }

       ret = sloc_terminate(passwd);
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s]", mname,
                        ret, mes);
       else
          printf("%s\n", mes);

       logman("%s:normal exit", mname);
    #endif
    }

    void d_status(void)
    {
       /* Get server status. Syntax:

             status */

       char mname[] = "d_status";
       char reply[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_STATUS, (char *)NULL, reply);
    #else
       ret = d_sr(SC_SEND_STATUS, (char *)NULL, reply, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    }

    void d_client_log_on(char *comm)
    {
       /* Turn client logging on with optional log file name.
          Syntax:

             client.log.on[ log.fname]

          Where 'log.fname' is the optional log file name. If no
          log file name is given 'd_log_file' will be used.
          It is an error if client logging is already on.
          Function returns a 'sockc' code. */

       char mname[] = "d_client_log_on";

       d_header(mname);

       if (logman_is_active())
          {
          d_out("%s:log already on", mname);
          return;
          }

       if (command_words(comm) > 1)
          {
          if (!command_word(comm, d_log_file, 2))
             {
             d_out("%s:error getting log file name", mname);
             return;
             }
           }
        else
           strcpy(d_log_file, SOCKC_LOG_FILE);

       if (logman_start(d_log_file, APNAME))
          {
          d_out("%s:error writing log file", mname);
          return;
          }

       if (logman_is_active())
          logman("%s:normal exit[0]", mname);
       else
          printf("ok\n");
    }

    void d_client_log_off(void)
    {
       /* Turn client logging off. Syntax:

             client.log.off

          It is an error if client logging is already off. */

       char mname[] = "d_client_log_off";

       d_header(mname);

       if (!logman_is_active())
          {
          d_out("%s:log already off", mname);
          return;
          }

       if (logman_is_active())
          logman("%s:normal exit[0]", mname);
       else
          printf("ok\n");

       logman_end();
    }

    void d_client_log_status(void)
    {
       /* Display status of client logging. Syntax:

             client.log.status */

       char mname[] = "d_client_log_status";

       d_header(mname);

       if (logman_is_active())
          logman("%s:exit:client log is on,name=%s", mname, d_log_file);
       else
          printf("%s:client log is off,name=%s\n", mname, d_log_file);
    }

    void d_server_log_on(char *comm)
    {
       /* Tell server to turn its logging on. Syntax:

             server.log.on[ log_fname]

          If no 'log_fname' is given, the default sever log file
          name will be used. It is an error if server logging is
          already on. */

       char mname[] = "d_server_log_on";
       char tmp[256], slog[256];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

       if (command_words(comm) > 1)
          {
          if (!command_word(comm, tmp, 2))
             {
             d_out("%s:error getting server log file name", mname);
             return;
             }

          if (words(tmp) > 1)
             sprintf(slog, "'%s'", tmp);
          else
             strcpy(slog, tmp);

    #ifdef IPC_TCP
          ret = d_sr(SC_SEND_LOG_ON, slog, tmp);
    #else
          ret = d_sr(SC_SEND_LOG_ON, slog, tmp, 256);
    #endif
          }
       else
    #ifdef IPC_TCP
          ret = d_sr(SC_SEND_LOG_ON, (char *)NULL, tmp);
    #else
          ret = d_sr(SC_SEND_LOG_ON, (char *)NULL, tmp, 256);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, tmp);

       logman("%s:normal exit", mname);
    }

    void d_server_log_off(void)
    {
       /* Tell server to turn its logging off. Syntax:

             server.log.off

          It is an error if the server log is already off. */

       char mname[] = "d_server_log_off";
       char reply[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_LOG_OFF, (char *)NULL, reply);
    #else
       ret = d_sr(SC_SEND_LOG_OFF, (char *)NULL, reply, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    }

    void d_server_log_status(void)
    {
       /* Get status of server logging. Syntax:

             server.log.status */

       char mname[] = "d_server_log_status";
       char reply[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_LOG_STATUS, (char *)NULL, reply);
    #else
       ret = d_sr(SC_SEND_LOG_STATUS, (char *)NULL, reply, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    }

    void d_socloc_log_on(char *comm)
    {
       /* Tell 'socloc' server to turn its logging on. Syntax:

             socloc.log.on[ log_fname]

          If no 'log_fname' is given, the default sever log file
          name will be used. It is an error if server logging is
          already on. */

       char mname[] = "d_socloc_log_on";
       char tmp[128], slog[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       if (command_words(comm) > 1)
          {
          if (!command_word(comm, tmp, 2))
             {
             d_out("%s:error getting server log file name", mname);
             return;
             }

          if (words(tmp) > 1)
             sprintf(slog, "'%s'", tmp);
          else
             strcpy(slog, tmp);

          ret = sloc_log_on(slog);
          }
       else
          ret = sloc_log_on((char *)NULL);

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          {
          sl_code_string(ret, tmp);
          printf("%s\n", tmp);
          }
    #endif
    }

    void d_socloc_log_off(void)
    {
       /* Tell 'socloc' server to turn its logging off. Syntax:

             socloc.log.off

          It is an error if the server log is already off. */

       char mname[] = "d_socloc_log_off";
       char mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_log_off();

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          {
          sl_code_string(ret, mes);
          printf("%s\n", mes);
          }
    #endif
    }

    void d_socloc_log_status(void)
    {
       /* Get status of 'socloc' server logging. Syntax:

             socloc.log.status */

       char mname[] = "d_socloc_log_status";
       char mes[128];
       int ret, lflag;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_log_status(&lflag, mes);

       if (ret != SL_OK)
          {
          if (logman_is_active())
             logman("%s:normal exit,rc[%d]", mname, ret);
          else
             {
             sl_code_string(ret, mes);
             printf("%s\n", mes);
             }

          return;
          }

       if (lflag)
          d_out("%s:socloc server log is active,log is %s", mname, mes);
       else
          d_out("%s:socloc server log is inactive,log is %s", mname, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[0]", mname);
    #endif
    }

    void d_connect(char *comm)
    {
       /* Connect to any server. TCP syntax is:

             connect [service s_name][ host hname][ port pnum][ ip ip_ad]

          QNX message passing syntax is:

             connect s_name

          QNX message passing variant allow only the service name which
          is mandatory and must exacly match the 'nameloc' name. In TCP
          all parameters except 'connect' keyword are optional. At
          least one parameter must be given. If the 'socloc' interface
          is off, the only keywords that make sense are 'host' and
          'port' both of which must be present. */

       char mname[] = "d_connect";
       char mes[128], *service, *hname, *ip_ad;
       int pos, ret, port, nwords;

       d_header(mname);
       nwords = command_words(comm);

    #ifdef IPC_TCP
       if (nwords < 3)
    #else
       if (nwords < 2)
    #endif
          {
          d_out("%s:at least one parameter must be supplied", mname);
          return;
          }

       /* alloc details */

    #ifdef IPC_TCP
       if ((service = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[service]", mname);
          return;
          }

       if ((hname = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          free(service);
          return;
          }

       if ((ip_ad = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[ip_ad]", mname);
          free(service);
          free(hname);
          return;
          }
    #endif

       /* get the position of the second command word */

       pos = command_indxword(comm, 2);

       /* if the first char in the second word is a quote,
          'command_indxword' will skip over this, we need to
          backup one position */

       if (comm[pos - 1] == '\"' || comm[pos - 1] == '\'')
          pos--;

    #ifdef IPC_TCP
       if (sk_flag)
          {
          if ((ret = sconnect_parse(&comm[pos], TRUE, service, hname,
                                    &port, ip_ad)) != SP_OK)
             {
             sp_code_string(ret, mes);
             d_out("%s:bad rc[%d,%s] from 'sconnect_parse'", mname, ret, mes);
             free(service);
             free(hname);
             free(ip_ad);
             return;
             }

          /* locate the socket server based on supplied details */

          if ((ret = sloc_ll_find(service, hname, &port, ip_ad)) != SL_OK)
             {
             sl_code_string(ret, mes);
             d_out("%s:bad rc[%d,%s] from 'sloc_ll_find'", mname, ret, mes);
             free(service);
             free(hname);
             free(ip_ad);
             return;
             }

          logman("%s:match service=%s,host=%s,port=%d", mname, service,
                        hname, port);
          }
       else
          {
          /* if 'socloc' interface is off, make sure host name and
             port number have been given, service name is not allowed */

          if ((ret = sconnect_parse(&comm[pos], FALSE, (char *)NULL, hname,
                                    &port, ip_ad)) != SP_OK)
             {
             sp_code_string(ret, mes);
             d_out("%s:bad rc[%d,%s] from 'sconnect_parse'", mname, ret, mes);
             free(service);
             free(hname);
             free(ip_ad);
             return;
             }

          /* check host name and port */

          if (!strlen(hname))
             {
             d_out("%s:host name has not been given", mname);
             free(service);
             free(hname);
             free(ip_ad);
             return;
             }

          if (port == 0)
             {
             d_out("%s:port number has not been given", mname);
             free(service);
             free(hname);
             free(ip_ad);
             return;
             }
          }
    #else
       if (!command_word(comm, serverhost, 2))
          {
          d_out("%s:error getting 'nameloc' service name", mname);
          free(hname);
          return;
          }
    #endif

    #ifdef IPC_TCP
       strcpy(serverhost, hname);

       if (sk_flag)
          strcpy(serverservice, service);
       else
          serverservice[0] = EOS;

       serverport = port;
       free(service);
       free(hname);
       free(ip_ad);
       (void)ipc_set_active(serverhost, serverport);
    #else
       (void)ipc_set_active(serverhost);
    #endif

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          printf("ok\n");
    }

    void d_socloc_connect(char *comm)
    {
       /* Connect to any 'socloc' server. Syntax is:

             socloc.connect [host hname][ port pnum][ ip ip_ad]

          All parameters except 'connect' keyword are optional. At
          least one parameter must be given. */

       char mname[] = "d_socloc_connect";
       char mes[128], *hname, *ip_ad;
       int pos, ret, port, nwords;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);

       if (nwords < 3)
          {
          d_out("%s:at least one parameter must be supplied", mname);
          return;
          }

       /* alloc details */

       if ((hname = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          return;
          }

       if ((ip_ad = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[ip_ad]", mname);
          free(hname);
          return;
          }

       /* get the position of the second command word */

       pos = command_indxword(comm, 2);

       /* if the first char in the second word is a quote,
          'command_indxword' will skip over this, we need to
          backup one position */

       if (comm[pos - 1] == '\"' || comm[pos - 1] == '\'')
          pos--;

       /* parse the connect string */

       if ((ret = sconnect_parse(&comm[pos], FALSE, (char *)NULL, hname,
                                 &port, ip_ad)) != SP_OK)
          {
          sp_code_string(ret, mes);
          d_out("%s:bad rc[%d,%s] from 'sconnect_parse'", mname, ret, mes);
          free(hname);
          free(ip_ad);
          return;
          }

       /* locate the 'socloc' server based on supplied details */

       if ((ret = sloc_config_find(hname, &port, ip_ad)) != SL_OK)
          {
          sl_code_string(ret, mes);
          d_out("%s:bad rc[%d,%s] from 'sloc_config_find'", mname, ret, mes);
          free(hname);
          free(ip_ad);
          return;
          }

       /* try to set active */

       if ((ret = sloc_set_active_socloc(hname, port)) != SL_OK)
          {
          sl_code_string(ret, mes);
          d_out("%s:bad rc[%d,%s] from 'sloc_set_active_socloc'", mname,
                ret, mes);
          free(hname);
          free(ip_ad);
          return;
          }

       free(hname);
       free(ip_ad);

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          printf("ok\n");
    #endif
    }

    void d_socloc_list(void)
    {
       /* Get the list of available socket servers from 'socloc'.
          Syntax:

             socloc.list */

       char mname[] = "d_socloc_list";
       char *list_out;
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       if ((list_out = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[list_out]", mname);
          return;
          }

       ret = sloc_get_list(list_out);

       if (ret == SC_OK)
          {
          d_out("current socket servers");
          d_display_list(list_out);
          }

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          {
          sl_code_string(ret, list_out);
          printf("%s\n", list_out);
          }

       free(list_out);
    #endif
    }

    void d_socloc_config_list(void)
    {
       /* Get the list of available 'socloc' servers.
          Syntax:

             socloc.config.list */

       char mname[] = "d_socloc_config_list";
       char *list_out;
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       if ((list_out = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[list_out]", mname);
          return;
          }

       ret = sloc_config_get_list(list_out);

       if (ret == SC_OK)
          {
          d_out("current 'socloc' servers");
          d_display_config_list(list_out);
          }

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          {
          sl_code_string(ret, list_out);
          printf("%s\n", list_out);
          }

       free(list_out);
    #endif
    }

    void d_socloc_get(void)
    {
       /* Get and display the current 'socloc' server. Syntax:

             socloc.get */

       char mname[] = "d_socloc_get";
       char hname[256];
       int port;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       hname[0] = EOS;
       port = 0;
       sloc_get_active_socloc(hname, &port);

       if (strlen(hname))
          d_out("connected to 'socloc' server '%s' on port %d", hname, port);
       else
          d_out("no current 'socloc' server");

       logman("%s:normal exit", mname);
    #endif
    }

    void d_socloc_find(char *comm)
    {
       /* Find the details of one or more socket servers. Syntax is:

             socloc.find [service sname][ host hname][ port pnum][ ip ip_ad]

          All parameters except 'find' keyword are optional. At
          least one parameter must be given. */

       char mname[] = "d_socloc_find";
       char mes[128], *sname, *hname, *ip_ad, *thelist;
       int pos, ret, port, nwords;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);

       if (nwords < 3)
          {
          d_out("%s:at least one parameter must be supplied", mname);
          return;
          }

       /* alloc details */

       if ((sname = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[sname]", mname);
          return;
          }

       if ((hname = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          free(sname);
          return;
          }

       if ((ip_ad = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[ip_ad]", mname);
          free(sname);
          free(hname);
          return;
          }

       /* get the position of the second command word */

       pos = command_indxword(comm, 2);

       /* if the first char in the second word is a quote,
          'command_indxword' will skip over this, we need to
          backup one position */

       if (comm[pos - 1] == '\"' || comm[pos - 1] == '\'')
          pos--;

       /* parse the connect string */

       if ((ret = sconnect_parse(&comm[pos], TRUE, sname, hname,
                                 &port, ip_ad)) != SP_OK)
          {
          sp_code_string(ret, mes);
          d_out("%s:bad rc[%d,%s] from 'sconnect_parse'", mname, ret, mes);
          free(sname);
          free(hname);
          free(ip_ad);
          return;
          }

       /* alloc list */

       if ((thelist = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[thelist]", mname);
          free(sname);
          free(hname);
          free(ip_ad);
          return;
          }

       /* get a list of socket servers based on supplied details */

       if ((ret = sloc_ll_find_list(sname, hname, &port, ip_ad, thelist))
           != SL_OK)
          {
          sl_code_string(ret, mes);
          d_out("%s:bad rc[%d,%s] from 'sloc_ll_find_list'", mname, ret, mes);
          free(sname);
          free(hname);
          free(ip_ad);
          free(thelist);
          return;
          }

       free(sname);
       free(hname);
       free(ip_ad);

       /* display list */

       if (ret == SC_OK)
          {
          d_out("matched socket servers");
          d_display_list(thelist);
          }

       free(thelist);

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
       else
          printf("ok\n");
    #endif
    }

    void d_socloc_service_name(void)
    {
       /* Display the service name of the current 'socloc' server.
          Syntax:

             socloc.service.name */

       char mname[] = "d_socloc_service_name";
       char sname[128], mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_service_name(sname);
       sl_code_string(ret, mes);

       if (logman_is_active())
          if (ret != SC_OK)
             logman("%s:bad rc[%d,%s] from 'sloc_service_name",
                           mname, ret, mes);
          else
             logman("%s:service name is '%s'", mname, sname);
       else
          if (ret != SC_OK)
             printf("%s\n", mes);
          else
             printf("%s\nok\n", sname);

       logman("%s:normal exit", mname);
    #endif
    }

    void d_service_name(void)
    {
       /* Get service name from server. Syntax:

             service.name */

       char mname[] = "d_service_name";
       char reply[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_SERVICE_NAME, (char *)NULL, reply);
    #else
       ret = d_sr(SC_SEND_SERVICE_NAME, (char *)NULL, reply, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    }

    void d_socloc_version(void)
    {
       /* Display the version ID of the current 'socloc' server.
          Syntax:

             socloc.version */

       char mname[] = "d_socloc_version";
       char version[50], mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_version(version);
       sl_code_string(ret, mes);

       if (ret != SC_OK)
          if (logman_is_active())
             logman("%s:bad rc[%d,%s] from 'sloc_version'", mname,
                           ret, mes);
          else
             printf("%s\n", mes);
       else
          if (logman_is_active())
             logman("%s:send rc[ok]:'socloc' reply=%s", mname, version);
          else
             printf("%s\nok\n", version);

       logman("%s:normal exit", mname);
    #endif
    }

    void d_version(void)
    {
       /* Get the version from the server. Syntax:

             version */

       char mname[] = "d_version";
       char reply[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_VERSION, (char *)NULL, reply);
    #else
       ret = d_sr(SC_SEND_VERSION, (char *)NULL, reply, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    }

    void d_client_version(void)
    {
       /* Display the 'sockc' client version. */

       char mname[] = "d_client_version";

       d_header(mname);

       if (logman_is_active())
          logman("%s:'sockc' client version is '%s'", mname, VERSION);
       else
          printf("%s\n", VERSION);
    }

    void d_socloc_config_find(char *comm)
    {
       /* Find a 'socloc' server. Since all port names are unique and
          running more than one 'socloc' server per host is not allowed,
          this find will only ever match one entry. Syntax:

             socloc.config.find [host hname][ port port_num][ ip ip_ad] */

       char mname[] = "d_socloc_config_find";
       char *hname, *ip_ad, mes[128];
       int ret, nwords, pos, port;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);

       if (nwords < 3)
          {
          d_out("%s:at least one parameter must be supplied", mname);
          return;
          }

       /* alloc details */

       if ((hname = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          return;
          }

       if ((ip_ad = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[ip_ad]", mname);
          free(hname);
          return;
          }

       /* get the position of the second command word */

       pos = command_indxword(comm, 2);

       /* if the first char in the second word is a quote,
          'command_indxword' will skip over this, we need to
          backup one position */

       if (comm[pos - 1] == '\"' || comm[pos - 1] == '\'')
          pos--;

       /* parse the connect string */

       if ((ret = sconnect_parse(&comm[pos], FALSE, (char *)NULL, hname,
                                 &port, ip_ad)) != SP_OK)
          {
          sp_code_string(ret, mes);
          d_out("%s:bad rc[%d,%s] from 'sconnect_parse'", mname, ret, mes);
          free(hname);
          free(ip_ad);
          return;
          }

       if ((ret = sloc_config_find(hname, &port, ip_ad)) == SL_OK)
          {
          if (strlen(ip_ad))
             d_out("socloc:host=%s,port=%d,ip=%s", hname, port, ip_ad);
          else
             d_out("socloc:host=%s,port=%d", hname, port);

          if (!logman_is_active())
             printf("ok\n");
          }
       else
          {
          sl_code_string(ret, mes);

          if (logman_is_active())
             logman("%s:bad rc[%s] from 'sloc_config_find'", mname, mes);
          else
             printf("%s\n", mes);
          }

       free(hname);
       free(ip_ad);

       if (logman_is_active())
          logman("%s:normal exit rc[%d]", mname, ret);
    #endif
    }

    void d_socloc_status(void)
    {
       /* Get the status of the currently connected 'socloc' server.
          Syntax:

             socloc.status */

       char mname[] = "d_socloc_status";
       char mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_status();
       sl_code_string(ret, mes);

       if (logman_is_active())
          d_out("%s:normal exit,rc[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_client_update(void)
    {
       /* Get the current 'socloc' server list and update the client
          config link list with it. */

       char mname[] = "d_socloc_client_update";
       char *thelist, mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       if ((thelist = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[thelist]", mname);
          return;
          }

       /* get the config list from the first active server */

       if ((ret = sloc_config_get_list(thelist)) != SL_OK)
          {
          d_out("%s:bad rc[%d] from 'sloc_config_get_list'",
                        mname, ret);
          free(thelist);
          return;
          }

       /* create a new list in memory */

       if ((ret = sl_config_put_list(thelist)) != SL_OK)
          {
          d_out("%s:bad rc[%d] from 'sl_config_put_list'",
                        mname, ret);
          free(thelist);
          return;
          }

       free(thelist);
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_client_update_file(void)
    {
       /* Get the current 'socloc' server list and update the client
          config link list with it and write these changes to the
          config file. */

       char mname[] = "d_socloc_client_update_file";
       char mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_config_update();
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_send(char *comm)
    {
       /* Send a message to the currently conncted socket server. Syntax:

             send typ [parm]

          Where 'typ' is the numeric command type or code and 'parm' is
          the contents of the message (which may be blank). */

       char mname[] = "d_send";
       char typ_char[128], *reply;
       int ret, pos, typ, nwords;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

       nwords = command_words(comm);

       if (nwords < 2)
          {
          d_out("%s:no command type/code", mname);
          return;
          }

       if (!command_word(comm, typ_char, 2))
          {
          d_out("%s:error getting send type code", mname);
          return;
          }

       /* type code must be numeric */

       if (!qatoi(typ_char, &typ))
          {
          d_out("%s:type code must be numeric", mname);
          return;
          }

       /* type code must be a positive integer */

       if (typ <= 0)
          {
          d_out("%s:type code out of range", mname);
          return;
          }

       /* get the position of the third command word */

       if (nwords > 2)
          {
          pos = command_indxword(comm, 3);

          /* if the first char in the third word is a quote,
             'command_indxword' will skip over this, we need to
             backup one position */

          if (comm[pos - 1] == '\"' || comm[pos - 1] == '\'')
             pos--;
          }

       if ((reply = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          d_out("%s:alloc fail[reply]", mname);
          return;
          }

       if (nwords > 2)
    #ifdef IPC_TCP
          ret = d_sr(typ, &comm[pos], reply);
    #else
          ret = d_sr(typ, &comm[pos], reply, SC_MAXCOMMAND);
    #endif
       else
    #ifdef IPC_TCP
          ret = d_sr(typ, (char *)NULL, reply);
    #else
          ret = d_sr(typ, (char *)NULL, reply, SC_MAXCOMMAND);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       free(reply);
       logman("%s:normal exit", mname);
    }

    void d_socloc_add(char *comm)
    {
       /* Add a socket server entry to 'socloc'. Syntax:

             socloc.add service host port[ ip]

          All parameters must be present except for the optional IP
          address. Any parameter containing spaces must be quoted. */

       char mname[] = "d_socloc_add";
       char *sname, *hname, *port_char, *ip_ad;
       char mes[128];
       int ret, nwords, len, port;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);
       len = strlen(comm);

       if (nwords < 4)
          {
          d_out("%s:parameters absent", mname);
          return;
          }

       /* alloc details */

       if ((sname = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[sname]", mname);
          return;
          }

       if ((hname = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          free(sname);
          return;
          }

       if ((port_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[port_char]", mname);
          free(sname);
          free(hname);
          return;
          }

       if (nwords > 4)
          {
          if ((ip_ad = (char *)malloc(len + 1)) == (char *)NULL)
             {
             d_out("%s:alloc fail[ip_ad]", mname);
             free(sname);
             free(hname);
             free(port_char);
             return;
             }
          }
       else
          ip_ad = (char *)NULL;

       /* get details */

       if (!command_word(comm, sname, 2))
          {
          d_out("%s:error getting service name", mname);
          free(sname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       if (!command_word(comm, hname, 3))
          {
          d_out("%s:error getting host", mname);
          free(sname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       if (!command_word(comm, port_char, 4))
          {
          d_out("%s:error getting port", mname);
          free(sname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       if (!qatoi(port_char, &port))
          {
          d_out("%s:port not numeric", mname);
          free(sname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       free(port_char);

       if (nwords > 4)
          if (!command_word(comm, ip_ad, 5))
             {
             d_out("%s:error getting IP address", mname);
             free(sname);
             free(hname);
             free(ip_ad);
             return;
             }

       ret = sloc_add(sname, hname, port, ip_ad);
       free(sname);
       free(hname);

       if (ip_ad != (char *)NULL)
          free(ip_ad);

       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_config_add(char *comm)
    {
       /* Add a 'socloc' entry to 'socloc'. Syntax:

             socloc.config.add host port[ ip]

          All parameters must be present except for the optional IP
          address. Any parameter containing spaces must be quoted. */

       char mname[] = "d_socloc_add";
       char *hname, *port_char, *ip_ad;
       char mes[128];
       int ret, nwords, len, port;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);
       len = strlen(comm);

       if (nwords < 3)
          {
          d_out("%s:parameters absent", mname);
          return;
          }

       /* alloc details */

       if ((hname = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          return;
          }

       if ((port_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[port_char]", mname);
          free(hname);
          return;
          }

       if (nwords > 3)
          {
          if ((ip_ad = (char *)malloc(len + 1)) == (char *)NULL)
             {
             d_out("%s:alloc fail[ip_ad]", mname);
             free(hname);
             free(port_char);
             return;
             }
          }
       else
          ip_ad = (char *)NULL;

       /* get details */

       if (!command_word(comm, hname, 2))
          {
          d_out("%s:error getting host", mname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       if (!command_word(comm, port_char, 3))
          {
          d_out("%s:error getting port", mname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       if (!qatoi(port_char, &port))
          {
          d_out("%s:port not numeric", mname);
          free(hname);
          free(port_char);

          if (ip_ad != (char *)NULL)
             free(ip_ad);

          return;
          }

       free(port_char);

       if (nwords > 3)
          if (!command_word(comm, ip_ad, 4))
             {
             d_out("%s:error getting IP address", mname);
             free(hname);
             free(ip_ad);
             return;
             }

       ret = sloc_config_add(hname, port, ip_ad);
       free(hname);

       if (ip_ad != (char *)NULL)
          free(ip_ad);

       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_delete(char *comm)
    {
       /* Delete a socket server entry to 'socloc'. Syntax:

             socloc.delete port */

       char mname[] = "d_socloc_delete";
       char *port_char;
       char mes[128];
       int ret, nwords, len, port;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);
       len = strlen(comm);

       if (nwords < 2)
          {
          d_out("%s:parameters absent", mname);
          return;
          }

       /* alloc details */

       if ((port_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[port_char]", mname);
          return;
          }

       /* get port */

       if (!command_word(comm, port_char, 2))
          {
          d_out("%s:error getting port", mname);
          free(port_char);
          return;
          }

       if (!qatoi(port_char, &port))
          {
          d_out("%s:port not numeric", mname);
          free(port_char);
          return;
          }

       free(port_char);
       ret = sloc_delete(port);
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_config_delete(char *comm)
    {
       /* Delete a 'socloc' entry. Syntax:

             socloc.config.delete port */

       char mname[] = "d_socloc_config_delete";
       char *port_char;
       char mes[128];
       int ret, nwords, len, port;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       nwords = command_words(comm);
       len = strlen(comm);

       if (nwords < 2)
          {
          d_out("%s:parameters absent", mname);
          return;
          }

       /* alloc details */

       if ((port_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[port_char]", mname);
          return;
          }

       /* get port */

       if (!command_word(comm, port_char, 2))
          {
          d_out("%s:error getting port", mname);
          free(port_char);
          return;
          }

       if (!qatoi(port_char, &port))
          {
          d_out("%s:port not numeric", mname);
          free(port_char);
          return;
          }

       free(port_char);
       ret = sloc_config_delete(port);
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s]", mname, ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_on(void)
    {
       /* Turn 'socloc' interface on. Check for the interface already
          on. */

       char mname[] = "d_socloc_on";

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       if (sk_flag)
          {
          d_out("%s:socloc interface is already on", mname);
          return;
          }

       if (!d_socloc_activate())
          {
          d_out("%s:socloc initialization failure", mname);
          return;
          }

       if (logman_is_active())
          logman("%s:normal exit", mname);
       else
          printf("ok\n");
    #endif
    }

    void d_socloc_off(void)
    {
       /* Turn 'socloc' interface off. Check for the interface already
          off. */

       char mname[] = "d_socloc_off";

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       if (!sk_flag)
          {
          d_out("%s:socloc interface is already off", mname);
          return;
          }

       sloc_term_api();
       sk_flag = FALSE;

       if (logman_is_active())
          logman("%s:normal exit", mname);
       else
          printf("ok\n");
    #endif
    }

    void d_socloc_dump(void)
    {
       /* Tell the 'socloc' server to dump the socket server list.
          Syntax:

             socloc.dump */

       char mname[] = "d_socloc_dump";
       char mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_dump_debug();
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:normal exit,rc[%d,%s", mname,
                        ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_config_dump(void)
    {
       /* Tell the 'socloc' server to dump the 'socloc' server list.
          Syntax:

             socloc.config.dump */

       char mname[] = "d_socloc_config_dump";
       char mes[128];
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_config_dump_debug();
       sl_code_string(ret, mes);

       if (logman_is_active())
          logman("%s:bad rc[%d,%s] from 'sloc_config_dump_debug", mname,
                        ret, mes);
       else
          printf("%s\n", mes);
    #endif
    }

    void d_socloc_trans_num(void)
    {
       /* Get the current transaction count from the 'socloc' server. Syntax:

             socloc.trans.num */

       char mname[] = "d_socloc_trans_num", mes[128];
       long trans_num;
       int ret;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_trans_num(&trans_num);

       if (ret != SL_OK)
          {
          if (logman_is_active())
             logman("%s:normal exit,rc[%d]", mname, ret);
          else
             {
             sl_code_string(ret, mes);
             printf("%s\n", mes);
             }

          return;
          }

       d_out("%s:current socloc transaction count is %ld", mname, trans_num);

       if (logman_is_active())
          logman("%s:normal exit,rc[0]", mname);
    #endif
    }

    void d_socloc_connect_num(void)
    {
       /* Get the current connection count from the 'socloc' server. Syntax:

             socloc.connect.num */

       char mname[] = "d_socloc_connect_num", mes[128];
       int ret, connect_num;

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       d_header(mname);

       if (!sk_flag)
          {
          d_out("%s:socloc interface not active", mname);
          return;
          }

       ret = sloc_connect_num(&connect_num);

       if (ret != SL_OK)
          {
          if (logman_is_active())
             logman("%s:normal exit,rc[%d]", mname, ret);
          else
             {
             sl_code_string(ret, mes);
             printf("%s\n", mes);
             }

          return;
          }

       d_out("%s:current socloc connection count is %d", mname, connect_num);

       if (logman_is_active())
          logman("%s:normal exit,rc[0]", mname);
    #endif
    }

    void d_trans_num(void)
    {
       /* Get the current transaction count from the current socket server. Syntax:

             trans.num */

       char mname[] = "d_trans_num", reply[128];
       int ret;

       d_header(mname);

       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

    #ifdef IPC_TCP
       ret = d_sr(SC_SEND_TRANS_NUM, (char *)NULL, reply);
    #else
       ret = d_sr(SC_SEND_TRANS_NUM, (char *)NULL, reply, 128);
    #endif

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    }

    void d_connect_num(void)
    {
       /* Get the current connection count from the current socket server. Syntax:

             connect.num */

       char mname[] = "d_connect_num", reply[128];
       int ret;

       d_header(mname);

    #ifdef IPC_QNX
       d_out("%s:applies to TCP IPC method only", mname);
       return;
    #else
       if (!is_connected())
          {
          d_out("%s:no active connection", mname);
          return;
          }

       ret = d_sr(SC_SEND_CONNECT_NUM, (char *)NULL, reply);

       if (ret != SC_OK)
          d_out("%s:send fail,rc[%d]", mname, ret);
       else
          d_out("%s:send rc[ok]:server reply=%s", mname, reply);

       logman("%s:normal exit", mname);
    #endif
    }

    #ifdef IPC_TCP
    void d_display_list(char *thelist)
    {
       /* Display a list of server entries. Only used for socket servers,
          not 'socloc' servers. Each entry in the list
          is delimited by 'SL_LIST_DELIM'. */

       char mname[] = "d_display_list";
       char *entry, *service, *hname, *port_char, *ip_ad;
       int i, len, nentries;

       d_header(mname);

       if (thelist == (char *)NULL)
          {
          d_out("%s:list is null", mname);
          return;
          }

       len = strlen(thelist);
       nentries = ll_words(thelist, SL_LIST_DELIM);

       if ((entry = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[entry]", mname);
          return;
          }

       if ((service = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[service]", mname);
          free(entry);
          return;
          }

       if ((hname = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          free(entry);
          free(service);
          return;
          }

       if ((port_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[port_char]", mname);
          free(entry);
          free(service);
          free(hname);
          return;
          }

       if ((ip_ad = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[ip_ad]", mname);
          free(entry);
          free(service);
          free(hname);
          free(port_char);
          return;
          }

       for(i = 1; i <= nentries; i++)
          {
          if (!ll_word(thelist, entry, i, SL_LIST_DELIM))
             {
             d_out("%s:error geting list entry[%d]", mname, i);
             free(entry);
             free(service);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (!command_word(entry, service, 1))
             {
             d_out("%s:error getting service from entry[%d]", mname, i);
             free(entry);
             free(service);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (!command_word(entry, hname, 2))
             {
             d_out("%s:error getting host from entry[%d]", mname, i);
             free(entry);
             free(service);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (!command_word(entry, port_char, 3))
             {
             d_out("%s:error getting port from entry[%d]", mname, i);
             free(entry);
             free(service);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (command_words(entry) > 3)
             {
             if (!command_word(entry, ip_ad, 4))
                {
                d_out("%s:error getting ip from entry[%d]", mname, i);
                free(entry);
                free(service);
                free(hname);
                free(port_char);
                free(ip_ad);
                return;
                }
             }
          else
             ip_ad[0] = EOS;

          if (strlen(ip_ad))
             d_out("server[%d]:service=%s,host=%s,port=%s,ip=%s", i, service,
                   hname, port_char, ip_ad);
          else
             d_out("server[%d]:service=%s,host=%s,port=%s", i, service,
                   hname, port_char);
          }

       free(entry);
       free(service);
       free(hname);
       free(port_char);
       free(ip_ad);
       logman("%s:normal exit", mname);
    }

    void d_display_config_list(char *thelist)
    {
       /* Display a list of 'socloc' server entries. Only used for
          'socloc' servers, not socket servers. Each entry in the list
          is delimited by 'SL_LIST_DELIM'. */

       char mname[] = "d_display_config_list";
       char *entry, *hname, *port_char, *ip_ad;
       int i, len, nentries;

       d_header(mname);

       if (thelist == (char *)NULL)
          {
          d_out("%s:list is null", mname);
          return;
          }

       len = strlen(thelist);
       nentries = ll_words(thelist, SL_LIST_DELIM);

       if ((entry = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[entry]", mname);
          return;
          }

       if ((hname = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[hname]", mname);
          free(entry);
          return;
          }

       if ((port_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[port_char]", mname);
          free(entry);
          free(hname);
          return;
          }

       if ((ip_ad = (char *)malloc(len + 1)) == (char *)NULL)
          {
          d_out("%s:alloc fail[ip_ad]", mname);
          free(entry);
          free(hname);
          free(port_char);
          return;
          }

       for(i = 1; i <= nentries; i++)
          {
          if (!ll_word(thelist, entry, i, SL_LIST_DELIM))
             {
             d_out("%s:error geting list entry[%d]", mname, i);
             free(entry);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (!command_word(entry, hname, 1))
             {
             d_out("%s:error getting host from entry[%d]", mname, i);
             free(entry);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (!command_word(entry, port_char, 2))
             {
             d_out("%s:error getting port from entry[%d]", mname, i);
             free(entry);
             free(hname);
             free(port_char);
             free(ip_ad);
             return;
             }

          if (command_words(entry) > 2)
             {
             if (!command_word(entry, ip_ad, 3))
                {
                d_out("%s:error getting ip from entry[%d]", mname, i);
                free(entry);
                free(hname);
                free(port_char);
                free(ip_ad);
                return;
                }
             }
          else
             ip_ad[0] = EOS;

          if (strlen(ip_ad))
             d_out("socloc[%d]:host=%s,port=%s,ip=%s", i, hname,
                   port_char, ip_ad);
          else
             d_out("socloc[%d]:host=%s,port=%s", i, hname, port_char);
          }

       free(entry);
       free(hname);
       free(port_char);
       free(ip_ad);
       logman("%s:normal exit", mname);
    }
    #endif

    #ifdef IPC_TCP
    int d_sr(int typ, char *parm, char *reply)
    #else
    int d_sr(int typ, char *parm, char *reply, int size_reply)
    #endif
    {
       /* Send and receive a message to the server. Its ok if 'parm'
          is NULL or empty. Upon success, server reply load loaded
          into 'reply' which must be already allocated to
          sufficient size. Function returns a 'sockc' code. */

       char mname[] = "d_sr";
       char *mess;

       logman("%s:enter", mname);

       /* make sure we are connected */

       if (!is_connected())
          {
          logman("%s:not connected to any server", mname);
          return(SC_NO_SERVER);
          }

       if ((mess = (char *)malloc(SC_MAXCOMMAND)) == (char *)NULL)
          {
          logman("%s:alloc fail[mess]", mname);
          return(SC_MEMORY_FAIL);
          }

       memset(mess, 0, SC_MAXCOMMAND);

       // format send string

       if (parm == (char *)NULL || !strlen(parm))
          sprintf(mess, "%d", typ);
       else
          sprintf(mess, "%d %s", typ, parm);

       logman("%s:send buf=%s,l=%d", mname, mess, strlen(mess));

    #ifdef IPC_TCP
       if (!ipc_send_receive(mess, reply))
    #else
       if (!ipc_send_receive(mess, reply, size_reply))
    #endif
          {
          logman("%s:error communicating with server", mname);
          free(mess);
    #ifdef IPC_TCP
          serverport = 0;
          serverservice[0] = EOS;
    #endif
          serverhost[0] = EOS;
          return(SC_VC_ERROR);
          }

       free(mess);
       logman("%s:normal exit,rc[ok],reply=%s,l=%d", mname,
                     reply, strlen(reply));
       return(SC_OK);
    }

    int get_token(char *keywrd)
    {
       /* Get keyword token. */

       char mname[] = "get_token";
       int i;
       int token = SCOM_NOT_FOUND;

       /* static array of command words, notice the dummy zero position */

       static char *coms[] = { " ", "TERM", "STATUS", "CLIENT.LOG.OFF",
                               "CLIENT.LOG.ON", "CLIENT.LOG.STATUS",
                               "SERVER.LOG.OFF", "SERVER.LOG.ON",
                               "SERVER.LOG.STATUS", "CONNECT",
                               "SOCLOC.LIST", "SOCLOC.CONFIG.LIST",
                               "SOCLOC.GET", "SOCLOC.LOG.ON",
                               "SOCLOC.LOG.OFF", "SOCLOC.LOG.STATUS",
                               "SOCLOC.CONNECT", "SOCLOC.FIND",
                               "SOCLOC.SERVICE.NAME", "SERVICE.NAME",
                               "SOCLOC.VERSION", "VERSION",
                               "SOCLOC.CONFIG.FIND", "SOCLOC.STATUS",
                               "SOCLOC.CLIENT.LIST", "SOCLOC.CLIENT.UPDATE",
                               "SOCLOC.CLIENT.UPDATE.FILE", "SEND",
                               "SOCLOC.ADD", "SOCLOC.CONFIG.ADD",
                               "SOCLOC.DELETE", "SOCLOC.CONFIG.DELETE",
                               "SOCLOC.DUMP", "SOCLOC.CONFIG.DUMP",
                               "SOCLOC.TERM", "CLIENT.VERSION",
                               "SOCLOC.ON", "SOCLOC.OFF", "SOCLOC.TRANS.NUM",
                               "SOCLOC.CONNECT.NUM", "TRANS.NUM", "CONNECT.NUM" };

       logman("%s:enter,keywrd='%s'", mname, keywrd);

       /* check for 'OFF' keyword separately */

       if (!stricmp(keywrd, "OFF"))
          {
          logman("%s:found 'OFF' keyword", mname);
          return(SCOM_OFF);
          }

       for(i = 1; i <= SCOM_MAXCOM; i++)
          if (!stricmp(keywrd, coms[i]))
             {
             token = i;
             break;
             }

       logman("%s:normal exit,token=%d", mname, token);
       return(token);
    }

    void d_display_connect_status(void)
    {
       /* Display to the screen the status of the connected 'socloc'
          server and socket server keeping in mind the 'socloc'
          on/off flag. */

    #ifdef IPC_TCP
       if (sk_flag)
          {
          sloc_get_active_socloc(sk_host, &sk_port);

          if (sk_port == 0)
             printf("%s:warning, no active socloc, use 'socloc.connect'\n",
                    APNAME);

          if (is_connected())
             printf("%s:%s,%d/%s,%s,%d\n", APNAME, sk_host, sk_port, serverservice,
                    serverhost, serverport);
          else
             printf("%s:%s,%d/?\n", APNAME, sk_host, sk_port);
          }
       else
          {
          if (is_connected())
             printf("%s:x/%s,%d\n", APNAME, serverhost, serverport);
          else
             printf("%s:x/?\n", APNAME);
          }
    #else
       if (is_connected())
          printf("%s:%s\n", APNAME, serverhost);
       else
          printf("%s:x\n", APNAME);
    #endif
    }

    void d_header(char *mname)
    {
       /* Output the function enter header if logging. */

       if (is_connected())
    #ifdef IPC_TCP
          logman("%s:enter,host=%s,port=%d", mname, serverhost,
                        serverport);
    #else
          logman("%s:enter:service=%s", mname, serverhost);
    #endif
       else
          logman("%s:enter,no connection", mname);
    }

    void d_out(char *fmt,...)
    {
       /* Output a message to the screen or use 'logman' to
          log the message. Output method depends on personal (client)
          logging status. Do not put a cr/lf at the end of the message.
          This will be automatically written to the end of the message. */

       char mes[MAXMES];
       va_list argptr;

       va_start(argptr, fmt);
       vsprintf(mes, fmt, argptr);

       if (logman_is_active())
          logman_nf(mes);
       else
          printf("%s\n", mes);
    }

    int is_connected(void)
    {
       /* Indicate whether there is an active connection.
          Function returns 'TRUE' if there is a connection,
          'FALSE' otherwise. */

    #ifdef IPC_TCP
       if (strlen(serverhost) && serverport != 0)
    #else
       if (strlen(serverhost))
    #endif
          return(TRUE);

       return(FALSE);
    }

    void term_app(void)
    {
       // Close sockets in use (TCP) and shutdown all API's.

    #ifdef IPC_TCP
       if (sk_flag)
          sloc_term_api();

       if (is_connected())
          (void)ipc_close();

    #ifdef OS_WIN32
       WSACleanup();
    #endif
    #endif

       if (logman_is_active())
          logman_end();
    }

/* [<][>][^][v][top][bottom][index][help] */