## root/source/db.c

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

## DEFINITIONS

This source file includes following definitions.

1. main
2. c_initialize
3. c_initialize
4. c_ipc_socloc_init
5. do_comm
6. c_open
7. c_close
8. c_next
9. c_top
10. c_get_rec
11. c_get_field
12. c_get_subfield
13. c_get_subsubfield
14. c_goto
15. c_count
16. c_put_field
17. c_put_subfield
18. c_put_subsubfield
19. c_write
20. c_delete
21. c_get_delete_flag
22. c_set_delete_flag
23. c_get_nfields
24. c_get_nsubfields
25. c_get_nsubsubfields
26. c_get_rec_size
27. c_get_field_size
28. c_get_subfield_size
29. c_get_subsubfield_size
30. c_get_rec_num
31. c_get_pos
32. c_set_pos
33. c_get_change_rec_flag
34. c_set_change_rec_flag
35. c_pack
36. c_new
37. c_find
38. c_find_field
39. c_find_part
40. c_find_field_part
41. c_get_rec_count
42. c_get_enf_change_rec_flag
43. c_set_enf_change_rec_flag
44. c_get_is_table_locked
45. c_set_is_table_locked
46. c_new_table
47. c_config_get_tmp_path
48. c_config_get_log
49. c_config_get_session
50. c_config_get_catalog
51. c_config_get_log_flag
52. c_config_get_session_flag
53. c_config_get_catalog_flag
54. c_config_get_replicate_flag
55. c_config_get_version
56. c_version
57. c_config_set_tmp_path
58. c_config_set_log
59. c_config_set_session
60. c_config_set_catalog
61. c_config_set_log_flag
62. c_config_set_session_flag
63. c_config_set_catalog_flag
64. c_config_set_replicate_flag
65. c_get_open_table_list
66. c_replicate_update
67. c_delete_table
68. c_exist
69. c_clear_table
70. c_copy_table
71. c_get_catalog_list
72. c_sort
73. c_get_sort_mem
74. c_set_sort_mem
75. c_get_sort_open_bin
76. c_set_sort_open_bin
77. c_delete_field
78. c_delete_subfield
79. c_delete_subsubfield
80. c_trans_num
81. c_connect_num
82. c_get_autopack
83. c_set_autopack
84. c_config_client_get_log
85. c_config_client_get_log_flag
86. c_config_client_set_log
87. c_config_client_set_log_flag
88. get_token
89. term_app

    /* DB - A command line for the database server/engine 'Bbuuzzb',
       Rick Smereka, Copyright (C) 1995-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 DOS version Dec/95, Rick Smereka

       Re-compiled for enhanced buffer I/O. Dec/96, Rick Smereka

       Re-compiled with new version of 'DBENG.C'. Jan/97, Rick Smereka

       Complete re-write for new high level API (dblocal).
       Jan/97, Rick Smereka

       Port to QNX V4.23a. Jan/97, Rick Smereka

       Add flexible compile for either single or multiuser.
       Feb/97, Rick Smereka

       Complete re-write for new API. Oct/97, Rick Smereka

       Port to 32bit Windows under CodeWarrior V4.
       Port to HP-UX under GNU C 2.8.1.
       Jan/99, Rick Smereka

       Modified 'c_open' to provide for situation where file
       data format is incorrect. Implemented a multi-
       platform logo. Added support for the 'new_table'
       command. Added function 'eng_initialize' to start the
       local database engine and report on the configuration
       settings. Feb/99, Rick Smereka

       Added 12 new commands to get and set configuration options.
       Apr/99, Rick Smereka

       Port to Red Hat Linux 5.2, Jul/99, Rick Smereka

       Re-compiled after re-structuring the definition of the common
       send and repy codes. Moved 'include' of the header 'flsocket.h'
       inside the 'MULTIUSER' if statement. Modified to use the
       'socloc' API if in multiuser mode. Changed keyword connecting
       character from '_' to '.'. Added command 'version'. Added
       display of currently connected 'Bbuuzzb' server in multiuser
       mode. Apr/2000, Rick Smereka

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

       Corrected some return codes and modified stated command syntax
       from old underscore word connector to new period word
       connector. Corrected bug in 'c_count' which ignored the table
       'process_deleted' flag when the 'all' option was not used.
       May/2001, Rick Smereka

       Added command 'get.open.table.list' and
       re-compiled for new database engine version. Jun/2001,
       Rick Smereka

       Modified for use with both sockets and QNX message passing IPC.
       Oct/2001, Rick Smereka

       Added support for the new commands 'DBCOM_GET_NSUBFIELDS',
       'DBCOM_GET_SUBFIELD_SIZE', 'DBCOM_GET_SUBFIELD', 'DBCOM_PUT_SUBFIELD',
       'DBCOM_GET_NSUBSUBFIELDS', 'DBCOM_GET_SUBSUBFIELD_SIZE',
       'DBCOM_GET_SUBSUBFIELD' and 'DBCOM_PUT_SUBSUBFIELD'. Re-wrote debug
       interface for system logging. Dec/2001, Rick Smereka

       Added support for the new commands 'DBCOM_CONFIG_GET_REPLICATE_FLAG'
       and 'DBCOM_CONFIG_SET_REPLICATE_FLAG'. Jan/2002, Rick Smereka

       Added support for the command 'DBCOM_REPLICATE_UPDATE'.
       Mar/2002, Rick Smereka

       Excluded include of 'flsocket.h' in the case of DOS.
       Apr/2002, Rick Smereka

       Added support for automatic field, subfield and subsubfield
       append using the value zero. Commands 'db.put.field',
       'db.put.subfield' and 'db.put.subsubfield' now allow a zero
       value (in the field, subfield and subsubfield number parameter)
       to signify an append. Added command 'DBCOM_EXIST'.
       May/2002, Rick Smereka

       Added command 'DBCOM_CLEAR_TABLE'. Changed call to 'sys_log_init'
       to include the application name. Jun/2002, Rick Smereka

       Added parameter to the 'DBCOM_GET_OPEN_TABLE_LIST' command.
       Added command 'DBCOM_GET_CATALOG_LIST'. Aug/2002,
       Rick Smereka

       Ported to Debian Linux. Jan/2003, Rick Smereka

       Modified for the updated 'socloc' API ('sloc.c').
       May/2003, Rick Smereka

       Modified for the updated 'sys_log' API ('sys_log.c').
       Added commands 'DBCOM_TRANS_NUM' and 'DBCOM_CONNECT_NUM'.
       Modified for the updated 'bbuuzzb' API.
       Jun/2003, Rick Smereka

       Enabled catalog functions in both single user and
       multiuser (client/server) modes. Dec/2003,
       Rick Smereka

       Added support for the commands 'DBCOM_GET_AUTOPACK' and
       'DBCOM_SET_AUTOPACK'. Mar/2004, Rick Smereka

       Added support for the commands 'DBCOM_CONFIG_CLIENT_GET_LOG',
       'DBCOM_CONFIG_CLIENT_GET_LOG_FLAG',
       'DBCOM_CONFIG_CLIENT_SET_LOG' and 'DBCOM_CONFIG_CLIENT_SET_LOG_FLAG'.
       Added include of 'appinit.h' and call to 'appinit_register_name'
       from the 'main' function. Removed the 'DEBUG' define.
       Added define 'APNAME'. Recoded function 'term_app'.
       Apr/2004, Rick Smereka

       Re-compile after changing the 'socloc' API. Added display messages
       to the the functions 'c_config_client_get_log',
       'c_config_client_get_log_flag', 'c_config_client_set_log' and
       'c_config_client_set_log_flag' to instruct user to the the 'non-client'
       commands instead. Jan/2005, Rick Smereka

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

       Changed 'c_new_table' to only display the table tid if a table
       open was requested. Mar/2006, Rick Smereka */

    #include "stdhead.h"
    #ifndef OS_DOS
    #include "flsocket.h"
    #include "appinit.h"
    #endif
    #include "dbmess.h"
    #include "dbiocode.h"
    #include "dbcomm.h"
    #ifdef IPC_TCP
    #include "socloc.h"
    #include "sloc.h"
    #include "slconfig.h"
    #include "sliocode.h"
    #ifdef OS_WIN32
    WSADATA wsaData;
    #endif
    #endif

    /* high level database API changes depending
       on whether we are compiling for single user
       or multiuser */

    #ifdef MULTIUSER
    #include "dbcs.h"
    #include "dbcscfg.h"
    #else
    #include "dbeng.h"
    #include "dblocal.h"
    #include "dbengcfg.h"
    #include "dblocfg.h"
    #endif

    #define VERSION "1.43.02-2006.03.28"

    #ifdef MULTIUSER
    #define APNAME "dbm"
    #else
    #define APNAME "db"
    #endif

    int main(void);
    int c_initialize(void);
    int do_comm(char *);
    int c_open(char *);
    int c_close(char *);
    int c_next(char *);
    int c_top(char *);
    int c_get_rec(char *);
    int c_get_field(char *);
    int c_get_subfield(char *);
    int c_get_subsubfield(char *);
    int c_goto(char *);
    int c_count(char *);
    int c_put_field(char *);
    int c_put_subfield(char *);
    int c_put_subsubfield(char *);
    int c_write(char *);
    int c_delete(char *);
    int c_get_delete_flag(char *);
    int c_set_delete_flag(char *);
    int c_get_nfields(char *);
    int c_get_nsubfields(char *);
    int c_get_nsubsubfields(char *);
    int c_get_rec_size(char *);
    int c_get_field_size(char *);
    int c_get_subfield_size(char *);
    int c_get_subsubfield_size(char *);
    int c_get_rec_num(char *);
    int c_get_pos(char *);
    int c_set_pos(char *);
    int c_get_change_rec_flag(char *);
    int c_set_change_rec_flag(char *);
    int c_pack(char *);
    int c_new(char *);
    int c_find(char *);
    int c_find_field(char *);
    int c_find_part(char *);
    int c_find_field_part(char *);
    int c_get_rec_count(char *);
    int c_get_enf_change_rec_flag(char *);
    int c_set_enf_change_rec_flag(char *);
    int c_get_is_table_locked(char *);
    int c_set_is_table_locked(char *);
    int c_new_table(char *);
    int c_config_get_tmp_path(void);
    int c_config_get_log(void);
    int c_config_get_session(void);
    int c_config_get_catalog(void);
    int c_config_get_log_flag(void);
    int c_config_get_session_flag(void);
    int c_config_get_catalog_flag(void);
    int c_config_get_replicate_flag(void);
    int c_config_get_version(void);
    int c_version(void);
    int c_config_set_tmp_path(char *);
    int c_config_set_log(char *);
    int c_config_set_session(char *);
    int c_config_set_catalog(char *);
    int c_config_set_log_flag(char *);
    int c_config_set_session_flag(char *);
    int c_config_set_catalog_flag(char *);
    int c_config_set_replicate_flag(char *);
    int c_get_open_table_list(char *);
    int c_delete_table(char *);
    int c_exist(char *);
    int c_clear_table(char *);
    int c_copy_table(char *);
    int c_get_catalog_list(char *);
    int c_sort(char *);
    int c_get_sort_mem(char *);
    int c_set_sort_mem(char *);
    int c_get_sort_open_bin(char *);
    int c_set_sort_open_bin(char *);
    int c_delete_field(char *);
    int c_delete_subfield(char *);
    int c_delete_subsubfield(char *);
    int c_trans_num(void);
    int c_connect_num(void);
    int c_get_autopack(char *);
    int c_set_autopack(char *);
    int c_config_client_get_log(void);
    int c_config_client_get_log_flag(void);
    int c_config_client_set_log(char *);
    int c_config_client_set_log_flag(char *);
    int get_token(char *);
    void term_app(void);

    #ifdef IPC_TCP
    int c_ipc_socloc_init(void);
    #endif

    int main(void)
    {
       char *comm;
       int done = FALSE;
       int ret;

        /* allocate command line buffer */

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

       /* build logo string based on platform */

    #ifndef MULTIUSER
    #ifndef OS_UNIX
       /* single user non-Unix */

       sprintf(comm, "DB Single User for %s Version %s", PLATFORM_STRING,
               VERSION);
    #else
       /* single user Unix */

       sprintf(comm, "DB Single User for %s Version %s", SUB_PLATFORM_STRING,
               VERSION);
    #endif
    #else
    #ifndef OS_UNIX
       /* c/s non-Unix */

       sprintf(comm, "DBM Client/Server for %s Version %s", PLATFORM_STRING,
               VERSION);
    #else
       /* c/s Unix */

       sprintf(comm, "DBM Client/Server for %s Version %s", SUB_PLATFORM_STRING,
               VERSION);
    #endif
    #endif

       printf("%s\n", comm);
       printf("By Rick Smereka, Copyright (c) 1995-2006\n");

    #ifndef OS_DOS
       // register application name with 'appinit'

       if (!appinit_register_name(APNAME))
          {
          free(comm);
          printf("%s:fatal error registering app name with appinit\n", APNAME);
          return(0);
          }
    #endif

       /* initialize local engine if we are running locally or
          startup the 'socloc' interface (TCP only) and connect to a
          Bbuuzzb database server if we are running in
          client/server mode */

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

       /* get and display 'Bbuuzzb' version */

       if ((ret = db_config_get_version(comm)) != DBENG_OK)
          {
          db_io_code_string(ret, comm);
          printf("%s:error getting 'Bbuuzzb' version,rc=%s\n", APNAME, comm);
          free(comm);
          term_app();
          return(0);
          }

       printf("based on version %s of 'Bbuuzzb'\n", comm);
       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");

       /* interpret loop */

       while(!done)
          {
          printf("%s> ", APNAME);
          get_rec(stdin, comm);

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

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

    #ifdef MULTIUSER
    int c_initialize(void)
    {
       /* Initialize socket communication, form connection to
          'socloc' server (TCP only), update the config list and connect
          to a 'Bbuuzzb' server. Function returns 'TRUE' upon
          success, 'FALSE' otherwise. */

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

    #ifdef IPC_TCP
       if (!c_ipc_socloc_init())
          return(FALSE);
    #endif

       /* attempt to locate a 'Bbuuzzb' server and connect to it */

       if ((ret = db_initialize()) != DBENG_OK)
          {
          db_io_code_string(ret, mes);
          printf("%s:error connecting to the Bbuuzzb server,rc[%s]. "
                 "Program abort\n", mname, mes);
          return(FALSE);
          }

       /* display current connected server host name and
          TCP port number */

    #ifdef IPC_TCP
       (void)db_get_active(mes, &ret);
       printf("%s:connected to Bbuuzzb server %s on TCP port %d (decimal)\n",
              mname, mes, ret);
    #endif

       /* get and display server version */

       (void)db_version(mes);
       printf("%s:Bbuuzzb server version is %s\n", mname, mes);
       return(TRUE);
    }
    #endif

    #ifndef MULTIUSER
    int c_initialize(void)
    {
       /* Start the 'DBENG' local engine, read the config file
          and display the result settings. Function returns
          'TRUE' upon success, 'FALSE' otherwise. */

       char mname[] = "c_initialize";
       char *mes;
       int ret, flag;

       if ((mes = (char *)malloc(DBENG_PATH_LIMIT)) == (char *)NULL)
          {
          printf("%s:alloc fail[mes]. Program abort\n", mname);
          return(FALSE);
          }

       ret = db_initialize();

       /* interpret code from init which may be
          a fatal config error */

       switch(ret)
          {
          case DBENG_OK:
             printf("%s:read config file successfully\n", mname);
             break;

          case DBENG_CONFIG_UNABLE_TO_OPEN:
             printf("%s:config file not found, loaded defaults\n", mname);
             break;

          default:
             db_io_code_string(ret, mes);
             printf("%s:fatal config error[%s]\n", mname, mes);
             printf("%s:terminating\n", mname);
             free(mes);
             return(FALSE);
             break;
          };

       (void)db_config_get_tmp_path(mes);
       printf("%s:tmp path is '%s'\n", mname, mes);
       (void)db_config_get_log(mes);
       printf("%s:log is '%s'\n", mname, mes);

       if ((ret = db_config_get_catalog(mes)) == DBENG_OK)
          printf("%s:catalog is '%s'\n", mname, mes);
       else
          printf("%s:catalog name not loaded\n", mname);

       (void)db_config_get_catalog_flag(&flag);

       if (flag_2_logic_string(flag, mes))
          printf("%s:catalog is %s\n", mname, mes);

       free(mes);
       return(TRUE);
    }
    #endif

    #ifdef IPC_TCP
    int c_ipc_socloc_init(void)
    {
       /* Initialize socket communication, form connection to
          'socloc' server (TCP only) and update the config list.
          Function returns 'TRUE' upon success, 'FALSE' otherwise. */

       char mname[] = "dbm:c_ipc_socloc_init";
       char *thelist, mes[128];
       int ret;

       /* startup WinSock (if Windoze) */

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

       /* attempt to connect to a 'socloc' server */

       if ((ret = sloc_initialize()) != SL_OK)
          {
          sl_code_string(ret, mes);
          printf("%s:error initializing socloc interface,rc[%s]. "
                "Program abort\n", mname, mes);
          return(FALSE);
          }

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

       if ((thelist = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
          {
          printf("%s:alloc fail[thelist]. Program abort\n", mname);
          return(FALSE);
          }

       if ((ret = sloc_config_get_list(thelist)) != SL_OK)
          {
          free(thelist);
          sl_code_string(ret, mes);
          printf("%s:error getting socloc config list,rc[%s]. "
                 "Program abort\n", mname, mes);
          return(FALSE);
          }

       if ((ret = sl_config_put_list(thelist)) != SL_OK)
          {
          sl_code_string(ret, mes);
          printf("%s:error putting socloc config list,rc[%s]. ",
                 "Program abort\n", mname, mes);
          free(thelist);
          return(FALSE);
          }

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

    int do_comm(char *comm)
    {
       /* Perform database commands. */

       char *keywrd;                 /* command keyword */
       int token;                    /* keyword token */
       int nwords;                   /* number of words */
       int status;                   /* return status from operation */
       int len;                      /* length of command */

       len = strlen(comm);

       if (!len)
          {
          printf("empty command\n");
          return(TRUE);
          }

       /* allocate to max as this string is re-used for the return
          status string */

       if ((keywrd = malloc(DBCOM_MAXCOMLINE + 1)) == NULL)
          {
          printf("do_comm:memory fail 'keywrd'\n");
          return(TRUE);
          }

       if (!word(comm, keywrd, 1))
          {
          printf("do_comm:error while retreving keyword, line skipped\n");
          free(keywrd);
          return(TRUE);
          }

       nwords = words(comm);

       if ((token = get_token(keywrd)) == DBCOM_NOT_FOUND)
          {
          printf("do_comm:unknown keyword '%s'\n", keywrd);
          free(keywrd);
          return(TRUE);
          }

       /* process command */

       switch(token)
          {
          case DBCOM_OPEN:
             status = c_open(comm);
             break;

          case DBCOM_CLOSE:
             status = c_close(comm);
             break;

          case DBCOM_NEXT:
             status = c_next(comm);
             break;

          case DBCOM_TOP:
             status = c_top(comm);
             break;

          case DBCOM_GET_REC:
             status = c_get_rec(comm);
             break;

          case DBCOM_GET_FIELD:
             status = c_get_field(comm);
             break;

          case DBCOM_GOTO:
             status = c_goto(comm);
             break;

          case DBCOM_COUNT:
             status = c_count(comm);
             break;

          case DBCOM_PUT_FIELD:
             status = c_put_field(comm);
             break;

          case DBCOM_WRITE:
             status = c_write(comm);
             break;

          case DBCOM_DELETE:
             status = c_delete(comm);
             break;

          case DBCOM_GET_DELETE_FLAG:
             status = c_get_delete_flag(comm);
             break;

          case DBCOM_SET_DELETE_FLAG:
             status = c_set_delete_flag(comm);
             break;

          case DBCOM_GET_NFIELDS:
             status = c_get_nfields(comm);
             break;

          case DBCOM_GET_REC_SIZE:
             status = c_get_rec_size(comm);
             break;

          case DBCOM_GET_FIELD_SIZE:
             status = c_get_field_size(comm);
             break;

          case DBCOM_GET_REC_NUM:
             status = c_get_rec_num(comm);
             break;

          case DBCOM_GET_POS:
             status = c_get_pos(comm);
             break;

          case DBCOM_SET_POS:
             status = c_set_pos(comm);
             break;

          case DBCOM_GET_CHANGE_REC_FLAG:
             status = c_get_change_rec_flag(comm);
             break;

          case DBCOM_SET_CHANGE_REC_FLAG:
             status = c_set_change_rec_flag(comm);
             break;

          case DBCOM_PACK:
             status = c_pack(comm);
             break;

          case DBCOM_NEW:
             status = c_new(comm);
             break;

          case DBCOM_FIND:
             status = c_find(comm);
             break;

          case DBCOM_FIND_FIELD:
             status = c_find_field(comm);
             break;

          case DBCOM_FIND_PART:
             status = c_find_part(comm);
             break;

          case DBCOM_FIND_FIELD_PART:
             status = c_find_field_part(comm);
             break;

          case DBCOM_GET_REC_COUNT:
             status = c_get_rec_count(comm);
             break;

          case DBCOM_GET_ENF_CHANGE_REC_FLAG:
             status = c_get_enf_change_rec_flag(comm);
             break;

          case DBCOM_SET_ENF_CHANGE_REC_FLAG:
             status = c_set_enf_change_rec_flag(comm);
             break;

          case DBCOM_GET_IS_TABLE_LOCKED:
             status = c_get_is_table_locked(comm);
             break;

          case DBCOM_SET_IS_TABLE_LOCKED:
             status = c_set_is_table_locked(comm);
             break;

          case DBCOM_NEW_TABLE:
             status = c_new_table(comm);
             break;

          case DBCOM_CONFIG_GET_TMP_PATH:
             status = c_config_get_tmp_path();
             break;

          case DBCOM_CONFIG_GET_LOG:
             status = c_config_get_log();
             break;

          case DBCOM_CONFIG_GET_SESSION:
             status = c_config_get_session();
             break;

          case DBCOM_CONFIG_GET_CATALOG:
             status = c_config_get_catalog();
             break;

          case DBCOM_CONFIG_GET_LOG_FLAG:
             status = c_config_get_log_flag();
             break;

          case DBCOM_CONFIG_GET_SESSION_FLAG:
             status = c_config_get_session_flag();
             break;

          case DBCOM_CONFIG_GET_CATALOG_FLAG:
             status = c_config_get_catalog_flag();
             break;

          case DBCOM_CONFIG_GET_REPLICATE_FLAG:
             status = c_config_get_replicate_flag();
             break;

          case DBCOM_CONFIG_GET_VERSION:
             status = c_config_get_version();
             break;

          case DBCOM_CONFIG_SET_TMP_PATH:
             status = c_config_set_tmp_path(comm);
             break;

          case DBCOM_CONFIG_SET_LOG:
             status = c_config_set_log(comm);
             break;

          case DBCOM_CONFIG_SET_SESSION:
             status = c_config_set_session(comm);
             break;

          case DBCOM_CONFIG_SET_CATALOG:
             status = c_config_set_catalog(comm);
             break;

          case DBCOM_CONFIG_SET_LOG_FLAG:
             status = c_config_set_log_flag(comm);
             break;

          case DBCOM_CONFIG_SET_SESSION_FLAG:
             status = c_config_set_session_flag(comm);
             break;

          case DBCOM_CONFIG_SET_CATALOG_FLAG:
             status = c_config_set_catalog_flag(comm);
             break;

          case DBCOM_CONFIG_SET_REPLICATE_FLAG:
             status = c_config_set_replicate_flag(comm);
             break;

          case DBCOM_GET_OPEN_TABLE_LIST:
             status = c_get_open_table_list(comm);
             break;

          case DBCOM_GET_NSUBFIELDS:
             status = c_get_nsubfields(comm);
             break;

          case DBCOM_GET_SUBFIELD_SIZE:
             status = c_get_subfield_size(comm);
             break;

          case DBCOM_GET_SUBFIELD:
             status = c_get_subfield(comm);
             break;

          case DBCOM_PUT_SUBFIELD:
             status = c_put_subfield(comm);
             break;

          case DBCOM_GET_NSUBSUBFIELDS:
             status = c_get_nsubsubfields(comm);
             break;

          case DBCOM_GET_SUBSUBFIELD_SIZE:
             status = c_get_subsubfield_size(comm);
             break;

          case DBCOM_GET_SUBSUBFIELD:
             status = c_get_subsubfield(comm);
             break;

          case DBCOM_PUT_SUBSUBFIELD:
             status = c_put_subsubfield(comm);
             break;

          case DBCOM_REPLICATE_UPDATE:
    #ifndef OS_DOS
             status = c_replicate_update();
             break;
    #endif

          case DBCOM_DELETE_TABLE:
             status = c_delete_table(comm);
             break;

          case DBCOM_EXIST:
             status = c_exist(comm);
             break;

          case DBCOM_CLEAR_TABLE:
             status = c_clear_table(comm);
             break;

          case DBCOM_COPY_TABLE:
             status = c_copy_table(comm);
             break;

          case DBCOM_GET_CATALOG_LIST:
             status = c_get_catalog_list(comm);
             break;

          case DBCOM_SORT:
             status = c_sort(comm);
             break;

          case DBCOM_GET_SORT_MEM:
             status = c_get_sort_mem(comm);
             break;

          case DBCOM_SET_SORT_MEM:
             status = c_set_sort_mem(comm);
             break;

          case DBCOM_GET_SORT_OPEN_BIN:
             status = c_get_sort_open_bin(comm);
             break;

          case DBCOM_SET_SORT_OPEN_BIN:
             status = c_set_sort_open_bin(comm);
             break;

          case DBCOM_DELETE_FIELD:
             status = c_delete_field(comm);
             break;

          case DBCOM_DELETE_SUBFIELD:
             status = c_delete_subfield(comm);
             break;

          case DBCOM_DELETE_SUBSUBFIELD:
             status = c_delete_subsubfield(comm);
             break;

          case DBCOM_TRANS_NUM:
             status = c_trans_num();
             break;

          case DBCOM_CONNECT_NUM:
             status = c_connect_num();
             break;

          case DBCOM_GET_AUTOPACK:
             status = c_get_autopack(comm);
             break;

          case DBCOM_SET_AUTOPACK:
             status = c_set_autopack(comm);
             break;

          case DBCOM_CONFIG_CLIENT_GET_LOG:
             status = c_config_client_get_log();
             break;

          case DBCOM_CONFIG_CLIENT_GET_LOG_FLAG:
             status = c_config_client_get_log_flag();
             break;

          case DBCOM_CONFIG_CLIENT_SET_LOG:
             status = c_config_client_set_log(comm);
             break;

          case DBCOM_CONFIG_CLIENT_SET_LOG_FLAG:
             status = c_config_client_set_log_flag(comm);
             break;

          case DBCOM_VERSION:
             status = c_version();
             break;

          case DBCOM_OFF:
             return(FALSE);
             break;

          default:
            printf("function not yet implemented\n");
            free(keywrd);
            return(TRUE);
          };

       db_io_code_string(status, keywrd);
       printf("%s\n", keywrd);

       /* if a server failover has ocurred, display details of
          new connected server (TCP only) */

    #ifdef MULTIUSER
    #ifdef IPC_TCP
       if (status == DBENG_FAILOVER)
          {
          (void)db_get_active(keywrd, &status);
          printf("now connected to Bbuuzzb server %s on TCP port %d (decimal)\n",
                 keywrd, status);
          }
    #endif
    #endif

       free(keywrd);
       return(TRUE);
    }

    int c_open(char *comm)
    {
       /* Open a table. The file name is expected on the command line.
          Function returns the 'DBENG' status. Syntax:

             open file_name

          Note that the returned 'tid' is printed on the screen. */

       char *fname;
       int tid;
       int len;
       int ret;

       /* must be at least two words on command line */

       if (command_words(comm) < 2)
          {
          printf("c_open:missing file name\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((fname = malloc(len + 1)) == NULL)
          {
          printf("c_open:unable to alloc 'fname'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fname, 2);
       ret = db_open(fname, &tid);

       if (ret == DBENG_OK || ret == DBENG_FILE_DATA_ERROR)
          printf("tid is %d\n", tid);

       if (ret == DBENG_FILE_DATA_ERROR)
          printf("table is still open\n");

       free(fname);
       return(ret);
    }

    int c_close(char *comm)
    {
       /* Close a table. Function returns the 'DBENG' status. Syntax:

             close tid */

       char *tid_char;
       int tid;
       int len;

       /* must be at least two words on command line */

       if (words(comm) < 2)
          {
          printf("c_close:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_close:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);    /* tid in char is second word */

       if (!qatoi(tid_char, &tid))
          {
          printf("c_close:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_close:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_close(tid));
    }

    int c_next(char *comm)
    {
       /* Get next record in a table. Function returns the 'DBENG' status.
          Syntax:

             next tid */

       char *tid_char;
       int tid;
       int len;

       if (words(comm) < 2)
          {
          printf("c_next:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_next:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_next:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_next:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_next(tid));
    }

    int c_top(char *comm)
    {
       /* Goto the top of the table. Note that file pointer is at the
          very top and no record is loaded. Function returns the 'DBENG'
          status. Syntax:

             top tid */

       char *tid_char;
       int tid;
       int len;

       if (words(comm) < 2)
          {
          printf("c_top:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_top:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_top:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_top:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_top(tid));
    }

    int c_get_rec(char *comm)
    {
       /* Get and display the current record. Function returns the 'DBENG'
          status. Syntax:

             get.rec tid */

       char *tid_char;
       char *rec;
       int rec_size;
       int nfields;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_rec:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_rec:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_rec:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_rec:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((ret = db_get_rec_size(tid, &rec_size)) != DBENG_OK)
          return(ret);

       if ((rec = malloc(rec_size + 1)) == NULL)
          {
          printf("c_get_rec:alloc fail 'rec'\n");
          return(DBENG_MEMORY_FAIL);
          }

       ret = db_get_rec(tid, rec);

       if (ret == DBENG_OK)
          {
          if ((ret = db_get_nfields(tid, &nfields)) != DBENG_OK)
             {
             free(rec);
             return(ret);
             }

          printf("rec=%s,l=%d,nfields=%d\n", rec, strlen(rec), nfields);
          }

       free(rec);
       return(ret);
    }

    int c_get_field(char *comm)
    {
       /* Get and display a field in the current record. Function returns
          the 'DBENG' status. Syntax:

             get.field tid field_num */

       char *tid_char;
       char *field_num_char;
       char *field;
       int field_size;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_get_field:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_get_field:missing field number\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_field:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_field:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_field:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_field:alloc fail 'field_num_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("c_get_field:non numeric field number\n");
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("c_get_field:invalid field number\n");
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((ret = db_get_field_size(tid, field_num, &field_size)) != DBENG_OK)
          return(ret);

       if (!field_size)
          {
          printf("c_get_field:null field\n");
          return(DBENG_OK);
          }

       if ((field = malloc(field_size + 1)) == NULL)
          {
          printf("c_get_field:alloc fail 'field'\n");
          return(DBENG_MEMORY_FAIL);
          }

       ret = db_get_field(tid, field_num, field);

       if (ret == DBENG_OK)
          printf("field=%s,l=%d\n", field, strlen(field));

       free(field);
       return(ret);
    }

    int c_get_subfield(char *comm)
    {
       /* Get and display a subfield in the current record. Function returns
          the 'DBENG' status. Syntax:

             get.subfield tid field_num subfield_num */

       char *tid_char, *field_num_char, *subfield, mname[] = "c_get_subfield";
       char *subfield_num_char;
       int subfield_size, field_num, subfield_num, nwords, tid, len, ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing sub-field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);

       if ((ret = db_get_subfield_size(tid, field_num, subfield_num,
                                       &subfield_size)) != DBENG_OK)
          return(ret);

       if (!subfield_size)
          {
          printf("c_get_field:empty subfield\n");
          return(DBENG_OK);
          }

       if ((subfield = (char *)malloc(subfield_size + 1)) == (char *)NULL)
          {
          printf("%s:alloc fail 'field'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       ret = db_get_subfield(tid, field_num, subfield_num, subfield);

       if (ret == DBENG_OK)
          printf("subfield=%s,l=%d\n", subfield, strlen(subfield));

       free(subfield);
       return(ret);
    }

    int c_get_subsubfield(char *comm)
    {
       /* Get and display a subsubfield in the current record. Function returns
          the 'DBENG' status. Syntax:

             get.subsubfield tid field_num subfield_num subsubfield_num */

       char *tid_char, *field_num_char, mname[] = "c_get_subsubfield";
       char *subfield_num_char, *subsubfield_num_char, *subsubfield;
       int subsubfield_size, field_num, subfield_num;
       int subsubfield_num, nwords, tid, len, ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 5)
          {
          printf("%s:missing subsubfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);

       if ((subsubfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subsubfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subsubfield_num_char, 5);

       if (!qatoi(subsubfield_num_char, &subsubfield_num))
          {
          printf("%s:non numeric subsubfield number\n", mname);
          free(subsubfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_num <= 0)
          {
          printf("%s:invalid subsubfield number\n", mname);
          free(subsubfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subsubfield_num_char);

       if ((ret = db_get_subsubfield_size(tid, field_num, subfield_num,
                                          subsubfield_num, &subsubfield_size))
            != DBENG_OK)
          return(ret);

       if (!subsubfield_size)
          {
          printf("c_get_field:empty subsubfield\n");
          return(DBENG_OK);
          }

       if ((subsubfield = (char *)malloc(subsubfield_size + 1)) == (char *)NULL)
          {
          printf("%s:alloc fail 'subsubfield'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       ret = db_get_subsubfield(tid, field_num, subfield_num,
                                subsubfield_num, subsubfield);

       if (ret == DBENG_OK)
          printf("subsubfield=%s,l=%d\n", subsubfield, strlen(subsubfield));

       free(subsubfield);
       return(ret);
    }

    int c_goto(char *comm)
    {
       /* Goto a specific record. Function returns the 'DBENG' status. Syntax:

             goto tid rec_num */

       char *tid_char;
       char *rec_num_char;
       long rec_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_goto:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_goto:missing record number\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_goto:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_goto:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_goto:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((rec_num_char = malloc(len + 1)) == NULL)
          {
          printf("c_goto:alloc fail 'rec_num_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, rec_num_char, 3);

       if (!qatol(rec_num_char, &rec_num))
          {
          printf("c_goto:non numeric record number\n");
          free(rec_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (rec_num <= 0L)
          {
          printf("c_goto:invalid record number\n");
          free(rec_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       ret = db_goto(tid, rec_num);
       free(rec_num_char);
       return(ret);
    }

    int c_count(char *comm)
    {
       /* Count records in a table. Function returns the 'DBENG' status. Syntax:

             count tid

          The number of active and deleted records will be displayed. */

       char *tid_char;
       long active_count, deleted_count;
       int nwords;
       int tid;
       int len;
       int ret;

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

       if (nwords < 2)
          {
          printf("c_count:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_count:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_count:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_count:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_count(tid, &active_count, &deleted_count);

       if (ret == DBENG_OK)
          printf("c_count:counted %ld active and %ld deleted record(s)\n",
                 active_count, deleted_count);

       return(ret);
    }

    int c_put_field(char *comm)
    {
       /* Put a field into the record. Function returns the 'DBENG' status.
          Syntax:

             put.field tid field_num field_data

          Note that if the field data contains spaces, you must quote the
          data. */

       char *tid_char;
       char *field_num_char;
       char *field_data;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("c_put_field:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_put_field:missing field number\n");
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("c_put_field:missing field data\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_put_field:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_put_field:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_put_field:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("c_put_field:alloc fail 'field_num_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("c_put_field:non numeric field number\n");
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num < 0)
          {
          printf("c_put_field:invalid field number\n");
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((field_data = malloc(len + 1)) == NULL)
          {
          printf("c_put_field:alloc fail 'field_data'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, field_data, 4);
       ret = db_put_field(tid, field_num, field_data);
       free(field_data);
       return(ret);
    }

    int c_put_subfield(char *comm)
    {
       /* Put a subfield into the field. Function returns the 'DBENG' status.
          Syntax:

             put.subfield tid field_num subfield_num 'data1 data 2...'

          Note that if the subfield data contains spaces, you must quote the
          data. */

       char *tid_char, *field_num_char, *subfield_num_char, *subfield_data;
       char mname[] = "c_put_subfield";
       int field_num, subfield_num, nwords, tid, len, ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 5)
          {
          printf("%s:missing subfield data\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num < 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric sub-field number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num < 0)
          {
          printf("%s:invalid sub-field number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);

       if ((subfield_data = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_data'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, subfield_data, 5);
       ret = db_put_subfield(tid, field_num, subfield_num, subfield_data);
       free(subfield_data);
       return(ret);
    }

    int c_put_subsubfield(char *comm)
    {
       /* Put a subsubfield into the field. Function returns the 'DBENG' status.
          Syntax:

             put.subfield tid field_num subfield_num subsubfield_num 'd1 d2...'

          Note that if the data contains spaces, you must quote the
          data. */

       char *tid_char, *field_num_char, *subfield_num_char, *subsubfield_data;
       char mname[] = "c_put_subsubfield", *subsubfield_num_char;
       int field_num, subfield_num, subsubfield_num, nwords, tid, len, ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 5)
          {
          printf("%s:missing subsubfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 6)
          {
          printf("%s:missing subsubfield data\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num < 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num < 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);

       if ((subsubfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subsubfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, subsubfield_num_char, 5);

       if (!qatoi(subsubfield_num_char, &subsubfield_num))
          {
          printf("%s:non numeric subsubfield number\n", mname);
          free(subsubfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_num < 0)
          {
          printf("%s:invalid subsubfield number\n", mname);
          free(subsubfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subsubfield_num_char);

       if ((subsubfield_data = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subsubfield_data'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, subsubfield_data, 6);
       ret = db_put_subsubfield(tid, field_num, subfield_num, subsubfield_num,
                                subsubfield_data);
       free(subsubfield_data);
       return(ret);
    }

    int c_write(char *comm)
    {
       /* Write the current record to the table. Function returns the 'DBENG'
          status. Syntax:

             write tid */

       char *tid_char;
       int tid;
       int len;

       if (words(comm) < 2)
          {
          printf("c_write:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_write:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_write:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_write:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_write(tid));
    }

    int c_delete(char *comm)
    {
       /* Delete the current record. Function returns the 'DBENG'
          status. Syntax:

             delete tid */

       char *tid_char;
       int tid;
       int len;

       if (words(comm) < 2)
          {
          printf("c_delete:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_delete:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_delete:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_delete:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_delete(tid));
    }

    int c_get_delete_flag(char *comm)
    {
       /* Get the current tables' 'process_deleted' flag. Function returns
          the 'DBENG' status. Flag value is displayed on the screen upon
          success. Syntax:

             get.delete.flag tid */

       char *tid_char;
       int tid;
       int len;
       int ret;
       int flag;

       if (words(comm) < 2)
          {
          printf("c_get_delete_flag:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_delete_flag:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_delete_flag:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_delete_flag:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_delete_flag(tid, &flag);

       if (ret == DBENG_OK)
          printf("c_get_delete_flag:'process_deleted' is %d\n", flag);

       return(ret);
    }

    int c_set_delete_flag(char *comm)
    {
       /* Set the current tables' 'process_deleted' flag. Function returns
          the 'DBENG' status. Note that 'flag_value' must be '0' or '1'.
          Syntax:

             set.delete.flag tid flag_value */

       char *tid_char;
       char *flag_char;
       int delete_flag;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_set_delete_flag:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_set_delete_flag:missing flag value\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_delete_flag:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_set_delete_flag:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_set_delete_flag:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((flag_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_delete_flag:alloc fail 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 3);

       if (!qatoi(flag_char, &delete_flag))
          {
          printf("c_set_delete_flag:non numeric flag value, must be '0' or '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (delete_flag < 0 || delete_flag > 1)
          {
          printf("c_set_delete_flag:invalid flag value, must be '0' or '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_set_delete_flag(tid, delete_flag);
       return(ret);
    }

    int c_get_nfields(char *comm)
    {
       /* Get the number of fields in the current record. Function returns
          the 'DBENG' status. The number of fields is displayed on the screen
          upon success. Syntax:

             get.nfields tid */

       char *tid_char;
       int tid;
       int len;
       int ret;
       int nfields;

       if (words(comm) < 2)
          {
          printf("c_get_nfields:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_nfields:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_nfields:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_nfields:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_nfields(tid, &nfields);

       if (ret == DBENG_OK)
          printf("c_get_nfields:nfields is %d\n", nfields);

       return(ret);
    }

    int c_get_nsubfields(char *comm)
    {
       /* Get the number of subfields in a field. Function returns
          the 'DBENG' status. The number of subfields is displayed
          on the screen upon success. Syntax:

             get.nsubfields tid field_num */

       char *tid_char, *field_num_char, mname[] = "c_get_nsubfields";
       int tid, len, ret;
       int nwords, nsubfields, field_num;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);
       ret = db_get_nsubfields(tid, field_num, &nsubfields);

       if (ret == DBENG_OK)
          printf("%s:nsubfields is %d\n", mname, nsubfields);

       return(ret);
    }

    int c_get_nsubsubfields(char *comm)
    {
       /* Get the number of subsubfields in a subfield. Function returns
          the 'DBENG' status. The number of subsubfields is displayed
          on the screen upon success. Syntax:

             get.nsubsubfields tid field_num subfield_num */

       char *tid_char, *field_num_char, *subfield_num_char;
       char mname[] = "c_get_nsubsubfields";
       int tid, len, ret;
       int nwords, nsubsubfields, field_num, subfield_num;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'sub_field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);
       ret = db_get_nsubsubfields(tid, field_num, subfield_num, &nsubsubfields);

       if (ret == DBENG_OK)
          printf("%s:nsubsubfields is %d\n", mname, nsubsubfields);

       return(ret);
    }

    int c_get_rec_size(char *comm)
    {
       /* Get the size of the current record. Function returns
          the 'DBENG' status. The record size is displayed on the screen
          upon success. Syntax:

             get.rec.size tid */

       char *tid_char;
       int tid;
       int len;
       int ret;
       int rec_size;

       if (words(comm) < 2)
          {
          printf("c_get_rec_size:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_rec_size:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_rec_size:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_rec_size:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_rec_size(tid, &rec_size);

       if (ret == DBENG_OK)
          printf("c_get_rec_size:record size is %d bytes\n", rec_size);

       return(ret);
    }

    int c_get_field_size(char *comm)
    {
       /* Get and display a field size in the current record. Function returns
          the 'DBENG' status. Syntax:

             get.field.size tid field_num */

       char *tid_char;
       char *field_num_char;
       int field_size;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_get_field_size:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("get_get_field_size:missing field number\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_field_size:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_field_size:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_field_size:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_field_size:alloc fail 'field_num_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("c_get_field_size:non numeric field number\n");
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("c_get_field_size:invalid field number\n");
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);
       ret = db_get_field_size(tid, field_num, &field_size);

       if (ret == DBENG_OK)
          printf("c_get_field_size:field[%d] size=%d\n", field_num, field_size);

       return(ret);
    }

    int c_get_subfield_size(char *comm)
    {
       /* Get the size of a subfield in a field. Function returns
          the 'DBENG' status. The subfield size is displayed
          on the screen upon success. Syntax:

             get.subfield.size tid field_num subfield_num */

       char *tid_char, *field_num_char, mname[] = "c_get_subfield_size";
       char *subfield_num_char;
       int tid, len, ret;
       int nwords, subfield_size, field_num, subfield_num;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);
       ret = db_get_subfield_size(tid, field_num, subfield_num, &subfield_size);

       if (ret == DBENG_OK)
          printf("%s:subfield size is %d\n", mname, subfield_size);

       return(ret);
    }

    int c_get_subsubfield_size(char *comm)
    {
       /* Get the size of a subsubfield in a subfield. Function returns
          the 'DBENG' status. The subsubfield size is displayed
          on the screen upon success. Syntax:

             get.subsubfield.size tid field_num subfield_num subsubfield_num */

       char *tid_char, *field_num_char, mname[] = "c_get_subsubfield_size";
       char *subfield_num_char, *subsubfield_num_char;
       int tid, len, ret;
       int nwords, subsubfield_size, field_num, subfield_num, subsubfield_num;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 5)
          {
          printf("%s:missing subsubfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((field_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'field_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, field_num_char, 3);

       if (!qatoi(field_num_char, &field_num))
          {
          printf("%s:non numeric field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(field_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(field_num_char);

       if ((subfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subfield_num_char, 4);

       if (!qatoi(subfield_num_char, &subfield_num))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(subfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subfield_num_char);

       if ((subsubfield_num_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'subsubfield_num_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, subfield_num_char, 5);

       if (!qatoi(subsubfield_num_char, &subsubfield_num))
          {
          printf("%s:non numeric subsubfield number\n", mname);
          free(subsubfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_num <= 0)
          {
          printf("%s:invalid subsubfield number\n", mname);
          free(subsubfield_num_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(subsubfield_num_char);
       ret = db_get_subsubfield_size(tid, field_num, subfield_num, subsubfield_num,
                                     &subsubfield_size);

       if (ret == DBENG_OK)
          printf("%s:subsubfield size is %d\n", mname, subsubfield_size);

       return(ret);
    }

    int c_get_rec_num(char *comm)
    {
       /* Get the current record number. Function returns
          the 'DBENG' status. The current record number is displayed on the screen
          upon success. Syntax:

             get.rec.num tid */

       char *tid_char;
       long rec_num;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_rec_num:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_rec_num:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_rec_num:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_rec_num:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_rec_num(tid, &rec_num);

       if (ret == DBENG_OK)
          printf("c_get_rec_num:record number is %ld\n", rec_num);

       return(ret);
    }

    int c_get_pos(char *comm)
    {
       /* Get the current file position from the beginning. Function returns
          the 'DBENG' status. The file position is displayed on the screen
          upon success. Syntax:

             get.pos tid */

       char *tid_char;
       long pos;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_pos:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_pos:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_pos:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_pos:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_pos(tid, &pos);

       if (ret == DBENG_OK)
          printf("c_get_pos:file position is %ld\n", pos);

       return(ret);
    }

    int c_set_pos(char *comm)
    {
       /* Set the table file position. Function returns the 'DBENG' status.
          Syntax:

             set.pos tid filepos */

       char *tid_char;
       char *file_pos_char;
       long file_pos;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("c_set_pos:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_set_pos:missing file position\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_pos:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_set_pos:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_set_pos:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((file_pos_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_pos:alloc fail 'file_pos_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, file_pos_char, 3);

       if (!qatol(file_pos_char, &file_pos))
          {
          printf("c_set_pos:non numeric file position\n");
          free(file_pos_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (file_pos < 0L)
          {
          printf("c_set_pos:invalid file position\n");
          free(file_pos_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(file_pos_char);
       ret = db_set_pos(tid, file_pos);
       return(ret);
    }

    int c_get_change_rec_flag(char *comm)
    {
       /* Get the current value of 'change_rec_flag'. Function returns
          the 'DBENG' status. The flag value is displayed on the screen
          upon success. Syntax:

             get.change.rec.flag tid */

       char *tid_char;
       int change_rec_flag;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_change_rec_flag:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_change_rec_flag:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_change_rec_flag:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_change_rec_flag:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_change_rec_flag(tid, &change_rec_flag);

       if (ret == DBENG_OK)
          printf("c_get_change_rec_flag:flag is %d\n", change_rec_flag);

       return(ret);
    }

    int c_set_change_rec_flag(char *comm)
    {
       /* Set the current tables' 'change_rec_flag'. Function returns
          the 'DBENG' status. Note that 'flag_value' must be '0' or '1'.
          Syntax:

             set.change.rec.flag tid flag_value */

       char *tid_char;
       char *flag_char;
       int delete_flag;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_set_change_rec_flag:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_set_change_rec_flag:missing flag value\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_change_rec_flag:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_set_change_rec_flag:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_set_change_rec_flag:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((flag_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_change_rec_flag:alloc fail 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 3);

       if (!qatoi(flag_char, &delete_flag))
          {
          printf("c_set_change_rec_flag:non numeric flag value, must be '0' "
                 "or '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (delete_flag < 0 || delete_flag > 1)
          {
          printf("c_set_change_rec_flag:invalid flag value, must be '0' or '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_set_change_rec_flag(tid, delete_flag);
       return(ret);
    }

    int c_pack(char *comm)
    {
       /* Pack a table. Function returns the 'DBENG' status. Syntax:

             pack tid */

       char *tid_char;
       int tid;
       int len;

       if (words(comm) < 2)
          {
          printf("c_pack:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_pack:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_pack:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_pack:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_pack(tid));
    }

    int c_new(char *comm)
    {
       /* Declare/start a new record. Function returns the 'DBENG' status.
          Syntax:

             new tid */

       char *tid_char;
       int tid;
       int len;

       if (words(comm) < 2)
          {
          printf("c_new:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_new:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_new:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_new:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       return(db_new(tid));
    }

    int c_find(char *comm)
    {
       /* Find field. All whole fields will be searched from (and including)
          the current record. String comparison is case insensitive unless
          a 'case_flag' is supplied ('1' for insensitive, '0' for sensitive).
          Function returns the 'DBENG' status. Syntax:

             find tid 'string' [case_flag] */

       char *tid_char;
       char *flag_char;
       char *findstr;
       int case_flag = TRUE;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("c_find:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_find:missing search string\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_find:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_find:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_find:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if (nwords > 3)
          {
          /* get the case flag */

          if ((flag_char = malloc(len + 1)) == NULL)
             {
             printf("c_find:alloc fail 'flag_char'\n");
             return(DBENG_MEMORY_FAIL);
             }

          (void)command_word(comm, flag_char, 4);

          if (!qatoi(flag_char, &case_flag))
             {
             printf("c_find:non numeric flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          if (case_flag < 0 || case_flag > 1)
             {
             printf("c_find:invalid flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          free(flag_char);
          }

       if ((findstr = malloc(len + 1)) == NULL)
          {
          printf("c_find:unable to alloc 'findstr'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, findstr, 3);
       ret = db_find(tid, case_flag, findstr, &field_num);
       free(findstr);

       if (ret == DBENG_OK)
          printf("c_find:match found in field %d\n", field_num);

       return(ret);
    }

    int c_find_field(char *comm)
    {
       /* Find field. A single whole field will be searched from (and including)
          the current record. String comparison is case insensitive unless
          a 'case_flag' is supplied ('1' for insensitive, '0' for sensitive).
          Function returns the 'DBENG' status. Syntax:

             find.field tid field_num 'string' [case_flag] */

       char *tid_char;
       char *fnum_char;
       char *flag_char;
       char *findstr;
       int case_flag = TRUE;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("c_find_field:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_find_field:missing field number\n");
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("c_find_field:missing search string\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_find_field:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_find_field:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_find_field:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((fnum_char = malloc(len + 1)) == NULL)
          {
          printf("c_find_field:unable to alloc 'fnum_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fnum_char, 3);

       if (!qatoi(fnum_char, &field_num))
          {
          printf("c_find_field:non numeric field number\n");
          free(fnum_char);
          return(DBENG_NO_SUCH_FIELD);
          }

       if (field_num <= 0)
          {
          printf("c_find_field:invalid field number\n");
          free(fnum_char);
          return(DBENG_NO_SUCH_FIELD);
          }

       free(fnum_char);

       if (nwords > 4)
          {
          /* get the case flag */

          if ((flag_char = malloc(len + 1)) == NULL)
             {
             printf("c_find_field:alloc fail 'flag_char'\n");
             return(DBENG_MEMORY_FAIL);
             }

          (void)command_word(comm, flag_char, 5);

          if (!qatoi(flag_char, &case_flag))
             {
             printf("c_find_field:non numeric flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          if (case_flag < 0 || case_flag > 1)
             {
             printf("c_find_field:invalid flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          free(flag_char);
          }

       if ((findstr = malloc(len + 1)) == NULL)
          {
          printf("c_find_field:unable to alloc 'findstr'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, findstr, 4);
       ret = db_find_field(tid, case_flag, findstr, field_num);
       free(findstr);

       if (ret == DBENG_OK)
          printf("c_find_field:match found\n");

       return(ret);
    }

    int c_find_part(char *comm)
    {
       /* Find field. Any part of all fields will be searched from (and including)
          the current record. String comparison is case insensitive unless
          a 'case_flag' is supplied ('1' for insensitive, '0' for sensitive).
          Function returns the 'DBENG' status. Syntax:

             find.part tid 'string' [case_flag] */

       char *tid_char;
       char *flag_char;
       char *findstr;
       int case_flag = TRUE;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("c_find_part:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_find_part:missing search string\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_find_part:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_find_part:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_find_part:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if (nwords > 3)
          {
          /* get the case flag */

          if ((flag_char = malloc(len + 1)) == NULL)
             {
             printf("c_find_part:alloc fail 'flag_char'\n");
             return(DBENG_MEMORY_FAIL);
             }

          (void)command_word(comm, flag_char, 4);

          if (!qatoi(flag_char, &case_flag))
             {
             printf("c_find_part:non numeric flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          if (case_flag < 0 || case_flag > 1)
             {
             printf("c_find_part:invalid flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          free(flag_char);
          }

       if ((findstr = malloc(len + 1)) == NULL)
          {
          printf("c_find_part:unable to alloc 'findstr'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, findstr, 3);
       ret = db_find_part(tid, case_flag, findstr, &field_num);
       free(findstr);

       if (ret == DBENG_OK)
          printf("c_find_part:match found in field %d\n", field_num);

       return(ret);
    }

    int c_find_field_part(char *comm)
    {
       /* Find field. Any part of a single field will be searched from (and
          including) the current record. String comparison is case insensitive
          unless a 'case_flag' is supplied ('1' for insensitive, '0' for
          sensitive). Function returns the 'DBENG' status. Syntax:

             find.field.part tid field_num 'string' [case_flag] */

       char *tid_char;
       char *fnum_char;
       char *flag_char;
       char *findstr;
       int case_flag = TRUE;
       int field_num;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("c_find_field_part:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_find_field_part:missing field number\n");
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("c_find_field_part:missing search string\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_find_field_part:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_find_field_part:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_find_field_part:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((fnum_char = malloc(len + 1)) == NULL)
          {
          printf("c_find_field_part:unable to alloc 'fnum_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fnum_char, 3);

       if (!qatoi(fnum_char, &field_num))
          {
          printf("c_find_field_part:non numeric field number\n");
          free(fnum_char);
          return(DBENG_NO_SUCH_FIELD);
          }

       if (field_num <= 0)
          {
          printf("c_find_field_part:invalid field number\n");
          free(fnum_char);
          return(DBENG_NO_SUCH_FIELD);
          }

       free(fnum_char);

       if (nwords > 4)
          {
          /* get the case flag */

          if ((flag_char = malloc(len + 1)) == NULL)
             {
             printf("c_find_field_part:alloc fail 'flag_char'\n");
             return(DBENG_MEMORY_FAIL);
             }

          (void)command_word(comm, flag_char, 5);

          if (!qatoi(flag_char, &case_flag))
             {
             printf("c_find_field_part:non numeric flag value, must be '0'"
                    " or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          if (case_flag < 0 || case_flag > 1)
             {
             printf("c_find_field_part:invalid flag value, must be '0' or '1'\n");
             free(flag_char);
             return(DBENG_INVALID_FUNCTION);
             }

          free(flag_char);
          }

       if ((findstr = malloc(len + 1)) == NULL)
          {
          printf("c_find_field_part:unable to alloc 'findstr'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, findstr, 4);
       ret = db_find_field_part(tid, case_flag, findstr, field_num);
       free(findstr);

       if (ret == DBENG_OK)
          printf("c_find_field_part:match found\n");

       return(ret);
    }

    int c_get_rec_count(char *comm)
    {
       /* Get the current record count. Note that records are not counted.
          Function returns the 'DBENG' status. The number of records is
          displayed on the screen upon success. Syntax:

             get.rec.count tid */

       char *tid_char;
       long active_count, deleted_count;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_rec_count:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_rec_count:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_rec_count:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_rec_count:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_rec_count(tid, &active_count, &deleted_count);

       if (ret == DBENG_OK)
          printf("c_get_rec_count:table contains %ld active and %ld deleted"
                 " record(s)\n", active_count, deleted_count);

       return(ret);
    }

    int c_get_enf_change_rec_flag(char *comm)
    {
       /* Get the table 'enf_change_rec_flag'. Function returns
          the 'DBENG' status. The flag value is displayed on the screen
          upon success. Syntax:

             get.enf.change.rec.flag tid */

       char *tid_char;
       int flag;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_enf_change_rec_flag:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_enf_change_rec_flag:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_enf_change_rec_flag:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_enf_change_rec_flag:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_enf_change_rec_flag(tid, &flag);

       if (ret == DBENG_OK)
          printf("c_get_enf_change_rec_flag:flag is %d\n", flag);

       return(ret);
    }

    int c_set_enf_change_rec_flag(char *comm)
    {
       /* Set the table 'enf_change_rec_flag'. 'flag_value' must be
          '0' or '1'. Function returns the 'DBENG' status. Syntax:

             set.enf.change.rec.flag tid flag_value */

       char *tid_char;
       char *flag_char;
       int flag;
       int tid;
       int len;
       int nwords;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_set_enf_change_rec_flag:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_set_enf_change_rec_flag:missing flag value\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_enf_change_rec_flag:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_set_enf_change_rec_flag:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_set_enf_change_rec_flag:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((flag_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_enf_change_rec_flag:alloc fail 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, flag_char, 3);

       if (!qatoi(flag_char, &flag))
          {
          printf("c_set_end_change_rec_flag:non numeric flag value, must be '0'"
                 " or '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (flag < 0 || flag > 1)
          {
          printf("c_set_enf_change_rec_flag:invalid flag value, must be '0' or"
                 " '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       return(db_set_enf_change_rec_flag(tid, flag));
    }

    int c_get_is_table_locked(char *comm)
    {
       /* Get the table 'is_table_locked' flag. Function returns
          the 'DBENG' status. The flag value is displayed on the screen
          upon success. Syntax:

             get.is.table.locked tid */

       char *tid_char;
       int flag;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("c_get_is_table_locked:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_get_is_table_locked:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_get_is_table_locked:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_get_is_table_locked:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_is_table_locked(tid, &flag);

       if (ret == DBENG_OK)
          printf("c_get_is_table_locked:flag is %d\n", flag);

       return(ret);
    }

    int c_set_is_table_locked(char *comm)
    {
       /* Set the table 'is_table_locked' flag. 'flag_value' must be
          '0' or '1'. Function returns the 'DBENG' status. Syntax:

             set.is.table.locked tid flag_value */

       char *tid_char;
       char *flag_char;
       int flag;
       int tid;
       int len;
       int nwords;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("c_set_is_table_locked:missing tid\n");
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("c_set_is_table_locked:missing flag value\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_is_table_locked:unable to alloc 'tid_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_set_is_table_locked:non numeric tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("c_set_is_table_locked:invalid tid\n");
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((flag_char = malloc(len + 1)) == NULL)
          {
          printf("c_set_is_table_locked:alloc fail 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, flag_char, 3);

       if (!qatoi(flag_char, &flag))
          {
          printf("c_set_is_table_locked:non numeric flag value, must be '0'"
                 " or '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (flag < 0 || flag > 1)
          {
          printf("c_set_is_table_locked:invalid flag value, must be '0' or"
                 " '1'\n");
          free(flag_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       return(db_set_is_table_locked(tid, flag));
    }

    int c_new_table(char *comm)
    {
       /* Create a new table. The file name is expected on the command line.
          If 'tid_flag' is a positive number, the table will be opened.
          Function returns the 'DBENG' status. Syntax:

             new.table file_name tid_flag

          Note that the returned 'tid' is printed on the screen. */

       char *fname, *tid_char;
       int nwords, tid, len, ret, should_open;

       nwords = command_words(comm);

       /* must be at least three words on command line */

       if (nwords < 2)
          {
          printf("c_new_table:missing file name\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       if (nwords < 3)
          {
          printf("c_new_table:missing tid flag\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((fname = malloc(len + 1)) == NULL)
          {
          printf("c_new_table:unable to alloc 'fname'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fname, 2);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("c_new_table:unable to alloc 'tid_char'\n");
          free(fname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 3);

       if (!qatoi(tid_char, &tid))
          {
          printf("c_new_table:non numeric tid flag\n");
          free(fname);
          free(tid_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(tid_char);
       should_open = (tid > 0) ? TRUE : FALSE;

       ret = db_new_table(fname, &tid);

       if (ret == DBENG_OK && should_open)
          printf("tid is %d\n", tid);

       free(fname);
       return(ret);
    }

    int c_config_get_tmp_path(void)
    {
       /* Display the current temporary file path.
          Syntax:

             config.get.tmp.path

          Function returns 'DBENG_OK' upon success,
          an engine i/o code otherwise. */

       int ret;
       char tmp_path[DBENG_PATH_LIMIT];

       ret = db_config_get_tmp_path(tmp_path);

       if (ret == DBENG_OK)
          printf("path for temp files is '%s'\n", tmp_path);

       return(ret);
    }

    int c_config_get_log(void)
    {
       /* Display the current log name/destination.
          Syntax:

             config.get.log

          Function returns 'DBENG_OK' upon success,
          an engine i/o code otherwise. */

       int ret;
       char slog[DBENG_PATH_LIMIT];

       ret = db_config_get_log(slog);

       if (ret == DBENG_OK)
          printf("log is '%s'\n", slog);

       return(ret);
    }

    int c_config_get_session(void)
    {
       /* Get the current path/file for the system session
          table. Note that the session table is only used
          in multiuser mode. Syntax:

             config.get.session

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

    #ifdef MULTIUSER
       char ses_table[DBENG_PATH_LIMIT];
       int ret;

       ret = db_config_get_session(ses_table);

       if (ret == DBENG_OK)
          printf("system session table is '%s'\n", ses_table);

       return(ret);
    #else
       printf("session table is only active in multiuser mode\n");
       return(DBENG_OK);
    #endif
    }

    int c_config_get_catalog(void)
    {
       /* Get the current path/file for the system catalog.
          Syntax:

             config.get.catalog

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char cat[DBENG_PATH_LIMIT];
       int ret;

       ret = db_config_get_catalog(cat);

       if (ret == DBENG_OK)
          printf("catalog is '%s'\n", cat);

       return(ret);
    }

    int c_config_get_log_flag(void)
    {
       /* Get the log flag. Syntax:

             config.get.log.flag

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char flag_ch[4];
       int flag;
       int ret;

       ret = db_config_get_log_flag(&flag);

       if (ret == DBENG_OK)
          if (flag_2_logic_string(flag, flag_ch))
             printf("logging is %s\n", flag_ch);

       return(ret);
    }

    int c_config_get_session_flag(void)
    {
       /* Get the engine session table flag. Syntax:

             config.get.session.flag

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char flag_ch[4];
       int flag;
       int ret;

       ret = db_config_get_session_flag(&flag);

       if (ret == DBENG_OK)
          if (flag_2_logic_string(flag, flag_ch))
             printf("session table is %s\n", flag_ch);

       return(ret);
    }

    int c_config_get_catalog_flag(void)
    {
       /* Get the engine catalog flag. Syntax:

             config.get.catalog.flag

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char flag_ch[4];
       int flag;
       int ret;

       ret = db_config_get_catalog_flag(&flag);

       if (ret == DBENG_OK)
          if (flag_2_logic_string(flag, flag_ch))
             printf("catalog is %s\n", flag_ch);

       return(ret);
    }

    int c_config_get_replicate_flag(void)
    {
       /* Get the engine replication flag. Syntax:

             config.get.replicate.flag

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char flag_ch[4];
       int flag;
       int ret;

       ret = db_config_get_replicate_flag(&flag);

       if (ret == DBENG_OK)
          if (flag_2_logic_string(flag, flag_ch))
             printf("replication is %s\n", flag_ch);

       return(ret);
    }

    int c_config_get_version(void)
    {
       /* Get the current 'dbeng' version ID string.
          Syntax:

             config.get.version

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char ver[128];
       int ret;

       ret = db_config_get_version(ver);

       if (ret == DBENG_OK)
          printf("current 'Bbuuzzb' database engine version is %s\n", ver);

       return(ret);
    }

    int c_version(void)
    {
       /* Get the current client and server (if in multiuser mode)
          version string.
          Syntax:

             version

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       char ver[128];
       int ret;

       printf("current client version is %s\n", VERSION);

    #ifdef MULTIUSER
       ret = db_version(ver);

       if (ret == DBENG_OK)
          printf("current 'Bbuuzzb' server version is %s\n", ver);
    #else
       ret = DBENG_OK;
    #endif

       return(ret);
    }

    int c_config_set_tmp_path(char *comm)
    {
       /* Set the current path for temporary files.
          Syntax:

             config.set.tmp.path tmp_path

          Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *path;
       int len;
       int ret;

       if (command_words(comm) < 2)
          {
          printf("c_config_set_tmp_path:missing path\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((path = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_tmp_path:unable to alloc 'path'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, path, 2);
       ret = db_config_set_tmp_path(path);
       free(path);
       return(ret);
    }

    int c_config_set_log(char *comm)
    {
       /* Set the current log destination.
          Syntax:

             config.set.log log_name

          Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *slog;
       int len;
       int ret;

       if (command_words(comm) < 2)
          {
          printf("c_config_set_log:missing log destination\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((slog = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_log:unable to alloc 'slog'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, slog, 2);
       ret = db_config_set_log(slog);
       free(slog);
       return(ret);
    }

    int c_config_set_session(char *comm)
    {
       /* Set the current system session table path/file.
          Syntax:

             config.set.session session_table

          Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *ses_table;
       int len;
       int ret;

       if (command_words(comm) < 2)
          {
          printf("c_config_set_session_table:missing path/file\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((ses_table = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_session_table:unable to alloc 'ses_table'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, ses_table, 2);
       ret = db_config_set_session(ses_table);
       free(ses_table);
       return(ret);
    }

    int c_config_set_catalog(char *comm)
    {
       /* Set the current catalog path/file.
          Syntax:

             config.set.catalog catalog

          Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *cat;
       int len;
       int ret;

       if (command_words(comm) < 2)
          {
          printf("c_config_set_catalog:missing path/file\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((cat = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_catalog:unable to alloc 'cat'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, cat, 2);
       ret = db_config_set_catalog(cat);
       free(cat);
       return(ret);
    }

    int c_config_set_log_flag(char *comm)
    {
       /* Set the current log flag.
          Syntax:

             config.set.log.flag flag

          The function 'logic_string_2_flag' is used to validate
          'flag' so value of 'flag' must be acceptable to the
          function. Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *flag_char;
       int len, flag;
       int ret;

       /* must be at least two words on command line */

       if (words(comm) < 2)
          {
          printf("c_config_set_log_flag:missing flag\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((flag_char = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_log_flag:unable to alloc 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 2);

       /* validate input flag */

       if (!logic_string_2_flag(flag_char, &flag))
          {
          printf("c_config_set_log_flag:flag is invalid\n");
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_config_set_log_flag(flag);
       return(ret);
    }

    int c_config_set_session_flag(char *comm)
    {
       /* Set the current session flag.
          Syntax:

             config.set.session.flag flag

          The function 'logic_string_2_flag' is used to validate
          'flag' so value of 'flag' must be acceptable to the
          function. Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *flag_char;
       int len, flag;
       int ret;

       /* must be at least two words on command line */

       if (words(comm) < 2)
          {
          printf("c_config_set_session_flag:missing flag\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((flag_char = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_session_flag:unable to alloc 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 2);

       /* validate input flag */

       if (!logic_string_2_flag(flag_char, &flag))
          {
          printf("c_config_set_session_flag:flag is invalid\n");
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_config_set_session_flag(flag);
       return(ret);
    }

    int c_config_set_catalog_flag(char *comm)
    {
       /* Set the current catalog flag.
          Syntax:

             config.set.catalog.flag flag

          The function 'logic_string_2_flag' is used to validate
          'flag' so value of 'flag' must be acceptable to the
          function. Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *flag_char;
       int len, flag;
       int ret;

       /* must be at least two words on command line */

       if (words(comm) < 2)
          {
          printf("c_config_set_catalog_flag:missing flag\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((flag_char = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_catalog_flag:unable to alloc 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 2);

       /* validate input flag */

       if (!logic_string_2_flag(flag_char, &flag))
          {
          printf("c_config_set_catalog_flag:flag is invalid\n");
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_config_set_catalog_flag(flag);
       return(ret);
    }

    int c_config_set_replicate_flag(char *comm)
    {
       /* Set the current replication flag.
          Syntax:

             config.set.replicate.flag flag

         The function 'logic_string_2_flag' is used to validate
          'flag' so value of 'flag' must be acceptable to the
          function. Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

       char *flag_char;
       int len, flag;
       int ret;

       /* must be at least two words on command line */

       if (words(comm) < 2)
          {
          printf("c_config_set_replicate_flag:missing flag\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((flag_char = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_replicate_flag:unable to alloc 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 2);

       /* validate input flag */

       if (!logic_string_2_flag(flag_char, &flag))
          {
          printf("c_config_set_replicate_flag:flag is invalid\n");
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_config_set_replicate_flag(flag);
       return(ret);
    }

    int c_get_open_table_list(char *comm)
    {
       /* Get and display a list of open tables. Function
          returns a 'dbeng' code. Syntax:

             get.open.table.list [pat]

          Where 'pat' is an optional pattern acceptable to
          the 'pmatch' function. The pattern will be matched
          with the physical file name. */

       char *tlist, *anentry, *pat;
       char mname[] = "c_get_open_table_list";
       int ret, nwords, i, is_pat;

       if ((tlist = (char *)malloc(DBENG_MAXRECFIELD)) == NULL)
          {
          printf("%s:alloc fail[tlist]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       nwords = command_words(comm);
       pat = (char *)NULL;

       if (nwords > 1)
          {
          is_pat = TRUE;

          if ((pat = (char *)malloc(strlen(comm) + 1)) == (char *)NULL)
             {
             printf("%s:alloc fail[pat]\n", mname);
             return(DBENG_MEMORY_FAIL);
             }

          (void)command_word(comm, pat, 2);
          }
       else
          is_pat = FALSE;

       if ((ret = db_get_open_table_list(pat, tlist)) != DBENG_OK)
          {
          free(tlist);

          if (is_pat)
             free(pat);

          return(ret);
          }

       if (is_pat)
          free(pat);

       nwords = ll_words(tlist, DBENG_LIST_DELIM);

       if (!nwords)
          {
          printf("%s:list empty\n", mname);
          free(tlist);
          return(ret);
          }

       if ((anentry = initstring(tlist)) == NULL)
          {
          printf("%s:alloc fail[anentry]\n", mname);
          free(tlist);
          return(DBENG_MEMORY_FAIL);
          }

       printf("list of open tables\n");

       for(i = 1; i <= nwords; i++)
          {
          if (!ll_word(tlist, anentry, i, DBENG_LIST_DELIM))
             {
             printf("%s:error getting list entry[%d]\n", mname, i);
             free(tlist);
             free(anentry);
             return(DBENG_INTERNAL_ERROR);
             }

          printf("table[%d]=%s\n", i, anentry);
          }

       free(tlist);
       free(anentry);
       return(DBENG_OK);
    }

    int c_replicate_update(void)
    {
       /* Update all replication details. Applies to TCP IPC
          method only. Syntax:

             replicate.update

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

    #ifdef MULTIUSER
    #ifdef IPC_TCP
       int ret;

       ret = db_replicate_update();
       return(ret);
    #else
       printf("replication applies to TCP IPC method only\n");
       return(DBENG_ACCESS_DENIED);
    #endif
    #else
       printf("replication is only active in multi-user mode\n");
       return(DBENG_OK);
    #endif
    }

    int c_delete_table(char *comm)
    {
       /* Delete a table. The file name (or table name) is expected on the
          command line. Function returns the 'DBENG' status. Syntax:

             delete.table file_name */

       char mname[] = "c_delete_table", *fname;
       int tid;
       int len;
       int ret;

       /* must be at least two words on command line */

       if (command_words(comm) < 2)
          {
          printf("%s:missing file name\n", mname);
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((fname = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'fname'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fname, 2);
       ret = db_delete_table(fname);
       free(fname);
       return(ret);
    }

    int c_exist(char *comm)
    {
       /* Test for the existance of a table. Function returns the
          'DBENG' status. Syntax:

             exist tname */

       char mname[] = "c_exist", *fname;
       int tid, exist_flag;
       int len;
       int ret;

       /* must be at least two words on command line */

       if (command_words(comm) < 2)
          {
          printf("%s:missing file name\n", mname);
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((fname = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'fname'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fname, 2);
       ret = db_exist(fname, &exist_flag);
       free(fname);

       if (ret == DBENG_OK)
          if (exist_flag)
             printf("%s:table does exist\n", mname);
          else
             printf("%s:table does not exist\n", mname);

       return(ret);
    }

    int c_clear_table(char *comm)
    {
       /* Clear a table of all records. Function returns the
          'DBENG' status. Syntax:

             clear.table tname */

       char mname[] = "c_clear_table", *fname;
       int tid;
       int len;
       int ret;

       /* must be at least two words on command line */

       if (command_words(comm) < 2)
          {
          printf("%s:missing file name\n", mname);
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((fname = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'fname'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fname, 2);
       ret = db_clear_table(fname);
       free(fname);
       return(ret);
    }

    int c_copy_table(char *comm)
    {
       /* Copy a table from source to destination. Both tables are
          expected to be open. Syntax:

             copy.table source_tid destination_tid */

       char mname[] = "c_copy_table", *src_tid_char, *dest_tid_char;
       int nwords, src_tid, dest_tid;
       int len;
       int ret;

       nwords = words(comm);

       /* must be at least three words on command line */

       if (nwords < 2)
          {
          printf("%s:missing source table tid\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 3)
          {
          printf("%s:missing destination table tid\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((src_tid_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          printf("%s:alloc fail[src_tid_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, src_tid_char, 2);

       if (!qatoi(src_tid_char, &src_tid))
          {
          printf("%s:non numeric source table tid\n", mname);
          free(src_tid_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(src_tid_char);

       if ((dest_tid_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          printf("%s:alloc fail[dest_tid_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, dest_tid_char, 3);

       if (!qatoi(dest_tid_char, &dest_tid))
          {
          printf("%s:non numeric destination table tid\n", mname);
          free(dest_tid_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(dest_tid_char);
       ret = db_copy_table(src_tid, dest_tid);
       return(ret);
    }

    int c_get_catalog_list(char *comm)
    {
       /* Get and display a list of catalog entires. Function
          returns a 'dbeng' code. Syntax:

             get.catalog.list [pat]

          Where 'pat' is an optional pattern acceptable to
          the 'pmatch' function. The pattern will be matched
          with the logical table name. */

       char *tlist, *anentry, *pat;
       char mname[] = "c_get_catalog_list";
       int ret, nwords, i, is_pat;

       if ((tlist = (char *)malloc(DBENG_MAXRECFIELD)) == NULL)
          {
          printf("%s:alloc fail[tlist]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       nwords = command_words(comm);
       pat = (char *)NULL;

       if (nwords > 1)
          {
          is_pat = TRUE;

          if ((pat = (char *)malloc(strlen(comm) + 1)) == (char *)NULL)
             {
             printf("%s:alloc fail[pat]\n", mname);
             return(DBENG_MEMORY_FAIL);
             }

          (void)command_word(comm, pat, 2);
          }
       else
          is_pat = FALSE;

       if ((ret = db_get_catalog_list(pat, tlist)) != DBENG_OK)
          {
          free(tlist);

          if (is_pat)
             free(pat);

          return(ret);
          }

       if (is_pat)
          free(pat);

       nwords = ll_words(tlist, DBENG_LIST_DELIM);

       if (!nwords)
          {
          printf("%s:list empty\n", mname);
          free(tlist);
          return(ret);
          }

       if ((anentry = initstring(tlist)) == NULL)
          {
          printf("%s:alloc fail[anentry]\n", mname);
          free(tlist);
          return(DBENG_MEMORY_FAIL);
          }

       printf("list of catalog entries\n");

       for(i = 1; i <= nwords; i++)
          {
          if (!ll_word(tlist, anentry, i, DBENG_LIST_DELIM))
             {
             printf("%s:error getting list entry[%d]\n", mname, i);
             free(tlist);
             free(anentry);
             return(DBENG_INTERNAL_ERROR);
             }

          printf("table[%d]=%s\n", i, anentry);
          }

       free(tlist);
       free(anentry);
       return(DBENG_OK);
    }

    int c_sort(char *comm)
    {
       /* Sort a table. Syntax:

             sort tid specs */

       char mname[] = "c_sort", *tid_char, *specs;
       int nwords, tid;
       int len;
       int ret;

       nwords = words(comm);

       /* must be at least three words on command line */

       if (nwords < 2)
          {
          printf("%s:missing table tid\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 3)
          {
          printf("%s:missing sort specification(s)\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = (char *)malloc(len + 1)) == (char *)NULL)
          {
          printf("%s:alloc fail[tid_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric table tid\n", mname);
          free(tid_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(tid_char);

       if ((specs = (char *)malloc(len + 1)) == (char *)NULL)
          {
          printf("%s:alloc fail[specs]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, specs, 3);
       ret = db_sort(tid, specs);
       free(specs);
       return(ret);
    }

    int c_get_sort_mem(char *comm)
    {
       /* Get the current allowable max sort memory. Function returns
          the 'DBENG' status. The amount is displayed on the screen
          upon success. Syntax:

             get.sort.mem tid */

       char mname[] = "c_get_sort_mem";
       char *tid_char;
       long mem;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_sort_max_mem(tid, &mem);

       if (ret == DBENG_OK)
          printf("%s:allowable sort memory is %ld bytes\n", mname, mem);

       return(ret);
    }

    int c_set_sort_mem(char *comm)
    {
       /* Set the allowable sort memory. Function returns the 'DBENG' status.
          Syntax:

             set.sort.mem tid mem */

       char mname[] = "c_set_sort_mem";
       char *tid_char;
       char *mem_char;
       long mem;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing sort memory\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((mem_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'mem_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, mem_char, 3);

       if (!qatol(mem_char, &mem))
          {
          printf("%s:non numeric memory amount\n", mname);
          free(mem_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (mem < 0L)
          {
          printf("%s:invalid amount of memory\n", mname);
          free(mem_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(mem_char);
       ret = db_set_sort_max_mem(tid, mem);
       return(ret);
    }

    int c_get_sort_open_bin(char *comm)
    {
       /* Get the current allowable sort open bin tables. Function returns
          the 'DBENG' status. The amount is displayed on the screen
          upon success. Syntax:

             get.sort.open.bin tid */

       char mname[] = "c_get_sort_open_bin";
       char *tid_char;
       int open_bin;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_sort_max_open_bin(tid, &open_bin);

       if (ret == DBENG_OK)
          printf("%s:allowable sort open bin tables is %d\n", mname, open_bin);

       return(ret);
    }

    int c_set_sort_open_bin(char *comm)
    {
       /* Set the allowable number of sort open bin tables. Function returns
          the 'DBENG' status. Syntax:

             set.sort.open.bin tid open_bin */

       char mname[] = "c_set_sort_open_bin";
       char *tid_char;
       char *open_bin_char;
       int open_bin;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing sort open bin\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((open_bin_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail 'open_bin_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, open_bin_char, 3);

       if (!qatoi(open_bin_char, &open_bin))
          {
          printf("%s:non numeric number of bin tables\n", mname);
          free(open_bin_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (open_bin <= 0)
          {
          printf("%s:invalid number of open bin tables\n", mname);
          free(open_bin_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(open_bin_char);
       ret = db_set_sort_max_open_bin(tid, open_bin);
       return(ret);
    }

    int c_delete_field(char *comm)
    {
       /* Delete a field from the current record. Function returns
          the 'DBENG' status. Syntax:

             delete.field tid fnum */

       char mname[] = "c_delete_field";
       char *tid_char;
       char *fnum_char;
       int fnum;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((fnum_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[fnum_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fnum_char, 3);

       if (!qatoi(fnum_char, &fnum))
          {
          printf("%s:non numeric field number\n", mname);
          free(fnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fnum <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(fnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(fnum_char);
       ret = db_delete_field(tid, fnum);
       return(ret);
    }

    int c_delete_subfield(char *comm)
    {
       /* Delete a subfield from the current record. Function returns
          the 'DBENG' status. Syntax:

             delete.subfield tid fnum sfnum */

       char mname[] = "c_delete_subfield";
       char *tid_char, *fnum_char, *sfnum_char;
       int fnum, sfnum, nwords, tid, len, ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((fnum_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[fnum_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fnum_char, 3);

       if (!qatoi(fnum_char, &fnum))
          {
          printf("%s:non numeric field number\n", mname);
          free(fnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fnum <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(fnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(fnum_char);

       if ((sfnum_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[sfnum_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, sfnum_char, 4);

       if (!qatoi(sfnum_char, &sfnum))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(sfnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sfnum <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(sfnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(sfnum_char);
       ret = db_delete_subfield(tid, fnum, sfnum);
       return(ret);
    }

    int c_delete_subsubfield(char *comm)
    {
       /* Delete a subsubfield from the current record. Function returns
          the 'DBENG' status. Syntax:

             delete.subsubfield tid fnum sfnum ssfnum */

       char mname[] = "c_delete_subsubfield";
       char *tid_char, *fnum_char, *sfnum_char, *ssfnum_char;
       int fnum, sfnum, ssfnum, nwords, tid, len, ret;

       nwords = command_words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing field number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 4)
          {
          printf("%s:missing subfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       if (nwords < 5)
          {
          printf("%s:missing subsubfield number\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((fnum_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[fnum_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, fnum_char, 3);

       if (!qatoi(fnum_char, &fnum))
          {
          printf("%s:non numeric field number\n", mname);
          free(fnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fnum <= 0)
          {
          printf("%s:invalid field number\n", mname);
          free(fnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(fnum_char);

       if ((sfnum_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[sfnum_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, sfnum_char, 4);

       if (!qatoi(sfnum_char, &sfnum))
          {
          printf("%s:non numeric subfield number\n", mname);
          free(sfnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sfnum <= 0)
          {
          printf("%s:invalid subfield number\n", mname);
          free(sfnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(sfnum_char);

       if ((ssfnum_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[ssfnum_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, ssfnum_char, 5);

       if (!qatoi(ssfnum_char, &ssfnum))
          {
          printf("%s:non numeric subsubfield number\n", mname);
          free(ssfnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (ssfnum <= 0)
          {
          printf("%s:invalid subsubfield number\n", mname);
          free(ssfnum_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(ssfnum_char);
       ret = db_delete_subsubfield(tid, fnum, sfnum, ssfnum);
       return(ret);
    }

    int c_trans_num(void)
    {
       /* Get the server current transaction count. Syntax:

             trans.num

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       int ret;

    #ifdef MULTIUSER
       long trans_num;

       ret = db_trans_num(&trans_num);

       if (ret == DBENG_OK)
          printf("server transaction count is %ld\n", trans_num);
    #else
       printf("transaction count is active only in multiuser mode\n");
       ret = DBENG_FUNCTION_NOT_IMPLEMENTED;
    #endif

       return(ret);
    }

    int c_connect_num(void)
    {
       /* Get the server current connection count. Syntax:

             connect.num

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

       int ret;

    #ifdef MULTIUSER
       int connect_num;

       ret = db_connect_num(&connect_num);

       if (ret == DBENG_OK)
          printf("server connection count is %d\n", connect_num);
    #else
       printf("connection count is active only in multiuser mode\n");
       ret = DBENG_FUNCTION_NOT_IMPLEMENTED;
    #endif

       return(ret);
    }

    int c_get_autopack(char *comm)
    {
       /* Get the current value of 'autopack'. Function returns
          the 'DBENG' status. The value is displayed on the screen
          upon success. Syntax:

             get.autopack tid */

       char mname[] = "c_get_autopack";
       char *tid_char;
       int pval;
       int tid;
       int len;
       int ret;

       if (words(comm) < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);
       ret = db_get_autopack(tid, &pval);

       if (ret == DBENG_OK)
          printf("%s:autopack threshold is %d\n", mname, pval);

       return(ret);
    }

    int c_set_autopack(char *comm)
    {
       /* Set the current tables' 'autopack' value. Function returns
          the 'DBENG' status.
          Syntax:

             set.autopack tid autopack_value */

       char mname[] = "c_set_autopack";
       char *tid_char;
       char *pval_char;
       int pval;
       int nwords;
       int tid;
       int len;
       int ret;

       nwords = words(comm);

       if (nwords < 2)
          {
          printf("%s:missing tid\n", mname);
          return(DBENG_NO_SUCH_TID);
          }

       if (nwords < 3)
          {
          printf("%s:missing autopack value\n", mname);
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((tid_char = malloc(len + 1)) == NULL)
          {
          printf("%s:unable to alloc 'tid_char'\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, tid_char, 2);

       if (!qatoi(tid_char, &tid))
          {
          printf("%s:non numeric tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       if (tid <= 0)
          {
          printf("%s:invalid tid\n", mname);
          free(tid_char);
          return(DBENG_NO_SUCH_TID);
          }

       free(tid_char);

       if ((pval_char = malloc(len + 1)) == NULL)
          {
          printf("%s:alloc fail[pval_char]\n", mname);
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, pval_char, 3);

       if (!qatoi(pval_char, &pval))
          {
          printf("%s:non numeric autopack threshold\n", mname);
          free(pval_char);
          return(DBENG_INVALID_FUNCTION);
          }

       if (pval < 0)
          {
          printf("%s:out of range autopack threshold\n", mname);
          free(pval_char);
          return(DBENG_INVALID_FUNCTION);
          }

       free(pval_char);
       ret = db_set_autopack(tid, pval);
       return(ret);
    }

    int c_config_client_get_log(void)
    {
       /* Display the current client log name.
          Multiuser only. Syntax:

             config.client.get.log

          Function returns 'DBENG_OK' upon success,
          an engine i/o code otherwise. */

    #ifdef MULTIUSER
       int ret;
       char slog[DBENG_PATH_LIMIT];

       ret = db_config_client_get_log(slog);

       if (ret == DBENG_OK)
          if (strlen(slog))
             printf("client log is '%s'\n", slog);
          else
             printf("no client log currently defined\n");

       return(ret);
    #else
       printf("only valid in multiuser mode\n");
       printf("use 'config.get.log' instead\n");
       return(DBENG_INVALID_FUNCTION);
    #endif
    }

    int c_config_client_get_log_flag(void)
    {
       /* Get the client log flag. Multiuser only. Syntax:

             config.client.get.log.flag

          Function returns 'DBENG_OK' upon success, an engine
          i/o code otherwise. */

    #ifdef MULTIUSER
       char flag_ch[4];
       int flag;
       int ret;

       ret = db_config_client_get_log_flag(&flag);

       if (ret == DBENG_OK)
          if (flag_2_logic_string(flag, flag_ch))
             printf("client logging is %s\n", flag_ch);

       return(ret);
    #else
       printf("only valid in multiuser mode\n");
       printf("use 'config.get.log.flag' instead\n");
       return(DBENG_INVALID_FUNCTION);
    #endif
    }

    int c_config_client_set_log(char *comm)
    {
       /* Set the current client log name. Multiuser only.
          Syntax:

             config.client.set.log log_name

          Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

    #ifdef MULTIUSER
       char *slog;
       int len;
       int ret;

       if (command_words(comm) < 2)
          {
          printf("c_config_set_log:missing log name\n");
          return(DBENG_INVALID_FILE_NAME);
          }

       len = strlen(comm);

       if ((slog = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_log:unable to alloc 'slog'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)command_word(comm, slog, 2);
       ret = db_config_client_set_log(slog);
       free(slog);
       return(ret);
    #else
       printf("only valid in multiuser mode\n");
       printf("use 'config.set.log' instead\n");
       return(DBENG_INVALID_FUNCTION);
    #endif
    }

    int c_config_client_set_log_flag(char *comm)
    {
       /* Set the current client log flag. Multiuser only.
          Syntax:

             config.client.set.log.flag flag

          Function returns 'DBENG_OK' upon success, an
          engine i/o code otherwise. */

    #ifdef MULTIUSER
       char *flag_char;
       int len, flag;
       int ret;

       /* must be at least two words on command line */

       if (words(comm) < 2)
          {
          printf("c_config_set_log_flag:missing flag\n");
          return(DBENG_INVALID_FUNCTION);
          }

       len = strlen(comm);

       if ((flag_char = (char *)malloc(len + 1)) == NULL)
          {
          printf("c_config_set_log_flag:unable to alloc 'flag_char'\n");
          return(DBENG_MEMORY_FAIL);
          }

       (void)word(comm, flag_char, 2);

       /* validate input flag */

       if (!logic_string_2_flag(flag_char, &flag))
          {
          printf("c_config_set_log_flag:flag is invalid\n");
          return(DBENG_INVALID_FUNCTION);
          }

       free(flag_char);
       ret = db_config_client_set_log_flag(flag);
       return(ret);
    #else
       printf("only valid in multiuser mode\n");
       printf("use 'config.set.log.flag' instead\n");
       return(DBENG_INVALID_FUNCTION);
    #endif
    }

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

       int i;
       int token = DBCOM_NOT_FOUND;

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

       static char *coms[] = { " ", "OPEN", "CLOSE", "NEXT", "TOP", "GET.REC",
                               "GET.FIELD", "GOTO", "COUNT", "PUT.FIELD", "WRITE",
                               "DELETE", "GET.DELETE.FLAG", "SET.DELETE.FLAG",
                               "GET.NFIELDS", "GET.REC.SIZE", "GET.FIELD.SIZE",
                               "GET.REC.NUM", "GET.POS", "SET.POS",
                               "GET.CHANGE.REC.FLAG", "SET.CHANGE.REC.FLAG",
                               "PACK", "NEW", "FIND", "FIND.FIELD", "FIND.PART",
                               "FIND.FIELD.PART", "GET.REC.COUNT",
                               "GET.ENF.CHANGE.REC.FLAG",
                               "SET.ENF.CHANGE.REC.FLAG",
                               "GET.IS.TABLE.LOCKED", "SET.IS.TABLE.LOCKED",
                               "NEW.TABLE", "CONFIG.GET.TMP.PATH",
                               "CONFIG.GET.LOG", "CONFIG.GET.SESSION",
                               "CONFIG.GET.CATALOG", "CONFIG.GET.LOG.FLAG",
                               "CONFIG.GET.SESSION.FLAG",
                               "CONFIG.GET.CATALOG.FLAG", "CONFIG.GET.VERSION",
                               "CONFIG.SET.TMP.PATH",
                               "CONFIG.SET.LOG", "CONFIG.SET.SESSION",
                               "CONFIG.SET.CATALOG", "CONFIG.SET.LOG.FLAG",
                               "CONFIG.SET.SESSION.FLAG",
                               "CONFIG.SET.CATALOG.FLAG", "VERSION",
                               "GET.OPEN.TABLE.LIST", "GET.NSUBFIELDS",
                               "GET.SUBFIELD.SIZE", "GET.SUBFIELD",
                               "PUT.SUBFIELD", "GET.NSUBSUBFIELDS",
                               "GET.SUBSUBFIELD.SIZE", "GET.SUBSUBFIELD",
                               "PUT.SUBSUBFIELD", "CONFIG.GET.REPLICATE.FLAG",
                               "CONFIG.SET.REPLICATE.FLAG", "REPLICATE.UPDATE",
                               "DELETE.TABLE", "EXIST", "CLEAR.TABLE",
                               "COPY.TABLE", "GET.CATALOG.LIST", "SORT",
                               "GET.SORT.MEM", "SET.SORT.MEM", "GET.SORT.OPEN.BIN",
                               "SET.SORT.OPEN.BIN", "DELETE.FIELD",
                               "DELETE.SUBFIELD", "DELETE.SUBSUBFIELD",
                               "TRANS.NUM", "CONNECT.NUM", "GET.AUTOPACK",
                               "SET.AUTOPACK", "CONFIG.CLIENT.GET.LOG",
                               "CONFIG.CLIENT.GET.LOG.FLAG",
                               "CONFIG.CLIENT.SET.LOG",
                               "CONFIG.CLIENT.SET.LOG.FLAG" };

       /* check for 'OFF' keyword separately */

       if (!stricmp(keywrd, "OFF"))
          return(DBCOM_OFF);

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

       return(token);
    }

    void term_app(void)
    {
       // Prepare to terminate the application. Shutdown all IPC API's.

       db_end();

       if (logman_is_active())
          logman_end();

    #ifdef IPC_TCP
       if (sloc_is_init())
          sloc_term_api();

    #ifdef OS_WIN32
       WSACleanup();
    #endif
    #endif

    #ifndef OS_DOS
       (void)appinit_remove_name();
    #endif
    }

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