]> andersk Git - moira.git/commitdiff
punt mrgdb
authordanw <danw>
Sun, 15 Feb 1998 17:48:29 +0000 (17:48 +0000)
committerdanw <danw>
Sun, 15 Feb 1998 17:48:29 +0000 (17:48 +0000)
94 files changed:
Imakefile
clients/addusr/Imakefile
clients/blanche/Imakefile
clients/mailmaint/Imakefile
clients/moira/Imakefile
clients/mrcheck/Imakefile
clients/mrtest/Imakefile
clients/mrtest/mrtest.c
clients/passwd/Imakefile
clients/userreg/Imakefile
dcm/dcm.pc
gdb/Imakefile [deleted file]
gdb/README [deleted file]
gdb/gdb.c [deleted file]
gdb/gdb.mss [deleted file]
gdb/gdb.prob [deleted file]
gdb/gdb_conn.c [deleted file]
gdb/gdb_db.c [deleted file]
gdb/gdb_debug.c [deleted file]
gdb/gdb_fserv.c [deleted file]
gdb/gdb_lib.h [deleted file]
gdb/gdb_ops.c [deleted file]
gdb/gdb_serv.c [deleted file]
gdb/gdb_struct.c [deleted file]
gdb/gdb_stype.c [deleted file]
gdb/gdb_trans.c [deleted file]
gdb/gdb_trans2.c [deleted file]
gdb/gdb_ugd.mss [deleted file]
gdb/gdb_version [deleted file]
gdb/library.mss [deleted file]
gdb/samp1.c [deleted file]
gdb/samp1a.c [deleted file]
gdb/slides.mss [deleted file]
gdb/tcl.c [deleted file]
gdb/tdbcl.c [deleted file]
gdb/test.c [deleted file]
gdb/tfsr.c [deleted file]
gdb/tsr.c [deleted file]
gdb/tst.c [deleted file]
include/Imakefile
include/gdb.h [deleted file]
include/mr_proto.h [deleted file]
include/update.h
incremental/Imakefile
lib/Imakefile
lib/mr_access.c
lib/mr_auth.c
lib/mr_call.c
lib/mr_connect.c
lib/mr_data.c [deleted file]
lib/mr_init.c
lib/mr_ops.c
lib/mr_param.c [deleted file]
lib/mr_private.h
lib/mr_query.c
man/moira.3
reg_svr/Imakefile
reg_svr/reg_svr.c
server/Imakefile
server/cache.pc
server/increment.pc
server/mr_glue.c
server/mr_main.c
server/mr_sauth.c
server/mr_scall.c
server/mr_server.h
server/mr_shutdown.c
server/mr_srvdata.c [deleted file]
server/mr_util.c
server/qfollow.pc
server/qrtn.pc
server/qsetup.pc
server/qsubs.c
server/queries2.c
server/query.h
server/qvalidate.pc
update/Imakefile
update/auth_002.c
update/checksum.c
update/client.c
update/config.c
update/exec_002.c
update/get_file.c
update/log.c [deleted file]
update/send_file.c
update/sendrecv.c [new file with mode: 0644]
update/smskey.c
update/ticket.c
update/update_server.c
update/update_server.h
update/update_test.c
update/xfer_002.c
update/xfer_003.c
util/imake.includes/config.Imakefile

index e51ea2ee862c8f902142f3d21d4ded6fb24eb1a4..2992db8d399d6a7b1dda99e746f7307bb4a04d2b 100644 (file)
--- a/Imakefile
+++ b/Imakefile
@@ -10,7 +10,7 @@
 
 #define have_subdirs
 CODE=Imakefile
-CLIENTDIRS=util include gdb lib clients man update
+CLIENTDIRS=util include lib clients man update
 SVRDIRS=server db backup dbck dcm gen reg_svr incremental regtape afssync
 #ifdef SVRBUILD
 SUBDIRS=$(CLIENTDIRS) $(SVRDIRS)
index 36b51b28b025594d74fd413ee99fbed9d90bee92..edbcd322e5051de2775c248eb003fd69ac128968 100644 (file)
@@ -13,7 +13,7 @@ SRCDIR=${SRCTOP}/clients/addusr
 CODE=${SRCS} Imakefile
 OBJS=addusr.o reg_stubs.o
 
-program(addusr,${OBJS},${MR_LIBDEP} ${GDB_LIBDEP}, -lkadm ${CLIBS} ${CRYPT},${PROGDIR})
+program(addusr,${OBJS},${MR_LIBDEP}, -lkadm ${CLIBS} ${CRYPT},${PROGDIR})
 
 reg_stubs.c: ../userreg/reg_stubs.c
        cp ../userreg/reg_stubs.c reg_stubs.c
index 7897f2952a3bc96fb0b8505f4299eeb063da06e7..871a7264addfa418139804956a3fcf39efe0d4ad 100644 (file)
@@ -13,4 +13,4 @@ SRCDIR=${SRCTOP}/clients/blanche
 CODE=${SRCS} Imakefile
 OBJS=blanche.o
 
-program(blanche,${OBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${PROGDIR})
+program(blanche,${OBJS},${MR_LIBDEP}, ${CLIBS},${PROGDIR})
index e680d45596c8c90e2ab5eff73a602b27957e470b..97929fcc096d0edcd3faf8d3234b9036d9082681 100644 (file)
@@ -13,4 +13,4 @@ SRCDIR=${SRCTOP}/clients/mailmaint
 CODE=${SRCS} Imakefile
 OBJS=mailmaint.o
 
-program(mailmaint,${OBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS} ${CURSES},${PROGDIR})
+program(mailmaint,${OBJS},${MR_LIBDEP}, ${CLIBS} ${CURSES},${PROGDIR})
index 1ffa5f5a3b4f2ebc1028e1e4cbee914b9d799778..f563725824f8b73bb4c8009b3e49c41170499ade 100644 (file)
@@ -22,8 +22,8 @@ NOBJS=        namespace.o globals.o lists.o menu.o \
 OBJS=  ${MOBJS} ${NOBJS}
 INCLUDE= -I$(BUILDTOP)/include -I$(BUILDTOP)/lib ${GDSSINC} ${COM_ERR_INC} -I/usr/athena/include -I.
 
-program(moira, ${MOBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${LIBGDSS} ${CLIBS} ${CRYPT} ${CURSES},${PROGDIR})
-program(namespace, ${NOBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${LIBGDSS} ${CLIBS} ${CRYPT} ${CURSES},${PROGDIR})
+program(moira, ${MOBJS},${MR_LIBDEP}, ${LIBGDSS} ${CLIBS} ${CRYPT} ${CURSES},${PROGDIR})
+program(namespace, ${NOBJS},${MR_LIBDEP}, ${LIBGDSS} ${CLIBS} ${CRYPT} ${CURSES},${PROGDIR})
 
 install::
        $(RM) $(DESTDIR)$(PROGDIR)/listmaint
index 1f380de918ec15d396f0d23ba9e89c854c191222..c379b1b268904de9e708cb72bf324a1368636306 100644 (file)
@@ -13,4 +13,4 @@ SRCDIR=${SRCTOP}/clients/mrcheck
 CODE=${SRCS} Imakefile
 OBJS=mrcheck.o
 
-program(mrcheck,${OBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${PROGDIR})
+program(mrcheck,${OBJS},${MR_LIBDEP}, ${CLIBS},${PROGDIR})
index 97868ba98616599ca3a284ab63c2b584ac720547..1c9f0de0e7194cbcb1d8a939c03a760ca8342d59 100644 (file)
@@ -14,4 +14,4 @@ CODE=${SRCS} Imakefile
 OBJS=  mrtest.o
 LOCAL_INCLUDES= $(READLINE_INCLUDES)
 
-program(mrtest, ${OBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${READLINE_LIBS} ${CLIBS},${ETCDIR})
+program(mrtest, ${OBJS},${MR_LIBDEP}, ${READLINE_LIBS} ${CLIBS},${ETCDIR})
index 7471b36f61297be079e778cf23982b910259d19a..ccc90aae5d57d15c4cc9a6feaeeda89b00b1ecdf 100644 (file)
@@ -27,7 +27,6 @@
 RCSID("$Header$");
 
 int recursion = 0, interactive;
-extern int sending_version_no;
 int count, quit = 0, cancel = 0;
 char *whoami;
 sigjmp_buf jb;
@@ -43,8 +42,6 @@ void test_noop(void);
 void test_connect(int argc, char **argv);
 void test_disconnect(void);
 void test_host(void);
-void test_new(void);
-void test_old(void);
 void test_motd(void);
 void test_query(int argc, char **argv);
 void test_auth(void);
@@ -142,10 +139,6 @@ void execute_line(char *cmdbuf)
     test_disconnect();
   else if (!strcmp(argv[0], "host"))
     test_host();
-  else if (!strcmp(argv[0], "new") || !strcmp(argv[0], "2"))
-    test_new();
-  else if (!strcmp(argv[0], "old") || !strcmp(argv[0], "1"))
-    test_old();
   else if (!strcmp(argv[0], "motd"))
     test_motd();
   else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
@@ -240,16 +233,6 @@ void test_noop(void)
     com_err("moira (noop)", status, "");
 }
 
-void test_new(void)
-{
-  sending_version_no = MR_VERSION_2;
-}
-
-void test_old(void)
-{
-  sending_version_no = MR_VERSION_1;
-}
-
 void test_connect(int argc, char *argv[])
 {
   char *server = "";
@@ -463,8 +446,6 @@ void test_list_requests(void)
   printf("connect, c\t\tConnect to Moira server\n");
   printf("disconnect, d\t\tDisconnect from server\n");
   printf("host\t\t\tIdentify the server host\n");
-  printf("new, 2\t\t\tUse new protocol\n");
-  printf("old, 1\t\t\tUse old protocol\n");
   printf("motd, m\t\t\tGet the Message of the Day\n");
   printf("query, qy\t\tMake a query.\n");
   printf("auth, a\t\t\tAuthenticate to Moira.\n");
index 7ae3ba2b7fe16068333a5a4f3ca43f5fe7b42447..a3047ff958206cb7ec564188285d12eada95ad29 100644 (file)
@@ -13,6 +13,6 @@ SRCDIR=${SRCTOP}/clients/passwd
 CODE=${SRCS} Imakefile
 OBJS=chfn.o chpobox.o chsh.o
 
-program(chfn, chfn.o,${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${PROGDIR})
-program(chpobox, chpobox.o,${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${PROGDIR})
-program(chsh, chsh.o,${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${PROGDIR})
+program(chfn, chfn.o,${MR_LIBDEP}, ${CLIBS},${PROGDIR})
+program(chpobox, chpobox.o,${MR_LIBDEP}, ${CLIBS},${PROGDIR})
+program(chsh, chsh.o,${MR_LIBDEP}, ${CLIBS},${PROGDIR})
index 2556fb8c630143becb28f19c3db72b9d521b2baf..1de5f3991f48104fe6f1dff356087c0500d063a0 100644 (file)
@@ -16,6 +16,6 @@ SCRIPTS= register xregister
 CODE=${SRCS} ${TEXT} ${SCRIPTS} Imakefile files.h userreg.h
 OBJS=  userreg.o display.o reg_stubs.o disable.o
 
-program(userreg, ${OBJS},${MR_LIBDEP} ${GDB_LIBDEP}, -lkadm ${CLIBS} ${CRYPT} ${CURSES},${PROGDIR})
+program(userreg, ${OBJS},${MR_LIBDEP}, -lkadm ${CLIBS} ${CRYPT} ${CURSES},${PROGDIR})
 
 depend:: ${CODE}
index 62fcdb0346963194a20c49cbc4cb374a083d669b..d4c0bf5713b5fc30773c1813ae547f0d07b1ab6f 100644 (file)
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#include <errno.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include <gdb.h>
-
 EXEC SQL INCLUDE sqlca;
 void sqlglm(char *, unsigned int *, unsigned int *);
 
@@ -41,7 +40,6 @@ EXEC SQL WHENEVER SQLERROR DO dbmserr();
 #define SOFT_FAIL(x) (((x) == MR_NO_MEM) || ((x) == MR_CANT_CONNECT) || ((x) == MR_CCONFIG) || ((x) == MR_DEADLOCK) || ((x) == MR_BUSY) || ((x) == MR_ABORT))
 
 char whobuf[256], *whoami = whobuf, *db = "moira";
-extern CONNECTION conn;
 
 int main(int argc, char **argv)
 {
@@ -240,7 +238,7 @@ void do_hosts(char *service)
   EXEC SQL END DECLARE SECTION;
 
   time(&now);
-  gdb_init();
+  mr_init();
 
   EXEC SQL CONNECT :db IDENTIFIED BY :db;
 
@@ -345,18 +343,17 @@ void do_hosts(char *service)
 
 int dcm_send_file(char *service, char *host, char *target)
 {
-  char addr[256], data[MAXPATHLEN];
-  int code;
+  char data[MAXPATHLEN];
+  int code, conn;
 
-  sprintf(addr, "%s:moira_update", host);
-  conn = start_server_connection(addr, "");
-  if (!conn || (connection_status(conn) == CON_STOPPED))
+  conn = mr_connect_internal(host, "moira_update");
+  if (!conn)
     {
-      com_err(whoami, connection_errno(conn), "can't connect to %s", addr);
+      com_err(whoami, errno, "can't connect to %s", host);
       return MR_CANT_CONNECT;
     }
 
-  code = send_auth(host);
+  code = send_auth(conn, host);
   if (code)
     {
       com_err(whoami, code, "authenticating to %s", host);
@@ -364,32 +361,29 @@ int dcm_send_file(char *service, char *host, char *target)
     }
 
   sprintf(data, "%s/%s.out", DCM_DIR, service);
-  code = send_file(data, target, 1);
-  if (code == MR_UNKNOWN_PROC)
-    code = send_file(data, target, 0);
+  code = send_file(conn, data, target, 0);
   if (code)
     com_err(whoami, code, "sending data to %s", host);
 
 done:
-  send_quit();
-  sever_connection(conn);
+  send_quit(conn);
+  close(conn);
   return code;
 }
 
 int dcm_execute(char *service, char *host, char *script)
 {
-  char addr[256], inst[MAXPATHLEN];
-  int code;
+  char inst[MAXPATHLEN];
+  int code, conn;
 
-  sprintf(addr, "%s:moira_update", host);
-  conn = start_server_connection(addr, "");
-  if (!conn || (connection_status(conn) == CON_STOPPED))
+  conn = mr_connect_internal(host, "moira_update");
+  if (!conn)
     {
-      com_err(whoami, connection_errno(conn), "can't connect to %s", addr);
+      com_err(whoami, errno, "can't connect to %s", host);
       return MR_CANT_CONNECT;
     }
 
-  code = send_auth(host);
+  code = send_auth(conn, host);
   if (code)
     {
       com_err(whoami, code, "authenticating to %s", host);
@@ -398,20 +392,20 @@ int dcm_execute(char *service, char *host, char *script)
 
   sprintf(inst, "/tmp/moira-update.XXXXXX");
   mktemp(inst);
-  code = send_file(script, inst, 0);
+  code = send_file(conn, script, inst, 0);
   if (code)
     {
       com_err(whoami, code, "sending instructions to %s", host);
       goto done;
     }
 
-  code = execute(inst);
+  code = execute(conn, inst);
   if (code)
     com_err(whoami, code, "executing instructions on %s", host);
 
 done:
-  send_quit();
-  sever_connection(conn);
+  send_quit(conn);
+  close(conn);
   return code;
 }
 
diff --git a/gdb/Imakefile b/gdb/Imakefile
deleted file mode 100644 (file)
index f861874..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# $Header$
-#
-# Copyright 1990 by the Massachusetts Institute of Technology.
-#
-# For copying and distribution information,
-# please see the file <mit-copyright.h>.
-#
-# Imakefile for GDB library.
-#
-
-SRCS = gdb_struct.c gdb_stype.c gdb.c gdb_trans.c gdb_trans2.c \
-       gdb_conn.c gdb_serv.c gdb_fserv.c gdb_db.c gdb_debug.c gdb_ops.c
-
-OBJECTS        = gdb.o gdb_struct.o gdb_stype.o gdb_trans.o gdb_trans2.o \
-       gdb_conn.o gdb_ops.o gdb_serv.o gdb_fserv.o gdb_db.o gdb_debug.o
-
-SRCDIR=$(SRCTOP)/gdb
-CODE=$(SRCS) Imakefile gdb_lib.h
-
-all::
-
-depend:: ${CODE}
-
-library_obj_rule()
-install_library_target(mrgdb,$(OBJECTS),$(SRCS))
diff --git a/gdb/README b/gdb/README
deleted file mode 100644 (file)
index 82f8dfb..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/************************************************************************/
-/*     
-/*                     Instructions for Installing GDB
-/*     
-/*                         Noah Mendelsohn
-/*                          April 22, 1987
-/*     
-/*     Copyright (C) 1987 Massachusetts Institute of Technology
-/*     
-/*                     =========================
-/*     
-/*     NOTE:  GDB is not currently a supported service of Project Athena
-/*     or of any other MIT organization.  It is a set of programs which
-/*     I have written while working for Project Athena and which I
-/*     am making available to the MIT community in the hope that they
-/*     will prove useful.  The decision as to whether GDB will become
-/*     supported is not mine to make.   If you wish to express an opinion,
-/*     you should write a note including the following people on the
-/*     distibution:
-/*     
-/*             Prof. Steve Lerman    (lerman@athena.mit.edu)
-/*             Prof. Jerry Saltzer   (Saltzer@athena.mit.edu)
-/*             Dan Geer              (geer@athena.mit.edu)
-/*             Noah Mendelsohn       (noah@athena.mit.edu)
-/*     
-/*     Thank you!
-/*     
-/*     This file is named: README
-/*     
-/************************************************************************/
-
-
-/************************************************************************/
-/*     
-/*                     Obtaining GDB
-/*     
-/************************************************************************/
-
-
-GDB is now available to the MIT community by anonymous ftp 
-from meathead.mit.edu.  There are currently two files:
-
-       1) README    (this file)
-
-       2) tar.file.Z  (compressed tar.file containing all of gdb)
-
-To install gdb, make a directory on your own system.  It can
-have any name, but we'll use gdb in this example:
-
-       % mkdir gdb
-       % cd gdb
-       % ftp meathead.mit.edu
-       ===>login as anonymous and give your user i.d. as passwd
-       ftp> cd gdb
-       ftp> get README
-       ftp> bin                       <= make sure transfer of tar.file.Z
-                                         is done in binary mode, or the
-                                         uncompress step below may fail
-       ftp> get tar.file.Z
-       ftp> quit
-
-       % uncompress tar.file.Z        <== this re-creates tar.file
-                                          If this step fails, you may have
-                                          forgotten to transfer the file
-                                          in binary mode (see above.)
-       % tar xf tar.file              <== this extracts all the gdb
-                                          files from the tar file
-
-/************************************************************************/
-/*     
-/*     Making the gdb libraries
-/*     
-/************************************************************************/
-
-To build the GDB library:
-
-       % make libgdb.a
-
-/************************************************************************/
-/*     
-/*     Formatting documentation
-/*     
-/************************************************************************/
-
-To format the gdb documents, you need scribe and access to a PostScript
-printer.  To make the user guide:
-
-       % make gdb_ugd.PS
-       % rm gdb_ugd.PS
-       % make gdb_ugd.PS
-
-The reason you do it twice is that scribe requires two tries at a document 
-in order to get the forward references to page numbers right.  The resulting
-gdb_ugd.PS file may be sent to your PostScript printer:
-
-       % lpr gdb_ugd.PS
-
-To format the library reference manual:
-
-       % make library.PS
-       % rm library.PS
-       % make library.PS
-
-/************************************************************************/
-/*     
-/*                     Writing and running programs
-/*     
-/************************************************************************/
-
-The user guide tells you how to do this.  Note that gdb.h winds up in
-the gdb directory (where the tar.file is) when you use these installation
-instructions, and so does libgdb.a.  You will have to use the appropriate
-Unix incantations, i.e. making links or telling cc and ld where to find 
-things in order for your compilations and loads to work.  Make sure you
-specify libgdb.a as one of the files to load along with your program.
-
-/************************************************************************/
-/*     
-/*                     Building the database server
-/*     
-/************************************************************************/
-
-The database server program is named dbserv.  To build it:
-
-       % make dbserv
-
-This MUST be done on a machine where RTI Ingres is installed.  You may
-have to edit the makefile if /rtingres is not the directory where Ingres
-lives, and you may have to put /rtingres/bin in your path before doing the 
-make.
-
-/************************************************************************/
-/*     
-/*                             Sample programs
-/*     
-/************************************************************************/
-
-Various test programs are included in the tar.file.  These are not intended
-primarily for users, they are used for my private testing, but a few of
-them are well commented and many of them work.  The ones whose names begin
-with the letter 't' are most likely to be useful.  Each of them can be
-built with 'make'.
-
-/************************************************************************/
-/*     
-/*                               Debugging
-/*     
-/************************************************************************/
-
-Both the dbx and the Saber C debuggers have successfully executed many 
-GDB applications.  I have found Saber to be particularly useful, and I
-have included a .saberinit file which should serve as a starting point
-for you.  (Warning:  .saberinit is supplied as a courtesy and I don't
-guarantee to check it out with every re-release.  If you know enough
-to use Saber, you can probably make any minor corrections which may
-be needed without too much trouble.)  Note that both debuggers have trouble
-on programs that fork.  See the gdb_debug routine and the GDB_NOFORK flag
-for a useful trick to avoid forking when debugging.
-
-/************************************************************************/
-/*     
-/*                             Mailing lists
-/*     
-/************************************************************************/
-
-gdb-users@athena.mit.edu       reaches all users of GDB bugs and fixes 
-                               are advertised here
-gdb-news@athena.mit.edu                announcements of interest to a wider
-                               community of people who may not want to 
-                               know about every 2 line change to the system
-
-noah@athena.mit.edu            the author
-
-
-
diff --git a/gdb/gdb.c b/gdb/gdb.c
deleted file mode 100644 (file)
index 27c62b2..0000000
--- a/gdb/gdb.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_c = "$Header$";
-#endif
-
-
-/************************************************************************/
-/*     
-/*                             gdb.c
-/*     
-/*     Global Database Library - main controlling functions and globally
-/*                               shared routines.
-/*     
-/*     Author: Noah Mendelsohn
-/*     
-/*     Copyright:  1986 MIT Project Athena
-/*     
-/*     
-/*     In addition to defining the main routines for gdb, this source
-/*     file #includes gdb_lib.h, which does the external definitions
-/*     for all global data used by the library.  Everyone else gets
-/*     externs for this data defined by gdb.h.
-/*     
-/************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h> 
-#include <pwd.h>
-#include "gdb.h"
-#include "gdb_lib.h"
-#include <errno.h>
-#ifdef POSIX
-#include <sys/utsname.h>
-#include <unistd.h>
-#endif
-
-#ifndef __NetBSD__
-extern int sys_nerr;
-extern char *sys_errlist[];
-#endif
-
-extern int errno;
-
-/* This global is defined to make sure that Moira clients are linked
- * against the correct library.
- */
-int link_against_the_moira_version_of_gdb = 0;
-int g_inited = FALSE;                          /* gdb_init has not been */
-                                               /* called */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                     gdb_init
-       /*      
-       /*      Initialize the global database facility.  Must be
-       /*      called before any of the other gdb functions
-       /*      are used.  Among other things, this function 
-       /*      sets to ignore signals for writing on broken pipes.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-gdb_init()
-{
-       register int i;
-       char hostname[255];                     /* name of local host */
-       int uid;                                /* Unix user-i.d. number */
-       char *username;                         /* string form of i.d. */
-
-       struct passwd *pw_struct;               /* passwd entry comes back */
-                                               /* here */
-#ifdef POSIX
-       struct utsname nameposix;
-       struct sigaction act;
-
-       sigemptyset(&act.sa_mask);
-       act.sa_flags = 0;
-#endif
-
-       /*
-        * So we know we've been initialized, and we do it only once
-        */
-       if (g_inited)
-               return 0;
-       g_inited = TRUE;
-
-       /*
-        * Initialize the system defined types table
-        */
-       gdb_i_stype();
-
-       /*
-        * Initialize the connection control data structures.
-        */
-       gdb_mcons = 0;                          /* number of connections */
-                                               /* in use so far */
-       for (i=0; i<GDB_MAX_CONNECTIONS; i++) {
-               gdb_cons[i].id = GDB_CON_ID;
-               gdb_cons[i].in.stream_buffer = NULL;
-               gdb_cons[i].in.stream_buffer_length = GDB_STREAM_BUFFER_SIZE;
-       }
-       /*
-        * Initialize the fd maps
-        */
-       gdb_mfd = 0;
-
-       FD_ZERO(&gdb_crfds);
-       FD_ZERO(&gdb_cwfds);
-       FD_ZERO(&gdb_cefds);
-
-       /*
-        * Initialize the server/client layer
-        */
-       gdb_i_srv();
-
-       /*
-        * Ignore the signal generated when writing to a pipe which has been
-        * closed at the other end.  gdb_move_data handles this condition
-        * synchronously.
-        */
-#ifdef POSIX
-       act.sa_handler = (void(*)()) SIG_IGN;
-       (void) sigaction(SIGPIPE, &act, NULL);
-#else
-       (void) signal(SIGPIPE, SIG_IGN);
-#endif
-
-       /*
-        * Make a note of the local host and user name
-        */
-#ifdef POSIX
-       (void) uname(&nameposix);
-       strncpy(hostname, nameposix.nodename, sizeof(hostname) - 1);
-#else
-       if (gethostname(hostname, sizeof(hostname)-1)!=0)
-               (void) strcpy(hostname, "????");
-#endif
-       gdb_host = db_alloc(strlen(hostname)+1);
-       (void) strcpy(gdb_host, hostname);
-
-       uid = getuid();
-
-       pw_struct = getpwuid(uid);
-
-       if (pw_struct != NULL && pw_struct ->pw_name != NULL &&
-           *pw_struct->pw_name !='\0') 
-               username = pw_struct->pw_name;
-       else
-               username = "????";
-       gdb_uname = db_alloc(strlen(username)+1);
-       (void) strcpy(gdb_uname, username);     
-       
-       return 0;
-}
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_chk_init
-       /*      
-       /*      Make sure gdb has been initialized, blow up if not.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_chk_init()
-{
-       if (!g_inited)
-               GDB_GIVEUP("You must call gdb_init before using GDB services.")
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_bitcount
-       /*      
-       /*      Count the number of bits in a word.  Adapted from 
-       /*      K&R.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_bitcount(inp)
-unsigned int inp;
-{
-       register unsigned int x = inp;          /* the word to check */
-       register int count;                     /* the count to return */
-
-       for (count=0; x !=0; x=x>>1)
-               if (x & 01)
-                       count++;
-
-       return count;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_fstring
-       /*      
-       /*      Utility routine to conditionally free a null
-       /*      terminated string.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-gdb_fstring(str)
-char *str;
-{
-       if (str != NULL)
-               db_free(str, strlen(str)+1);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_givup
-       /*      
-       /*      Called when a fatal error occurs.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_givup(errormsg)
-char *errormsg;
-{
-       fprintf(gdb_log,"\n\nFATAL GDB ERROR:\n\n\t");
-       fprintf(gdb_log,errormsg);
-       fprintf(gdb_log,"\n\n");
-       exit(100);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      connection_perror
-       /*      
-       /*      Acts like gdb_perror, but takes its errno from 
-       /*      the connection.  Resets errno as a side effect.
-       /*      THIS ROUTINE IS A NO_OP IF connection_status(con)!=CON_STOPPING
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-connection_perror(con, msg)
-CONNECTION con;
-char *msg;
-{
-       if (con == NULL || connection_status(con) != CON_STOPPING)
-               return;
-       errno = connection_errno(con);
-       gdb_perror(msg);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_perror
-       /*      
-       /*      Performs same function as system perror, but does
-       /*      it on gdb_log instead of stderr.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-gdb_perror(msg)
-char *msg;
-{
-       if(msg != NULL)
-               fprintf(gdb_log, "%s: ", msg);
-       if(errno < sys_nerr)
-               fprintf(gdb_log, "%s.\n", sys_errlist[errno]);
-       else
-               fprintf(gdb_log, "errno %d is out of range of message table.\n", errno);
-}
-
diff --git a/gdb/gdb.mss b/gdb/gdb.mss
deleted file mode 100644 (file)
index 158c13e..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-@device(imprint10)
-@make(Report, Form 1)
-@style(hyphenation on)
-@style(BindingMargin 0)
-@style(justification off)
-@style(FontFamily ComputerModernRoman10)
-@style(footnotes "")
-@begin(center)
-@majorheading(GDB)
-@heading(Global Databases for Project Athena)
-@subheading(Noah Mendelsohn)
-@subheading(April 17, 1986)
-@end(center)
-@blankspace(1 cm)
-This note is intended as a brief introduction to the Global Database
-(GDB)  system being
-developed at MIT Project Athena.
-GDB is an ongoing effort, still in its early stages, to provide the
-services of a high performance shared relational database to the
-heterogeneous systems comprising the Athena network.  Specifications
-have been developed for a set of library routines to be used by
-@i[clients] to access the database.  
-Current plans are to use the Ingres relational database product from
-RTI as a local data manager, but to support access via the client
-library from any Berkeley Unix@+[TM]@foot(@+[TM]Unix is a trademark of
-AT&T Bell Laboratories) system in the internet.  Though early
-versions will manage only a single copy of any given relation,
-replication may be added at some point in the future.  
-In the meantime the client library provides a uniform framework for
-writing database applications at Athena.
-
-While designing the client library it became apparent that many of its
-underlying services for structured data storage and transmission would
-be of value for a variety of applications.  Most of these interfaces
-have been exposed, and the GDB project has undertaken as a secondary
-goal the development of these simple services for structured data
-maintenance and transmission.
-
-@section(Raison d'etre@+[1]@foot[@+[1]with apologies for lack of accents in the
-font!])
-
-The GDB project was motivated by the observation that Athena
-applications tend to exploit the computational and display services of
-the system much more effectively than they use the network.
-Furthermore,
-those applications which do use the network tend to have strong
-machine type affinities, running comfortably on either a Vax or an
-RT/PC,
-but rarely both.  Indeed, the @i[strategic] Athena database system is
-currently unavailable on the RT/PC's.
-
-Of the many unexplored uses of the network, globally accessible
-databases seem to have great value in a variety of disciplines, and
-they are also badly needed for certain aspects of Athena
-administration.  By providing well architected services for global
-data sharing, we hope to achieve at least two goals: (1) set the
-precedent that user written applications and Athena supplied services,
-like @b[madm], @b[chhome], and @b[passwd], run compatibly 
-from any machine in the network, and (2) encourage
-the development of new database applications by eliminating the need
-for individual projects and departments to develop their own
-transmission and encapsulation protocols.
-
-@section(Implementation Goals)
-
-The following goals have been established for the architecture and
-implementation of GDB:
-
-@begin(itemize)
-Access to databases stored on incompatible machines (e.g. RT/PC to
-Vax) should be supported transparently.
-
-Multiple databases, possibly at several sites,  should be accessible
-simultaneously.  The ability to do concurrent activity on the several
-databases is desirable.
-
-Appropriate facilities for managing structured data returned from the
-database should be provided for programmers (e.g. access fields by
-name.)
-
-Asynchronous operation should be supported, for several reasons:
-@begin(itemize)
-Required for control of simultaneous access to multiple databases.
-
-Needed for graceful interruption of long-running or erroneous
-requests.
-
-Facilitates pipelining of requests, thereby maximizing overlap of
-server and client processing.
-@end(itemize)
-
-When the internal interfaces used for session control and data
-transmission can be generalized without adding unnecessarily to their
-complexity, then those interfaces should be documented and exposed.
-@end(itemize)
-
-@section(Implementation Strategy)
-
-Several approaches to achieving these goals were considered, and an
-implementation strategy has been chosen.  
-
-One approach to achieving the required function would be to rely on
-the appearance of RTI products containing the necessary facilities.
-At the very least, we would need a full function Ingres port to the
-4.2 system on the RT/PC.  RTI would further have to extend Ingres for
-access to databases through the internet, and they would have to
-support such access across multiple machine types.  These extensions
-would give us a core of function suitable for limited application,
-though we would have to see whether flexibility and performance were
-truly appropriate for our needs.  If RTI should come forward with a
-commitment to produce these products within the next few months, then
-need for the libraries described herein might not be so great.
-Lacking such products from RTI, it seems essential that we carry
-forward with a strategy for database access from @i[all] of the
-workstations in the Athena network.
-
-Having decided to do at least some of the necessary work ourselves,
-several implementation strategies are possible.  One, which is
-currently being pursued by Roman Budzianowski, is to interpose the
-appropriate transmission services between the RTI Ingres front end and
-back end.  This technique has a number of interesting advantages, and
-some disadvantages.  The primary advantage is the ability to run
-existing Ingres applications, including some of the forms and query
-facilities, through the network.  Also, Roman reports that he has
-succeeded in running an interesting subset of applications without too
-much effort.  The disadvantages of Roman's approach are the lack of 
-a strategy for supporting non-Vax machines until RTI comes out with
-the appropriate base products, and the dependence on undocumented
-interfaces.   
-In some cases, the front-end and the back-end are sharing files, while
-in others signals seem to be sent.  It remains to be seen how successfully
-we can divine these undocumented interfaces, how stable they remain
-over time, and whether--given an RTI Ingres on the RT/PC--we can
-figure out how to do the right byte swapping on the binary data sent
-through Ingres' pipes and files.  Our conclusion is that Roman's
-effort should continue, because it can
-achieve valuable results without excessive effort.
-Nevertheless, this scheme falls short of our requirement for balanced
-support of all the machines in the Athena network, so we recommend an
-alternate implementation as the primary base for Athena application
-development. 
-
-A machine independent access method for relational databases could be
-constructed in many different ways.  One technique we have considered
-and rejected is to base an implementation on the RPC prototype
-developed by Steve Miller and Bob Souza.  While RPC is
-convenient, and the prototype appears to be of very high quality, it
-fails to meet our needs in several crucial areas.  We have concluded
-that asynchronous interaction between clients and servers is
-essential for performance, for parallel execution of multiple queries,
-and for interruptibility of ongoing operations.  Synchronous RPC seems
-ill-suited to these requirements.  A secondary concern is the lack of
-support for procedure calls across heterogeneous architectures in the
-current version of the RPC prototype.  The right hooks are supposedly
-there, but the necessary alignment and type conversion routines have
-not been built.  Indeed, the prototype has yet to be ported to the
-RT/PC.
-
-As a result of this analysis, we have designed a system which uses RTI
-Ingres for the things it does (or purports to do) well, and we have
-added a flexible, asynchronous transport mechanism for transmission of
-structured data between heterogeneous processors.  The specification,
-outlined in a separate document, includes libraries for creation and
-management of tuples and relations in virtual memory, along with a
-simple mechanism for typing the fields comprising a tuple.  Layered
-upon these are services for transmitting fields, tuples and relations
-through the internet, doing the necessary conversions and
-re-alignments when moving between incompatible machines.  These
-services, in turn, are used by a library which provides almost
-all of the services of Ingres EQUEL to clients throughout the network.
-
-@section(Project Status)
-
-The specification for the interfaces to the client library routines is
-available in draft form and is now being refined.  In parallel, design
-is proceeding on the protocol to be used between the sites, and on the
-related software structures used to encapsulate and parse the
-transmitted data.  The design does include a simple but flexible
-proposal for managing asynchronous activities.  Coding will start soon
-on those pieces of the library which seem to be stable;  refinement of
-the other parts will take a few more weeks.  While our rate of
-progress will depend greatly on the number of people doing the work
-and on their other responsibilities (neither of which are clear at
-this time), I'm optimistic that a basic implementation will start
-showing signs of life within a couple of months, with polishing taking
-a bit longer.
diff --git a/gdb/gdb.prob b/gdb/gdb.prob
deleted file mode 100644 (file)
index efd1856..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/************************************************************************/
-/*     
-/*                   PROBLEMS WITH THE GDB CODE
-/*     
-/************************************************************************/
-
-* Go through all of wesommers changes in /u1/sms/gdb
-       - Eye catchers faster
-       - fastprogress
-       - signal handling
-       - some fatal error stuff
-
-* check error return handling on all system calls used by GDB
-
-* terminate_db was never written
-
-* comments on start_performing_db_operation lie
-
-* clean up comments in dbserv.qc
-
-* clean up comments in gdb_db.c
-
-* Fix ptr <--> int casts on semantic routines
-
-* Buffer input through gdb_move_data
-
-* Ingres version 5 support
-
-* Bouncing connections so that there is only one GDB port
-
-* decode of descriptor currently assumes that NULL will be passed if receiving
-  into unallocated descriptor.  Autos sometimes aren't null.
-
-* Straighten out description of db_query in the library reference.
-
-* Document retrieval limit setting
-
-* Debug retrieval limit setting
-
-* Document -l option on dbserv
-
-* Document user and host fields and how to zap for anonymous use.
-  Also, indicate risks of trusting the information in those fields.
-
-* There is some inconsistency in the use of tuple vs. tuple descriptor
-  as argument to the routines like FIELD_OFFSET_IN_TUPLE
-
-* Offsets would be more convenient if from the start of the tuple rather than
-  from the start of the 0th field.
-
-* Some of the routines defined as macros may not work if semicolons are
-  used after invocation.  This should be documented our changed.
-
-* there is some inconsistency in the semantic routines over which
-  decode routines presume null values of their targets, and which
-  ones actively free any existing data.  Likewise for the null
-  routines.  For the moment, we'll ignore it as an internal issue,
-  but this should be fixed when it starts causing more trouble than
-  it's worth.
-
-
-* should check all uses of register declaration to make sure they
-  are appropriate
-
-* make sure null values are handlined properly when tuples are 
-  initialized.  Looks like the string routines may be easily confused   
-  about non-initialized null values.
-
-* must update documentation and sample programs to indicate requirement
-  to call the gdb_init routine.  Perhaps there should be a closeup routine
-  too?
-
-** create-tuple-descriptor may be mis-computing data-len in the case
-   where alignment is leaving gas.  Looks like the gas is not getting
-   added in. (I think this was fixed during debugging with Saber.)
-
-* must make a plan to exhaustively test code paths.  Several whole
-  routines have not been tried at all
-
-* the design for out of band signalling and operation interruption must 
-  be considered more carefully.
-
-* perhaps gdb.h should be split into a piece which is visible to all
-  users (i.e. lives in /usr/include) and an internal piece used only
-  for compiling the library.
-
-* we need some way to mark and distinguish inbound and outbound half 
-  sessions.  For the moment, they can be implicit in their position in
-  the connection data structure, but that seems a bit tacky.  Could
-  use routine pointers to to do the reading and the writing.
-
-* could implement a buffer/flush scheme at some level to avoid repeated
-  and unnecessary system calls for write/read.  Not clear what level is
-  best to do this--I'm inclined to do it in the oeprations themselves, not 
-  in the transport service.
-
-* should come up with a way to encode those types which need a recursive
-  call on cleanup.  We can probably get rid of null_tuple_strings that
-  way, and pick up a bit of generality.
-
-* don't yet have a proper architecture for the routines used at the
-  server end.  Which one's should be exposed and documented to 
-  implementors of new services?  How general should they be?
-
-* CONN_STATUS values should be cleaned up.
-
-* make sure the cancellation function in OPERATION_DATA is handled properly.
-
-* How do we really want to handle predecessor failing conditions.  Should
-  we purge the queue, as currently claimed, or just attempt the next one?
-  Probably just attempt the next one.
-
-* select timer handling is being implemented very approximately for now
-  We are setting the full timer each time the real select is called, not
-  accounting for time already elapsed when select is called repeatedly.
-
-* level of indirection on select is really not clear
-
-* in dealing with file descriptor masks passed to functions, one should
-  probably use the & notation consistently to avoid unnecessary structure
-  copying.  See especially in the interfaces to gdb_fd_copy, etc. in
-  gdb_trans.c
-
-* current semantics of op_select imply that lots of manipulation of
-  operation queues will be required as operations complete and the
-  lists get logically shorter.  We may want to change the semantics
-  of op_select and/or provide new operations for adding and deleting
-  operations from an operation list, possibly with attendant re-allocation.
-
-* how do we do exception handling on the connections?
-
-* gdb_hcon_progress: how to handle cancelling, etc.
-
-* the distinction between initialization and continuation routines 
-  is looking pretty artificial.  Leading to duplicate code in 
-  places like gdb_hcon_progress.  
-
-* out of band signalling not implemented.  The sockets are set to null
-  during creation.
-
-* when starting peer sessions a race condition is built into the current
-  algorithm.  startup may fail when the two sides are initiated at about
-  the same time.  Must be fixed for production use.
-
-* start_peer_connection has no way to return a reason for failure.
-
-* connections are currently made to a well known port.   Eventually this
-  should be fixed.
-
-* one could argue that the creation of the listening socket should be done
-  once during initialization, not repeatedly.  On the other hand, this
-  significantly raises the cost for someone who never listens.
-
-* We could automate the activation of gdb_init by checking for a flag
-  in the appropriate routines.
-* define consistent set of op_results, apply them in gdb_ops.c
-
-* synchronous calling of continuation routines may be a mistake?  I don't
-  think so, since the length of the chain is statically limited.  Would
-  be a mistake in the case of extensive re-queueing, but then we go back
-  to the queue manager, NO?
-
-* queue_operation takes a half connection as an argument, but they are
-  not properly described in the spec.   There should be macros to 
-  extract the input and output half connections from a connection.
-
-* our writeup should note ease of supporting shared state servers
-  (e.g. a very live conferencing system?)
-
-* for performance, changes should be made to minimize the number of read
-  and write system calls done.  This could (perhaps) be done with look-behind
-  on the outbound and buffered read on the inbound queues, used in conjunction
-  with the iovec technique.  Should improve performance significantly.
-  May also need a 'block' hint for use on a half connection which allows
-  an application queueing lots of little requests to get them batched
-  together.
-
-* we're not handling the case where select returns -1 in cnsel, particularly
-  for EBADF indicating a closed descriptor.
-
-* start_peer_connection should use randomized waits to re-try connect and
-  avoid the current startup window.
-
-* need a better way to return errors on things like starting a connection.
-  should scan all of the synchronous interfaces to find out where this
-  should be used.
-
-* it's possible that HCON_BUSY should be replaced by a mechanism to lock
-  all of gdb_progress
-
-* most operations should have cancellation routines.
-
-* when tuples are sent for server/client stuff, make sure the descriptors
-  are properly destroyed when not needed
-
-* should integrate deletion as an operation on a type, along with
-  optimization for nop'ing it.  Should then go through all of code
-  which does things like null-tuple-strings and straighten it out.
-
-* document start_sending_object start_receiving_object
-
-* anything which starts an operation should make sure that the
-  status of the supplied operation is NOT_RUNNING.  There is a 
-  nasty condition which results when the same operation is started
-  twice.
-
-* disable GDB_PORT because it encourages conflict among applications
-
-* implement validate routines in create_forking_server
-
-* check userinfod and inetd to make sure that server environment is 
-  appropriate.
-
-* build async versions of db ops, at both client and server
-
-* use of "string" vs "STRING" in documentation is confusing
-
-* macros for getting at fields in tuples
-
-* document non-portabilities
-       - 4.2 dependencies
-       - representation of data by enc/dec
-
-* are text lengths being handled well on queries? (Looks ok, 9/17/86)
-
-* lots of error checking is missing in dbserv
-
-* Confusion in documentation as to whether receive_object allocates
-  a new relation (for example)
-
-* delete relation needs a way to delete non-contiguous data other
-  than strings
-
-* syntax checking of queries
-
-* return codes for operations, especially DB operations, are a mess.
-
-* we should have some equivalent of perror
-
-* we can possibly give some information about where we were at   
-  the time of a failure if we keep a logical stack. 
-
-* gdb_init should be callable multiple times
-
-* i.d. fields are currently implemented with strings, which is very
-  slow.  Should re-implement with integers as magic numbers
-
-* must figure out handling of errors on queued database requests.  
-  which ones cause a tear-down.  Are there problems dequeueing
-  the appropriate operations in the right order?  Could things get
-  out of sync if other things are queued ahead?  Seems to require
-  a pretty good understanding of how things get cancelled implicitly
-  and explicitly.  Maybe all explicit cancellations should be done
-  using terminate_db.  There is also some question about how 
-  careful we have to be in handling the explicit cancellation of
-  a single db operation, or whether that should be supported.  Not
-  clear that we have enough of a bracket context to do that cleanly.
-
-* document preempt_and_start_receiving_object, also, maybe should
-  do one for sending.
-
-* Notes should be provided on create/delete semantics.  Current is:
-       tuple_descs are reference counted.  Your creates should
-       match your deletes.   Same is true for relations and operations.
-       Likewise tuples EXCEPT:  if you create a tuple, add it to 
-       a relation, and delete the relation, the tuple itself is
-       deleted, and all dangling pointers to it are invalid.
-
-* Must assign version numbers to all programs, documents and files
-
-* gdb_ugd should reference K&R
-
-* should make a CSTRING_T to represent a null terminated string by its pointer
-
-* should be able to limit the number of tuples retrieved.
-
-* Perhaps should be able to interrupt ongoing database operations, or
-  in any case, the restriction on severing the connection should be
-  documented.
-
-* send_object and receive_object should return OP_SUCCESS not OP_COMPLETE
-
-* create_type is documented, but it does not exist.  Also, it is mentioned
-  in the language reference, but not really written up properly.
-
-* add missing chapters to the user's guide
-
-* Steve: forward reference in user guide to async
-
-* Steve: diagrams of general system structure and flow
-
-* More reference material in user guide
-       - GDB data types
-       - Other structures
-
-* what are rules about memory allocation
-       - what does it
-
-* confusion over pointers and macros in documentation
-
-* Missing chapters
-
-* i.d. fields should be changed upon deletion to try and catch misuse 
-  of deleted data
-
-* explicit host addresses are not accepted
-
-*debugging forked servers is very difficult
-
-*there should be more detailed failure codes on send_object receive_object
-
-\f/************************************************************************/
-/*     
-/*                     "Solved" Problems 
-/*     
-/************************************************************************/
-
-* need a routine to wait for all the operations in a list
-  should be easy to build out of op_sel (DONE)
-
-* there should be a macro called TERMINATED for internal use which
-  would be true when an operation was completed or cancelled.  This
-  should be used by most of the routines which check for completion,
-  in anticipation of the day when error recovery is done properly.
-  (DONE...name of the macro is OP_DONE)
-
-* see if select can be used with a listening socket (DONE...it works)
-
-* we need a send_object and receive_object as well as start_sending_object
-  and start_receiving_object (DONE, but documentation is missing)
-
-* should put handling in select for the exceptfd case to catch closing 
-  connections, and likewise should check for errors on read/write.  Maybe
-  only errors on read/write should be checked.  (DONE..exceptfd's are 
-  irrelavent...I think they're for getting signals, anyway, we do the
-  right thing now when a socket fails by closing the corresponding
-  connection.)
-
-* make sure port numbers are handled OK in the server/client model
-  (DONE)
-
-* the database server MUST delete its relations, and we must decide
-  how tuple descriptor reclamation is to be done (Done)
-
-* make db_alloc and db_free replaceable (Done)
-
-* James had problems with create_tuple_descriptor in that he got
-  one of the parameters duplicated (not a gdb problem)
-
-* async queries and db_ops (Done)
-
-* we should put eye catchers into structured data and check it. (done)
-
-* db_query is not nearly asynchronous enough (Done)
-
-* Strings:  James forgot to initialize strings after creating tuple;
-
-* we are missing a delete_relation routine, which would have to
-  recursively delete all tuples after calling delete_tuple_strings
-  or whatever on them.  This should be called by the decode relation
-  and the null relation semantic routines.  (Done)
-
-* naming inconsistency between "new-tuple" and "create-_____" all others (Done)
-
-
-/************************************************************************/
-/*     
-/*             Problems in Providing SQL Support
-/*     
-/************************************************************************/
-
-* Character strings in SQL limited to 255 bytes, in literal at least
-
-
diff --git a/gdb/gdb_conn.c b/gdb/gdb_conn.c
deleted file mode 100644 (file)
index ba5b5c7..0000000
+++ /dev/null
@@ -1,1055 +0,0 @@
-/*
- * $Source$
- * $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_conn_c = "$Header$";
-#endif
-
-/************************************************************************
- *     
- *                        gdb_conn.c
- *     
- *           GDB - Connection Management Services
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena 
- *             For copying and distribution information, please see
- *             the file <mit-copyright.h>.
- *     
- *     Routines used in the creation and maintenance of CONNECTIONS.
- *     Note: these are closely related to the services provided
- *     by gdb_trans.c and gdb_trans2.c.
- *     
- *     
- ************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "gdb.h"
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <errno.h>
-#ifdef SOLARIS
-#include <sys/filio.h>
-#endif /* SOLARIS */
-#ifdef POSIX
-#include <unistd.h>
-#endif
-
-extern int errno;
-
-CONNECTION gdb_allocate_connection();
-
-/************************************************************************
- *     
- *                     start_peer_connection (start_peer_connection)
- *     
- *     Starts a connection to another process which itself will be 
- *     issuing a start_peer_connection to us.  Current implementation
- *     builds at most one stream, with the risk of a hang if 
- *     the attempts to connect cross in the night.  This is a bug,
- *     but this level of support is acceptable for casual debugging
- *     of applications, and perhaps for some production use in
- *     controlled settings.  I think the only other way to do it 
- *     is to risk building two streams in parallel, possibly tearing
- *     one down when the duplication is discovered.  Seems complicated
- *     and messy.
- *     
- ************************************************************************/
-
-CONNECTION
-start_peer_connection(id)
-char *id;                                      /* null terminated string */
-{
-       register CONNECTION con;                /* the connection we're */
-                                               /* creating */
-
-       GDB_INIT_CHECK
-
-       /*
-        * Try to allocate a connection and fill it in with null values.
-        */
-
-       con = g_make_con();
-
-       /*
-        * In this implementation, we use a single fd for both inbound and
-        * outbound traffic.  Try to connect to other side.  If that 
-        * doesn't work, wait to accept a connection from the other side.
-        * Current implementation of this is synchronous--may be a problem?
-        * Also note timing window bug in the following.  If the two peers
-        * are started at just about the same time, the race may not be handled
-        * propoerly.  If the connections come up, then verify the level of
-        * protocol being observed on the connections.  If incompatible,
-        * then turn off the connection.
-        */
-
-       if(!g_try_connecting(con,id)) {
-               g_try_accepting(con,id);
-               if(con->status == CON_STARTING)
-                       g_ver_iprotocol(con);
-       } else
-               if(con->status == CON_STARTING)
-                       g_ver_oprotocol(con);
-
-
-       if (con->status == CON_UP) {
-               /*
-                * We've successfully started the connection, now mark
-                * it for non-blocking I/O.  Also, update the high water
-                * mark of fd's controlled by our system.
-                */
-               int nb = 1;
-               if(ioctl(con->in.fd, FIONBIO, (char *)&nb)== (-1)) { 
-                       g_stop_with_errno(con);
-                       return con;
-               }
-               if (con->in.fd +1 > gdb_mfd) 
-                       gdb_mfd = con->in.fd + 1;
-               /*
-                * Allocate a buffer, if necessary, and reset buffer pointers
-                * so first request will result in a long read into the buffer
-                */
-               g_allocate_connection_buffers(con);
-
-               return con;
-       } else
-               return NULL;
-}
-
-
-/************************************************************************/
-/*     
-/*                             g_make_con
-/*     
-/*     Internal routine to allocate a new connection structure and
-/*     initialize all its fields to logical null values.
-/*     
-/************************************************************************/
-
-CONNECTION
-g_make_con()
-{
-       register CONNECTION con;
-
-       /*
-        * Try to allocate a connection, fatal error if none available
-        */
-       con = gdb_allocate_connection();
-       if (con == NULL)
-               GDB_GIVEUP("start_peer_connection: Tried to allocate too many connections") /* <==RECOVERABLE */
-       
-       /*
-        * Give the fields their initial values
-        */
-        g_null_con(con);
-
-       return con;
-
-}
-
-
-/************************************************************************/
-/*     
-/*                             g_null_con
-/*     
-/*     Sets a connection descriptor to have all null values in 
-/*     its fields.  This routine does NOT do any of the cleanup
-/*     which is necessary after the connection has really been used.
-/*     
-/************************************************************************/
-
-int
-g_null_con(con)
-CONNECTION con;
-{
-       /*
-        * Initialize the connection control data structure.
-        */
-       con->id = GDB_CON_ID;
-        con->status = CON_STARTING;
-       con->oob_fcn = NULL;                    /* out of band signalling */
-                                               /* is not currently */
-                                               /* implemented */
-       con->errno = 0;                         /* system errno gets */
-                                               /* copied here iff it */
-                                               /* causes this con to die */
-       /*
-        * Initialize input half connection to null state before trying
-        * to bring it up.
-        */
-       con->in.status = OP_NOT_STARTED;
-       con->in.fd = -1;
-       con->in.oob_fd = -1;
-       con->in.op_q_first = (struct oper_data *)&con->in;
-       con->in.op_q_last = (struct oper_data *)&con->in;
-       con->in.next_byte = NULL;
-       con->in.remaining = 0;
-       con->in.flags = 0;
-
-       /*
-        * Initialize output half connection to null state before trying
-        * to bring it up.
-        */
-       con->out.status = OP_NOT_STARTED;
-       con->out.fd = -1;
-       con->out.oob_fd = -1;
-       con->out.op_q_first = (struct oper_data *)&con->out;
-       con->out.op_q_last = (struct oper_data *)&con->out;
-       con->out.next_byte = NULL;
-       con->out.remaining = 0;
-       con->out.flags = 0;
-
-       return;
-
-}
-
-
-/************************************************************************/
-/*     
-/*                     gdb_allocate_connection
-/*     
-/*     Return an unused entry in the connection array.  Unused entries
-/*     are recognized by being marked as CON_STOPPED.
-/*     
-/*     Note that gdb_mcons is the number of descriptors which have 
-/*     ever been used (i.e. a high water mark), so status fields
-/*     are invalid above that.
-/*     
-/************************************************************************/
-
-CONNECTION
-gdb_allocate_connection()
-{
-       register int i;                         /* index of next one */
-                                               /* to check */
-
-       /*
-        * First look for one below the high water mark
-        */
-       for(i=0; i<gdb_mcons; i++) {
-               if (gdb_cons[i].status == CON_STOPPED)
-                       return &gdb_cons[i];
-       }
-
-       /*
-        * Allocate one which has never been used, if possible
-        */
-
-       if (i>=GDB_MAX_CONNECTIONS)
-               GDB_GIVEUP("gdb: tried to allocate too many simulataneous connections.\n, See GDB_MAX_CONNECTIONS in gdb.h.") /* <==RECOVERABLE */
-
-       gdb_mcons++;                            /* bump the high water mark */
-       gdb_cons[i].status = CON_STOPPED;       /* initialize status of the */
-                                               /* new connection */
-       return &gdb_cons[i];                    /* return new highest con */
-                                               /* ever used*/       
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_try_connecting
-/*     
-/*     Try to start a connection to the designated site, filling 
-/*     in the appropriate information in the connection descriptor
-/*     if successful.  Return TRUE if connection succeeded or if
-/*     error was fatal enough that we shouldn't try accepting.  Returns
-/*     FALSE if we should try accepting.
-/*     
-/************************************************************************/
-
-int
-
-g_try_connecting(con,id)
-CONNECTION con;
-char *id;
-{
-       int peer;                               /* socket for talking to
-                                                  peer */
-       char on = 1;                            /* flag for ioctl */
-       struct sockaddr_in target;              /* build the peer address */
-                                               /* here */
-       struct hostent *peer_host;              /* host where peer is */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Make sure connection is marked stopped until we 
-       /*      get it going.
-       /*      
-       /*----------------------------------------------------------*/
-
-       con->status = CON_STOPPED;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Find out host where peer is, and validate it.  Take
-       /*      care of port at the same time.
-       /*      
-       /*----------------------------------------------------------*/
-
-       memset((char *)&target, 0, sizeof(target));
-       g_parse_target(id, &peer_host, &target.sin_port);
-       if (peer_host == NULL) {
-               fprintf(gdb_log,"gdb: g_try_connecting...  '%s' is not a valid host:server\n",
-                       id);
-               return TRUE;                    /* so we won't try accepting */
-       }
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Create a socket
-       /*      
-       /*----------------------------------------------------------*/
-
-       peer = socket(AF_INET, SOCK_STREAM, 0);
-       if (peer < 0) {
-               g_stop_with_errno(con);
-               return TRUE;                    /* fatal error */
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Get information and bind socket using well known 
-       /*      port (BUG: this restricts us to one pair of peers
-       /*      per host pair, as well as being bad practice on 
-       /*      the network.  It will do for debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-       memcpy((char *)&target.sin_addr,peer_host->h_addr,peer_host->h_length);
-       target.sin_family = peer_host->h_addrtype;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Make the connection
-       /*      
-       /*----------------------------------------------------------*/
-
-       if(connect(peer, (struct sockaddr *)&target, sizeof(target)) < 0) {
-               if (errno == ECONNREFUSED)
-                       return FALSE;           /* other side not yet */
-                                               /* up, but no other fatal */
-                                               /* errors*/
-               else {
-                       gdb_perror("gdb: unexpected error connecting");
-                       g_stop_with_errno(con);
-                       return TRUE;
-               }
-       }
-
-       if ((gdb_Options & GDB_OPT_KEEPALIVE) &&
-           setsockopt(peer, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) {
-           gdb_perror("gdb: unable to start keepalives");
-           g_stop_with_errno(con);
-           return(TRUE);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      The connection has been made, fill in the connection
-       /*      control data structure.
-       /*      
-       /*----------------------------------------------------------*/
-
-       con->in.fd = peer;
-       con->out.fd = peer;
-       con->status = CON_STARTING;
-
-       return TRUE;
-
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_parse_target
-/*     
-/*     For a given server or peer i.d., figure out the host and the
-/*     port.  Arguments are:  
-/*     
-/*             string i.d. of the server, which is     
-/*             in one of two forms:
-/*     
-/*                     host:servicename (where service name must not begin
-/*                               with #)
-/*     
-/*                     host:#portnumber  (where portnumber is the actual
-/*                                number of the port to be used)
-/*     
-/*                     (actually, a 3rd form, with no port number supplied,
-/*                     will use a default GDB_PORT, but this is unsafe
-/*                     and it will be disabled in production versions
-/*                     of the gdb system.)
-/*     
-/*             **hostent: returned to indicate host to be used.  Null
-/*                     if host could not be found
-/*     
-/*             *port   pointer to an integer where the port number will
-/*                     be put.  We return the port number in network
-/*                     byte order.
-/*     
-/************************************************************************/
-
-int
-g_parse_target(id, host, port)
-char *id;
-struct hostent **host;
-u_short *port;
-{
-       char buffer[256];                       /* longest host name */
-       register char *ip, *bp;                 /* for copying name */
-       struct servent *serv;                   /* returned from */
-                                               /* get service by name */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      copy the host name part only to local buffer
-       /*      
-       /*----------------------------------------------------------*/
-
-       ip = id;
-       bp = buffer;
-
-       while (*ip != '\0' && *ip != ':')
-               *bp++ = *ip++;
-       *bp = '\0';
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Look up the host name, return if bad.
-       /*      
-       /*----------------------------------------------------------*/
-
-       *host = gethostbyname(buffer);
-
-       if (*host == NULL)
-               return;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Set up the port address
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (*ip++ != ':') {
-               *port = GDB_PORT;
-               return;
-       }
-       
-       if (*ip == '\0') {
-               *host = NULL;
-               return;
-       }
-
-       if (*ip == '#') {
-               /*
-                * port number supplied explictly
-                */
-               ip++;
-               if (*ip < '0' || *ip>'9') {
-                       *host = NULL;
-                       return;
-               }
-               *port = htons((u_short)atoi(ip));
-       } else {
-               /*
-                * service identified by name
-                */
-               serv = getservbyname(ip, "tcp");
-               if (serv == NULL) {
-                       *host = NULL;
-                       return;
-               }
-               *port = serv->s_port;
-       }
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_try_accepting
-/*     
-/*     Try to accept a connection to the designated site, filling 
-/*     in the appropriate information in the connection descriptor
-/*     if successful.
-/*     
-/************************************************************************/
-
-int
-g_try_accepting(con,id)
-CONNECTION con;
-char *id;
-{
-       int slisten;                            /* socket on which
-                                                  we listen for connections */
-
-       int peer;                               /* socket for talking to
-                                                  peer */
-       int fromlen;
-       struct sockaddr_in self, from;
-       int retries = GDB_BIND_RETRY_COUNT;
-       int onoff = 1;                          /* used as argument to */
-                                               /* setsockopt */
-
-       struct hostent *peer_host;              /* host where peer is */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Make sure connection is marked stopped until we 
-       /*      get it going.
-       /*      
-       /*----------------------------------------------------------*/
-
-       con->status = CON_STOPPED;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Create a socket on which to listen.  Tell it that
-       /*      it's OK to re-use the port address, which may still
-       /*      appear busy if connections are taking awhile to go
-       /*      away.
-       /*      
-       /*----------------------------------------------------------*/
-
-       slisten = socket(AF_INET, SOCK_STREAM, 0);
-       if (slisten < 0) {
-               gdb_perror("g_try_accepting: error creating listen socket");
-               g_stop_with_errno(con);
-       }
-       /* Try 4.2 method */
-       if(setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, (char *)0, 0)<0)
-       /* that didn't work, try 4.3 */
-               if(setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR,
-                             (char *)&onoff, sizeof(int)) <0)
-                       GDB_GIVEUP("g_try_accepting: could not set SO_REUSEADDR");
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Find out host where peer is, and validate it.  Take
-       /*      care of port at the same time.  This is redundant
-       /*      given that g_try_connecting is always called first.
-       /*      
-       /*----------------------------------------------------------*/
-
-       memset((char *)&self, 0, sizeof(self));
-       g_parse_target(id, &peer_host, &self.sin_port);
-       if (peer_host == NULL) {
-               GDB_GIVEUP("gdb_try_accepting: bad port not caught by try connecting")
-       }
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Bind the socket to ourselves, using the well known
-       /*      port (See bug note in g_try_connecting.
-       /*      
-       /*      This code should really go in initialization, I think.
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (bind(slisten,(struct sockaddr *)&self,sizeof(self)) < 0) {
-               if (errno == EADDRINUSE && retries--) {
-                       fprintf(gdb_log,"gdb: port address in use, will retry %d more time(s)\n",retries+1);
-                       sleep(GDB_BIND_RETRY_INTERVAL);
-                       continue;
-               } else {
-                       gdb_perror("gdb: error binding listen socket");
-                       g_stop_with_errno(con);
-                       (void) close(slisten);                  
-                       return;
-               }
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Listen for connections.
-       /*      
-       /*----------------------------------------------------------*/
-
-       (void) listen (slisten, 5);             /* does not block, just */
-                                               /* sets the maximum backlog */
-                                               /* of pending non-accepted */
-                                               /* cons.*/
-       fromlen = sizeof(from);
-       peer = accept(slisten, (struct sockaddr *)&from, &fromlen);
-       if (peer < 0) {
-               g_stop_with_errno(con);
-               gdb_perror("gdb_try_accepting: error accepting connection");
-               (void) close(slisten);
-               return;
-       }
-
-       (void) close (slisten);                 /* we're not using the */
-                                               /* listening socket */
-                                               /* anymore, only the */
-                                               /* connection to the peer */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      The connection has been made, fill in the connection
-       /*      control data structure.
-       /*      
-       /*----------------------------------------------------------*/
-
-       con->in.fd = peer;
-       con->out.fd = peer;
-       con->status = CON_STARTING;
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_ver_oprotocol
-/*     
-/*     Called when an outbound connection is started to verify 
-/*     the version of the protocol being observed.
-/*     
-/************************************************************************/
-
-int
-g_ver_oprotocol(con)
-CONNECTION con;
-{
-#ifdef VERIFY_PROTOCOL
-       char ver = GDB_PROTOCOL_VERSION;
-       char theirs;
-       int len;
-
-        int onoff = 0;                         /* for ioctl to turn off */
-
-       /*
-       * Because the connection was accepted on a non-blocking 
-       * listening socket, the connection itself may be non-blocking.
-       *  We can't tolerate that here.  It will be reset later.
-       */
-       if (ioctl(con->in.fd, FIONBIO, (char *)&onoff) < 0) { 
-               g_stop_with_errno(con);
-               gdb_perror("Can't turn off FIONBIO in g_ver_iprotocol");
-               return;
-       }
-
-       while (write(con->out.fd, &ver, 1) < 0) {
-               g_stop_with_errno(con);
-               return;
-       }
-
-       do {
-               len = read(con->in.fd, &theirs, 1);
-               if (len == (-1)) {
-                       g_stop_with_errno(con);
-                       return;
-               }
-       } while (len !=1);
-
-       if (theirs == ver)
-               con->status = CON_UP;
-       else
-               con->status = CON_STOPPED;
-#else
-       con->status = CON_UP;
-#endif
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_ver_iprotocol
-/*     
-/*     Called when an inbound connection is started to verify 
-/*     the version of the protocol being observed.
-/*     
-/************************************************************************/
-
-int
-g_ver_iprotocol(con)
-CONNECTION con;
-{
-#ifdef VERIFY_PROTOCOL
-       char ver = GDB_PROTOCOL_VERSION;
-       char theirs;
-       int len;
-       int old_nbio;
-        int onoff = 0;                         /* for ioctl to turn off */
-
-       /*
-       * Because the connection was accepted on a non-blocking 
-       * listening socket, the connection itself may be non-blocking.
-       *  We can't tolerate that here.  It will be reset later.
-       */
-       if (ioctl(con->in.fd, FIONBIO, (char *)&onoff) < 0) { 
-               g_stop_with_errno(con);
-               gdb_perror("Can't turn off FIONBIO in g_ver_iprotocol");
-               return;
-       }
-
-       do {
-               len = read(con->in.fd, &theirs, 1);
-               if (len == (-1)) {
-                       g_stop_with_errno(con);
-                       return;
-               }
-        } while (len !=1) ;
-
-       if (theirs == ver)
-               con->status = CON_UP;
-       else
-               con->status = CON_STOPPED;
-
-       while (write(con->out.fd, &ver, 1) < 0) {
-               g_stop_with_errno(con);
-               return;
-       }
-#else
-       con->status = CON_UP;
-#endif
-}
-
-
-/************************************************************************/
-/*     
-/*                     sever_connection (sever_connection)
-/*     
-/*     Unconditionally, but cleanly, terminates a connection.  All
-/*     pending operations on the connection are cancelled, and the
-/*     file descriptor for the connection is closed.  This routine
-/*     should be called directly from applications wishing to shut
-/*     down a connection.  No transmissions are attempted
-/*     by this routine.  Returns NULL, in the hope that applications
-/*     will assign this to their old CONNECTION variable.
-/*     
-/************************************************************************/
-
-CONNECTION
-sever_connection(con)
-CONNECTION con;
-{
-       if (con == NULL)
-               return NULL;
-       GDB_CHECK_CON(con, "sever_connection")
-       if (con->status == CON_UP || con->status == CON_STARTING)
-               g_stop_connection(con);
-       if (con->status != CON_STOPPED)
-               gdb_de_allocate_connection(con);
-
-       return NULL;
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_stop_with_errno
-/*     
-/*     This connection is stopping because of a problem on a syscall.
-/*     We record the errno in the connection descriptor for inspection
-/*     by the application, then stop the connection.
-/*     
-/************************************************************************/
-
-int
-g_stop_with_errno(con)
-CONNECTION con;
-{
-       con->errno = errno;
-       g_stop_connection(con);
-       
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_stop_connection
-/*     
-/*     Unconditionally, but cleanly, terminates a connection.  All
-/*     pending operations on the connection are cancelled, and the
-/*     file descriptor for the connection is closed.  This routine is 
-/*     for internal use.  Applications call sever_connection, which 
-/*     also de_allocates the descriptor.  No transmissions are attempted
-/*     by this routine.
-/*     
-/************************************************************************/
-
-int
-g_stop_connection(con)
-CONNECTION con;
-{
-       /*
-        * Shutdown activity on the two half connections.
-        */
-       g_cleanup_half_connection(&(con->in));
-       g_cleanup_half_connection(&(con->out));
-
-       /*
-        * Remove the file descriptor from the select bit maps
-        */
-       if (!(con->in.flags & HCON_UNUSED) && con->in.fd >= 0)
-               FD_CLR(con->in.fd,  &gdb_crfds);
-       if (!(con->out.flags & HCON_UNUSED) && con->out.fd >= 0)
-               FD_CLR(con->out.fd, &gdb_cwfds);
-       /*
-        * Close the file descriptor.  Note, this presumes that in fact
-        * 1) in is never the unused half and
-        * 2) when the connection is bi-directional, in and out share an
-        *    fd.  We could do with a more elaborate scheme to control
-        *    this in the future.
-        */
-       (void) close(con->in.fd);
-
-       /*
-        * Mark the connection as stopping.  We can't reclaim the 
-        * descriptor until the application does a sever, or else there
-        * would be a risk of re-allocating it out from under the application.
-        */
-
-       con->status = CON_STOPPING;
-
-       return;
-}
-
-
-/************************************************************************/
-/*     
-/*                     gdb_de_allocate_connection
-/*     
-/*     Return a connection whose file descriptors have been closed
-/*     to the pool.
-/*     
-/************************************************************************/
-
-int
-gdb_de_allocate_connection(con)
-CONNECTION con;
-{
-       register int i;                                 
-
-       con->status = CON_STOPPED;
-
-       i = gdb_mcons-1;                        /* start at last one used */
-
-       /*
-        * Reset gdb_mcons to be the number of connections in use
-        */
-       while (i>=0 && gdb_cons[i].status == CON_STOPPED)
-               i--;
-
-       gdb_mcons = i + 1;
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_cleanup_half_conection
-/*     
-/*     Terminate all pending operations on the supplied half 
-/*     connection.  Note that the algorithm used here presumes
-/*     that cancel_operation will de-queue the operation descriptor, 
-/*     therefore we have to be careful here about when we look at 
-/*     chain pointers.
-/*     
-/************************************************************************/
-
-int
-g_cleanup_half_connection(hcon)
-HALF_CONNECTION hcon;
-{
-       OPERATION current, next;
-
-       current = hcon->op_q_first;
-
-       /*
-        * Loop through all operations in the queue canceling them.
-        * Make sure to pick up pointer to 'next' before the current
-        * one is canceled, as cancelling may invalidate the pointer.
-        */
-
-       while (current != (OPERATION)hcon) {
-               next = current->next;
-               (void) cancel_operation(current);
-               current = next;
-       }
-}
-
-
-/************************************************************************/
-/*     
-/*                 create_listening_connection (create_listening_connection)
-/*     
-/*     Starts a special type of connection which is used to listen
-/*     for incoming connection requests.  The inbound half-connection
-/*     is the only one used for this special kind of connection.
-/*     
-/*     It is the user's responsibility to insure that only appropriate
-/*     types of operation are queued on a connection of this sort.  In
-/*     general, these connections are intended for internal use by
-/*     GDB, and they are not intended to be visible to servers or
-/*     clients directly.
-/*     
-/*     The id supplied should be in one of two forms.  If just a 
-/*     string is supplied then it is presumed to be the name of
-/*     a registered tcp service.  If the name begins with a #, then
-/*     the rest is interpreted as the integer port number to be used.
-/*     
-/*     In future implementations, the id may have more structure, which
-/*     is why we define it as a string.
-/*     
-/************************************************************************/
-
-CONNECTION
-create_listening_connection(id)
-char *id;
-{
-       register CONNECTION con;                /* the connection we're */
-                                               /* creating */
-
-       register int slisten;                   /* socket on which
-                                                  we listen for connections */
-
-       struct sockaddr_in self;
-       int retries = GDB_BIND_RETRY_COUNT;
-       int onoff = 1;                          /* used as argument to */
-                                               /* setsockopt */
-       struct servent *serv;
-
-       GDB_INIT_CHECK
-
-       /*
-        * Try to allocate a connection and fill it in with null values.
-        */
-
-       con = g_make_con();
-
-       /*
-        * Try to create a socket for listening
-        */
-       con->in.fd = socket(AF_INET, SOCK_STREAM, 0);
-       slisten = con->in.fd;                   /* easier and faster than */
-                                               /* using con->in.fd all the */
-                                               /* time*/
-       if (slisten < 0 ) {
-               gdb_perror("create_listening_connection: error creating listen socket");
-               (void) g_stop_with_errno(con);
-               return con;
-       }
-       /*
-        * Set options so the listening address can be re-used (this
-        * has its dangers, but otherwise we can't restart our servers
-        * for long periods after they crash because of connections which
-        * take a long to time clean up and hold ports in use.)
-        */
-
-       /* Try 4.2 method */
-       if(setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, (char *)0,0)<0)
-       /* that didn't work, try 4.3 */
-               if(setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR,
-                             (char *)&onoff, sizeof(int)) <0)
-                       GDB_GIVEUP("create_listening_connection: could not set SO_REUSEADDR")
-                         ;
-       /*
-        * Make the listening socket non-blocking so we won't have to do
-        * selects before polling it (change made by Bill Sommerfeld - wesommer)
-        */
-       if (ioctl(slisten, FIONBIO, (char *)&onoff) < 0) { /*<==FIX,,,add comment */
-               g_stop_with_errno(con);
-               gdb_perror("ioctl for listening socket");
-               return con;
-       }
-               /*----------------------------------------------------------*/
-       /*      
-       /*      Bind the socket to ourselves, using port derived from
-       /*      the supplied id string.
-       /*      
-       /*----------------------------------------------------------*/
-
-       memset((char *)&self, 0, sizeof(self));
-       /*
-        * Determine our port number
-        */
-       if (*id == '#')
-               self.sin_port = htons((u_short)atoi(id+1));
-       else {
-               serv = getservbyname(id, "tcp");
-               if (serv == NULL) {
-                       fprintf(gdb_log,"gdb create_listening_connection: cannot become service named %s\n",id);
-                       return NULL;            /* BUG: causes connetion */
-                                               /* descriptor leakage.  Should */
-                                               /* return an error code in */
-                                               /* the connection descriptor*/
-               }
-               self.sin_port = serv->s_port;
-
-       }
-       /*
-        * Try and re-try the bind until it works or until retry count
-        * is exhausted.
-        */
-       while (bind(slisten,(struct sockaddr *)&self,sizeof(self)) < 0) {
-               if (errno == EADDRINUSE && retries--) {
-                       fprintf(gdb_log,"gdb create_listening_connection: port address in use, will retry %d more time(s)\n",retries+1);
-                       sleep(GDB_BIND_RETRY_INTERVAL);
-                       continue;
-               } else {
-                       gdb_perror("gdb create_listening_connection: error binding listen socket");
-                       g_stop_with_errno(con);
-                       return con;
-               }
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Listen for connections.
-       /*      
-       /*----------------------------------------------------------*/
-
-       (void) listen (slisten, 5);             /* does not block, just */
-                                               /* sets the maximum backlog */
-                                               /* of pending non-accepted */
-                                               /* cons.*/
-
-       con->in.flags |= HCON_LISTEN;
-       con->out.flags |= HCON_UNUSED;
-       con->status = CON_UP;
-       if (con->in.fd +1 > gdb_mfd) 
-               gdb_mfd = con->in.fd + 1;
-       return con;
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_allocate_connection_buffers
-/*     
-/*     Create a buffer which can be used to receive large
-/*     chunks of data from the socket.  This is currently done only
-/*     on the inbound half connection.  Also, the buffers are not freed 
-/*     once allocated, even if the connection descriptor is re-used.
-/*     
-/************************************************************************/
-
-int
-g_allocate_connection_buffers(con)
-CONNECTION con;
-{
-       HALF_CONNECTION inbound = &(con->in);
-
-       /*
-        * See if there is already one allocated, if not, allocate one.
-        */
-       if (inbound->stream_buffer == (char *)NULL) {
-               inbound->stream_buffer = 
-                 db_alloc(inbound->stream_buffer_length);
-       }
-
-       /*
-        * In any case, make sure that it is effectively empty
-        */
-       inbound -> stream_buffer_next = inbound -> stream_buffer;
-       inbound -> stream_buffer_remaining = 0;
-}
diff --git a/gdb/gdb_db.c b/gdb/gdb_db.c
deleted file mode 100644 (file)
index 07f299e..0000000
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_db_c = "$Header$";
-#endif
-
-/************************************************************************/
-/*     
-/*                             gdb_db.c
-/*     
-/*     Authors: Susan Ryan and Noah Mendelsohn
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*             For copying and distribution information, please see
-/*             the file <mit-copyright.h>.
-/*     
-/************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include <string.h>
-#include "gdb.h"
-
-
-
-\f/************************************************************************/
-/*     
-/*                             start_accessing_db (start_accessing_db)
-/*     
-/*     1) Creates a new db structure to describe the database.
-/*     
-/*     2) Parses the supplied db_ident into a server and a db name
-/*     
-/*     3) Opens a connection to the server, sending the name of the 
-/*        database as an argument
-/*     
-/*     4) Asynchronously receives a return code from the server
-/*        to indicate whether the database could be accessed
-/*     
-/*     5) If successful, the handle on the new structure is placed into
-/*        the variable supplied by the caller.  Otherwise, the structure
-/*        is de_allocated and failure status is returned to the caller.
-/*     
-/*     Note: this code was adapted from an earlier synchronous 
-/*           implementation and there may yet be some loose ends.
-/*     
-/************************************************************************/
-
-#define MIN_NAME_LEN 1   /*completely arbitrary */
-#define FAILURE NULL /*until we decide what it should really be */
-                    /*note if fails returns NULL for the db_handle value*/
-                    /*as per above     */
-
-DATABASE g_make_db();
-int g_iadb();
-
-struct adb_data {
-       DATABASE db;
-       OPERATION get_retcode;
-};
-
-int
-start_accessing_db (op, db_ident, db_handle)
-OPERATION op;
-char *db_ident;
-DATABASE *db_handle;               
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      Declarations
-       /*      
-       /*----------------------------------------------------------*/
-
-       register DATABASE db;                   /* the newly created */
-                                               /* structure */
-       register struct adb_data *arg;          /* holds our state */
-                                               /* during async operation*/
-       char *ident, *server, *temp_server;     /* loop variables for */
-                                               /* parsing*/
-       char *db_name, *temp_name;
-       int count;                              /* counts chars during parse */
-
-       CONNECTION connexn;                     /* the connection to the */
-                                               /* database server*/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                  Execution begins here
-       /*      
-       /*      Make sure parameters are correct, then allocate a
-       /*      structure.
-       /*      
-       /*----------------------------------------------------------*/
-
-       GDB_INIT_CHECK
-
-       db_name = NULL;
-       temp_name = NULL;
-       ident = NULL ;
-       server = NULL;
-
-       GDB_CHECK_OP(op, "start_accessing_db")
-
-       if ((db_ident == NULL)|| (strlen(db_ident)<MIN_NAME_LEN)) {
-               fprintf (gdb_log,"access_db: correct syntax is db_name@server \n");
-               *db_handle = NULL;
-               return (OP_CANCELLED);
-       }
-
-       db = g_make_db();
-        *db_handle = db;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Loop to count lengths of server and database names
-       /*      Allocate space for each and copy them both
-       /*      
-       /*----------------------------------------------------------*/
-
-       count = 1;
-       ident = db_ident;
-        while (*ident++ != '@') {
-               count++;
-       }
-
-        db_name = db_alloc (count);            /* space for db_name */
-                                               /* note: this is cleaned */
-                                               /* up by the tear down rtn*/
-
-       count = 1;
-        while (*ident++ != '\0') 
-               count++;
-
-       count += strlen(GDB_DB_SERVICE)+1;      /* leave room for :service */
-        server = db_alloc (count);             /* space for host:service */
-                                               /* note: this is cleaned */
-                                               /* up by the tear down rtn*/
-
-       /*
-        * copy head of db_ident string from db_name@server to db_name
-        */
-       temp_name = db_name;
-       while (*db_ident != '@') {
-               *temp_name = *db_ident;
-               temp_name++;
-               db_ident++;
-       }
-       *temp_name = '\0';
-
-        db->name = db_name;                             
-
-       /*
-        * Set up server host name
-        */
-       temp_server = server;   
-       db_ident++;                             /* skip the '@' */
-        while (*db_ident!= '\0') {
-               *temp_server = *db_ident;
-               temp_server++;
-               db_ident++;     
-       }
-
-       /*
-        * Append :service id to the server host name
-        */
-       *temp_server++ = ':';
-       *temp_server = '\0';
-       (void) strcat(server, GDB_DB_SERVICE);
-
-       db->server = server;
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Create a connection to the server.
-       /*      
-       /*----------------------------------------------------------*/
-
-       connexn = start_server_connection (server, db_name);
-
-       if (connexn==NULL || connection_status(connexn) != CON_UP) {
-            connection_perror(connexn, "Error starting server connection");
-            fprintf (gdb_log, "gdb:access_db: couldn't connect to server %s \n", server);
-            g_tear_down(*db_handle);
-            OP_STATUS(op) = OP_CANCELLED;
-            return (OP_CANCELLED);
-       }
-
-        db->connection = connexn;
-
-       /*
-        * Start asynchronously receiving the return code from the 
-        * data base server.  May take awhile, since ingres is so
-        * slow to start up.
-        */
-
-       arg = (struct adb_data *)db_alloc(sizeof(struct adb_data));
-       arg->get_retcode = create_operation();
-       arg->db = db;
-
-       start_receiving_object (arg->get_retcode, connexn, 
-                               (char *)&(OP_RESULT(op)), INTEGER_T);   
-       /*
-        * Error handling
-        */
-       if (OP_STATUS(arg->get_retcode) == OP_CANCELLED) {
-           g_tear_down (*db_handle);
-           OP_STATUS(op) = OP_CANCELLED;
-           delete_operation(arg->get_retcode);
-           db_free((char *)arg, sizeof(struct adb_data));
-           return OP_CANCELLED;
-        }
-
-       /*
-        * We've successfully queued the receive of the return code.
-        * That's about all we have to do if things go well, but if the
-        * operation fails later, we have to be there to clean up.  To
-        * get control back, we queue ourselves as a second operation
-        * so we can see how the first did, and so we can free up arg.
-        */
-       initialize_operation(op, g_iadb, (char *)arg, (int (*)())NULL); 
-       (void) queue_operation(connexn, CON_INPUT, op);
-
-       return OP_RUNNING;              
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_iadb
-       /*      
-       /*      Init routine for getting return code on accessing a
-       /*      database.  If all went well, (or even if it didn't), then
-       /*      we are done.  All we have to do is clean up the stuff we've
-       /*      allocated.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_iadb(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct adb_data *arg;
-{
-       int rc;
-
-       /*
-        * Figure out how the receipt went
-        */
-       rc = OP_STATUS(arg->get_retcode);
-
-       /*
-        * Release all transient data structures.
-        */
-       if (rc != OP_COMPLETE || op->result != DB_OPEN)
-               g_tear_down(arg->db);
-       else
-               DB_STATUS(arg->db) = DB_OPEN;
-         
-       delete_operation(arg->get_retcode);
-       db_free((char *)arg, sizeof(struct adb_data));
-       
-       return rc;
-}
-\f
-/************************************************************************/
-/*     
-/*                     g_tear_down
-/*     
-/*     this is called by access_db and perf_db_op when a fatal error 
-/*     is reached. It is an attempt to intelligently handle the error,
-/*     and tear down connections and data structures if necessary.
-/*     
-/*     The current version simply tears down everything, perhaps later
-/*     versions should make provision for closing the db as necessary,
-/*     and/or other less drastic ways to handle the errors.
-/*      
-/************************************************************************/
-
-int
-g_tear_down (db_handle)
-DATABASE db_handle;
-{
-       register DATABASE db = db_handle; 
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      If the db is opened, and the connexn is severed, 
-       /*      some error handling, closing of the db should be done 
-       /*      at the server.
-       /*      
-       /*      Also, at the server, perhaps a return code to indicate
-       /*      that user tried to open non-existant db???
-       /*      
-       /*----------------------------------------------------------*/
-         
-
-       if (db==NULL)
-               return;
-
-
-               (void) sever_connection (db->connection);
-
-       /*
-        * Free up the separately allocated strings to which the
-        * database descriptor points
-        */
-       gdb_fstring(db->server);
-       gdb_fstring(db->name);
-
-       /*
-        * Free the descriptor itself
-        */
-       db_free ((char *)db,sizeof(struct db_struct));
-       return;
-}
-\f
-/************************************************************************/
-/*     
-/*                       g_make_db
-/*     
-/*     Allocate and initialize a database descriptor structure.
-/*     
-/************************************************************************/
-
-DATABASE
-g_make_db()
-{
-       register DATABASE db;
-
-       db = (DATABASE)db_alloc (sizeof(struct db_struct));
-       db->id = GDB_DB_ID;
-       db->connection = NULL;
-       db->name = NULL;
-       db->server = NULL;
-       DB_STATUS(db) = DB_CLOSED;
-       
-       return db;
-}
-\f/************************************************************************/
-/*     
-/*                             access_db (access_db)
-/*     
-/*     Does a start_accessing_db and waits for it to complete.
-/*     
-/************************************************************************/
-
-int
-access_db (db_ident, db_handle)
-char *db_ident;
-DATABASE *db_handle;               
-{
-       register OPERATION op;
-       register int status;
-       register int result;
-
-       GDB_INIT_CHECK
-
-       /*
-        * Create an operation and use it to asynchronously access
-        * the database
-        */
-       op = create_operation();
-       (void) start_accessing_db(op, db_ident, db_handle);
-
-       /*
-        * Wait for it to complete, note whether the operation completed
-        * at all, and if so, whether it returned a successful result
-        * in accessing the database.  Then reclaim the space used for
-        * the operation.
-        */
-       (void) complete_operation(op);
-       status = OP_STATUS(op);
-       result = OP_RESULT(op);
-
-       delete_operation(op);
-
-       /*
-        * Tell the caller either that we were interrupted, or pass
-        * on the actual result of accessing the database.  If it
-        * failed, then tear everything down after all.
-        */
-       if (status==OP_COMPLETE)
-               return result;
-       else
-               return status;
-}
-\f/************************************************************************/
-/*     
-/*               start_performing_db_operation (start_performing_db_operation)
-/*     
-/*     Asynchronously performs  any operation except for a query
-/*     on the remote database.
-/*     
-/*     The operation is encoded as a GDB string and sent to the server.
-/*     
-/*     An integer return code is received back and returned to the caller.
-/*     
-/*     Note that this operation executes on both the outbound and inbound
-/*     half connections.  Since there is no explicit sync between the two
-/*     directions, operations like this pipeline freely from requestor
-/*     to server, but there is no way to cancel this operation once it
-/*     has started without severing the accompanying connection.
-/*     
-/************************************************************************/
-
-int g_ipdb();
-
-struct pdb_data {
-       DATABASE db;                            /* the database we're */
-                                               /* working on */
-       OPERATION send_request;                 /* used to send the string */
-                                               /* containing the db oper. */
-                                               /* to be performed */
-       OPERATION get_retcode;                  /* used to get back the */
-                                               /* response to our request */
-       STRING s;                               /* the operation string */
-                                               /* itself.  This is sent. */
-};
-
-#define MIN_REQUEST_LEN 1 /*completely arbitrary */
-#undef FAILURE
-#define FAILURE -1
-
-int
-start_performing_db_operation (op, db_handle,request)
-OPERATION op;
-DATABASE db_handle; 
-char *request;
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      Declarations
-       /*      
-       /*----------------------------------------------------------*/
-
-       register struct pdb_data *arg;          /* holds our state */
-                                               /* during async operation*/
-       register DATABASE db = db_handle;       /* fast working copy */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                  Execution begins here
-       /*      
-       /*      Make sure parameters are correct, then allocate a
-       /*      structure.
-       /*      
-       /*----------------------------------------------------------*/
-
-       GDB_CHECK_OP(op, "start_performing_db_operation ")
-        if (db==NULL) {
-               fprintf (gdb_log, "gdb: start_performing_db_operation: supplied database is NULL\n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-       GDB_CHECK_DB(db, "start_performing_db_operation")
-
-       if (DB_STATUS(db) != DB_OPEN) {
-               fprintf (gdb_log, "gdb: start_performing_db_operation: request to closed database ");
-               OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-       }
-
-        if (db->connection == NULL) {
-                fprintf (gdb_log,
-                        "gdb: start_performing_db_operation: connection severed, request cancelled\n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-        if (connection_status(db->connection) != CON_UP ) {
-                fprintf (gdb_log, "gdb: start_performing_db_operation: problems maintaining connection ");
-               connection_perror(db->connection, "Reason for connection failure");
-               fprintf (gdb_log, "request cancelled \n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-        if ((request == NULL) || (strlen (request)<MIN_REQUEST_LEN)) { 
-                fprintf (gdb_log, "gdb: start_performing_db_operation: request either missing or too short\n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-                  /*should we disallow empty requests? */
-        }
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Asynchronously send the request to the server
-       /*      
-       /*----------------------------------------------------------*/
-
-       /*
-        * Allocate a structure to hold our state while we're gone
-        * waiting for this to complete.
-        */
-
-       arg = (struct pdb_data *)db_alloc(sizeof(struct pdb_data));
-       arg->db = db;
-       arg->send_request = create_operation();
-
-       /*
-        * Send the request string to the server
-        */
-       STRING_DATA(arg->s) = request;
-       MAX_STRING_SIZE(arg->s) = strlen (request) +1;
-       start_sending_object (arg->send_request, db->connection, 
-                               (char *)&(arg->s), STRING_T);   
-       if (OP_STATUS(arg->send_request) == OP_CANCELLED) {
-           OP_STATUS(op) = OP_CANCELLED;
-           delete_operation(arg->send_request);
-           db_free((char *)arg, sizeof(struct pdb_data));
-           return OP_CANCELLED;
-        }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Asynchronously receive the return code (note, we
-       /*      really don't know whether the request has even been
-       /*      sent yet...doesn't really matter.)
-       /*      
-       /*----------------------------------------------------------*/
-
-       arg->get_retcode = create_operation();
-       /*
-        *  This must come here as it sets op_result 
-        */
-       initialize_operation(op, g_ipdb, (char *)arg, (int (*)())NULL);
-
-       start_receiving_object (arg->get_retcode, db->connection, 
-                               (char *)&(OP_RESULT(op)), INTEGER_T);   
-       if (OP_STATUS(arg->get_retcode) == OP_CANCELLED) {
-           OP_STATUS(op) = OP_CANCELLED;
-           (void) cancel_operation(arg->send_request);/* this could be a bug, */
-                                               /* because we introduce */
-                                               /* indeterminism into */
-                                               /* the reply stream, probably */
-                                               /* should shutdown the whole */
-                                               /* db here */
-           delete_operation(arg->send_request);
-           delete_operation(arg->get_retcode);
-           db_free((char *)arg, sizeof(struct adb_data));
-           return OP_CANCELLED;
-        }
-
-       /*
-        * We've successfully queued the receive of the return code.
-        * That's about all we have to do if things go well, but if the
-        * operation fails later, we have to be there to clean up.  To
-        * get control back, we queue ourselves as a second operation
-        * so we can see how the first did, and so we can free up arg.
-        */
-       (void) queue_operation(db->connection, CON_INPUT, op);
-       return OP_RUNNING;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_ipdb
-       /*      
-       /*      Init routine for getting return code on performin a db
-       /*      operation.  If all went well, (or even if it didn't),
-       /*      then we are done.  All we have to do is clean up the
-       /*      stuff we've allocated.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_ipdb(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct pdb_data *arg;
-{
-       int rc1, rc2;
-
-       /*
-        * Figure out how the receipt went
-        */
-       rc1 = OP_STATUS(arg->send_request);
-       rc2 = OP_STATUS(arg->get_retcode);
-
-       /*
-        * Release all transient data structures.
-        */
-       if (rc1 != OP_COMPLETE || rc2 != OP_COMPLETE)
-               g_tear_down(arg->db);
-         
-       delete_operation(arg->send_request);
-       delete_operation(arg->get_retcode);
-       db_free((char *)arg, sizeof(struct pdb_data));
-       
-       return rc2;
-}
-\f
-/************************************************************************/
-/*     
-/*                     perform_db_operation (perform_db_operation)
-/*     
-/*     Do a database operation synchronously.  This just calls
-/*     the async routine and waits for it to complete.
-/*     
-/************************************************************************/
-
-perform_db_operation (db_handle,request)
-DATABASE db_handle; 
-char *request;
-{
-       register OPERATION op;
-       register int status;
-       register int result;
-
-       /*
-        * Create an operation and use it to asynchronously perform
-        * the operation
-        */
-       op = create_operation();
-       (void) start_performing_db_operation(op, db_handle, request);
-
-       /* 
-        * Wait for it to complete, note whether the operation
-        * completed at all, and if so, whether it returned a
-        * successful result.  Then reclaim the space used for the
-        * operation.
-        */
-       (void) complete_operation(op);
-       status = OP_STATUS(op);
-       result = OP_RESULT(op);
-
-       delete_operation(op);
-
-       /*
-        * Tell the caller either that we were interrupted, or pass
-        * on the actual result of accessing the database.  If it
-        * failed, then tear everything down after all.
-        */
-       if (status==OP_COMPLETE)
-               return result;
-       else
-               return status;
-}
-\f/************************************************************************/
-/*     
-/*               start_db_query (start_db_query)
-/*     
-/*     Asynchronously performs a database query on the remote
-/*     database.
-/*     
-/*     The operation is encoded as a GDB string and sent to the server.
-/*     
-/*     An integer return code is received back and returned to the caller.
-/*     
-/*     If the return code indicates success, then we go into a loop
-/*     receiving the retrieved data.  Each returned tuple is preceeded by
-/*     a so-called yes/no flag, which indicates whether tuple data is really
-/*     to follow.  Last tuple is followed by a NO flag.
-/*     
-/*     Note that this operation executes on both the outbound and inbound
-/*     half connections.  Since there is no explicit sync between the two
-/*     directions, operations like this pipeline freely from requestor
-/*     to server, but there is no way to cancel this operation once it
-/*     has started without severing the accompanying connection.
-/*     
-/************************************************************************/
-
-int g_idbq();
-int g_cdbq();
-
-struct dbq_data {
-       /*
-        * Following may be used throughout processing
-        */
-       DATABASE db;                            /* the database we're */
-                                               /* working on */
-       RELATION rel;
-       TUPLE_DESCRIPTOR tpd;
-       /*
-        * used primarily in first phase for sending query and getting
-        * return code
-        */
-       OPERATION send_query;                   /* used to send the string */
-                                               /* containing the query */
-                                               /* to be performed */
-       OPERATION send_descriptor;              /* used to send the tuple */
-                                               /* descriptor to the server */
-       OPERATION get_retcode;                  /* used to get back the */
-                                               /* response to our request */
-       STRING s;                               /* the operation string */
-                                               /* itself.  This is sent. */
-       /*
-        * Following are used during later phase to receive the tuples 
-        */
-       int state;                              /* are we expecting a yes/no */
-                                               /* or a tuple next? */
-#define YESNO 1
-#define TUPDATA 2
-       int yesno;                              /* an indicator of whether */
-                                               /* another tuple is to follow*/
-#define YES 1
-       OPERATION receive_yesno_or_data;
-       TUPLE tup;                              /* a place to put */
-                                               /* the next tuple */
-};
-
-int
-start_db_query (op, db_handle,rel, query)
-OPERATION op;
-DATABASE db_handle; 
-RELATION rel;
-char *query;
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      Declarations
-       /*      
-       /*----------------------------------------------------------*/
-
-       register struct dbq_data *arg;          /* holds our state */
-                                               /* during async operation*/
-       register DATABASE db = db_handle;       /* fast working copy */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                  Execution begins here
-       /*      
-       /*      Make sure parameters are correct, then allocate a
-       /*      structure.
-       /*      
-       /*----------------------------------------------------------*/
-
-       GDB_CHECK_OP(op, "start_db_query ")
-
-        if (rel ==NULL) {
-               fprintf (gdb_log, "gdb: query_db: input rel is null \n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-        if (db==NULL) {
-               fprintf (gdb_log, "gdb: start_db_query: supplied database is NULL\n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-       GDB_CHECK_DB(db, "start_db_query")
-
-       if (DB_STATUS(db) != DB_OPEN) {
-               fprintf (gdb_log, "gdb: start_db_query: request to closed database ");
-               OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-       }
-
-        if (db->connection == NULL) {
-                fprintf (gdb_log,"gdb: start_db_query: connection severed, request cancelled\n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-        if (connection_status(db->connection) != CON_UP ) {
-                fprintf (gdb_log,"gdb: start_db_query: problems maintaining connection ");
-               connection_perror(db->connection, "Reason for connection failure");
-               fprintf (gdb_log,"request cancelled \n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-        if (query == NULL || *query == '\0') { 
-                fprintf (gdb_log, "gdb: start_db_query: request string is null\n");
-                OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-        }
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Asynchronously send the query to the server
-       /*      
-       /*----------------------------------------------------------*/
-
-       /*
-        * Allocate a structure to hold our state while we're gone
-        * waiting for this to complete.
-        */
-
-       arg = (struct dbq_data *)db_alloc(sizeof(struct dbq_data));
-       arg->db = db;
-       arg->rel = rel;
-       arg->send_query = create_operation();
-
-       /*
-        * Send the query string to the server
-        */
-       (void) string_alloc(&(arg->s), strlen(query)+11);
-       (void) strcpy(STRING_DATA(arg->s), "retrieve ");
-       (void) strcat(STRING_DATA(arg->s), query);
-               MAX_STRING_SIZE(arg->s) = strlen (query) +11;
-       start_sending_object (arg->send_query, db->connection, 
-                               (char *)&(arg->s), STRING_T);   
-       if (OP_STATUS(arg->send_query) == OP_CANCELLED) {
-           OP_STATUS(op) = OP_CANCELLED;
-           delete_operation(arg->send_query);
-           string_free(&(arg->s));
-           db_free((char *)arg, sizeof(struct dbq_data));
-           return OP_CANCELLED;
-        }
-
-       /*
-        * Send the tuple descriptor to the server
-        */
-
-       arg->send_descriptor = create_operation();
-       arg->tpd = DESCRIPTOR_FROM_RELATION(arg->rel);
-
-       start_sending_object (arg->send_descriptor, db->connection, 
-                               (char *)&(arg->tpd), TUPLE_DESCRIPTOR_T);
-       if (OP_STATUS(arg->send_descriptor) == OP_CANCELLED) {
-           OP_STATUS(op) = OP_CANCELLED;
-           (void) cancel_operation(arg->send_query);/* this could be a bug, */
-                                               /* because we introduce */
-                                               /* indeterminism into */
-                                               /* the reply stream, probably */
-                                               /* should shutdown the whole */
-                                               /* db here */
-           delete_operation(arg->send_query);
-           delete_operation(arg->send_descriptor);
-           string_free(&(arg->s));
-           db_free((char *)arg, sizeof(struct dbq_data));
-           return OP_CANCELLED;
-        }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Asynchronously receive the return code (note, we
-       /*      really don't know whether the query/and the descriptor
-       /*      have even been sent yet...doesn't really matter.)
-       /*      
-       /*----------------------------------------------------------*/
-
-       arg->get_retcode = create_operation();
-       start_receiving_object (arg->get_retcode, db->connection, 
-                               (char *)&(OP_RESULT(op)), INTEGER_T);   
-       if (OP_STATUS(arg->get_retcode) == OP_CANCELLED) {
-           OP_STATUS(op) = OP_CANCELLED;
-           (void) cancel_operation(arg->send_query);/* this could be a bug, */
-                                               /* because we introduce */
-                                               /* indeterminism into */
-                                               /* the reply stream, probably */
-                                               /* should shutdown the whole */
-                                               /* db here */
-           (void) cancel_operation(arg->send_descriptor);
-           string_free(&(arg->s));
-           delete_operation(arg->send_query);
-           delete_operation(arg->send_descriptor);
-           delete_operation(arg->get_retcode);
-           db_free((char *)arg, sizeof(struct adb_data));
-           return OP_CANCELLED;
-        }
-
-       /*
-        * We've successfully queued the receive of the return code.
-        * That's about all we have to do if things go well, but if the
-        * operation fails later, we have to be there to clean up.  To
-        * get control back, we queue ourselves as a second operation
-        * so we can see how the first did, and so we can free up arg.
-        */
-       initialize_operation(op, g_idbq, (char *)arg, (int (*)())NULL);
-       (void) queue_operation(db->connection, CON_INPUT, op);
-
-       return OP_RUNNING;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_idbq
-       /*      
-       /*      Init routine for getting return code on performing a
-       /*      bd query.  If there was an error, then we are done except for
-       /*      cleaning up all the dynamic memory we allocated.
-       /*      If the return code was 0,then we must asynchronously
-       /*      do the following iteratively until a no is received:
-       /*      
-       /*        while (async_receive(yes/no) == yes) {
-       /*             async receive new tuple
-       /*             add it to the relation 
-       /*        } 
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_idbq(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct dbq_data *arg;
-{
-       int rc1, rc2, rc3;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      See how the three asynchronous operations went,and
-       /*      clean up after them.
-       /*      
-       /*----------------------------------------------------------*/
-
-       /*
-        * Figure out how the receipt went
-        */
-       rc1 = OP_STATUS(arg->send_query);
-       rc2 = OP_STATUS(arg->send_descriptor);
-       rc3 = OP_STATUS(arg->get_retcode);
-
-       /*
-        * Release all transient data structures which were used in the
-        * preliminary operations.
-        */
-       delete_operation(arg->send_query);
-       delete_operation(arg->get_retcode);
-       string_free(&(arg->s));
-       /*
-        * If we've failed for any reason, then mark ourselves complete and
-        * return.
-        */
-       if (rc1 != OP_COMPLETE || rc2 != OP_COMPLETE|| rc3 != OP_COMPLETE
-           || OP_RESULT(op) != OP_SUCCESS) {
-                   OP_STATUS(op) = rc3;        /* we must have done */
-                                               /* about as well as */
-                                               /* the last one */
-               
-                   db_free((char *)arg, sizeof(struct dbq_data));
-                   return rc3;                 /* tell the dispatcher */
-                                               /* that we're either */
-                                               /* cancelled or complete */
-        }
-         
-       /*----------------------------------------------------------*/
-       /*      
-       /*      We've successfully received a return code of 0 from
-       /*      Ingres, which means we are now going to begin the
-       /*      yes/no loop.
-       /*      
-       /*----------------------------------------------------------*/
-
-       op->fcn.cont = g_cdbq;                  /* after the preempting */
-                                               /* receive completes, the */
-                                               /* dispatcher will call */
-                                               /* this routine. */
-       arg->state = YESNO;                     /* tell continuation routine */
-                                               /* that we're receiving */
-                                               /* a yes/no */
-       arg->tup = NULL;                        /* so we won't try to clean */
-                                               /* it up */
-       arg->receive_yesno_or_data = create_operation();
-       
-       preempt_and_start_receiving_object(arg->receive_yesno_or_data,
-                                          op,
-                                          (char *)&(arg->yesno),
-                                          INTEGER_T);
-       return OP_PREEMPTED;    
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_cdbq
-       /*      
-       /*      Continuation routine for receiving results of a query.
-       /*      Tbis is called repeatedly each time either a yes/no or
-       /*      a new tuple is received.  It repeatedly preempts itself
-       /*      to receive the next yes/no or tuple until a 'no'
-       /*      is finally received.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_cdbq(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct dbq_data *arg;
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*      See whether the preempting operation completed
-       /*      successfully.  If not, we just clean up and cancel
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (OP_STATUS(arg->receive_yesno_or_data) != OP_COMPLETE) {
-               delete_operation(arg->receive_yesno_or_data);
-               if (arg->tup != NULL)
-                       delete_tuple(arg->tup);
-               db_free((char *)arg, sizeof(struct dbq_data));
-               OP_STATUS(op) = OP_CANCELLED;
-               return OP_CANCELLED;
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Whatever it was, we received it cleanly.  If it 
-       /*      was tuple data, then accept it and prepare to receive
-       /*      a yesno.  If it was a yes, then prepare to receive
-       /*      the tuple data.  If it was a NO, then we're all done.
-       /*      
-       /*      Note that g_cdbg will be recalled by the dispatcher
-       /*      after the preempting routines have completed.
-       /*      
-       /*----------------------------------------------------------*/
-
-       /*
-        * New TUPLE DATA
-        */
-
-       if (arg->state == TUPDATA) {
-               ADD_TUPLE_TO_RELATION(arg->rel, arg->tup);
-               arg->tup = NULL;                /* so we won't try to */
-                                               /* delete it in case of error*/
-               reset_operation(arg->receive_yesno_or_data);
-               arg->state = YESNO;
-               preempt_and_start_receiving_object(arg->receive_yesno_or_data,
-                                                  op,
-                                                  (char *)&(arg->yesno),
-                                                  INTEGER_T);
-               return OP_PREEMPTED;    
-       }
-
-       /*
-        * We just received a yes or no. If it's a YES, prepare to
-        * receive some more tuple data.
-        */
-       if (arg->yesno == YES)  {
-               arg->tup = create_tuple(arg->tpd);
-               reset_operation(arg->receive_yesno_or_data);
-               arg->state = TUPDATA;
-               preempt_and_start_receiving_object(arg->receive_yesno_or_data,
-                                                  op,
-                                                  (char *)arg->tup,
-                                                  TUPLE_DATA_T);
-               return OP_PREEMPTED;    
-       }
-       /*
-        * We just received a NO.  Looks like we're all done cleanly.
-        */
-       delete_operation(arg->receive_yesno_or_data);
-       if (arg->tup != NULL)
-               delete_tuple(arg->tup);
-       db_free((char *)arg, sizeof(struct dbq_data));
-       OP_STATUS(op) = OP_COMPLETE;
-       return OP_COMPLETE;
-       
-}
-\f
-/************************************************************************/
-/*     
-/*                             db_query (db_query)
-/*     
-/*     Perform a relational query on the specified database.
-/*     
-/*     This just calls the asynchronous form of doing a query and
-/*     waits for it to complete.
-/*     
-/*     
-/************************************************************************/
-
-int
-db_query(db_handle, rel, query)
-DATABASE db_handle; 
-RELATION rel;
-char *query;
-{
-       register OPERATION op;
-       register int status;
-       register int result;
-
-       /*
-        * Create an operation and use it to asynchronously perform
-        * the operation
-        */
-       op = create_operation();
-       (void) start_db_query(op, db_handle, rel, query);
-
-       /* 
-        * Wait for it to complete, note whether the operation
-        * completed at all, and if so, whether it returned a
-        * successful result.  Then reclaim the space used for the
-        * operation.
-        */
-       (void) complete_operation(op);
-       status = OP_STATUS(op);
-       result = OP_RESULT(op);
-
-       delete_operation(op);
-
-       /*
-        * Tell the caller either that we were interrupted, or pass
-        * on the actual result of accessing the database.  If it
-        * failed, then tear everything down after all.
-        */
-       if (status==OP_COMPLETE)
-               return result;
-       else
-               return status;
-}
diff --git a/gdb/gdb_debug.c b/gdb/gdb_debug.c
deleted file mode 100644 (file)
index 3bf0c74..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_debug_c = "$Header$";
-#endif
-
-/************************************************************************/
-/*      
-/*                      gdb_debug.c
-/*      
-/*      Debugging interfaces for gdb.  Some of these are
-/*     designed to be called from dbx.
-/*      
-/*      routines included are:
-/*     
-/*             gdb_debug set the debugging status flags
-/*      
-/*              gd_types_print prints all the available types currently in
-/*                      the type table
-/*              
-/*              gd_con_status prints all the status codes for connections
-/*      
-/*              gd_sum_cons summarizes all current connections detailing 
-/*                      for each flags, half connections with their 
-/*                      respective operation queues.
-/*      
-/*              gd_op_q (halfcon) prints the queue associated with a 
-/*                      specified half connection (not directly callable) 
-/*              
-/*              gd_op_status a listing of the available states of an
-/*                      operation
-/*      
-/*      Copyright 1986 MIT Project Athena
-/*             For copying and distribution information, please see
-/*             the file <mit-copyright.h>.
-/*      
-/************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include "gdb.h"
-
-/************************************************************************/
-/*     
-/*                     gdb_debug
-/*     
-/*     Toggle a debugging flag.  Warning:  the interface to this routine
-/*     may change over time.
-/*     
-/************************************************************************/
-
-int
-gdb_debug(flag)
-{
-       gdb_Debug ^= flag;                      /* toggle the flag */
-}
-
-/************************************************************************/
-/*     
-/*                     print_relation
-/*     
-/************************************************************************/
-
-int
-print_relation(name, relation)
-char *name;
-RELATION relation;
-{
-       FCN_PROPERTY(RELATION_T,FORMAT_PROPERTY)(name, (char *)&(relation));
-}
-/************************************************************************/
-/*     
-/*                     print_tuple
-/*     
-/************************************************************************/
-
-int
-print_tuple(name, tuple)
-char *name;
-TUPLE tuple;
-{
-       FCN_PROPERTY(TUPLE_T,FORMAT_PROPERTY)(name, (char *)&(tuple));
-}
-
-/************************************************************************/
-/*     
-/*                     print_tuple_descriptor
-/*     
-/************************************************************************/
-
-int
-print_tuple_descriptor(name, tuple_descriptor)
-char *name;
-TUPLE_DESCRIPTOR tuple_descriptor;
-{
-       FCN_PROPERTY(TUPLE_DESCRIPTOR_T,FORMAT_PROPERTY)(name, 
-                                            (char *)&(tuple_descriptor));
-}
-
-/************************************************************************/
-/*      
-/*                      gd_types_print
-/*
-/*      This is a routine for printing all the available types and 
-/*      their typecodes.
-/*      
-/************************************************************************/
-
-int
-gd_types_print ()
-{
-       register int i;
-
-       printf ("\n\nTHE AVAILABLE TYPES WITH THEIR TYPE CODES ARE: \n\n");
-
-       printf ("typecode     name\n");
-
-       for (i = 0; i < gdb_n_types; i++) {
-               printf ("%2d       %s \n", i, STR_PROPERTY(i,NAME_PROPERTY));
-       }
-}
-\f
-/************************************************************************/
-/*      
-/*                      con_status
-/*      
-/*      This routine will print all the status codes for operations 
-/*      This is just a listing of the status numbers located in gdb.h
-/*      
-/************************************************************************/
-
-int
-gd_con_status () 
-{
-        /*----------------------------------------------------------*/
-        /*      
-        /*      REMEMBER... these need to be fixed when the connection
-        /*      status coded in gdb.h are redefined.
-        /*      
-        /*----------------------------------------------------------*/
-
-        printf ("THE STATUS CODES ARE: \n\n");
-        printf (" CODE     STATUS\n");
-        printf ("   1      CON_STOPPED\n");
-        printf ("   2      CON_UP\n");
-        printf ("   3      CON_STARTING\n");
-        printf ("   4      CON_STOPPING\n"); 
-
-}
-
-\f
-/************************************************************************/
-/*      
-/*                      summarize connections (gd_sum_con)
-/*      
-/************************************************************************/
-
-gd_sum_con (index)
-int index;
-{
-        if ((index > gdb_mcons) || (gdb_cons[index].status<1)) {
-                printf ("gdb_cons[%d] is not a valid connection \n",index);
-                return;
-        }
-
-        if (gdb_cons[index].status == CON_STOPPED) {
-                printf ("connection gdb_cons[%d] is stopped\n",index);
-                return;
-        }
-
-        /*----------------------------------------------------------*/
-        /*      
-        /*      REMEMBER this also must be changed when the def'n
-        /*      of status fields in gdb.h is changed 
-        /*      
-        /*----------------------------------------------------------*/
-
-                
-        printf ("status of connection number %d is %2d \n",index,gdb_cons[index].status);
-        printf ("The information for each half-connexn: \n\n");
-
-        printf ("    the inbound half-connection\n");
-        printf ("              status: %2d \n",gdb_cons[index].in.status);
-        printf ("              flags : %2d \n",gdb_cons[index].in.status);
-        printf ("              file descr: %2d \n",gdb_cons[index].in.fd);
-        printf ("              The operation queue is:\n");
-        gd_op_q (&(gdb_cons[index].in));
-
-        printf ("    the outbound half-connection\n");
-        printf ("              status: %2d \n",gdb_cons[index].out.status);
-        printf ("              flags : %2d \n",gdb_cons[index].out.status);
-        printf ("              file descr: %2d \n",gdb_cons[index].out.fd);
-        printf ("              The operation queue is:\n");
-        gd_op_q (&(gdb_cons[index].out));
-      }
-
-\f
-/************************************************************************/
-/*
-/*                      op_q (gd_op_q) 
-/*      
-/************************************************************************/
-
-
-int 
-gd_op_q (half_con)
-HALF_CONNECTION half_con;
-
-{
-        int i;                                  /*counter for the ith
-                                                  queued op */
-        OPERATION current;
-        
-        current = half_con->op_q_first;  
-
-        i = 0;
-        
-        if (current == NULL) {
-                printf ("no operations in queue yet\n");
-                return ;
-        }
-
-
-        printf ("OPERATION       STATUS\n\n");
-
-        while (current != (OPERATION)half_con)  {
-                printf ("%2d              %2d \n", i++ , current->status);
-                current = current ->next;
-        }
-}
-\f
-/************************************************************************/
-/*      
-/*                      op status
-/*      this is a routine in which all the status codes and their 
-/*      translations are printed.
-/*      
-/************************************************************************/
-       
-int 
-gd_op_status ()
-{
-        /*----------------------------------------------------------*/
-        /*      
-        /*      REMEMBER these also need to be changed when 
-        /*      states of an operation in gdb.h is redefined
-        /*      
-        /*----------------------------------------------------------*/
-
-          printf ("CODE    OPERATION STATE\n\n");
-          printf (" 1      OP_NOT_STARTED\n");
-          printf (" 2      OP_QUEUED\n");
-          printf (" 3      OP_RUNNING\n");
-          printf (" 4      OP_COMPLETE\n");
-          printf (" 5      OP_CANCELLING\n");
-          printf (" 6      OP_CANCELLED\n");
-          printf (" 7      OP_MARKED\n");
-}
diff --git a/gdb/gdb_fserv.c b/gdb/gdb_fserv.c
deleted file mode 100644 (file)
index 7275b4e..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_fserv_c = "$Header$";
-#endif
-
-
-/************************************************************************
- *     
- *                        gdb_fserv.c
- *     
- *           GDB - Routines to implement forking servers.
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena 
- *             For copying and distribution information, please see
- *             the file <mit-copyright.h>.
- *     
- ************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/signal.h>
-#include "gdb.h"
-#include <sys/resource.h>
-#ifdef POSIX
-#include <unistd.h>
-#endif
-
-
-/************************************************************************
- *     
- *                     create_forking_server (create_forking_server)
- *     
- *     Called by an application to turn itself into a forking model
- *     server.  Returns from this routine occur only in the forked
- *     children.  The parent lives in this routine forever, waiting
- *     for incoming connection requests and doing the appropriate
- *     forking.
- *     
- *     Children are expected to do their own cleanup, but this routine
- *     does do the work of reaping the resulting zombie processes.
- *     
- *     ARGUMENTS:
- *     ----------
- *     
- *             service-id      identifies the port to be used for
- *                             listening.  Same rules as for
- *                             create_listening_connection.
- *     
- *             validate-rtn    pointer to a function to be called to
- *                             validate the incoming client.  Should
- *                             return TRUE if client is acceptable,
- *                             else false.  If this is NULL, all clients
- *                             are accepted.
- *     
- *     GLOBAL VARIABLES
- *     ----------------
- *     
- *     Children created by this routine inherit the global variables
- *     gdb_sockaddr_of_client, which is of type sockaddr_in and 
- *     gdb_socklen, which is the returned length of the sockaddr.
- *     These are the Berkeley identifiers of the clients as accepted.
- *     Use of this interface is non-portable to other than Berkeley 
- *     systems.
- *     
- *     The client's request tuple may be found in gdb_client_tuple.
- *     
- ************************************************************************/
-
-
-CONNECTION
-create_forking_server(service, validate)
-char *service;
-int (*validate)();
-{
-       void start_accepting_client();
-       CONNECTION incoming;                    /* listen for incoming */
-                                               /* children here */
-       CONNECTION client = NULL;               /* connection to client */
-                                               /* is created here */
-       OPERATION listenop;                     /* used to asynchronously */
-                                               /* listen for a child */
-                                               /* connection request */
-       GDB_INIT_CHECK
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Set up parent execution environment
-       /*      
-       /*----------------------------------------------------------*/
-
-       g_do_signals();                         /* set up signal handling */
-
-       incoming = create_listening_connection(service);
-       if (incoming == NULL || connection_status(incoming) != CON_UP)
-               GDB_GIVEUP("create_forking_server: can't create listening connection")
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Repeatedly listen for incoming
-       /*      
-       /*----------------------------------------------------------*/
-
-       listenop = create_operation();
-       while (TRUE) {
-               gdb_socklen = sizeof(gdb_sockaddr_of_client);
-               client = NULL;
-               (void) start_accepting_client(incoming, listenop, &client, 
-                                      gdb_sockaddr_of_client, &gdb_socklen,
-                                      &gdb_client_tuple);
-               if(complete_operation(listenop) != OP_COMPLETE ||
-                  client == NULL) {
-                   gdb_perror("GDB create_forking_server: failed to accept client");
-                   reset_operation(listenop);
-                   (void) sever_connection(client);
-                   continue;
-                 }
-               
-
-                /*
-                 * Call the validate routine, if it fails, 
-                 * refuse the client.
-                 */
-               if (validate != NULL && !(*validate)()) {
-                       reset_operation(listenop);
-                       start_replying_to_client(listenop, client, 
-                                                GDB_REFUSED, "","");
-                       (void) complete_operation(listenop); 
-                       reset_operation(listenop);
-                       (void) sever_connection(client);
-                       continue;                       
-               }
-                /*
-                 * Create  the child for this client
-                 */
-               if ((gdb_Debug & GDB_NOFORK) || fork() == 0) {
-                       /*
-                        * This is the child, or we're in noforking
-                        * debug mode.
-                        */
-                       reset_operation(listenop);
-                       start_replying_to_client(listenop, client, 
-                                                GDB_ACCEPTED, "","");
-                       if (complete_operation(listenop) != OP_COMPLETE) 
-                               exit(8);
-                       return client;          /* return to application */
-                                               /* program */
-               }
-               /*
-                * Still in the parent
-                */
-               (void) sever_connection(client);
-               reset_operation(listenop);
-       }
-}
-\f
-/************************************************************************/
-/*     
-/*                             gdb_reaper
-/*     
-/*     Called on SIGCHILD to reap all dead children.
-/*     
-/************************************************************************/
-#ifndef POSIX
-int
-#else
-void
-#endif
-gdb_reaper()
-{
-#ifdef POSIX
-       int status;
-#else
-       union wait status;
-#endif
-       
-#ifdef POSIX
-       while (waitpid(-1, &status, WNOHANG) >0);
-#else
-       while (wait3(&status, WNOHANG, (struct rusage *)0) >0);
-#endif
-}
-\f
-/************************************************************************/
-/*     
-/*                             g_do_signals
-/*     
-/*     Set up signal handling for a forking server.
-/*     
-/************************************************************************/
-
-int
-g_do_signals()
-{
-#ifdef POSIX
-    struct sigaction act;
-
-    act.sa_handler = gdb_reaper;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = 0;
-    (void) sigaction(SIGCHLD, &act, (struct sigaction *)0);
-#else /* sun */
-    (void) signal(SIGCHLD, gdb_reaper);
-#endif 
-}
diff --git a/gdb/gdb_lib.h b/gdb/gdb_lib.h
deleted file mode 100644 (file)
index b9f5205..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-/************************************************************************/
-/*     
-/*                     gdb_lib.h
-/*     
-/*     Includes used within the Global Database Facilities library.
-/*     Should NOT be included by typical users of gdb.
-/*     
-/*     Author: Noah Mendelsohn
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-
-/************************************************************************/
-/*     
-/*                         USER IDENTIFICATION
-/*     
-/*     gdb_init puts the user's i.d. and hostname as strings here.
-/*     
-/************************************************************************/
-
-char *gdb_uname;                               /* user's string name */
-char *gdb_host;                                        /* name of local host */
-                                               /* goes here */
-
-
-/************************************************************************/
-/*     
-/*                         MEMORY MANAGEMENT
-/*     
-/*     These vectors point to the memory allocation and free routines.
-/*     The standard routines supplied with the system are gdb_am and
-/*     gdb_fm, but users may supply their own by clobbering the vectors.
-/*     
-/************************************************************************/
-
-char *((*gdb_amv)()) = gdb_am;
-int  (*gdb_fmv)() = gdb_fm;
-
-
-
-/************************************************************************/
-/*     
-/*     
-/*                       SYSTEM TYPE DEFINITIONS
-/*     
-/*     Declarations used to control the definition and use of 'types'
-/*     as supported by the global database system.
-/*     
-/*     
-/************************************************************************/
-
-int    gdb_Options=0;                          /* GDB options are set here */
-
-int    gdb_Debug=0;                            /* debugging flags are */
-                                               /* stored here */
-FILE *gdb_log = stderr;                                /* all debugging */
-                                               /* output goes on stderr*/
-
-char g_errstr[150];                            /* build emsgs here */
-
-/*
- *                     g_type_table
- * 
- * This is the table where the actual definitions for the types are
- * kept.
- */
-
-gdb_type_def g_type_table[GDB_MAX_TYPES];
-int gdb_n_types;                               /* number of entries in */
-                                               /* table */
-/*
- *                     connection failure indicator
- * 
- * This variable is used to communicate between gdb_move_data and
- * g_con_progress without passing an extra parameter through lots
- * of procedure calls.  When set to FALSE, it indicates that the 
- * connection currently being processed has encountered a fatal error
- * and should be severed.
- */
-int gdb_conok;                                 
-\f
-/************************************************************************/
-/*     
-/*          CONNECTION AND DATA TRANSMISSION SERVICES
-/*     
-/*     These are the global data structures used by the routines
-/*     which maintain connections and do asynchronous data transfer
-/*     on them.
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_cons
-       /*      
-       /*      This is the array of connection control data 
-       /*      structures for gdb.  Every connection has its 
-       /*      structure stored here, but they are in no 
-       /*      particular order.  Because the connection data
-       /*      itself cannot be moved (due to possible dangling
-       /*      pointers), there may be some unused connections 
-       /*      in the middle of this array.  gdb_mcons is the
-       /*      1 based number of the highest connection which is
-       /*      actually in use at this time.  This is a considerable
-       /*      optimization for the typical case where very few
-       /*      are in use, and turnover is low.
-       /*      
-       /*----------------------------------------------------------*/
-
-int    gdb_mcons;                              /* 0 based index of */
-                                               /* last connection */
-                                               /* currently in use */
-
-int  gdb_mfd;                                  /* number of the highest */
-                                               /* file descriptor in use */
-                                               /* for a connection */
-struct con_data gdb_cons[GDB_MAX_CONNECTIONS]; /* actual connection data */
-                                               /* is stored here */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Bit maps of the file descriptors involved in connections.
-       /*      Technically, this is redundant with the information in
-       /*      the connection descriptors above, but it makes select
-       /*      preparation much faster.
-       /*      
-       /*----------------------------------------------------------*/
-
-fd_set gdb_crfds, gdb_cwfds, gdb_cefds;                /* connection related file */
-                                               /* descriptor maps to be */
-                                               /* used in select */
-fd_set last_crfds, last_cwfds, last_cefds;     /* these file desc. bit */
-                                               /* masks are set up */
-                                               /* for each select call */
-                                               /* to include the user */
-                                               /* supplied and the */
-                                               /* connection related */
-                                               /* fd's */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_notime
-       /*      
-       /*      Pass this to select when doing a poll.
-       /*      
-       /*----------------------------------------------------------*/
-
-struct timeval gdb_notime = {0,0};
-\f
-/************************************************************************/
-/*     
-/*                    SERVER/CLIENT MANAGEMENT
-/*     
-/*     Definitions used in starting and maintaining communication 
-/*     between servers and clients (as opposed to peers.)
-/*     
-/************************************************************************/
-
-TUPLE_DESCRIPTOR gdb_tosrv;                    /* descriptor for request */
-                                               /* tuples sent to the */
-                                               /* server during negotiation*/
-
-TUPLE_DESCRIPTOR gdb_fmsrv;                    /* descriptor for request */
-                                               /* tuples sent from the */
-                                               /* server during negotiation*/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Global variables inherited by a child from a server
-       /*      parent.
-       /*      
-       /*----------------------------------------------------------*/
-
-TUPLE gdb_client_tuple;                                /* request tuple sent from */
-                                               /* the client */
-
-char gdb_sockaddr_of_client[100];              /* this should really be */
-                                               /* sockaddr_in, but I don't */
-                                               /* want everyone to have */
-                                               /* to include all those */
-                                               /* big .h files */
-int gdb_socklen;                               /* length of above */
-
diff --git a/gdb/gdb_ops.c b/gdb/gdb_ops.c
deleted file mode 100644 (file)
index ce922ac..0000000
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
- * $Source$
- * $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_ops_c = "$Header$";
-#endif
-
-
-/************************************************************************
- *     
- *                        gdb_ops.c
- *     
- *           GDB - Asynchronous Operations and Their Synchronous
- *                 Counterparts
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena 
- *             For copying and distribution information, please see
- *             the file <mit-copyright.h>.
- *     
- *     These routines provide a suite of asynchronous operations 
- *     on connections.
- *     
- ************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include "gdb.h"
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#ifdef SOLARIS
-#include <sys/filio.h>
-#endif
-
-/************************************************************************
- *     
- *                     send_object (send_object)
- *     
- *     Synchronous form of start_sending_object.  Returns either
- *     OP_CANCELLED, or OP_RESULT(op).
- *     
- ************************************************************************/
-
-int
-send_object(con, objp, type)
-CONNECTION con;
-char *objp;
-int type;
-{
-       register OPERATION op;
-       register int retval;
-
-
-       op = create_operation();
-       start_sending_object(op, con, objp, type);
-       (void) complete_operation(op);
-       if (OP_STATUS(op) == OP_COMPLETE)
-               retval =  OP_RESULT(op);
-       else
-               retval = OP_STATUS(op);
-       delete_operation(op);
-       return retval;
-}
-
-
-/************************************************************************/
-/*     
-/*                     start_send_object (g_snobj)
-/*     
-/*     Start the asynchronous transmission of a gdb object.
-/*     Note that this routine must be passed the address of the object,
-/*     not the object itself.
-/*     
-/*     The following three routines work together, and may be considered
-/*     as a single entity implementing the operation.  The first merely
-/*     saves away its arguments and queues the operation on the designated
-/*     connection.  These stay there until they percolate to the head of
-/*     the queue.  The second is the initialization routine, which is
-/*     called by the connection maintenance logic when the operation
-/*     first reaches the head of the queue.  This routine encodes
-/*     the supplied data for transmission, and then sends it.  If the
-/*     transmission executes synchronously, then the third routine is
-/*     called immediately to clean up.  If not, the third routine is
-/*     marked as the 'continuation' routine, which will cause its 
-/*     invocation when the transmission completes.
-/*     
-/*     The data is preceded by its length expressed as a 32-bit number in 
-/*     network byte order.
-/*     
-/************************************************************************/
-
-struct obj_data {
-       char    *objp;                          /* address of the object to */
-                                               /* be sent */
-       int     type;                           /* type code for the object */
-                                               /* to be sent*/
-       char    *flattened;                     /* address of first byte */
-                                               /* of flattened data */
-       int     len;                            /* length of the flattened */
-                                               /* data */
-};
-
-int g_isnobj();
-int g_csnobj();
-
-int
-start_sending_object(op, con, objp, type)
-OPERATION op;
-CONNECTION con;
-char *objp;
-int type;
-{
-       struct obj_data *arg;
-
-       /*
-        * Make sure the supplied connection is a legal one
-        */
-       GDB_CHECK_CON(con, "start_sending_object")
-       GDB_CHECK_OP(op, "start_sending_object")
-
-       arg = (struct obj_data *)db_alloc(sizeof(struct obj_data));
-
-       arg->objp = objp;
-       arg->type = type;
-       initialize_operation(op, g_isnobj, (char *)arg, (int (*)())NULL);
-       (void) queue_operation(con, CON_OUTPUT, op);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_isnobj
-       /*      
-       /*      Init routine for sending an object.  This routine is 
-       /*      called by the connection management logic when the send
-       /*      request percolates to the top of the queue.  This routine
-       /*      reformats the data into an appropriate form for transmission.
-       /*      The format used is a length, represented as a 32-bit # in 
-       /*      network byte order, followed by the data itself.  The
-       /*      continuation routine below is called, either synchronously 
-       /*      or asynchronously, once the transmission is complete.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_isnobj(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct obj_data *arg;
-{
-       /*
-        * Find out the encoded length of the data
-        */
-       arg->len = FCN_PROPERTY(arg->type, CODED_LENGTH_PROPERTY)
-                              (arg->objp, hcon);
-
-       /*
-        * Allocate space and flatten (encode) the data
-        */
-       arg->flattened = db_alloc(arg->len+sizeof(int32));
-       *(uint32 *)arg->flattened = htonl((uint32)arg->len);
-
-       FCN_PROPERTY(arg->type, ENCODE_PROPERTY)
-                              (arg->objp, hcon, arg->flattened+sizeof(int32));
-
-       /*
-        * Set up continuation routine in case it's needed after the return
-        */
-       op->fcn.cont = g_csnobj;
-
-       /*
-        * Start sending the data, maybe even complete
-        */
-       if (gdb_send_data(hcon, arg->flattened, arg->len + sizeof(int32)) == 
-           OP_COMPLETE) {              
-               return g_csnobj(op, hcon, arg)  ;/* this return is a little */
-                                               /* subtle.  As continuation */
-                                               /* routines call each other */
-                                               /* synchronously, the last */
-                                               /* one determines whether we */
-                                               /* completed or are still */
-                                               /* running.  That status */
-                                               /* percolates back through */
-                                               /* the entire call chain. */
-       } else {
-               return OP_RUNNING;
-       }
-}
-
-
-       
-
-       
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*                       g_csnobj
-       /*      
-       /*      Continuation routine for sending an object.  Since there is
-       /*      only one transmission, started by the init routine, this is
-       /*      called when that transmission is done, and it does all the
-       /*      associated clean up.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_csnobj(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct obj_data *arg;
-{
-       op->result = OP_SUCCESS;                
-       db_free((char *)arg->flattened, arg->len + sizeof(int32));
-                                               /* free the sent data */
-       db_free((char *)arg, sizeof(struct obj_data));  /* free the state structure */
-       return OP_COMPLETE;
-}
-
-
-/************************************************************************/
-/*     
-/*                     receive_object (receive_object)
-/*     
-/*     Synchronous form of start_receiving_object.  Returns either
-/*     OP_CANCELLED, or OP_RESULT(op).
-/*     
-/************************************************************************/
-
-int
-receive_object(con, objp, type)
-CONNECTION con;
-char *objp;
-int type;
-{
-       register OPERATION op;
-       register int retval;
-
-       op = create_operation();
-       start_receiving_object(op, con, objp, type);
-       (void) complete_operation(op);
-       if (OP_STATUS(op) == OP_COMPLETE)
-               retval =  OP_RESULT(op);
-       else
-               retval = OP_STATUS(op);
-       delete_operation(op);
-       return retval;
-}
-
-
-/************************************************************************/
-/*     
-/*                     start_receiving_object (g_rcobj)
-/*     
-/*     Start the asynchronous receipt of a gdb object.  Note that this
-/*     routine must be passed the address of the object, not the object
-/*     itself.  In the case of structured objects, this routine may 
-/*     allocate the necessary storage.  The work to build the object is
-/*     done by the object's decode routine.
-/*     
-/*     The following three routines work together, and may be considered
-/*     as a single entity implementing the operation.  The first merely
-/*     saves away its arguments and queues the operation on the designated
-/*     connection.  These stay there until they percolate to the head of
-/*     the queue.  The second is the initialization routine, which is
-/*     called by the connection maintenance logic when the operation
-/*     first reaches the head of the queue.  This routine initiates a read
-/*     for the length of the object, and sets up a continuation routine
-/*     to read the object itself.  When the object itself has been read, it 
-/*     is decoded and the operation completes.
-/*     
-/*     The data is preceded by its length expressed as a 32-bit number in 
-/*     network byte order.
-/*     
-/*                     preempt_and_start_receiving_object (g_prcobj)
-/*     
-/*     Similar to above, but may be called only from an active operation
-/*     (i.e. an init or continue routine) on an inbound half connection.
-/*     The receive effectively pre-empts the old operation, which wil
-/*     continue after the receive is done.
-/*     
-/*     
-/************************************************************************/
-
-struct robj_data {
-       char    *objp;                          /* address of the object to */
-                                               /* be received */
-       int     type;                           /* type code for the object */
-                                               /* to be received */
-       char    *flattened;                     /* address of first byte */
-                                               /* of flattened data */
-       int     len;                            /* length of the flattened */
-                                               /* data */
-};
-
-int g_ircobj();
-int g_c1rcobj();
-int g_c2rcobj();
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*              start_receiving_object
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-start_receiving_object(op, con, objp, type)
-OPERATION op;
-CONNECTION con;
-char *objp;
-int type;
-{
-       struct robj_data *arg;
-
-       /*
-        * Make sure the supplied connection is a legal one
-        */
-       GDB_CHECK_CON(con, "start_receiving_object")
-       GDB_CHECK_OP(op, "start_receiving_object")
-
-       arg = (struct robj_data *)db_alloc(sizeof(struct robj_data));
-
-       arg->objp = objp;
-       arg->type = type;
-       initialize_operation(op, g_ircobj, (char *)arg, (int (*)())NULL);
-       (void) queue_operation(con, CON_INPUT, op);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*              preempt_and_start_receiving_object
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-preempt_and_start_receiving_object(op, oldop, objp, type)
-OPERATION op;
-OPERATION oldop;
-char *objp;
-int type;
-{
-       struct robj_data *arg;
-
-       /*
-        * Make sure the supplied connection is a legal one
-        */
-       GDB_CHECK_OP(op, "preempt_and_start_receiving_object")
-       GDB_CHECK_OP(oldop, "preempt_and_start_receiving_object")
-
-       arg = (struct robj_data *)db_alloc(sizeof(struct robj_data));
-
-       arg->objp = objp;
-       arg->type = type;
-       initialize_operation(op, g_ircobj, (char *)arg, (int (*)())NULL);
-       (void) g_preempt_me(oldop, op);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_ircobj
-       /*      
-       /*      Initialization routine for receiving an object.  
-       /*      Called when the receive operation percolates to the
-       /*      top of the queue.  First, we must receive the single
-       /*      32-bit # which carries the length of the rest of the data.
-       /*      We do that now, either synchronously or asynchronously.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_ircobj(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct robj_data *arg;
-{
-       op->fcn.cont = g_c1rcobj;
-       if(gdb_receive_data(hcon, (char *)&(arg->len), sizeof(int32)) == OP_COMPLETE) {
-               return g_c1rcobj(op, hcon, arg);/* this return is a little */
-                                               /* subtle.  As continuation */
-                                               /* routines call each other */
-                                               /* synchronously, the last */
-                                               /* one determines whether we */
-                                               /* completed or are still */
-                                               /* running.  That status */
-                                               /* percolates back through */
-                                               /* the entire call chain. */
-       } else {
-               return OP_RUNNING;
-       }
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_c1rcobj
-       /*      
-       /*      At this point, we have received the length.  Now, allocate
-       /*      the space for the rest of the data, and start receiving
-       /*      it.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_c1rcobj(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct robj_data *arg;
-{
-       /*
-        * Now we know the length of the encoded data, convert the length
-        * to local byte order, and allocate the space for the receive.
-        */
-       arg->len = (int) ntohl((uint32)arg->len);
-       if (arg->len > 65536)
-         return OP_CANCELLED;
-
-       arg->flattened = db_alloc(arg->len);
-       if (arg->flattened == NULL)
-         return OP_CANCELLED;
-       /*
-        * Now start receiving the encoded object itself.  If it all comes in
-        * synchronously, then just go on to the c2 routine to decode it and
-        * finish up.  Else return OP_RUNNING, so the rest of the system 
-        * can get some work done while we wait.
-        */
-       op->fcn.cont = g_c2rcobj;
-       if(gdb_receive_data(hcon, arg->flattened, arg->len ) == OP_COMPLETE) {
-               return g_c2rcobj(op, hcon, arg);
-       } else {
-               return OP_RUNNING;
-       }
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                    g_c2rcobj
-       /*      
-       /*      At this point, all the data has been received.  Decode
-       /*      it into the place provided by the caller, free all
-       /*      temporarily allocated memory, and return.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_c2rcobj(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct robj_data *arg;
-{
-       /*
-        * Decode the received data into local representation.
-        */
-       FCN_PROPERTY(arg->type, DECODE_PROPERTY)
-                         (arg->objp, hcon, arg->flattened);
-       op->result = OP_SUCCESS;
-       db_free(arg->flattened, arg->len);      /* free the received data */
-       db_free((char *)arg, sizeof(struct robj_data)); /* free the state structure */
-       return OP_COMPLETE;
-}
-
-
-/************************************************************************/
-/*     
-/*                     complete_operation(complete_operation)
-/*     
-/*     Wait for a given operation to complete, allowing everything
-/*     to progress in the meantime.  Returns the last known status
-/*     of the operation, which in general will be OP_COMPLETE unless
-/*     errors were encountered (and this version of the code doesn't
-/*     do error handing right anyway!)
-/*     
-/*     We do this by (1) calling gdb_progress to assure that all
-/*     possible progress has been made, which is always a good thing
-/*     to do when we get the chance and (2) looping on calls to 
-/*     con_select, which will make all possible future progress, 
-/*     but without burning cycles unnecessarily in the process.
-/*     
-/************************************************************************/
-
-int
-complete_operation(op)
-OPERATION op;
-{
-       (void) gdb_progress();
-
-       while(op->status != OP_COMPLETE && op->status != OP_CANCELLED)
-               (void) con_select(0, (fd_set *)NULL, (fd_set *)NULL,
-                          (fd_set *)NULL, (struct timeval *)NULL);
-
-       return op->status;
-
-}
-
-
-/************************************************************************/
-/*     
-/*                     cancel_operation(cancel_operation)
-/*     
-/*     Attempts to cancel an operation.  
-/*     
-/************************************************************************/
-
-int
-cancel_operation(op)
-OPERATION op;
-{
-       register HALF_CONNECTION hcon = op->halfcon;
-
-       if (op->status != OP_RUNNING && op->status != OP_QUEUED)
-               return op->status; 
-
-       if (hcon == NULL)
-               GDB_GIVEUP("cancel_operation: operation is queued but half connection is unknown")
-
-       /*
-        * If we're at the head of the queue and running, then we have to
-        * call the cancelation routine for this particular operation so
-        * it can clean up.
-        */
-       if (op->prev == (OPERATION)hcon) {
-               if (op->status == OP_RUNNING && op->cancel != NULL)
-                       (*op->cancel)(op->halfcon, op->arg);
-       }
-
-       /*
-        * Looks safe, now cancel it.
-        */
-       op->next->prev = op->prev;              /* de-q it */
-       op->prev->next = op->next;              /* "  "  " */
-       op->status = OP_CANCELLED;
-       op->halfcon = NULL;
-
-       return OP_CANCELLED;
-}
-
-
-/************************************************************************/
-/*     
-/*                     start_listening
-/*     
-/*     Start the asynchronous acquisition of a connection.  This
-/*     results in the queuing of a GDB "OPERATION" to do the
-/*     requested listening.
-/*     
-/************************************************************************/
-
-struct lis_data {
-       char    *otherside;                     /* data returned from an */
-                                               /* accept */
-       int     *otherlen;                      /* length of the otherside */
-                                               /* field */
-       int     *fdp;                           /* ptr to the fd of the */
-                                               /* newly accepted */
-                                               /* connection */
-};
-
-int g_ilis();
-int g_clis();
-
-void
-gdb_start_listening(op, con, otherside, lenp, fdp)
-OPERATION op;
-CONNECTION con;
-char *otherside;
-int  *lenp;
-int  *fdp;
-{
-       struct lis_data *arg;
-
-       GDB_INIT_CHECK
-
-       /*
-        * Make sure the supplied connection is a legal one
-        */
-       GDB_CHECK_CON(con, "start_listening")
-       GDB_CHECK_OP(op, "start_listening")
-
-       arg = (struct lis_data *)db_alloc(sizeof(struct lis_data));
-
-       arg->otherside = otherside;
-       arg->otherlen = lenp;
-       arg->fdp = fdp;
-       initialize_operation(op, g_ilis, (char *)arg, (int (*)())NULL);
-       (void) queue_operation(con, CON_INPUT, op);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_ilis
-       /*      
-       /*      Init routine for doing a listen.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_ilis(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct lis_data *arg;
-{
-       int rc;
-
-       /*
-        * Set up continuation routine in case it's needed after the return
-        */
-       op->fcn.cont = g_clis;
-
-       /*
-        * Try doing the listen now, and then decide whether to go
-        * right on to the continuation routine or to let things hang
-        * for the moment.
-        */
-       rc = gdb_start_a_listen(hcon, arg->otherside, arg->otherlen, arg->fdp);
-       if (rc==OP_COMPLETE) {          
-               return g_clis(op, hcon, arg);   /* this return is a little */
-                                               /* subtle.  As continuation */
-                                               /* routines call each other */
-                                               /* synchronously, the last */
-                                               /* one determines whether we */
-                                               /* completed or are still */
-                                               /* running.  That status */
-                                               /* percolates back through */
-                                               /* the entire call chain. */
-       } else {
-               return OP_RUNNING;
-       }
-}
-
-
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*                       g_clis
-       /*      
-       /*      Continuation routine for accepting a connection.
-       /*
-       /*      At this point, the fd has been accepted and all
-       /*      the necessary information given back to the caller.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_clis(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct lis_data *arg;
-{
-       op->result = OP_SUCCESS;                
-       db_free((char *)arg, sizeof(struct lis_data));  
-                                               /* free the state structure */
-       return OP_COMPLETE;
-}
-
-
-/************************************************************************/
-/*     
-/*                     start_accepting_client
-/*     
-/*     Start the asynchronous acquisition of a client.  This queueable
-/*     operation first tries to accept a connection.  On this connection,
-/*     it reads a startup string from the client, and then completes.
-/*     
-/*     The return values from this are not quite what you might expect.
-/*     In general, the operation will show complete, rather than cancelled,
-/*     if it gets as far as creating the new connection at all.  If
-/*     subsequent activities result in errors from system calls, then
-/*     this operation will complete with a status of OP_COMPLETE and a 
-/*     result of OP_CANCELLED.  In this case, the applications IS given
-/*     a connection descriptor for the new connection, and that descriptor
-/*     has an errno value indicating why the failure occurred.  The 
-/*     caller must then sever this connection to free the descriptor.
-/*     
-/************************************************************************/
-
-struct acc_data {
-       char    *otherside;                     /* data returned from an */
-                                               /* accept */
-       int     *otherlen;                      /* length of the otherside */
-                                               /* field */
-       OPERATION listenop;                     /* used to listen for */
-                                               /* the fd */
-       OPERATION receiveop;                    /* used when receiving */
-                                               /* tuple from the client */
-       CONNECTION con;                         /* the connection we're */
-                                               /* trying to create */
-       CONNECTION *conp;                       /* this is where the caller */
-                                               /* wants the connection */
-                                               /* returned */
-       TUPLE *tuplep;                          /* pointer to tuple we */
-                                               /* are going to receive */
-                                               /* from new client */
-};
-
-int g_iacc();
-int g_i2acc();
-
-void
-start_accepting_client(listencon, op, conp, otherside, lenp, tuplep)
-CONNECTION listencon;
-OPERATION op;
-CONNECTION *conp;
-char *otherside;
-int  *lenp;
-TUPLE *tuplep;
-{
-       struct acc_data *arg;
-
-       GDB_INIT_CHECK
-
-       /*
-        * Make sure the supplied connection and operation are legal
-        */
-       GDB_CHECK_CON(listencon, "start_accepting_client")
-       GDB_CHECK_OP(op, "start_accepting_client")
-
-       arg = (struct acc_data *)db_alloc(sizeof(struct acc_data));
-
-       arg->otherside = otherside;
-       arg->otherlen = lenp;
-       arg->conp = conp;
-       *conp = NULL;                           /* in case we fail */
-       arg->listenop = create_operation();
-       arg->receiveop = create_operation();
-       arg->con = g_make_con();
-       arg->tuplep = tuplep;
-       *tuplep = NULL;                         /* in case we fail */
-
-       /*
-        * Queue an operation ahead of us which will accept an fd and
-        * put it in arg->con->in.  As a byproduct, pick up the from
-        * information that we return to the caller.
-        */
-       gdb_start_listening(arg->listenop, listencon,
-                           arg->otherside, 
-                           arg->otherlen, &(arg->con->in.fd));
-       
-       /*
-        * Now queue us behind it.  By the time we run our init routine,
-        * a connection should have been acquired.
-        */
-       initialize_operation(op, g_iacc, (char *)arg, (int (*)())NULL);
-       (void) queue_operation(listencon, CON_INPUT, op);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_iacc
-       /*      
-       /*      Init routine for accepting a connection.  By the 
-       /*      time this runs, the listen has been done, the 
-       /*      'from' data put in position for the caller, and
-       /*      the fd plugged into the connection descriptor.
-       /*      If all went well, fill out the connection descriptor
-       /*      and then requeue us on that to do the receive of
-       /*      the requested tuple.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_iacc(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct acc_data *arg;
-{
-       register CONNECTION con = arg->con;
-
-       /*
-        * Set up 2nd init routine for after we re-queue ourselves
-        */
-       op->fcn.cont = g_i2acc;
-       /*
-        * See whether we successfully accepted a connection.  If
-        * not, we just cancel ourselves.  If so, fill out the
-        * connection descriptor and related data structures properly,
-        * then requeue ourselves on the new connection.
-        */
-       if (OP_STATUS(arg->listenop) != OP_COMPLETE ||
-           OP_RESULT(arg->listenop) != OP_SUCCESS ||
-           con->in.fd <=0) {
-                   (void) sever_connection(con);
-                   g_clnup_accept(arg);
-                   op->result = OP_CANCELLED;
-                   return OP_CANCELLED;
-       }
-
-       /*
-        * OK, we got an fd, but the connection and related structures 
-        * aren't really set up straight, and the fd must be put
-        * into non-blocking mode.  There really should be a common
-        * routine for this, since some of the logic exists in 2
-        * or 3 places.
-        */
-       con->status = CON_STARTING;
-       con->out.fd = con->in.fd;
-       g_ver_iprotocol(con);                   /* make sure we're at */
-                                               /* same level of protocol */
-       if (con->status == CON_UP) {
-               /*
-                * We've successfully started the connection, now mark
-                * it for non-blocking I/O.  Also, update the high water
-                * mark of fd's controlled by our system.
-                */
-               int nb = 1;
-               if(ioctl(con->in.fd, FIONBIO, (char *)&nb)== (-1)) {
-                       g_stop_with_errno(con);
-                       *arg->conp = con;       /* give failed con to */
-                                               /* caller so he can find */
-                                               /* errno */
-                       gdb_perror("gdb: ioctl for non-block failed");
-                       g_clnup_accept(arg);
-                       op->result = OP_CANCELLED; /* we didn't really, but */
-                                                /* we want caller to look */
-                                                /* at the connection so he */
-                                                /* can find errno*/
-                       return OP_COMPLETE;
-               }
-               if (con->in.fd +1 > gdb_mfd) 
-                       gdb_mfd = con->in.fd + 1;
-               /*
-                * Allocate a buffer, if necessary, and reset buffer pointers
-                * so first request will result in a long read into the buffer
-                */
-               g_allocate_connection_buffers(con);
-
-       } else {
-               *arg->conp = con;               /* give failed con to */
-                                               /* caller so he can find */
-                                               /* errno */
-               g_clnup_accept(arg);
-               op->result = OP_CANCELLED;
-               return OP_COMPLETE;
-       }
-
-       /*
-        * Before we requeue ourselves on the new connection, queue
-        * up a receive for the expected tuple.  Then we'll be 
-        * sure that it's there by the time we run.
-        */
-       start_receiving_object(arg->receiveop, con, (char *)(arg->tuplep),
-                              TUPLE_T);
-       /*
-        * Requeue ourselves behind the receive operation.
-        */
-
-       (void) requeue_operation(con, CON_INPUT, op);
-       return OP_REQUEUED;
-}
-
-
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_i2acc
-       /*      
-       /*      Second init routine for accepting a connection. 
-       /*      This one is run after the operation is requeued on
-       /*      the new connection.  By the time we run here, the
-       /*      attempt to receive the tuple has already been made.
-       /*      We just check on status and clean-up.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_i2acc(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct acc_data *arg;
-{
-       int rc;
-
-       rc = OP_STATUS(arg->receiveop);         /* if it completes, then */
-                                               /* so do we! */
-       *arg->conp = arg->con;                  /* give caller the new con */
-       if (rc != OP_COMPLETE) 
-               (void) g_stop_connection(arg->con);
-       /*
-        * Release all transient data structures.
-        */
-       g_clnup_accept(arg);
-       
-       return OP_COMPLETE;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_clnup_accept
-       /*      
-       /*      Free all data structures used by start_accepting_client.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_clnup_accept(arg)
-struct acc_data *arg;
-{
-       delete_operation(arg->listenop);
-       delete_operation(arg->receiveop);
-       db_free((char *)arg, sizeof(struct acc_data));  
-}
diff --git a/gdb/gdb_serv.c b/gdb/gdb_serv.c
deleted file mode 100644 (file)
index 11ec00a..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * $Source$
- * $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_serv_c = "$Header$";
-#endif
-
-
-/************************************************************************
- *     
- *                        gdb_serv.c
- *     
- *           GDB - Routines to implement the server/client model
- *                 of connections.
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena 
- *             For copying and distribution information, please see
- *             the file <mit-copyright.h>.
- *     
- ************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include <string.h>
-#include "gdb.h"
-#include <sys/ioctl.h>
-#ifdef SOLARIS
-#include <sys/filio.h>
-#endif
-#ifdef POSIX
-#include <unistd.h>
-#endif
-
-       /*----------------------------------------------------------
-        *      
-        *      The following field names and types describe the
-        *      tuple sent from clients to servers during negotiation.
-        *      
-        *----------------------------------------------------------*/
-
-char *g_tsv_field_names[] = {"server_id",
-                           "parms",
-                           "host",
-                           "user"};
-FIELD_TYPE g_tsv_ftypes[] = {STRING_T,
-                           STRING_T,
-                           STRING_T,
-                           STRING_T};
-
-#define TSV_FLDCOUNT 4
-
-#define TSV_SERVER_ID 0
-#define TSV_PARMS     1
-#define TSV_HOST      2
-#define TSV_USER      3
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      The following field names and types describe the
-       /*      tuple returned from the server to the client during
-       /*      negotiation.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *g_fsv_field_names[] = {"disposition",
-                            "server_id",
-                            "parms"};
-FIELD_TYPE g_fsv_ftypes[] = {INTEGER_T,
-                            STRING_T,
-                            STRING_T};
-
-#define FSV_FLDCOUNT 3
-
-#define FSV_DISPOSITION 0
-#define FSV_SERVER_ID   1
-#define FSV_PARMS       2
-
-
-/************************************************************************/
-/*     
-/*                       gdb_i_srv
-/*     
-/*     Initialize the server client layer.
-/*     
-/*     This routine is called during gdb_init to do the processing
-/*     common to all server/client handing.
-/*     
-/*     In particular, we build the tuple descriptors for the 
-/*     messages used in negotiating the server/client startup.
-/*     
-/************************************************************************/
-
-int
-gdb_i_srv()
-{
-       gdb_tosrv = create_tuple_descriptor(TSV_FLDCOUNT, g_tsv_field_names, 
-                                           g_tsv_ftypes);
-       gdb_fmsrv = create_tuple_descriptor(FSV_FLDCOUNT, g_fsv_field_names, 
-                                           g_fsv_ftypes);
-       gdb_client_tuple = NULL;
-       gdb_socklen = sizeof(gdb_sockaddr_of_client);
-}
-
-
-/************************************************************************/
-/*     
-/*                start_server_connection (start_server_connection)
-/*     
-/*     This routine is called from a client that wishes to make a
-/*     connection to a server.  In the current implementation, the
-/*     string argument supplied is just the internet name of the 
-/*     host on which the server runs.  This will later be generalized
-/*     to a more flexible naming scheme.
-/*     
-/*     This routine builds a connection to the requested server, 
-/*     sends the server i.d. and parms to the server (as strings), 
-/*     and waits for a response indicating whether the server has
-/*     agreed to the connection.  The server responds in one of three
-/*     ways (1) connection accepted (2) connection declined (3) redirect.
-/*     In this last case, the server returns a forwarding address to
-/*     be substituted for the server_id, and the whole process is tried
-/*     again repeatedly until a connection is established or a
-/*     retry limit is exceeded.
-/*     
-/************************************************************************/
-
-CONNECTION
-start_server_connection(server_id, parms)
-char *server_id;
-char *parms;
-{
-       CONNECTION con;                         /* the connection we're */
-                                               /* creating */
-       TUPLE response = NULL;                  /* each time we try a server */
-                                               /* it sends back its */
-                                               /* response here */
-       int retries = GDB_MAX_SERVER_RETRIES;   /* number of servers we'll */
-                                               /* try before giving up in */
-                                               /* fear of a loop */
-
-       char serv_id[GDB_MAX_SERVER_ID_SIZE];   /* a place to store server */
-                                               /* id's.  New ones go here */
-                                               /* when our request is */
-                                               /* forwarded */
-       char latest_parms[GDB_MAX_SERVER_PARMS_SIZE];
-                                               /* likewise for parms */
-
-       GDB_INIT_CHECK
-
-       /*
-        * Try to allocate a connection and fill it in with null values.
-        */
-
-       con = g_make_con();
-
-       /*
-        * Loop asking different servers to accept our connection
-        * until one does or we are flatly refused.
-        */
-
-       /*
-        * Allocate a buffer, if necessary, and reset buffer pointers
-        * so first request will result in a long read into the buffer
-        */
-       g_allocate_connection_buffers(con);
-
-
-       g_try_server(&con, server_id, parms, &response);
-
-        while ((retries--) &&
-              con != NULL && 
-              response != NULL &&
-              *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION)==GDB_FORWARDED) {
-
-               (void) sever_connection(con);
-               con = g_make_con();
-               (void) strcpy(serv_id, 
-                      STRING_DATA(*(STRING *) 
-                                  (FIELD_FROM_TUPLE(response, 
-                                                    FSV_SERVER_ID))));
-               (void) strcpy(latest_parms, 
-                      STRING_DATA(*(STRING *) 
-                                  (FIELD_FROM_TUPLE(response, 
-                                                    FSV_PARMS))));
-               null_tuple_strings(response);
-               delete_tuple(response);
-               g_try_server(&con, serv_id, latest_parms, &response);
-       }
-
-       /*
-        * At this point, we are done trying servers, now find out
-         * whether we get to keep the connnection or whether it
-         * didn't work.  First, see whether the connection is even up.
-        */
-       if (con == NULL ||
-           connection_status(con) != CON_UP) {
-               return con;
-       }
-
-       /*
-        * We have at least some active connection, now see whether we 
-        * are going to get to keep it
-        */
-       if (response != NULL &&
-           *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION) == GDB_ACCEPTED) {
-               null_tuple_strings(response);
-               delete_tuple(response);
-               return con;
-       } else {
-               if (response != NULL) {
-                       null_tuple_strings(response);
-                       delete_tuple(response);
-               }
-               (void) sever_connection(con);
-               return NULL;
-       }
-}
-
-/************************************************************************/
-/*     
-/*                          g_try_server
-/*     
-/*     Builds a single connection to a server and returns status
-/*     to indicate whether the connection has been accepted, declined,
-/*     or is to be retried.  This status is conveyed in a tuple received
-/*     back from the server.
-/*     
-/************************************************************************/
-
-int
-g_try_server(conp, server_id, parms, responsep)
-CONNECTION *conp;
-char *server_id;
-char *parms;
-TUPLE *responsep;
-{
-
-       register CONNECTION con = *conp;
-       int flag = 1;
-       
-       /* 
-        * In this implementation, we use a single fd for both inbound and
-        * outbound traffic.  Try to connect to other side.  Current
-        * implementation of this is synchronous--may be a problem?  If the
-        * connections come up, then verify the level of protocol being
-        * observed on the connections.  If incompatible, then turn off the
-        * connection.
-        */
-
-       if(!g_try_connecting(con,server_id) || 
-          con->status != CON_STARTING) {
-               return;                         /* If there we an error, */
-                                               /* connection will have been */
-                                               /* left CON_STOPPING with */
-                                               /* possible errno set */
-       }
-       g_ver_oprotocol(con);
-       if (con->status != CON_UP) {
-               return;
-       }
-
-       /*
-        * We've successfully started the connection, now mark
-        * it for non-blocking I/O.  Also, update the high water
-        * mark of fd's controlled by our system.
-        */
-       if(ioctl(con->in.fd, FIONBIO, (char *)&flag)== (-1)) {
-                       g_stop_with_errno(con);
-                       gdb_perror("gdb: ioctl for non-block failed");
-                       return;
-       }
-       if (con->in.fd +1 > gdb_mfd) 
-                       gdb_mfd = con->in.fd + 1;
-
-       g_ask_server(conp, server_id, parms, responsep);        
-
-       return;
-}
-
-
-/************************************************************************/
-/*     
-/*                     g_ask_server
-/*     
-/*     Called once we are in touch with the server and our physical
-/*     transmission protocol is comprehensible.  This routine
-/*     sends out a tuple containing the server i.d. and parameter
-/*     strings and it returns a tuple received back from the server
-/*     containing the server's response.
-/*     
-/************************************************************************/
-
-int
-g_ask_server(conp, server_id, parms, responsep)
-CONNECTION *conp;
-char *server_id;
-char *parms;
-TUPLE *responsep;
-{
-       register CONNECTION con = *conp;
-       TUPLE out_tuple;
-       int rc;
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Create a tuple to be sent out containing the
-       /*      server_id and parms.
-       /*      
-       /*----------------------------------------------------------*/
-
-       out_tuple = create_tuple(gdb_tosrv);    /* descriptor was pre- */
-                                               /* built during */
-                                               /* initialization*/
-
-       (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_SERVER_ID),
-                    strlen(server_id)+1);
-       (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,0))),
-                      server_id);
-
-       if (parms == NULL) parms = "";
-       (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_PARMS),
-                    strlen(parms)+1);
-       (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,1))),
-                      parms);
-
-       (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_HOST),
-                    strlen(gdb_host)+1);
-       (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,
-                                                              TSV_HOST))),
-                      gdb_host);
-       (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_USER),
-                    strlen(gdb_uname)+1);
-       (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,TSV_USER))),
-                      gdb_uname);
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Send the tuple to the server, and make sure that
-       /*      we succeeded.
-       /*      
-       /*----------------------------------------------------------*/
-
-       rc = send_object(con, (char *)&out_tuple, TUPLE_T);
-
-       null_tuple_strings(out_tuple);
-       delete_tuple(out_tuple);
-
-       if (rc != OP_SUCCESS) {
-               return;                         /* cleanup from dying send */
-                                               /* should have made this */
-                                               /* CON_STOPPING with errno */
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      OK, we sent it out, now lets read back the response.
-       /*      
-       /*----------------------------------------------------------*/
-
-       rc = receive_object(con, (char *)responsep, TUPLE_T);
-
-       if (rc != OP_SUCCESS) {
-               return;                         /* cleanup from dying send */
-                                               /* should have made this */
-                                               /* CON_STOPPING with errno */
-       }
-}
-
-
-/************************************************************************/
-/*     
-/*                     start_replying_to_client
-/*     
-/*     Queue an operation which will send a reply to the specified
-/*     client.
-/*     
-/************************************************************************/
-
-struct rtc_data {
-       TUPLE reply_data;
-       OPERATION tuple_send;
-};
-
-int g_irtc();
-int g_i2rtc();
-
-int
-start_replying_to_client(op, con, disposition, serverid, parms)
-OPERATION op;
-CONNECTION con;
-int disposition;
-char *serverid;                                        /* null terminated */
-char *parms;                                   /*   "     "       */
-{
-       register struct rtc_data *arg;
-       register TUPLE t;
-
-       /*
-        * Make sure the supplied connection is a legal one
-        */
-       GDB_CHECK_CON(con, "start_replying_to_client")
-
-       arg = (struct rtc_data *)db_alloc(sizeof(struct rtc_data));
-
-       /*
-        * create an empty operation and a tuple
-        */
-       arg->tuple_send = create_operation();
-       arg->reply_data = create_tuple(gdb_fmsrv);
-       /*
-        * Fill in the response tuple
-        */
-       t = arg->reply_data;                    /* quicker and easier here */
-
-       *(int *)FIELD_FROM_TUPLE(t,FSV_DISPOSITION) = disposition;
-       (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_SERVER_ID),
-                    strlen(serverid)+1);
-       (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_SERVER_ID))),
-                                      serverid);
-
-       (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_PARMS),
-                    strlen(parms)+1);
-       (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_PARMS))),
-                                      parms);
-
-       /*
-        * Queue an operation ahead of us which will send the response tuple
-        * to the client
-        */
-       start_sending_object(arg->tuple_send, con, (char *)&arg->reply_data,
-                            TUPLE_T);
-       
-       /*
-        * Now queue us behind it.  By the time we run our init routine,
-        * a connection should have been acquired.
-        */
-       initialize_operation(op, g_irtc, (char *)arg, (int (*)())NULL);
-       (void) queue_operation(con, CON_INPUT, op);
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_irtc
-       /*      
-       /*      Init routine for replying to a client.  If all went
-       /*      well, (or even if it didn't), then we are done.
-       /*      All we have to do is clean up the stuff we've allocated.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-g_irtc(op, hcon, arg)
-OPERATION op;
-HALF_CONNECTION hcon;
-struct rtc_data *arg;
-{
-       int rc;
-
-       /*
-        * Figure out the return information to our caller
-        */
-       rc = OP_STATUS(arg->tuple_send);
-
-       /*
-        * Release all transient data structures.
-        */
-       null_tuple_strings(arg->reply_data);
-       delete_tuple(arg->reply_data);
-       delete_operation(arg->tuple_send);
-       db_free((char *)arg, sizeof(struct rtc_data));
-       return rc;
-}
diff --git a/gdb/gdb_struct.c b/gdb/gdb_struct.c
deleted file mode 100644 (file)
index 4ebda47..0000000
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_struct_c = "$Header$";
-#endif
-
-
-/************************************************************************/
-/*     
-/*                        gdb_struct.c
-/*     
-/*           GDB - Structured Data Maintenance Routines
-/*     
-/*     Author: Noah Mendelsohn
-/*     Copyright: 1986 MIT Project Athena 
-/*             For copying and distribution information, please see
-/*             the file <mit-copyright.h>.
-/*     
-/*     These routines implement the following layers of the 
-/*     Client Library Specification of the GDB system:
-/*     
-/*             Layer           Function
-/*             -----           --------
-/*               2             Structured Data Management at a 
-/*                             Single Site
-/*               
-/*               4             Memory Management
-/*     
-/*               5             String Management
-/*     
-/*     Some of the routines specified are actually implemented as
-/*     macros defined in gdb.h.
-/*     
-/************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "gdb.h"
-
-\f
-/************************************************************************/
-/*     
-/*                     MEMORY MANAGEMENT
-/*     
-/*     In anticipation of the day when we may want to do something 
-/*     fancy with memory management, all of the gdb routines which
-/*     require dynamic allocation of memory call the routines named
-/*     db_alloc and db_free.  For the moment, these are implemented
-/*     as calls to malloc and free.  
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_am
-       /*      
-       /*      Allocate memory for use by gdb.  Current implementation
-       /*      just does a malloc.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-gdb_am(bytes)
-int bytes;
-{
-       return(malloc((unsigned)bytes));
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_fm
-       /*      
-       /*      Return allocated memory.  Note: the current 
-       /*      implementation ignores the byte count supplied,
-       /*      but future implementations may require that it 
-       /*      be correct.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-int
-gdb_fm(ptr, bytes)
-char *ptr;
-int bytes;
-{
-       free(ptr);
-       return;
-}
-\f
-/************************************************************************/
-/*     
-/*                     STRING MANAGEMENT
-/*     
-/*     To allow dynamic manipulation of strings in gdb without
-/*     excessive memory re-allocation, we define a string as a
-/*     counted byte space.  Though this space will frequently be used
-/*     to store a standard null terminated string, that is not
-/*     required.
-/*     
-/*     Current representation for a string is a pointer followed by
-/*     an integer length.  A null pointer indicates a null string, in
-/*     which case the length is arbitrary.  Any other pointer is to
-/*     memory which was allocated by db_alloc in which must be free'd
-/*     eventually with db_free.
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*              string_alloc (string_alloc)
-       /*      
-       /*      Fills in supplied string descriptor and returns 
-       /*      pointer to the newly allocated data.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-string_alloc(stringp, bytes)
-STRING *stringp;                               /* pointer to string */
-                                               /* descriptor to be */
-                                               /* filled in */
-int    bytes;                                  /* number of bytes to alloc */
-{
-       GDB_INIT_CHECK
-
-       MAX_STRING_SIZE(*stringp) = bytes;      /* put length in returned */
-                                               /* string descriptor-- */
-                                               /* will be irrelavent if */
-                                               /* alloc fails */
-
-       STRING_DATA(*stringp) = db_alloc(bytes); /* try to get the data */
-       return (STRING_DATA(*stringp));         /* return ptr to new string */
-                                               /* if any */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                string_free (string_free)
-       /*      
-       /*      Releases the data space for a gdb string.  Must have
-       /*      been allocated with string_alloc.  Remember to pass
-       /*      in the address of the string descriptor, not the 
-       /*      descriptor itself!
-       /*      
-       /*----------------------------------------------------------*/
-int
-string_free(stringp)
-STRING *stringp;
-{
-       GDB_INIT_CHECK
-
-       if (stringp->ptr == NULL)
-               return;  
-       db_free(stringp->ptr, stringp->length);
-       stringp->ptr = NULL;
-       stringp->length = 0;
-       return;
-}
-\f
-/************************************************************************/
-/*     
-/*         STRUCTURED DATA MANAGEMENT AT A SINGLE SITE
-/*     
-/*     These routines provide the abstraction of typed, structured
-/*     data at a single site.  Tuples are collections of typed fields,
-/*     and they are each described by a tuple descriptor.  Relations
-/*     are circularly linked lists of tuples.  For completeness, a
-/*     relation also carries a tuple descriptor, which should match
-/*     the descriptor for each of its constituent tuples.  This allows
-/*     a null relation to be typed.
-/*     
-/*     Some of the facilities of structured data management are 
-/*     defined as macros in gdb.h.  In many cases, the routines
-/*     declared below are known by defines of more descriptive
-/*     names, also in gdb.h.
-/*     
-/************************************************************************/
-/************************************************************************/
-/*     
-/*                  TUPLE_DESCRIPTOR MANAGEMENT
-/*     
-/************************************************************************/
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*          create_tuple_descriptor (create_tuple_descriptor)
-       /*      
-       /*      Allocates space for a tuple descriptor and fills
-       /*      it in.  Gives up if space is not available.  
-       /*      Should be passed a list of integer coded types
-       /*      and a list of string field names.  
-       /*      
-       /*      Tuple descriptors are reference counted, and they are
-       /*      not really deleted until the reference count goes
-       /*      to zero.   It is presumed that all callers use the
-       /*      create and delete routines, or otherwise maintain
-       /*      the reference count appropriately.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-TUPLE_DESCRIPTOR
-create_tuple_descriptor(number_of_fields, name_list, type_list)
-char *name_list[];
-FIELD_TYPE type_list[];
-int  number_of_fields;
-{
-       register TUPLE_DESCRIPTOR tpd;          /* pointer to new descriptor */
-       register int i;
-       register int data_len;                  /* length of the actual */
-       int field_len;                          /* length of current field */
-       int align;                              /* code describing alignment */
-                                               /* requirement for this field*/
-                                               /* (4 for fullword, 1 for */
-                                               /* char, etc.) */
-       int next_offset;                        /* byte offset to next field */
-       int descriptor_length;                  /* length of the part of */
-                                               /* the allocated storage */
-                                               /* actually used for the */
-                                               /* descriptor.*/
-       int str_len;                            /* we also have to retain */
-                                               /* the string names for the */
-                                               /* fields.  These are stored */
-                                               /* immediately off the end */
-                                               /* of the descriptor, and */
-                                               /* all are allocated */
-                                               /* together.  This is the */
-                                               /* length of the string data */
-       char *next_name;                        /* place to put the next */
-                                               /* copied fieldname*/
-
-
-       GDB_INIT_CHECK
-
-       /*
-        * Calculate size and allocate descriptor
-        */
-
-       descriptor_length = sizeof(struct tupl_desc) +
-                           (number_of_fields-1) * sizeof(struct tupld_var);
-
-       str_len = 0;
-
-       for (i=0; i<number_of_fields; i++)
-               str_len += strlen(name_list[i]) +1;
-
-       tpd = (TUPLE_DESCRIPTOR)db_alloc(descriptor_length+str_len);    
-                                               /* try to allocate it */
-
-       if (tpd == NULL)
-               GDB_GIVEUP("create_tuple_descriptor (gbd_ctd) could not get enough memory.\n") 
-
-         /*
-          * Fill in the descriptor fields:
-          * 
-          * Each field is aligned according to its own alignment code.
-          * Going in to the top of the for loop, next_offset is set to
-          * the offset of the first possible byte for storing the next field.
-          * During the loop, that number is rounded up, if necessary, to
-          * achieve the alignment actually required for the field.  Finally,
-          * the length of the new field is added, which yields the first
-          * possible byte of any field to follow.
-          */
-
-       tpd->id = GDB_DESC_ID;
-
-       tpd->ref_count = 1;                     /* whoever asked for creation*/
-                                               /* is expected to delete*/
-
-       tpd->field_count = number_of_fields;
-       tpd->str_len = str_len;
-
-       data_len = sizeof(struct tuple_dat) - 1; /*  tuple_dat includes the */
-                                                /*  first byte of data */
-       next_offset = 0;
-       next_name = ((char *)tpd) + descriptor_length;
-                                               /* place to put first */
-                                               /* field name*/
-       for (i=0; i<number_of_fields; i++) {
-               /*
-                * Calculate lengths and alignments for the field data.
-                */
-               field_len = INT_PROPERTY(type_list[i],LENGTH_PROPERTY);
-               align = INT_PROPERTY(type_list[i],ALIGNMENT_PROPERTY);
-               /*
-                * Copy the string field name into the newly allocated
-                * space just after the descriptor itself.
-                */
-               tpd->var[i].name = strcpy(next_name, name_list[i]);
-               next_name += strlen(next_name) + 1;
-               /*
-                * Put in the type and the length for the field data
-                */
-               tpd->var[i].type = type_list[i];
-               tpd->var[i].length = field_len;
-               /*
-                * Now store the actual offset of this field, and 
-                * compute the first byte address we could conceivably
-                * use for the next field.
-                */
-               next_offset = GDB_ROUNDUP(next_offset, align);
-               tpd->var[i].offset = next_offset;
-               next_offset += field_len;
-       }
-       
-       data_len += next_offset;
-       tpd->data_len = data_len;
-
-       return tpd;                             /* return the new descriptor */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*          delete_tuple_descriptor (delete_tuple_descriptor)
-       /*      
-       /*      Return the space for a tuple descriptor
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-delete_tuple_descriptor(t)
-TUPLE_DESCRIPTOR t;
-{
-       int descriptor_length;
-       register int ref_count;                 /* buffer the reference */
-                                               /* count here */
-
-       if (t == NULL)
-               return ;
-       
-       GDB_CHECK_TPD(t, "delete_tuple_descriptor")
-
-
-       /*
-        * Decrement the reference count.  If it's not zero, then just 
-        * return.
-        */
-       if ((ref_count = --(t->ref_count)) >0) 
-               return ;
-       if (ref_count <0)
-               GDB_GIVEUP("Tuple descriptor reference count is less than zero")
-       /*
-        * Current representation is to allocate the space for the string
-        * right off the end of the descriptor itself.  We therefore have
-        * to add their length into the amount we free.
-        */
-       descriptor_length = gdb_descriptor_length(t->field_count);      
-       db_free((char *)t, descriptor_length+t->str_len);
-
-       return ;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                 field_index (field_index)
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-field_index(tuple_descriptor, field_name)
-TUPLE_DESCRIPTOR tuple_descriptor;
-char *field_name;
-{
-       register int i;
-       register int n;
-       register TUPLE_DESCRIPTOR tpd = tuple_descriptor;
-
-       /*
-        * Make sure supplied descriptor is valid
-        */
-       if (tpd == NULL)
-               GDB_GIVEUP("null tuple descriptor passed to field_index function")
-       GDB_CHECK_TPD(tpd, "field_index")
-
-       n = tpd -> field_count;
-
-       /*
-        * Loop through each field in descriptor, return index if match
-        */
-
-       for(i=0; i<n; i++) 
-               if (strcmp(field_name, tpd->var[i].name) == 0)
-                       return i;
-       /*
-        * No match, return -1
-        */
-       return (-1);    
-}
-
-\f
-/************************************************************************/
-/*     
-/*                     TUPLE MANAGEMENT
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                create_tuple (create_tuple)
-       /*      
-       /*      Allocate space for a new tuple, given its 
-       /*      descriptor.  Giveup if out of memory.
-       /*      
-       /*----------------------------------------------------------*/
-
-TUPLE
-create_tuple(descriptor)
-TUPLE_DESCRIPTOR descriptor;
-{
-       register TUPLE t;
-
-       GDB_CHECK_TPD(descriptor, "create_tuple")
-
-       t = (TUPLE)db_alloc(descriptor -> data_len);
-
-       if (t == NULL)
-               GDB_GIVEUP("create_tuple (create_tuple) could not allocate enough memory.\n")
-
-       t->id = GDB_TUP_ID;
-
-       t->desc = descriptor;                   /* fill in descriptor */
-                                               /* pointer in new tuple */
-       REFERENCE_TUPLE_DESCRIPTOR(descriptor); /* bump the reference count */
-#ifdef GDB_CHECK
-       /*
-        * Only for the sake of  keeping things clean, null out the pointers.
-        * Wastes time, but helps debugging.
-        */
-       t->next = t->prev = NULL;
-#endif
-
-       return t;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*              delete_tuple (delete_tuple)
-       /*      
-       /*      Release the data space occupied by a tuple. 
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-delete_tuple(t)
-TUPLE t;
-{
-       register TUPLE_DESCRIPTOR tpd;
-       if (t==NULL)
-               GDB_GIVEUP("Delete_tuple called with null tuple")
-       GDB_CHECK_TUP(t, "delete_tuple")
-       tpd = t->desc;
-       db_free((char *)t, t->desc->data_len);
-       delete_tuple_descriptor(tpd);           /* does a reference counted */
-                                               /* delete*/
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                   initialize_tuple (initialize_tuple)
-       /*      
-       /*      Set each field in tuple to its null value.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-initialize_tuple(t)
-TUPLE t;
-{
-       register char *field_data;              /* pointer to first byte */
-                                               /* of field data in tuple*/
-       register TUPLE_DESCRIPTOR tpd;          /* pointer to descriptor */
-       register int i;                         /* counter of fields */
-       int num_fields;                         /* total number of fields */
-
-       /*
-        * Return if no tuple at all supplied--perhaps this should be
-        * an error.  If supplied, make sure it looks like a tuple.
-        */
-
-       if (t == NULL)
-               return;
-
-       GDB_CHECK_TUP(t, "initialize_tuple")
-
-       /*
-        * Set up to loop through fields:  get tuple descriptor, field count
-        * and pointer to first data byte in the tuple.
-        */
-
-       tpd = t->desc;
-       num_fields = tpd->field_count;
-       field_data = t->data;                   /* address of first byte of */
-                                               /* user data */
-
-
-       /*
-        * For each field in the tuple, loop calling its null value 
-        * initialization routine.
-        */
-
-       for (i=0; i<num_fields; i++) {
-               FCN_PROPERTY(tpd->var[i].type, NULL_PROPERTY)
-                            (field_data+tpd->var[i].offset);
-       }
-}
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*            null_tuple_strings (null_tuple_strings)
-       /*      
-       /*      Reclaim the space for all fields in the tuple
-       /*      whose type is 'string.'
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-null_tuple_strings(t)
-TUPLE t;
-{
-       register char *field_data;              /* pointer to first byte of */
-                                               /* field data in tuple */
-       register TUPLE_DESCRIPTOR tpd;          /* pointer to descriptor */
-       register int i;                         /* counter of fields */
-       int num_fields;                         /* total number of fields */
-
-       /*
-        * Return if no tuple at all supplied--perhaps this should be
-        * an error
-        */
-
-       if (t == NULL)
-               return;
-
-       GDB_CHECK_TUP(t, "null_tuple_strings")
-
-       /*
-        * Set up to loop through fields:  get tuple descriptor, field count
-        * and pointer to first data byte in the tuple.
-        */
-
-       tpd = t->desc;
-       num_fields = tpd->field_count;
-       field_data = t->data;                   /* address of first byte of */
-                                               /* user data */
-
-       /*
-        * For each field in the tuple, loop calling its null value 
-        * initialization routine.
-        */
-
-       for (i=0; i<num_fields; i++) {
-               if(FIELD_TYPE_IN_TUPLE(tpd,i) == STRING_T &&
-                  (*(char **)(field_data+FIELD_OFFSET_IN_TUPLE(tpd,i)))!=NULL)
-                       string_free((STRING *)(field_data+
-                                              FIELD_OFFSET_IN_TUPLE(tpd,i)));
-       }
-}
-\f
-/************************************************************************/
-/*     
-/*                     RELATION MANAGEMENT
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*             create_relation (create_relation)
-       /*      
-       /*----------------------------------------------------------*/
-
-RELATION
-create_relation(desc)
-TUPLE_DESCRIPTOR desc;
-{
-       register RELATION r;
-
-       GDB_CHECK_TPD(desc, "create_relation")
-
-       r = (RELATION)db_alloc(sizeof(struct rel_dat));
-
-       if (r == NULL) 
-               GDB_GIVEUP("create_relation (create_relation) could not get enough space.\n")
-
-       /*
-        * Fill in the empty relation.  Create a null circular list
-        * of tuples and also hang the description.
-        */
-
-       r->id = GDB_REL_ID;
-
-       r->first = (TUPLE)r;
-       r->last = (TUPLE)r;
-       r->desc = desc;
-       REFERENCE_TUPLE_DESCRIPTOR(desc);       /* bump the reference count */
-
-       return r;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*              delete_relation
-       /*      
-       /*      Deletes the tuples which comprise a relation.
-       /*      For each tuple, it does a null-tuple-strings 
-       /*      prior to deleting, but it does not yet handle
-       /*      any other non-contiguous data.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-delete_relation(rel)
-RELATION rel;
-{
-       register TUPLE t, next;
-       TUPLE_DESCRIPTOR desc;
-
-       /*
-        * Make sure a proper relation is supplied.
-        */
-
-       if (rel == NULL)
-               GDB_GIVEUP("delete_relation called with null relation")
-        GDB_CHECK_REL(rel, "delete_relation")
-
-       t = FIRST_TUPLE_IN_RELATION(rel);
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Free all the tuples
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (t!=NULL) {
-               null_tuple_strings(t);
-               next = NEXT_TUPLE_IN_RELATION(rel, t);
-               delete_tuple(t);
-               t = next;
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Give back the memory for the relation
-       /*      
-       /*----------------------------------------------------------*/
-
-       desc = DESCRIPTOR_FROM_RELATION(rel);
-       db_free((char *)rel, sizeof(struct rel_dat));
-       delete_tuple_descriptor(desc);          /* does a reference */
-                                               /* counted delete */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*              tuples_in_relation
-       /*      
-       /*      Returns number of tuples in a relation.
-       /*      
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-tuples_in_relation(rel)
-RELATION rel;
-{
-       register int count;
-       register RELATION r=rel;
-       register TUPLE t;
-
-       count = 0;
-
-       for (t=FIRST_TUPLE_IN_RELATION(r);
-            t != NULL;
-            t=NEXT_TUPLE_IN_RELATION(r,t)) {
-                 count++;
-        }
-       return count;
-}
-       
-
-
diff --git a/gdb/gdb_stype.c b/gdb/gdb_stype.c
deleted file mode 100644 (file)
index b47257c..0000000
+++ /dev/null
@@ -1,1810 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_stype_c = "$Header$";
-#endif
-
-
-/************************************************************************
- *     
- *                        gdb_stype.c
- *     
- *           GDB - System Data Type Definitions
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena 
- *             For copying and distribution information, please see
- *             the file <mit-copyright.h>.
- *     
- *     This file initializes the definitions for all system defined
- *     data types, and it includes the type specific semantic routines
- *     for each of the system defined types.
- *     
- *     The initialization routine which adds these type definitions 
- *     to the type definition table is at the end of this source file.
- *     
- ************************************************************************
- *     
- *     This file is organized into one section for each system
- *     defined type followed at the end by a final section which
- *     initializes the type tables.  Each of the type specific
- *     sections does #defines for each type specific parameter.  The
- *     gdb_i_stype initialization routine at the end of this source
- *     file uses these defines to initialize the appropriate entry in
- *     the type definition tables.
- *     
- *     NOTE: some of the type definitions in this file may be machine
- *     dependent.
- *     
- ************************************************************************/
-
-#include <mit-copyright.h>
-#include <stdio.h>
-#include <string.h>
-#include "gdb.h"
-#include <netinet/in.h>                                /* for htonl routine */
-
-
-/************************************************************************
- *     
- *                          INTEGER_T
- *     
- ************************************************************************/
-
-#define IN_LEN                 (sizeof(int))
-#define IN_ALI                 IN_LEN
-#define IN_NULL        g_in_null
-#define IN_CDLEN       g_in_cdlen
-#define IN_ENC                 g_in_enc
-#define IN_DEC         g_in_dec
-#define IN_FORM                g_in_form
-#define IN_NAME                "INTEGER_T"
-
-#define IN_EXTERNSIZE 4                                /* length of an encoded */
-                                               /* integer */
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_in_null
-       /*      
-       /*      Fill in a null value for an integer.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_in_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       *((int *)dp) = 0;                       /* fill in a null value */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_in_cdlen
-       /*      
-       /*      Return coded length for an integer.  We're currently
-       /*      using the Berkeley 'htonl' routine which converts 
-       /*      an integer (actually a long, ahem!) to a canonical
-       /*      4 byte form.>
-       /*      
-       /*----------------------------------------------------------*/
-
-
-/*ARGSUSED*/
-int
-g_in_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       return IN_EXTERNSIZE;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_in_enc
-       /*      
-       /*      Encode an integer for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-char *
-g_in_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register char *cp;                      /* next char in output */
-       register char *op = outp;
-       register char *endp = outp+IN_EXTERNSIZE;
-
-       uint32 converted;                       /* the integer goes here */
-                                               /* in network byte order*/
-
-       /*
-        * Put it in network format, then copy one byte at a time to
-        * account for the fact that the RT has trouble with unaligned longs
-        */
-
-       converted = htonl(*(uint32 *)dp);
-
-       cp = (char *)&converted;
-       *op++ = *cp++;
-       *op++ = *cp++;
-       *op++ = *cp++;
-       *op++ = *cp++;
-
-       return endp;                            /* return pointer to next */
-                                               /* unused output byte*/
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_in_dec
-       /*      
-       /*      Decode an integer from external form to local
-       /*      representation.
-       /*      
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-char *
-g_in_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register char *ip = inp;                /* next byte of input */
-       int buffer;
-       register char *bp;                      /* next byte in buffer */
-
-       /*
-        * Copy a byte at a time to buffer to account for RT difficulties
-        * with unaligned ints.
-        */
-       bp = (char *)&buffer;
-       *bp++ = *ip++;
-       *bp++ = *ip++;
-       *bp++ = *ip++;
-       *bp++ = *ip++;
-
-       /*
-        * Convert it and return pointer to next byte of input.
-        */
-
-       *(int *)outp = ntohl((u_long)buffer);
-       return ip;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_in_form
-       /*      
-       /*      Format an integer on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_in_form(name, dp)
-char *name;                                    /* string name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       fprintf(gdb_log, "INTEGER_T\t%s=%d\n",name,(*(int *)dp));
-}
-
-
-/************************************************************************/
-/*     
-/*                          STRING_T
-/*     
-/************************************************************************/
-
-#define ST_LEN                 (sizeof(STRING))
-#define ST_ALI                 (sizeof(char *))
-#define ST_NULL        g_st_null
-#define ST_CDLEN       g_st_cdlen
-#define ST_ENC                 g_st_enc
-#define ST_DEC         g_st_dec
-#define ST_FORM                g_st_form
-#define ST_NAME                "STRING_T"
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_st_null
-       /*      
-       /*      Fill in a null value for a string.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_st_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       register STRING *stp = (STRING *)dp;    /* re-type as string */
-       STRING_DATA(*stp) = NULL;               /* no data */
-       MAX_STRING_SIZE(*stp) = 0;              /* for cleanliness */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_st_cdlen
-       /*      
-       /*      Return coded length for a string.  We have to send the
-       /*      actual length of the data along with the data itself.
-       /*      For this reason, we leave space for a coded integer
-       /*      in addition to the data bytes.  We actually call the
-       /*      integer coding routines to code the length.
-       /*      
-       /*      Note that a separate type understanding null termination
-       /*      might be an interesting optimization someday.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_st_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       register STRING *stp = (STRING *)dp;    /* re-type as string */
-
-       return (MAX_STRING_SIZE(*stp) + 
-               g_in_cdlen((char *)&MAX_STRING_SIZE(*stp),hcon));
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_st_enc
-       /*      
-       /*      Encode a string for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_st_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register STRING *stp = (STRING *)dp;    /* re-type as string */
-       int len;
-       register char *nextp;                   /* place to put next output */
-                                               /* byte */
-       /*
-        * Use the integer coding routine to get the length encoded first
-        */
-
-       len = MAX_STRING_SIZE(*stp);            /* length of both source */
-                                               /* and coded form*/
-       nextp = (char *)g_in_enc((char *)&len, hcon, outp);
-       
-       /*
-        * Now, copy the data itself after the encoded integer length
-        */
-       if (len > 0)
-               memcpy(nextp, STRING_DATA(*stp), len);
-                                               /* copy the data without */
-                                               /* changing representation*/
-       return nextp+len;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_st_dec
-       /*      
-       /*      Decode a string from external form.  We always
-       /*      allocate new space for the string, intentionally
-       /*      ignoring any which may have been in use before.  If we
-       /*      freed it, we would not be robust against calls on
-       /*      uninitialized fields.  This may have nasty side
-       /*      effects if the intention was to leave 'gas' at the end
-       /*      of the string, but we want to accurately copy the
-       /*      data.  Note that string_free is robust against null
-       /*      pointers.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_st_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to input data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register STRING *stp = (STRING *)outp;  /* re-type as string */
-       int len;
-       register char *nextp;                   /* next byte to scan */
-       /*
-        * Use the integer coding routine to get the length encoded first
-        */
-
-       nextp = (char *)g_in_dec((char *)&len, hcon, inp);
-
-
-       /*
-        * Allocate memory for the string.  If length is 0, then null it
-        * out.  Note that we had considered freeing any existing strings
-        * which might be there, but this turns out to cause lots of
-        * trouble for the many callers who don't want to initialize before
-        * a decode.
-        */
-       if (len == 0) {
-               STRING_DATA(*stp) = NULL;
-               MAX_STRING_SIZE(*stp) = 0;
-               return nextp;
-       }
-       (void) string_alloc(stp, len);          /* this sets string length */
-                                               /* in addition to doing the */
-                                               /* allocation */
-       
-       /*
-        * Now, copy the data itself 
-        */
-       memcpy(STRING_DATA(*stp), nextp, len);  /* copy the data without */
-                                               /* changing representation*/
-       return nextp+len;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_st_form
-       /*      
-       /*      Format a string on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_st_form(name, dp)
-char *name;                                    /* string name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       register STRING *stp = (STRING *)dp;    /* re-type as string */
-       int len;
-       register char *cp;                      /* next char to print */
-       register char *past_end;                /* 1st one not to print */
-
-       len = MAX_STRING_SIZE(*stp);
-       fprintf(gdb_log, "STRING_T\t%s[%d]=\"", name,len);
-       
-       if (len == 0 ) {
-               fprintf(gdb_log, "\"\n");
-               return;
-       }
-          
-
-       cp = STRING_DATA(*stp);
-       past_end = cp + len;
-
-       while (cp < past_end)
-               (void) putc(*cp++, gdb_log);
-
-       fprintf(gdb_log,"\"\n");
-}
-
-
-/************************************************************************/
-/*     
-/*                          REAL_T
-/*     
-/************************************************************************/
-
-#define RL_LEN                 (sizeof(double))
-#define RL_ALI                 RL_LEN
-#define RL_NULL        g_rl_null
-#define RL_CDLEN       g_rl_cdlen
-#define RL_ENC                 g_rl_enc
-#define RL_DEC         g_rl_dec
-#define RL_FORM                g_rl_form
-#define RL_NAME                "REAL_T"
-
-#define RL_EXTERNSIZE 32                       /* length of ascii coding */
-                                               /* must change lengths in */
-                                               /* encode and decode */
-                                               /* routines to match*/
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rl_null
-       /*      
-       /*      Fill in a null value for an real.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_rl_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       *((double *)dp) = 0.0;                  /* fill in a null value */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rl_cdlen
-       /*      
-       /*      Return coded length for an real.  For now, we just
-       /*      code as a 12 digit ASCII converted string.  Obviously,
-       /*      we can do much better in the future.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-/*ARGSUSED*/
-int
-g_rl_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       return RL_EXTERNSIZE;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rl_enc
-       /*      
-       /*      Encode an real for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-char *
-g_rl_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register char *cp;                      /* next char in output */
-       register char *endp = outp+RL_EXTERNSIZE;
-
-       /*
-        * Convert the data into printable ASCII in the output stream
-        * Note that the width in the format below must be less than
-        * RL_EXTERNSIZE, because sprintf needs space for its terminating
-        * null.
-        */
-
-       (void) sprintf(outp,"%30le",*((double *)dp));
-
-       /*
-        * Sprintf produces output of unpredictable length, and with 
-        * a null termination.  Pad it out to the desired length.
-        */
-
-       cp = outp + strlen(outp);               /* find out where convertd */
-                                               /* string stops*/
-       while (cp < endp)
-               *cp++ = ' ';                    /* pad to desired length */
-
-       return outp+RL_EXTERNSIZE;              /* return pointer to next */
-                                               /* unused output byte*/
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rl_dec
-       /*      
-       /*      Decode an real from external form
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-char *
-g_rl_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       (void) sscanf(inp,"%30le", (double *)outp);
-       return inp+RL_EXTERNSIZE;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rl_form
-       /*      
-       /*      Format an real on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_rl_form(name, dp)
-char *name;                                    /* string name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       fprintf(gdb_log, "REAL_T\t\t%s=%le\n",name,*((double *)dp) );
-}
-
-
-/************************************************************************/
-/*     
-/*                          DATE_T
-/*     
-/************************************************************************/
-
-#define DT_LEN                 25                      /* see ingres definition */
-#define DT_ALI                 1                       /* char data, need not align */
-#define DT_NULL        g_dt_null
-#define DT_CDLEN       g_dt_cdlen
-#define DT_ENC                 g_dt_enc
-#define DT_DEC         g_dt_dec
-#define DT_FORM                g_dt_form
-#define DT_NAME                "DATE_T"
-
-#define DT_EXTERNSIZE   DT_LEN                 /* length of ascii coding */
-                                               /* must change lengths in */
-                                               /* encode and decode */
-                                               /* routines to match*/
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_dt_null
-       /*      
-       /*      Fill in a null value for a date.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_dt_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       register char *cp = dp;                 /* next character to fill in */
-       register char *endp = dp + DT_LEN;
-
-       /*
-        * Fill the field with character blanks
-        */
-       while (cp < endp)
-               *cp++ = ' ';
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_dt_cdlen
-       /*      
-       /*      Return coded length for an date.  For now, we just
-       /*      code as a 25 digit ASCII converted string.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-/*ARGSUSED*/
-int
-g_dt_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       return DT_EXTERNSIZE;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_dt_enc
-       /*      
-       /*      Encode a date for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-char *
-g_dt_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register char *ip = dp;                 /* next char in input */
-       register char *op = outp;               /* next char in output */
-       register char *endp = op+DT_EXTERNSIZE;
-
-       /*
-        * Copy the input untransformed to the output 
-        */
-
-       while (op < endp)
-               *op++ = *ip++;                  /* pad to desired length */
-
-       return endp;                            /* return pointer to next */
-                                               /* unused output byte*/
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_dt_dec
-       /*      
-       /*      Decode an date from external form
-       /*      
-       /*----------------------------------------------------------*/
-
-/*ARGSUSED*/
-char *
-g_dt_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register char *ip = inp;                /* next char in input */
-       register char *op = outp;               /* next char in output */
-       register char *endp = op+DT_EXTERNSIZE;
-
-       /*
-        * Copy the input untransformed to the output 
-        */
-
-       while (op < endp)
-               *op++ = *ip++;                  /* pad to desired length */
-
-       return endp;                            /* return pointer to next */
-                                               /* unused output byte*/
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_dt_form
-       /*      
-       /*      Format a date on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_dt_form(name, dp)
-char *name;                                    /* string name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       char buf[DT_EXTERNSIZE+1];
-
-       memcpy(buf, dp, DT_EXTERNSIZE);         /* copy date to buffer */
-       buf[DT_EXTERNSIZE] = '\0';              /* null terminate it */
-       fprintf(gdb_log, "DATE_T\t\t%s=%s\n",name,buf);
-}
-
-
-/************************************************************************/
-/*     
-/*                          TUPLE_DESCRIPTOR_T
-/*     
-/*     The external representation of a tuple descriptor will be to
-/*     send the count of the number of fields, and then a one byte
-/*     signed integer describing each type followed by all the
-/*     corresponding null terminated strings.  The tuple descriptor
-/*     will really get re-created wth proper offsets and lengths upon
-/*     receipt by the create_tuple_descriptor operation.
-/*     
-/************************************************************************/
-
-#define TPD_LEN        (sizeof(TUPLE_DESCRIPTOR))
-#define TPD_ALI        (sizeof(TUPLE_DESCRIPTOR))
-#define TPD_NULL       g_tpd_null
-#define TPD_CDLEN      g_tpd_cdlen
-#define TPD_ENC        g_tpd_enc
-#define TPD_DEC                g_tpd_dec
-#define TPD_FORM       g_tpd_form
-#define TPD_NAME       "TUPLE_DESCRIPTOR_T"
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tpd_null
-       /*      
-       /*      Fill in a null value for a tuple_descriptor.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_tpd_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       register TUPLE_DESCRIPTOR *tdp = (TUPLE_DESCRIPTOR *)dp; 
-                                               /* re-type as */
-                                               /* tuple_descriptor */
-       (*tdp) = NULL;                          /* no data */
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tpd_cdlen
-       /*      
-       /*      Return coded length for a tuple_descriptor.  
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_tpd_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       register TUPLE_DESCRIPTOR tdp = *((TUPLE_DESCRIPTOR *)dp);      
-                                               /* re-type as */
-                                               /* tuple_descriptor */
-       register int coded_len;                 /* the value we're trying */
-                                               /* to compute */
-
-       /*
-        * Validate the descriptor
-        */
-       if (tdp == NULL)
-               GDB_GIVEUP("g_tpd_cdlen (coded length) was given a null tuple descriptor\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TPD(tdp,"g_tpd_cdlen: compute coded length of tuple descriptor")
-
-       coded_len = g_in_cdlen((char *)&(tdp->field_count),hcon);
-                                               /* we're going to send */
-                                               /* the field count as a */
-                                               /* true integer*/
-
-       coded_len += tdp->str_len + tdp->field_count;
-                                               /* space for all the */
-                                               /* strings, with nulls, */
-                                               /* and for the one byte */
-                                               /* types*/
-
-       return coded_len;
-               
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tpd_enc
-       /*      
-       /*      Encode a tuple_descriptor for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_tpd_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register TUPLE_DESCRIPTOR tdp = *((TUPLE_DESCRIPTOR *)dp);
-                                               /* re-type as */
-                                               /* tuple_descriptor */
-       register char *nextp;                   /* place to put next output */
-                                               /* byte */
-       register int i;                         /* a loop counter  */
-
-       /*
-        * Validate the descriptor
-        */
-       if (tdp == NULL)
-               GDB_GIVEUP("g_tpd_enc (encode) was given a null tuple descriptor\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TPD(tdp,"g_tpd_enc: encode tuple descriptor")
-
-       /*
-        * Use the integer coding routine to send the number of fields first
-        */
-                                               /* and coded form*/
-       nextp = (char *)g_in_enc((char *)&(tdp->field_count), hcon, outp);
-
-       /*
-        * Next, put in the one byte codes for each of the field types
-        */
-
-       for (i=0; i<tdp->field_count; i++) {
-               *nextp++ = tdp->var[i].type & 0xff; /* put out the one byte */
-                                                  /* type codes */
-       }
-
-       /*
-        * Finally, copy all the null terminated strings.
-        */
-       memcpy(nextp,((char *)(tdp))+gdb_descriptor_length(tdp->field_count), 
-              tdp->str_len);           /* copy the string data all */
-                                               /* at once */
-       return nextp+tdp->str_len;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tpd_dec
-       /*      
-       /*      Decode a tuple_descriptor from external form.  For
-       /*      safety in memory management, we always re-allocate the
-       /*      space for the tuple_descriptor. If the pointer passed
-       /*      to us is not null, then we assume that it points to a
-       /*      legal tuple descriptor, which we first free.  Because
-       /*      data representation may change, we must re-do the
-       /*      create-tuple-descriptor, so it can determine the local
-       /*      machine dependent representation and alignment rules
-       /*      for the data.
-       /*      
-       /*----------------------------------------------------------*/
-
-#define GDB_MAX_DECODED_FIELDS 100
-
-char *
-g_tpd_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to input data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register TUPLE_DESCRIPTOR *tdp = (TUPLE_DESCRIPTOR *)outp;      
-                                               /* re-type as */
-                                               /* tuple_descriptor */
-       int field_count;                        /* number of fields in the */
-                                               /* newly received descriptor*/
-       register int i;                         /* a loop counter */
-
-       register int tmp;                       /* working variable to hold */
-                                               /* type while they're being */
-                                               /* sign extended */
-       char *nextt;                            /* next byte to scan for */
-                                               /* a type code byte*/
-       char *nextn;                            /* next byte to scan for */
-                                               /* a string name */
-       char *field_names[GDB_MAX_DECODED_FIELDS];
-                                               /* put pointers to the */
-                                               /* field names here */
-       FIELD_TYPE field_types[GDB_MAX_DECODED_FIELDS];
-                                               /* put the field types in */
-                                               /* the array here*/
-       /*
-        * Use the integer coding routine to get the number of fields
-        */
-
-       nextt = (char *)g_in_dec((char *)&field_count, hcon, inp);
-       if (field_count > GDB_MAX_DECODED_FIELDS)
-               GDB_GIVEUP("g_tpd_dec: Trying to decode tuple descriptor with too many fields.\n")
-
-
-       /*
-        * For each field, pick up its type code, being sure to sign extend,
-        * and a pointer to its string name.
-        */
-       nextn = nextt + field_count;            /* there is one byte of */
-                                               /* type info for each field, */
-                                               /* after that comes the */
-                                               /* first string.  nextn */
-                                               /* now points to the first */
-                                               /* string */
-       for (i=0; i<field_count; i++) {
-               tmp = *nextt++;                 /* type code, may need */
-                                               /* sign extension */
-               if (tmp & 0x80)
-                       tmp |= ((~0) ^ 0xff);   /* sign extend if needed */
-                                               /* this is the most machine */
-                                               /* independent sign extension */
-                                               /* I could come up with. */
-                                               /* Presumes char is one byte, */
-                                               /* but makes no assumption */
-                                               /* about sizeof(int) */
-               field_types[i] = tmp;
-               field_names[i] = nextn;         /* pointer to name of the */
-                                               /* field */
-               nextn += strlen(nextn) +1;      /* set up for possible name */
-                                               /* to follow */
-       }
-
-       /*
-        * In case there was already a tuple descriptor here, free it.
-        */
-
-       delete_tuple_descriptor(*tdp);
-
-       /*
-        * Create a new descriptor based on the information we have received.
-        */
-       *tdp = create_tuple_descriptor(field_count, field_names, field_types);
-
-       return nextn;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tpd_form
-       /*      
-       /*      Format a tuple_descriptor on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_tpd_form(name, dp)
-char *name;                                    /* tuple_descriptor name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       register TUPLE_DESCRIPTOR tdp = *((TUPLE_DESCRIPTOR *)dp);      
-                                               /* re-type as */
-                                               /* tuple_descriptor */
-       register int i;                         /* loop variable through */
-                                               /* field definitions */
-
-
-       /*
-        *  Handle the special case where the descriptor is null
-        */
-       if (tdp == NULL) {
-               fprintf(gdb_log, "TUPLE_DESCRIPTOR %s (loc=NULL)\n", name);
-               return;
-       }
-
-       /*
-        * Validate the descriptor
-        */
-       GDB_CHECK_TPD(tdp,"g_tpd_form: format tuple descriptor")
-
-       /*
-        * Descriptor is not null
-        */
-       fprintf(gdb_log, "TUPLE_DESCRIPTOR %s (loc=0x%x)\n", name, tdp);
-
-       for (i=0; i<tdp->field_count; i++) {
-               fprintf(gdb_log,"\tField Type Code = %3d %20s\tField Name=%s\n" ,
-                       tdp->var[i].type, 
-                       STR_PROPERTY(tdp->var[i].type,NAME_PROPERTY),
-                       tdp->var[i].name);
-       }
-       fprintf(gdb_log,"\n");
-}
-
-
-/************************************************************************/
-/*     
-/*                          TUPLE_T
-/*     
-/*     There is a distinction between the type tuple_t and the
-/*     type tuple_data_t.  Tuple_t is a complete self-contained
-/*     tuple, with its descriptor.  It actually refers to the
-/*     tuple variable itself, which is a pointer.  Tuple_data 
-/*     is only the data portion of the tuple, not the descriptor.
-/*     It is used when the receiving tuple is already allocated,
-/*     with a correct descriptor, for sending just the data.
-/*     
-/*     Note that some of the routines for tuple_t could have been
-/*     implemented in terms of tuple_data_t routines.  For the
-/*     moment, they have not been, but that may later be changed.
-/*     Doesn't seem to make much difference as long as they are
-/*     short and simple, and this way does save a bit of overhead.
-/*     
-/************************************************************************/
-
-#define TP_LEN                 (sizeof(TUPLE))
-#define TP_ALI                 TP_LEN
-#define TP_NULL        g_tp_null
-#define TP_CDLEN       g_tp_cdlen
-#define TP_ENC                 g_tp_enc
-#define TP_DEC         g_tp_dec
-#define TP_FORM                g_tp_form
-#define TP_NAME                "TUPLE_T"
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tp_null
-       /*      
-       /*      Fill in a null value for a tuple.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_tp_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       *((TUPLE *)dp) = NULL;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tp_cdlen
-       /*      
-       /*      Return coded length for a tuple.  We have to send the
-       /*      descriptor along with the data itself.  We do this
-       /*      with calls to the appropriate encodeing routines.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_tp_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       register TUPLE tup = *((TUPLE *)dp);    /* deref as tuple */
-       register int len;                       /* accumulated length */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-
-       /*
-        * Validate the tuple
-        */
-       if (tup == NULL)
-               GDB_GIVEUP("g_tp_cdlen (coded length) was given a null tuple\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TUP(tup,"g_tp_cdlen: compute coded length of tuple")
-
-       /*
-        * First, get length of the descriptor when coded.
-        */
-
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-        len = g_tpd_cdlen((char *)&tpd,hcon);
-
-       /*
-        * Now, for each field, add in its coded length
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               len += (int)FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   CODED_LENGTH_PROPERTY)
-                          (FIELD_FROM_TUPLE(tup, i),hcon);
-       }
-       
-       return len;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tp_enc
-       /*      
-       /*      Encode a tuple for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_tp_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register TUPLE tup = *((TUPLE *)dp);    /* deref as tuple */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-       char *op;                               /* next byte of output */
-
-       /*
-        * Validate the tuple
-        */
-       if (tup == NULL)
-               GDB_GIVEUP("g_tp_enc (encode) was given a null tuple\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TUP(tup,"g_tp_enc: encode tuple")
-
-       /*
-        * First, get the tuple descriptor and encode it
-        */
-
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-        op = (char *)g_tpd_enc((char *)&tpd, hcon, outp);
-
-       /*
-        * Now, for each field, code it
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               op = (char *)FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   ENCODE_PROPERTY)
-                          (FIELD_FROM_TUPLE(tup, i),hcon, op);
-       }
-       
-       return op;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tp_dec
-       /*      
-       /*      Decode a tuple from external form.  For safety
-       /*      in memory management, we always re-allocate the
-       /*      space for the tuple, so the lengths come out right.
-       /*      This may have nasty side effects if the intention
-       /*      was to leave 'gas' at the end of the tuple, but
-       /*      we want to accurately copy the data.  Note that
-       /*      tuple_free is robust against null pointers.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_tp_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to input data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register TUPLE tup;                     /* the new tuple */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-       char *ip;                               /* next byte of input */
-
-       /*
-        * First, get the tuple descriptor and decode it
-        */
-
-       tpd = NULL;                             /* so decode will know */
-                                               /* there's no existing one */
-                                               /* to free */
-        ip = (char *)g_tpd_dec((char *)&tpd, hcon, inp);
-
-       /*
-        * Now make an empty tuple based on the descriptor
-        */
-
-       tup = create_tuple(tpd);
-
-       /*
-        * The tuple descriptor has a reference count of 2 here, one 
-        * from the tpd_dec routine, and one from the create_tuple.
-        * Since we don't expect to explicitly undo the two separately,
-        * we decrement the count here.
-        */
-
-       UNREFERENCE_TUPLE_DESCRIPTOR(tpd);      /* decr. the reference count */
-
-       /*
-        * Now, for each field, decode it.
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               ip = (char *)FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   DECODE_PROPERTY)
-                          (FIELD_FROM_TUPLE(tup, i),hcon, ip);
-       }
-       
-       *((TUPLE *)outp) = tup;                 /* put the new tuple */
-                                               /* pointer where the */
-                                               /* caller wants it */
-       return ip;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tp_form
-       /*      
-       /*      Format a tuple on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_tp_form(name, dp)
-char *name;                                    /* tuple name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       register TUPLE tup = *((TUPLE *)dp);    /* deref as tuple */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-
-
-       /*
-        * Handle special case where tuple is null
-        */
-
-       if (tup==NULL) {
-               fprintf(gdb_log,"\nTUPLE Name=%s is NULL\n---------------------------\n",name);
-               return;
-       }
-
-       GDB_CHECK_TUP(tup,"g_tp_form: format tuple")
-       /*
-        * Get the descriptor--for now, we won't print it 
-        */
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-
-       /*
-        * Print a header
-        */
-
-       fprintf(gdb_log,"\nTUPLE at address: 0x%x Name=%s\n---------------------------\n",tup,name);
-
-       /*
-        * Now, for each field, print it
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   FORMAT_PROPERTY)
-                          (tpd->var[i].name,FIELD_FROM_TUPLE(tup, i));
-       }
-       
-       fprintf(gdb_log,"END_OF_TUPLE\n");
-}
-
-
-/************************************************************************/
-/*     
-/*                          TUPLE_DATA_T
-/*     
-/*     The distinction between tuple_data_t and tuple_t is a
-/*     subtle one.  Tuple_t is used when a single tuple is to
-/*     be decoded, outside of any larger context.  It (re)allocates
-/*     memory for both the tuple itself and its descriptor.
-/*     
-/*     Tuple_data is used in the case where the tuple and its
-/*     descriptor are already allocated, but only the data is 
-/*     to be received.  This is useful in cases like receiving an
-/*     entire relation, in which the descriptor is common to 
-/*     all the tuples, and should not be resent or reallocated
-/*     with each one.  Receive relation can send the tuple descriptor
-/*     once, then do a create_tuple followed by a decode tuple_data
-/*     to receive the tuple field data into the existing tuple.
-/*     
-/*     Note that the definition of null is different in the two cases.
-/*     The null value for a tuple is just a null pointer.  The null
-/*     for tuple data is to null each of the fields in the tuple
-/*     recursively.  The routines in this section may dereference
-/*     null pointers if the tuples they are passed are null.  Note
-/*     also that there is one less level of indirection in passing
-/*     data to these routines than to those of tuple_t.  
-/*     
-/*     Note  also that the null and decode routines supplied here
-/*     presume that any fields with dependent memory (e.g. string_t
-/*     fields have already been cleaned up.)
-/*     
-/*     Note that this is not quite a kosher type, in the sense that
-/*     it's length is not fixed.  The entry for length below 
-/*     is meaningless, because the real length is computed from the
-/*     desc.  Among other things, this means that TUPLEs cannot
-/*     contain fields of this type.
-/*     
-/************************************************************************/
-
-#define TDT_LEN        (sizeof(TUPLE))
-#define TDT_ALI        TDT_LEN
-#define TDT_NULL       g_tdt_null
-#define TDT_CDLEN      g_tdt_cdlen
-#define TDT_ENC        g_tdt_enc
-#define TDT_DEC                g_tdt_dec
-#define TDT_FORM       g_tdt_form
-#define TDT_NAME       "TUPLE_DATA_T"
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tdt_null
-       /*      
-       /*      Fill in a null value for a tuple.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_tdt_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       TUPLE tup = (TUPLE)dp;                  /* dp is of type TUPLE, */
-                                               /* which is actually */
-                                               /* a pointer to the */
-                                               /* tuple data */
-       TUPLE_DESCRIPTOR tpd;                   /* the descriptor for this */
-                                               /* tuple*/
-       register int i;                         /* a loop counter */
-
-       /*
-        * For each field in the tuple, call its null routine
-        */
-       tup->id = GDB_TUP_ID;
-
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-
-       for (i=0; i<tpd->field_count; i++) {
-               FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),NULL_PROPERTY)
-                   (FIELD_FROM_TUPLE(tup,i));
-       }
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tdt_cdlen
-       /*      
-       /*      Return coded length for tuple data.  Since the descriptor
-       /*      for the tuple is known at both sides, we send only
-       /*      the coded fields, not even the field counts.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_tdt_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       register TUPLE tup = (TUPLE)dp;         /* arg typed as tuple */
-       register int len;                       /* accumulated length */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-
-       /*
-        * Validate the tuple data
-        */
-       if (tup == NULL)
-               GDB_GIVEUP("g_tdt_cdlen (coded length) was given null tuple data\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TUP(tup,"g_tdt_cdlen: compute coded length of tuple data")
-       /*
-        * First, find the tuple descriptor and set initial coded len to 0
-        */
-
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-        len = 0;
-
-       /*
-        * Now, for each field, add in its coded length
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               len += (int)FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   CODED_LENGTH_PROPERTY)
-                          (FIELD_FROM_TUPLE(tup, i),hcon);
-       }
-       
-       return len;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tdt_enc
-       /*      
-       /*      Encode tuple data for transmission.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_tdt_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register TUPLE tup = (TUPLE)dp;         /* type as tuple */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-       char *op = outp;                        /* next byte of output */
-
-       /*
-        * Validate the tuple data
-        */
-       if (tup == NULL)
-               GDB_GIVEUP("g_tdt_enc (encode) was given null tuple data\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TUP(tup,"g_tdt_enc: encode of tuple data")
-       /*
-        * First, get the tuple descriptor 
-        */
-
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-
-       /*
-        * Now, for each field, code it
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               op = (char *)FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   ENCODE_PROPERTY)
-                          (FIELD_FROM_TUPLE(tup, i),hcon, op);
-       }
-       
-       return op;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tdt_dec
-       /*      
-       /*      Decode tuple data from external form.  We presume
-       /*      that the tuple itself is allocated, and the descriptor
-       /*      properly set up for the local machine representation.
-       /*      Here we just decode the fields.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_tdt_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to input data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register TUPLE tup = (TUPLE)outp;       /* the filled in tuple */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-       char *ip = inp;                         /* next byte of input */
-
-       /*
-        * Validate the tuple data
-        */
-       if (tup == NULL)
-               GDB_GIVEUP("g_tdt_dec (decode) was given null tuple data\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_TUP(tup,"g_tdt_dec: decode of tuple data")
-       /*
-        * First, get the tuple descriptor 
-        */
-
-        tpd = DESCRIPTOR_FROM_TUPLE(tup);
-
-       /*
-        * Now, for each field, decode it.
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               ip = (char *)FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   DECODE_PROPERTY)
-                          (FIELD_FROM_TUPLE(tup, i),hcon, ip);
-       }
-       
-       return ip;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_tdt_form
-       /*      
-       /*      Format tuple data on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_tdt_form(name, dp)
-char *name;                                    /* tuple name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       register TUPLE tup = (TUPLE)dp;         /* as tuple */
-       register int i;                         /* index to fields */
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this tuple */
-
-
-       /*
-        * Handle special case where we're given a null address for the 
-        * tuple
-        */
-       if (tup==NULL) {
-               fprintf(gdb_log,"\nTUPLE Name=%s is NULL\n---------------------------\n",name);
-               return;
-       }
-
-
-       /*
-        * Validate the tuple data
-        */
-       GDB_CHECK_TUP(tup,"g_tdt_form: format tuple data")
-       /*
-        * Get the descriptor--for now, we won't print it 
-        */
-       tpd = DESCRIPTOR_FROM_TUPLE(tup);
-
-       /*
-        * Print a header
-        */
-
-       fprintf(gdb_log,"\nTUPLE at address: 0x%x  Name=%s\n---------------------------\n",tup,name);
-
-       /*
-        * Now, for each field, print it
-        */
-       
-       for (i=0; i<tpd->field_count; i++) {
-               FCN_PROPERTY(FIELD_TYPE_IN_TUPLE(tpd,i),
-                                   FORMAT_PROPERTY)
-                          (tpd->var[i].name,FIELD_FROM_TUPLE(tup, i));
-       }
-       
-       fprintf(gdb_log,"END_OF_TUPLE\n");
-}
-
-
-/************************************************************************/
-/*     
-/*                          RELATION_T
-/*     
-/*     Relations consist of link lists of tuples, all of which are
-/*     presumed to share a tuple descriptor.  For transmission, 
-/*     these are encoded as follows:
-/*     
-/*     1) A count of the number of tuples, sent as a properly coded
-/*        integer.
-/*     
-/*     2) The tuple descriptor itself, encoded by its encoding routine.
-/*     
-/*     3) For each tuple, its tuple data, encoded using the routines
-/*        of the tuple_data_t type.
-/*     
-/************************************************************************/
-
-#define REL_LEN        (sizeof(RELATION))
-#define REL_ALI        REL_LEN
-#define REL_NULL       g_rel_null
-#define REL_CDLEN      g_rel_cdlen
-#define REL_ENC        g_rel_enc
-#define REL_DEC                g_rel_dec
-#define REL_FORM       g_rel_form
-#define REL_NAME       "RELATION_T"
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rel_null
-       /*      
-       /*      Fill in a null value for a relation.  Maybe we should
-       /*      check for an existing relation and properly free it,
-       /*      but for now, we don't.
-       /*      
-       /*----------------------------------------------------------*/
-int
-g_rel_null(dp)
-char *dp;                                      /* pointer to the data */
-{
-       *((RELATION *)dp) = NULL;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rel_cdlen
-       /*      
-       /*      Return coded length for a relation.  
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_rel_cdlen(dp,hcon)
-char *dp;                                      /* pointer to the data */
-HALF_CONNECTION hcon;
-{
-       register RELATION rel = *((RELATION *)dp); /* deref as relation */
-       int  len;                               /* accumulated length */
-       register TUPLE t;                       /* index to a tuple */
-       int tuple_count = 0;                    /* number of tuples in this */
-                                               /* relation*/
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this */
-                                               /* relation */
-
-       /*
-        * Validate the relation
-        */
-       if (rel == NULL)
-               GDB_GIVEUP("g_rel_cdlen (coded  length) was given null relation\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_REL(rel,"g_rel_cdlen: compute coded length of relation")
-       /*
-        * First, get the tuple descriptor for this relation
-        */
-
-       tpd = DESCRIPTOR_FROM_RELATION(rel);
-
-       /*
-        * Count the number of tuples in the relation
-        */
-       for (t=FIRST_TUPLE_IN_RELATION(rel); t != NULL; 
-            t = NEXT_TUPLE_IN_RELATION(rel,t))
-               tuple_count++;
-       /*
-        * Start with the coded length for the tuple count and the
-        * descriptor, which are sent first.
-        */
-
-       len = g_in_cdlen((char *)&tuple_count, hcon);   /* length of tuple_count */
-                                               /* in coded form */
-        len += g_tpd_cdlen((char *)&tpd, hcon);
-
-       /*
-        * Now, for each tuple, add in its coded length
-        */
-       
-       for (t=FIRST_TUPLE_IN_RELATION(rel); t != NULL; 
-            t = NEXT_TUPLE_IN_RELATION(rel,t))
-               len += g_tdt_cdlen((char *)t, hcon);
-       
-       return len;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rel_enc
-       /*      
-       /*      Encode a relation for transmission
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_rel_enc(dp, hcon, outp)
-char *dp;                                      /* pointer to data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register RELATION rel = *((RELATION *)dp); /* deref as relation */
-       char *op;                               /* pointer to next unused */
-                                               /* output byte*/
-       register TUPLE t;                       /* index to a tuple */
-       int tuple_count = 0;                    /* number of tuples in this */
-                                               /* relation*/
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this */
-                                               /* relation */
-
-       /*
-        * Validate the relation
-        */
-       if (rel == NULL)
-               GDB_GIVEUP("g_rel_enc (encode) was given null relation\nthis may be due to an attempt to transmit invalid data")
-       GDB_CHECK_REL(rel,"g_rel_enc: encode relation")
-
-       /*
-        * First, get the tuple descriptor for this relation
-        */
-
-       tpd = DESCRIPTOR_FROM_RELATION(rel);
-
-       /*
-        * Count the number of tuples in the relation
-        */
-       for (t=FIRST_TUPLE_IN_RELATION(rel); t != NULL; 
-            t = NEXT_TUPLE_IN_RELATION(rel,t))
-               tuple_count++;
-       /*
-        * Encode the count and the tuple descriptor for this relation
-        */
-
-       op = (char *)g_in_enc((char *)&tuple_count, hcon,outp); 
-                                               /* length of tuple_count */
-                                               /* in coded form */
-        op = (char *)g_tpd_enc((char *)&tpd, hcon,op);
-
-       /*
-        * Now, encode each tuple
-        */
-       
-       for (t=FIRST_TUPLE_IN_RELATION(rel); t != NULL; 
-            t = NEXT_TUPLE_IN_RELATION(rel,t))
-               op = (char *)g_tdt_enc((char *)t, hcon, op);
-       
-       return op;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rel_dec
-       /*      
-       /*      Decode a relation from external form.  We should 
-       /*      really check to make sure the relation we are given
-       /*      is null, and if not, call delete_relation on it 
-       /*      first.  For the moment, we just presume it's null.
-       /*      
-       /*      We proceed by decoding the integer count and the
-       /*      tuple descriptor, from which we create the null
-       /*      relation.  We then loop for each tuple, doing a
-       /*      create, a decode, and an add to relation.
-       /*      
-       /*----------------------------------------------------------*/
-
-char *
-g_rel_dec(outp, hcon, inp)
-char *inp;                                     /* pointer to input data */
-HALF_CONNECTION hcon;                          /* connection descriptor */
-char *outp;                                    /* place to put the output */
-{
-       register RELATION rel;                  /* build the relation here */
-       char *ip;                               /* pointer to next unused */
-                                               /* input byte*/
-       register TUPLE t;                       /* index to a tuple */
-       register int i;                         /* loop counter on tuples */
-       int tuple_count = 0;                    /* number of tuples in this */
-                                               /* relation*/
-       TUPLE_DESCRIPTOR tpd;                   /* descriptor for this */
-                                               /* relation */
-
-       /*
-        * First, get the field count and tuple descriptor for this relation
-        */
-
-       ip = (char *)g_in_dec((char *)&tuple_count, hcon, inp);
-
-       tpd = NULL;                             /* so decode will know */
-                                               /* there's no existing one */
-                                               /* to free */
-       ip = (char *)g_tpd_dec((char *)&tpd, hcon, ip);
-
-       /*
-        * Now, create a null relation using the descriptor
-        */
-       
-       rel = create_relation(tpd);
-
-       /*
-        * The reference count for the tuple descriptor is currently 2, 
-        * one from the tpd_dec and one from the create relation.  Since
-        * these will not be undone separately, we decrement the reference
-        * count to 1
-        */
-
-       UNREFERENCE_TUPLE_DESCRIPTOR(tpd);
-
-       /*
-        * For each tuple, create it, receive it, add it to the relation
-        */
-       
-       for (i=0; i<tuple_count; i++) {
-               t = create_tuple(tpd);
-               ip = (char *)g_tdt_dec((char *)t, hcon, ip);
-               ADD_TUPLE_TO_RELATION(rel, t);          
-       }
-
-       /*
-        * Now store the address of the created relation where requested
-        * and return pointer to next available input byte.
-        */
-
-       *((RELATION *)outp) = rel;
-
-       return ip;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      g_rel_form
-       /*      
-       /*      Format a relation on output logging file for
-       /*      debugging.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_rel_form(name, dp)
-char *name;                                    /* relation name of the field */
-char *dp;                                      /* pointer to the data */
-{
-       register RELATION rel = *((RELATION *)dp); /* deref as relation */
-       register TUPLE t;
-       int count =0;
-       char buffer[50];
-
-       /*
-        * Handle special case where relation is null
-        */
-
-       if (rel == NULL) {
-               fprintf(gdb_log,"\nRELATION Name=%s is NULL\n===========================\n",name);
-               return;
-       }
-
-       GDB_CHECK_REL(rel,"g_rel_form: format relation")
-
-       /*
-        * Print a header
-        */
-
-       fprintf(gdb_log,"\nRELATION at address: 0x%x Name=%s\n===========================\n",rel,name);
-
-       /*
-        * Now, for each field, print it
-        */
-       
-       for (t=FIRST_TUPLE_IN_RELATION(rel); t != NULL; 
-            t = NEXT_TUPLE_IN_RELATION(rel,t)){
-               (void) sprintf(buffer,"Number %d",++count);
-               g_tdt_form(buffer,(char *)t);
-       }
-       
-       fprintf(gdb_log,"END_OF_RELATION\n");
-}
-
-
-/************************************************************************/
-/*     
-/*        DECLARE AND INITIALIZE THE SYSTEM TYPE DEFINITION 
-/*                            TABLES
-/*     
-/*     This representation is clearly a real pain to keep up to date
-/*     properly, mostly because C has such a lousy pre-processor.
-/*     Probably this should be re-arranged so an initialization routine
-/*     is called to set up the tables, but even that might be a nuissance.
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      gdb_i_stype
-       /*      
-       /*      Called at startup to initialize the type table with
-       /*      the entries for the system types.
-       /*      
-       /*----------------------------------------------------------*/
-
-#define ITYPE(inx,lp,ap,np,clp,ep,dp,fp,name) {\
-       g_type_table[inx][LENGTH_PROPERTY].i = lp; \
-       g_type_table[inx][ALIGNMENT_PROPERTY].i = ap; \
-       g_type_table[inx][NULL_PROPERTY].f = np; \
-       g_type_table[inx][CODED_LENGTH_PROPERTY].f = clp; \
-       g_type_table[inx][ENCODE_PROPERTY].cpf = ep; \
-       g_type_table[inx][DECODE_PROPERTY].cpf = dp; \
-       g_type_table[inx][FORMAT_PROPERTY].f = fp; \
-       g_type_table[inx][NAME_PROPERTY].cp = name; \
-}
-
-int
-gdb_i_stype()
-{
-       gdb_n_types = SYSTEM_TYPE_COUNT;
-
-       ITYPE(INTEGER_T,IN_LEN,IN_ALI,IN_NULL,IN_CDLEN,IN_ENC,IN_DEC,IN_FORM,
-             IN_NAME)
-       ITYPE(STRING_T,ST_LEN,ST_ALI,ST_NULL,ST_CDLEN,ST_ENC,ST_DEC,ST_FORM,
-             ST_NAME)
-       ITYPE(REAL_T,RL_LEN,RL_ALI,RL_NULL,RL_CDLEN,RL_ENC,RL_DEC,RL_FORM,
-             RL_NAME)
-       ITYPE(DATE_T,DT_LEN,DT_ALI,DT_NULL,DT_CDLEN,DT_ENC,DT_DEC,DT_FORM,
-             DT_NAME)
-       ITYPE(TUPLE_DESCRIPTOR_T,TPD_LEN,TPD_ALI,TPD_NULL,TPD_CDLEN,TPD_ENC,
-             TPD_DEC,TPD_FORM,TPD_NAME)
-       ITYPE(TUPLE_T,TP_LEN,TP_ALI,TP_NULL,TP_CDLEN,TP_ENC,TP_DEC,TP_FORM,
-             TP_NAME)
-       ITYPE(TUPLE_DATA_T,TDT_LEN,TDT_ALI,TDT_NULL,TDT_CDLEN,TDT_ENC,TDT_DEC,
-             TDT_FORM,TDT_NAME)
-       ITYPE(RELATION_T,REL_LEN,REL_ALI,REL_NULL,REL_CDLEN,REL_ENC,REL_DEC,
-             REL_FORM,REL_NAME)
-}
diff --git a/gdb/gdb_trans.c b/gdb/gdb_trans.c
deleted file mode 100644 (file)
index 36ad945..0000000
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_trans_c = "$Header$";
-#endif
-
-/************************************************************************/
-/*     
-/*                        gdb_trans.c
-/*     
-/*           GDB - Data Transport Services Routines (Part 1)
-/*     
-/*     Author: Noah Mendelsohn
-/*     Copyright: 1986 MIT Project Athena 
-/*             For copying and distribution information, please see
-/*             the file <mit-copyright.h>.
-/*     
-/*     These routines implement layer 6 of the Client Library
-/*     Specification of the GDB system, as well as the facilities
-/*     outlined in the GDB Protocol Specification. (Part 1 of 2)
-/*
-/*     Some of the routines specified are actually implemented as
-/*     macros defined in gdb.h.
-/*     
-/************************************************************************/
-
-#include <mit-copyright.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdio.h>
-#include <varargs.h>
-#include <errno.h>
-extern int errno;
-#include "gdb.h"
-
-\f
-/************************************************************************/
-/*     
-/*                     OPERATION Manipulation
-/*     
-/*     The routines in this section provide services for creating
-/*     and manipulating GDB queueable operations.  
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                 create_operation (create_operation)
-       /*      
-       /*      Allocates space for an operation descriptor and 
-       /*      returns a pointer to it.  Initialize the eyecatcher
-       /*      so that in the future we can prove by inspection that
-       /*      this really is an operation descriptor.
-       /*      
-       /*----------------------------------------------------------*/
-
-OPERATION
-create_operation()
-{
-       register OPERATION op;
-       GDB_INIT_CHECK
-       op = (OPERATION)db_alloc(sizeof(OPERATION_DATA));
-       op->status = OP_NOT_STARTED;            /* things like */
-                                               /* reset_operation */
-                                               /* want valid status */
-                                               /* at all times*/
-       op->id = GDB_OP_ID;
-       return op;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                 reset_operation (reset_operation)
-       /*      
-       /*      Sets the status of an operation to OP_NOT_STARTED
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-reset_operation(op)
-OPERATION op;
-{
-       register int status;
-
-       GDB_CHECK_OP(op, "reset_operation")
-
-       status = OP_STATUS(op);
-       if (status == OP_QUEUED || 
-           status == OP_RUNNING)
-               GDB_GIVEUP("gdb:reset_operation invalid on running operation")
-       op->status = OP_NOT_STARTED;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                delete_operation(delete_operation)
-       /*      
-       /*      Frees an operation descriptor.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-delete_operation(op)
-OPERATION op;
-{
-       GDB_CHECK_OP(op, "delete_operation");
-       op->id = -1;
-       db_free((char *)op, sizeof(OPERATION_DATA));
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                initialize_operation(initialize_operation)
-       /*      
-       /*      Initialize the data in an operation descriptor
-       /*      based on the supplied parameters.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-initialize_operation(operation, init_function, arg, cancel_function)
-OPERATION operation;                           /* initialize this */
-int (*init_function)();                                /* function to call when */
-                                               /* starting operation */
-char *arg;                                     /* arg to pass to init and */
-                                               /* continue routines */
-int (*cancel_function)();                      /* call this function */
-                                               /* when cancelling the op. */
-                                               /* may be NULL, may not */
-                                               /* be elided */
-{
-       register OPERATION op = operation;      /* just for speed */
-
-       GDB_CHECK_OP(op, "initialize_operation")
-
-
-       /*
-        * Fill in boilerplate - same for all newly initialized ops.
-        */
-       op->next = op->prev = NULL;             /* it's not in a queue yet */
-       op->tag = (-1);                         /* not tagged until queued */
-       op->status = OP_NOT_STARTED;
-       op->flags = 0;
-       op->result = (-1);                      /* result is not valid until */
-                                               /* status is OP_COMPLETE. */
-                                               /* All users of result field */
-                                               /* are expected to treat -1 */
-                                               /* invalid */
-       op->halfcon = NULL;                     /* not queued yet */
-
-       /*
-        * Fill in supplied parameters
-        */
-       op->arg = arg;
-       op->fcn.init = init_function;
-       op->cancel = cancel_function;
-
-       return;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*          create_list_of_operations (create_list_of_operations)
-       /*      
-       /*      Allocates and fills in a data structure which 
-       /*      contains a list of operations.  This list is
-       /*      suitable for passing to op_select.
-       /*      
-       /*      The facilities of <varargs.h> are used to parse 
-       /*      the variable length parameter list to this function.
-       /*      See "man 3 varargs" for details.
-       /*      
-       /*----------------------------------------------------------*/
-
-/*VARARGS1*/
-
-LIST_OF_OPERATIONS
-create_list_of_operations(count, va_alist)
-int    count;
-va_dcl
-{
-       va_list ap;                             /* the control structure */
-                                               /* for varargs parsing */
-
-       register int i;
-       register LIST_OF_OPERATIONS newlist;    /* newly allocated list */
-
-       /*
-        * Allocate the new list of operations, initialize its count.
-        */
-       newlist = (LIST_OF_OPERATIONS)
-                  db_alloc(size_of_list_of_operations(count));
-       newlist->count = count;
-
-       /*
-        * Using the facilities of varargs.h, pick up the operations
-        * and put them in the list.
-        */
-       va_start(ap);
-       for (i=0; i<count; i++) {
-               newlist->op[i] = va_arg(ap, OPERATION);
-               GDB_CHECK_OP((newlist->op[i]), "create_list_of_operations")
-       }
-       va_end(ap);
-
-       return newlist;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*          delete_list_of_operations(delete_list_of_operations)
-       /*      
-       /*      Deallocate the space for a list of operations.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-delete_list_of_operations(op_list)
-LIST_OF_OPERATIONS op_list;
-{
-       db_free((char *)op_list, size_of_list_of_operations(op_list->count));
-}
-\f
-/************************************************************************/
-/*     
-/*                     OPERATION QUEUE MANIPULATION
-/*     
-/*     Routines to queue (initiate) and track completion of GDB
-/*     operations.
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      op_select(op_select)
-       /*      
-       /*      This function is an analog of the standard Berkeley
-       /*      select system call.  It provides all the functions
-       /*      of select, but in addition, it awaits completion
-       /*      of a specified list of queued gdb operations.  
-       /*      
-       /*      This function returns when any combination of the
-       /*      following are found to be true:
-       /*      
-       /*      1) Any of the designated operations has completed
-       /*         or terminated prematurely.
-       /*      
-       /*      2) Activity is detected on any of the explictly supplied
-       /*         file descriptors or the supplied timer has expired.
-       /*      
-       /*      The count returned is only for file descriptors 
-       /*      explicitly listed.  Completed operatons may be detected
-       /*      by checking OP_STATUS for each of the operations in
-       /*      the list.  File descriptors controlled by CONNECTIONS
-       /*      should never be passed explictly in the bit maps to
-       /*      this routine.  Only user controlled file descriptors 
-       /*      may be explictly selected.
-       /*      
-       /*      Return code summary:
-       /*              
-       /*              -2      One or more listed operations completed.
-       /*                      Timer did not ring (as far as we could
-       /*                      tell), other fd's did not complete, or
-       /*                      we didn't get far enough to bother 
-       /*                      looking. (see fairness below.)
-       /*      
-       /*              -1      An error was returned on select of a 
-       /*                      user supplied socket.  errno has the
-       /*                      error code.
-       /*      
-       /*              0       The timer rang.  Some operations may
-       /*                      be complete, but it's unlikely.
-       /*      
-       /*              >0      This many user supplied fd's were
-       /*                      satisfied--same as for select.
-       /*                      Operations in the list may also have
-       /*                      completed.
-       /*      
-       /*      Fairness is not guaranteed.  This routine tends to
-       /*      favor activity on CONNECTIONs.  In particular, if
-       /*      some operation(s) in the list can be completed 
-       /*      synchronously, a real select is never done to 
-       /*      check on the file descriptors.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-op_select(op_list, nfds, readfds, writefds, exceptfds, timeout)
-LIST_OF_OPERATIONS op_list;
-int    nfds;
-fd_set  *readfds, *writefds, *exceptfds;
-struct timeval *timeout;
-{
-       int rc;                                 /* return code holder */
-       fd_set rfds, wfds, efds;                /* local copys of read */
-                                               /* write, and exception */
-                                               /* fd's */
-
-       /*
-        * Make sure that any activity which can be done immediately is
-        * indeed done now--we may not have to wait at all.
-        */
-       (void) gdb_fastprogress();   /*<==FIX (check to make sure this is OK)*/
-
-       /* 
-        * Loop checking for termination conditions, and if none arise,
-        * use con_select to make wait for one or more of the
-        * connections to wake up and do the appropriate processing.
-        */
-       while (TRUE) {
-               /*
-                * If any of the queue operations have completed,
-                * then just return now.
-                */
-               if (gdb_list_complete(op_list)) 
-                       return (-2);            /* no fd's satisfied here */
-
-               /*
-                * Use con_select to await all the appropriate events
-                */
-               g_fd_copy(nfds, readfds, &rfds);
-               g_fd_copy(nfds, writefds, &wfds);
-               g_fd_copy(nfds, exceptfds, &efds);
-
-               rc = con_select(nfds, &rfds, &wfds, &efds, timeout);
-
-               /*
-                * At this point, either some of the supplied fd's have
-                * been satisfied(rc>0), or the timer has rung (rc=0),
-                * an error was returned from select on a user specified socket
-                * (-1) or none of these (-2).  In any case, there may
-                * have been progress on one of the connections, and
-                * con_select will already have progressed as far as 
-                * possible before returning.  Now, decide what to
-                * do, given the return code.
-                */
-               if (rc>= (-1)) {
-                       /*
-                        * Return updated bit-maps to caller.
-                        */
-                       g_fd_copy(nfds, &rfds, readfds);
-                       g_fd_copy(nfds, &wfds, writefds);
-                       g_fd_copy(nfds, &efds, exceptfds);
-                       return rc;
-               }       
-       }       
-}
-\f
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      op_select_all(op_select_all)
-       /*      
-       /*      Similar to op_select_any, but returns (-1) only
-       /*      in the case that all of the designated descriptors
-       /*      are OP_COMPLETE or OP_CANCELLED.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-op_select_all(op_list, nfds, readfds, writefds, exceptfds, timeout)
-LIST_OF_OPERATIONS op_list;
-int    nfds;
-fd_set  *readfds, *writefds, *exceptfds;
-struct timeval *timeout;
-{
-       register int i;
-        int rc = -1;
-       register int left = op_list->count;
-
-       /*
-        * take care of those which are already complete by decrementing
-        * and reseting them
-        */
-
-       for (i=0; i<op_list->count; i++) {
-               if (op_list->op[i]->status==OP_COMPLETE) {
-                       op_list->op[i]->flags |= OPF_MARKED_COMPLETE;
-                       op_list->op[i]->status = OP_MARKED;
-                                               /* so op_select_any won't */
-                                               /* fall right through*/
-                       
-                       left--;
-                       continue;
-               }
-               if (op_list->op[i]->status==OP_CANCELLED) {
-                       op_list->op[i]->flags |= OPF_MARKED_CANCELLED;
-                       op_list->op[i]->status = OP_MARKED;
-                                               /* so op_select_any won't */
-                                               /* fall right through*/
-                       
-                       left--;
-               }
-       }
-
-       
-       /*
-        * As long as there are incomplete operations left in the list,
-        * keep calling op_select_any
-        */
-       while (left) {
-               rc = op_select(op_list, nfds, readfds, writefds, exceptfds, 
-                              timeout);
-               if (rc>=0)
-                       break;
-               for (i=0; i<op_list->count; i++) {
-                       if (op_list->op[i]->status==OP_COMPLETE) {
-                               op_list->op[i]->flags |= OPF_MARKED_COMPLETE;
-                               op_list->op[i]->status = OP_MARKED;
-                                               /* so op_select_any won't */
-                                               /* fall right through*/
-                               
-                               left--;
-                               continue;
-                       }
-                       if (op_list->op[i]->status==OP_CANCELLED) {
-                               op_list->op[i]->flags |= OPF_MARKED_CANCELLED;
-                               op_list->op[i]->status = OP_MARKED;
-                                               /* so op_select_any won't */
-                                               /* fall right through*/
-                               
-                               left--;
-                       }
-               }
-       }
-
-       /*
-        * Clean up the marked operations and return
-        */
-       for (i=0; i<op_list->count; i++) {
-               if (op_list->op[i]->status==OP_MARKED) {
-                       op_list->op[i]->status = (op_list->op[i]->flags & 
-                                                 OPF_MARKED_COMPLETE) ?
-                                                   OP_COMPLETE : 
-                                                   OP_CANCELLED;
-                       op_list->op[i]->flags &= ~(OPF_MARKED_COMPLETE |
-                                                 OPF_MARKED_CANCELLED);
-               }
-       }
-
-       return rc;
-
-}
-\f
-/************************************************************************/
-/*     
-/*     Internal transport layer routines, not called directly
-/*     from client library.
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                   gdb_list_complete
-       /*      
-       /*      Given a list of gdb operations, return TRUE if any
-       /*      of them are complete, otherwise return FALSE.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-gdb_list_complete(op_list)
-LIST_OF_OPERATIONS op_list;
-{
-       register int i;
-       register int status;
-       register LIST_OF_OPERATIONS oplist = op_list; /* for speed */
-        int count = oplist -> count;
-
-       for (i=0; i<count; i++) {
-               status = OP_STATUS(oplist->op[i]);
-               if (status == OP_COMPLETE ||
-                   status == OP_CANCELLED)
-                       return TRUE;
-       }
-
-       return FALSE;           
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                        g_fd_copy
-       /*      
-       /*      Copy one set of fd masks to another. 
-       /*      
-       /*----------------------------------------------------------*/
-
-g_fd_copy(nfds, source, targ)
-int nfds;
-fd_set *source, *targ;
-{
-       register int i;
-       register int n = howmany(nfds, NFDBITS); /* number of words for */
-                                                /* this many fd's */
-
-       for (i=0; i<n; i++)
-               targ->fds_bits[i] = source->fds_bits[i];
-}
-       /*----------------------------------------------------------*/
-       /*      
-       /*                        g_fd_or_and_copy
-       /*      
-       /*      Or two sets of file descriptor masks together and
-       /*      copy to a third.  Parameters are:
-       /*      
-       /*      1) First mask count
-       /*      2) Second mask count
-       /*      3) pointer to first mask
-       /*      4) Pointer to second mask
-       /*      5) Pointer to output mask
-       /*      
-       /*----------------------------------------------------------*/
-
-g_fd_or_and_copy(nfds1, nfds2 , source1, source2, targ)
-int nfds1, nfds2;
-fd_set *source1, *source2, *targ;
-{
-       register int i;
-       fd_set *longer;                         /* points to whichever */
-                                               /* of the two masks is */
-                                               /* longer */
-       int tot_words = howmany(max(nfds1,nfds2), NFDBITS);
-       int shared_words = howmany(min(nfds1,nfds2), NFDBITS);
-
-
-       /*
-        * For words which exist in both masks, or the bits together
-        */
-       for (i=0; i<shared_words; i++)
-               targ->fds_bits[i] = source1->fds_bits[i] | 
-                                   source2->fds_bits[i];
-       /*
-        * Copy the rest of whichever is longer
-        */
-       longer = (nfds1>nfds2) ? source1 : source2;
-       
-       while (i<tot_words) {
-               targ->fds_bits[i] = longer->fds_bits[i];
-               i++;
-       }
-
-       return;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                        g_compute_return_fds
-       /*      
-       /*      When con_select returns, the count it gives back 
-       /*      applies only to user supplied fd's, not those 
-       /*      relating to connections.  Unfortunately, select
-       /*      gives back both in the masks it returns.  Here we
-       /*      fix only the count to reflect the fact that we will be
-       /*      turning off bits when and if they are returned.
-       /*      
-       /*      We can assume here that the masks provided are as long
-       /*      as merged_nfds, which means they are at least as long
-       /*      as gdb_mfd.
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-g_compute_return_fds(select_count, rfds, wfds, efds)
-int select_count;                              /* count of 1 bits as */
-                                               /* returned from select */
-fd_set *rfds, *wfds, *efds;                    /* read, write, and except */
-                                               /* maps as returned from */
-                                               /* select */
-{
-       register int i;
-       register int return_count = select_count; /* the value we'll return */
-       register int words;                     /* number of words in each */
-                                               /* of the connection masks */
-
-
-       /*
-        * Since we can only decrement the count, there's no sense doing
-        * any work if it's already 0;
-        */
-       if (return_count == 0)
-               return 0;
-       /*
-        * Figure out how many words we have to look at to get all the
-        * bits covered by connection masks.
-        */
-       words = howmany(gdb_mfd, NFDBITS);
-
-       /*
-        * For words which are involved in the connection masks, check
-        * for matches and decrement the count accordingly.  Stop when
-        * the count hits 0 or we're out of words.
-        */
-       for (i=0; i<words && (return_count>0) ; i++) {
-               return_count -= g_bitcount((unsigned int)
-                                          (gdb_crfds.fds_bits[i] & 
-                                           rfds->fds_bits[i])); 
-               return_count -= g_bitcount((unsigned int)
-                                          (gdb_cwfds.fds_bits[i] & 
-                                           wfds->fds_bits[i])); 
-               return_count -= g_bitcount((unsigned int)
-                                          (gdb_cefds.fds_bits[i] & 
-                                           efds->fds_bits[i])); 
-       }
-
-       return return_count;
-}
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                        g_fd_reset_conbits
-       /*      
-       /*      Given a user supplied fd bit mask and a connection
-       /*      related bit mask, turn off any of the connection related
-       /*      bits in the user mask, and copy the result to a supplied
-       /*      target.
-       /*      
-       /*      1) User mask count
-       /*      2) Connection mask count
-       /*      3) Pointer to user mask
-       /*      4) Pointer to connection mask
-       /*      5) Pointer to output mask
-       /*      
-       /*      Output is always the same length as the user mask.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-g_fd_reset_conbits(nfds, con_nfds , source, conbits, targ)
-int nfds, con_nfds;
-fd_set *source, *conbits, *targ;
-{
-       register int i;
-       register int tot_words = howmany(nfds, NFDBITS); /* this rtn never*/
-                                               /* returns a mask longer */
-                                               /* than nfds */
-       register int shared_words = howmany(min(nfds, con_nfds), NFDBITS);
-
-
-       /*
-        * For words which exist in both masks, turn off bits from conmask
-        */
-       for (i=0; i<shared_words; i++)
-               targ->fds_bits[i] = source->fds_bits[i] & 
-                                   ~(conbits->fds_bits[i]);
-       /*
-        * Copy the rest of source, if any
-        */
-       if (tot_words > shared_words)
-               while (i<tot_words) {
-                       targ->fds_bits[i] = source->fds_bits[i];
-                       i++;
-               }
-
-       return;
-}
-
-\f
-/************************************************************************/
-/*     
-/*                     CONNECTION MANIPULATION
-/*     
-/*     Routines to control data transmission on gdb connections.
-/*     
-/************************************************************************/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*               con_select (con_select)
-       /*      
-       /*      This operation has exactly the same semantics as the select
-       /*      system call, except that (1) it implicitly selects all file
-       /*      descriptors controlled by connections, as well as those
-       /*      explictly specified and (2) it allows transmission and
-       /*      receipt to progress on all connections and (3) it considers
-       /*      a connection to be selected iff a transmission operation
-       /*      which had been pending becomes complete.  One may consider
-       /*      that con_select turns the fd's controlled by sockets into
-       /*      packet streams rather than byte streams.  Note also that
-       /*      this operation differs from a traditional select and an
-       /*      op_select in that it is not robust against waiting for
-       /*      connections with pre-completed activity. This could be
-       /*      added, but since it's an internal routine anyway, it seems
-       /*      not to be worthwhile. Also, this routine presumes that all 
-       /*      possible progress has been made before con_select is invoked.
-       /*      
-       /*      This operation hangs in a select.  If activity is
-       /*      discovered on any of the sockets controlled by the database
-       /*      library, then the corresponding input is read and
-       /*      appropriate processing is done.  If any of the transmission
-       /*      operations which had been pending on one of these
-       /*      connections completes, then con_select may return.  In
-       /*      fact, con_select attempts to complete any further
-       /*      connection related activity which can be done without
-       /*      blocking, but con_select never blocks AFTER a transmission
-       /*      operation has gone complete.
-       /*      
-       /*      If activity is detected on any of the file descriptors
-       /*      supplied by the user, then a count and bit fields are
-       /*      returned just as for select. (Activity on database sockets
-       /*      is never reflected in either count or bitfields.)  Timeout
-       /*      causes a return, as with select.  Upon return, the program
-       /*      must check for competion or termination on all of the
-       /*      connections in which he/she is interested, for activity on
-       /*      the selected file descriptors, and for timeouts, if
-       /*      requested, since any or all of these may be reported
-       /*      together.
-       /*      
-       /*      Return values for con_select: >0 same as for select, 0 time
-       /*      expired, -1, error in select on user fd, -2, connections
-       /*      have progressed but nothing else of interest.
-       /*      
-       /*      
-       /*----------------------------------------------------------*/
-
-int
-con_select(nfds, readfds, writefds, exceptfds, timeout)
-int    nfds;
-fd_set  *readfds, *writefds, *exceptfds;
-struct timeval *timeout;
-{
-       int merged_nfds;                        /* the index of the last */
-                                               /* file desc we care about.*/
-       int select_fds;                         /* number of file */
-                                               /* returned from select */
-                                               /* descriptors */
-       int return_fds;                         /* fds count to be returned */
-                                               /* to the user */
-       int complete_count;                     /* number of connections on */
-                                               /* which operations have */
-
-                                               /* completed */
-
-       /*
-        * figure out highest number file descriptor to worry about
-        */
-       merged_nfds = max(nfds, gdb_mfd);       /* the number we control */
-                                               /* or last one the user */
-                                               /* supplied, whichevere is */
-                                               /* higher */
-       /*
-        * Loop waiting for activity to occur and processing it as appropriate.
-        * Note that the order of the tests, calls to select, and gdb_progress
-        * in this code is critical.  Think it through before you change it
-        * to make sure that progress is always made when possible, and that
-        * returns are always made when needed.
-        */
-       while (TRUE) {
-               /*
-                * Prepare working copies of the file descriptor maps
-                * based on the ones supplied by the caller, as well as
-                * all the descriptors used by connections.  The latter
-                * are mapped in the gdb_c?fds global variables.
-                */
-               g_fd_or_and_copy(nfds,gdb_mfd,readfds,&gdb_crfds,&last_crfds);
-               g_fd_or_and_copy(nfds,gdb_mfd,writefds,&gdb_cwfds,&last_cwfds);
-               g_fd_or_and_copy(nfds,gdb_mfd,exceptfds,&gdb_cefds,&last_cefds);
-               /*
-                * Use select to wait for something to happen.  Compute
-                * number select would have returned if connection related
-                * fd's had not been supplied.
-                */
-               select_fds = select(merged_nfds, &last_crfds, &last_cwfds, &last_cefds, 
-                                   timeout);
-               /*
-                * There are some messy things we have to worry about here:
-                * 
-                * 1) Select could return an error.  In particular, some
-                *    versions of Unix will return -1 with EBADF if one
-                *    of the sockets has closed.  We should call a 
-                *    procedure here to see if this has happened to one
-                *    of ours.  
-                * 
-                * 2) Other versions of Unix will claim that there is activity
-                *    on our socket when in fact the other end is closed.  
-                *    We will leave it to gdb_move_data to try the select
-                *    and make the appropriate decision.
-                * 
-                * Yes folks, messy but true.  If we got an error (case 1),
-                * then let's see if we get the same error when we're only
-                * looking at the caller's fd's.
-                * 
-                */
-               return_fds = 0;
-               if (select_fds < 0)
-                       if ( errno != EBADF)
-                               return -1;
-                       else {
-                               g_fd_or_and_copy(nfds,0,readfds,&gdb_crfds,&last_crfds);
-                               g_fd_or_and_copy(nfds,0,writefds,&gdb_cwfds,&last_cwfds);
-                               g_fd_or_and_copy(nfds,0,exceptfds,&gdb_cefds,&last_cefds);
-                               if (select(nfds, &last_crfds, &last_cwfds, &last_cefds, 
-                                          &gdb_notime)<0) {
-                                       g_fd_copy(nfds, &last_crfds, readfds);
-                                       g_fd_copy(nfds, &last_cwfds, writefds);
-                                       g_fd_copy(nfds, &last_cefds, exceptfds);
-                                       return -1; /* select EBADF   */
-                               } else {
-                                       /*
-                                        * We should close the connection here
-                                        */
-                                       GDB_GIVEUP("con_select: EBADF on GDB controlled file.")
-                               }
-                       }
-               else {
-                       return_fds = g_compute_return_fds(select_fds,
-                                                   &last_crfds, &last_cwfds, &last_cefds);
-               }
-               /*
-                * If some connection related descriptors were selected, then
-                * try to make progress on them.  Find out if any new operations
-                * could be completed.
-                */
-               if (select_fds != return_fds)
-                       complete_count = gdb_fastprogress();
-               else
-                       complete_count = 0;
-               /*
-                * Now, based on the number of operations complete,
-                * the number of user file descriptors satisfied, and
-                * the possible return of a timeout from select, decide
-                * whether to return to the caller.  Note that timeout
-                * is identified by select_fds == 0.
-                */
-               if (complete_count > 0 ||       /* operations are complete */
-                   return_fds >0 ||            /* user files satisfied */
-                   select_fds ==0) {           /* timeout in select */
-                       /*
-                        * Connection related fd bits are never returned 
-                        * to the caller.  Reset them.  The count of bits
-                        * was already adjusted appropriately above.  I don't
-                        * think there's too much wasted effort in this, 
-                        * but we should watch it if profiling indicates
-                        * lots of time being spent computing in con_select.
-                        * Put the updated bit masks in the caller supplied
-                        * maps.
-                        */
-                       g_fd_reset_conbits(nfds,gdb_mfd,&last_crfds,&gdb_crfds,
-                                          readfds);
-                       g_fd_reset_conbits(nfds,gdb_mfd,&last_cwfds,&gdb_cwfds,
-                                          writefds);
-                       g_fd_reset_conbits(nfds,gdb_mfd,&last_cefds,&gdb_cefds,
-                                          exceptfds);
-                       if (select_fds ==0)
-                               return 0;       /* real timeout */
-                       if (return_fds ==0)     /* something must have */
-                                               /* completed, but our */
-                                               /* count looks like a */
-                                               /* timeout*/
-                               return (-2);    /* only connections have */
-                                               /* somethine complete */
-                       else
-                               return return_fds;
-               }
-       }
-}
diff --git a/gdb/gdb_trans2.c b/gdb/gdb_trans2.c
deleted file mode 100644 (file)
index dea58ba..0000000
+++ /dev/null
@@ -1,1260 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_gdb_trans2_c = "$Header$";
-#endif
-
-
-/************************************************************************
- *     
- *                        gdb_trans2.c
- *     
- *           GDB - Data Transport Services Routines (Part 2)
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena 
- *             For copying and distribution information, please see
- *             the file <mit-copyright.h>.
- *     
- *     
- *     These routines implement layer 6 of the Client Library
- *     Specification of the GDB system, as well as the facilities
- *     outlined in the GDB Protocol Specification.  Part 2 of 2.
- *
- *     Some of the routines specified are actually implemented as
- *     macros defined in gdb.h.
- *     
- ************************************************************************/
-
-#include <mit-copyright.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdio.h>
-#include "gdb.h"
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <string.h>
-extern int errno;                              /* Unix error slot */
-
-/*
- * The following values are returned by g_con_progress
- */
-#define NOPROGRESS 0                           /* nothing happened on this */
-                                               /* connection--must be 0*/
-#define PROGRESS 1                             /* connection has progressed */
-#define COMPLETE 2                             /* an operation has */
-                                               /* completed on this con */
-\f
-/************************************************************************/
-/*     
-/*                          queue_operation(queue_operation)
-/*     
-/*     Add an operation to the queue for a given connection, and
-/*     then allows all connections to progress.  Returns the last
-/*     known status of the operation.
-/*     
-/************************************************************************/
-
-int
-queue_operation(con, direction, op)
-CONNECTION con;
-int     direction;
-OPERATION op;
-{
-       register HALF_CONNECTION hcon = (direction==CON_INPUT)?(&(con->in)):
-                                                              (&(con->out));
-       GDB_CHECK_CON(con, "queue_operation")
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "op queued: con=0x%x dir=%s op=0x%x Q was %s empty\n",
-                       con, (direction == CON_INPUT)?"INPUT":"OUTPUT",
-                       op, (hcon->op_q_first == (OPERATION)hcon)?"":"not");
-       /*
-        * Make sure connection is up
-        */
-       if (con->status != CON_UP) {
-               op->status = OP_CANCELLED;
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "\nop NOT queued\n");
-               return OP_CANCELLED;
-       }
-
-       /*
-        * Put the new operation at the end of the queue
-        */
-       op->prev = hcon->op_q_last;
-       op->next = (OPERATION)hcon;
-       hcon->op_q_last->next = op;
-       hcon->op_q_last = op;
-       /*
-        * Mark it as queued
-        */
-       op->status = OP_QUEUED;
-       op->halfcon = hcon;
-
-       /*
-        * Force progress on this connection
-        */
-       (void) g_con_progress(con - gdb_cons);
-       /*
-        * Con_select with notime is used here as a kind of fudge for
-        * doing a fastprogress with a select built in before it.
-        */
-       (void) con_select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0,
-                  &gdb_notime);/* XXX */
-       /*
-        * Return the last known status of the operation
-        */
-       return op->status;
-}
-/************************************************************************/
-/*     
-/*                          requeue_operation
-/*     
-/*     This routine may be called from an init or continuation routine
-/*     to cause the current operation to be requeued on a new connection.
-/*     The init routine field ofthe operation should be properly set to 
-/*     indicate the routine to receive control when the operation actually
-/*     runs on the new connection.  The caller of this routine is 
-/*     responsible for returning the status OP_REQUEUED to its caller.
-/*     
-/*     This routine returns the status of the newly queued operation.
-/*     Note, however, that even if this operation returns the status
-/*     CANCELLED, the operation itself may not continue to execute
-/*     on the old connection and it should return the status OP_REQUEUED,
-/*     NOT OP_CANCELLED (at least in this implementation.)
-/*     
-/************************************************************************/
-
-int
-requeue_operation(con, direction, op)
-CONNECTION con;
-int     direction;
-OPERATION op;
-{
-       /*
-        * Make sure the connection supplied is a legal one
-        */
-       GDB_CHECK_CON(con, "requeue_operation")
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "op requeued: new con=0x%x dir=%s op=0x%x\n",
-                       con, (direction == CON_INPUT)?"INPUT":"OUTPUT",
-                       op);
-       /*
-        * Dequeue the operation from its old half connection
-        */
-       (void) g_op_newhead(op->halfcon);
-
-       /*
-        * Now queue it on the new one
-        */
-       return queue_operation(con, direction, op);
-}
-
-/************************************************************************/
-/*     
-/*                       g_preempt_me
-/*     
-/*     Sticks a new operation in ahead of the current one and runs it
-/*     on the current connection.  May be called only from an init or
-/*     continuation routine.  The old operation must have completely
-/*     prepared the descriptor for the new operation, i.e. it should
-/*     be in the same state as it would be for a call to queue_operation.
-/*     g_preempt_me makes it possible for operations to be built by
-/*     composition of other smaller operations, since newop runs, in
-/*     a sense, as a subroutine of oldop.  opdop must (1) reset its
-/*     initialization routine to be a routine to be called when newop
-/*     completes or cancels and (2) return the status OP_PREEMPTED to
-/*     its caller.
-/*     
-/************************************************************************/
-
-int
-g_preempt_me(oldop, newop)
-OPERATION oldop;
-OPERATION newop;
-{
-       register OPERATION old=oldop, new=newop;
-       register HALF_CONNECTION hc = old->halfcon;
-
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "op preempted: halfcon=0x%x oldop=0x%x newop=0x%x\n",
-                       hc,oldop,newop);
-       /*
-        * link in the new operation
-        */
-       old->prev = new;
-       hc->op_q_first = new;
-       new->prev = (OPERATION)hc;
-       new->next = old;
-       /*
-        * Set the status of the new operation
-        */
-       new->status = OP_QUEUED;
-       new->halfcon = hc;
-       /*
-        * Change the status of the old operation (one could argue that
-        * this should be done in gdb_hcon_progress after the return code
-        * is detected.)
-        */
-       old->status = OP_QUEUED;
-       return OP_QUEUED;
-}
-
-
-\f
-/************************************************************************/
-/*     
-/*                        gdb_progress
-/*     
-/*     This routine should be called whenever it is suspected that
-/*     progress can be made on any connection.  This routine will
-/*     cause all connections to proceed as far as they can without 
-/*     blocking, and will make a best effort to avoid long blocks.
-/*     This routine MAY retain control for long periods when sustained
-/*     progress is possible, but it will not knowingly hang.  
-/*     
-/*     Returns: number of connections on which OPERATIONS have 
-/*     COMPLETED (not just progressed).
-/*     
-/************************************************************************/
-
-int
-
-gdb_progress()
-{
-       register int i;                         /* index to available */
-                                               /* connections */
-       register int return_value = 0;          /* the value we return */
-       int rc;                                 /* short term storage for */
-                                               /* a return code */
-       int progress_made;                      /* true when some con */
-                                               /* made progress during */
-                                               /* latest pass through list */
-       int complete_map[GDB_MAX_CONNECTIONS];  /* indicates whether a */
-                                               /* transmission operation */
-                                               /* is newly complete on */
-                                               /* corresponding connection */
-                                               /* 1 if yes else 0  */
-       int maxcon = gdb_mcons;                 /* gdb_mcons may change */
-                                               /* out from under us if */
-                                               /* connections break.  This */
-                                               /* is the initial value. */
-
-       /*
-        * Zero out the completion map for all connections.
-        */
-       for (i=0; i<maxcon; i++)
-               complete_map[i]=0;
-
-        /*
-        * Make repeated passes through all the fd's until a pass is made
-        * in which none makes any progress.  This logic is important, 
-        * because it catches the case where A is blocked, B makes progress,
-        * and A unblocks during the period where B is progressing.
-        */
-
-       do {
-               progress_made = FALSE;
-               for (i=0; i<gdb_mcons; i++) {
-                       if (rc = g_con_progress(i)) { /* note: NOPROGRESS==0 */
-                               progress_made = TRUE;
-                               if (rc == COMPLETE)
-                                       complete_map[i] = 1;
-                       }
-               }
-       } while (progress_made);
-
-        /*
-        * We've gone as far as we can, now find out how many connections
-        * have had operations complete.
-        */
-       for (i=0; i<maxcon; i++) 
-               return_value += complete_map[i];
-
-       return return_value;
-}
-
-\f
-/************************************************************************/
-/*     
-/*                     gdb_fastprogress
-/*     
-/*     Similar to gdb_progress, but this routine attempts progress
-/*     only on those connections which have already shown themselves
-/*     to be ready for activity by a prior select.  This is safe to do
-/*     when (1) the only activity we are interested in is that related
-/*     to ongoing I/O and (2) a select was recently done to set the
-/*     last_c.fds flags.  Condition (1) is violated in the case where
-/*     an operation may be newly at the head of a queue and its init 
-/*     routine may not have had a chance to run. Condition (2) is violated 
-/*     when we are entering after having done significant computation.
-/*     
-/*     This routine was introduced by Bill Sommerfeld after profiling 
-/*     revealed that unnecessary attempts to progress on quiescent
-/*     sockets were causing excessive overhead in the system.  I am
-/*     still suspicious that this routine may be getting called in
-/*     places where a full gdb_progress is needed.  e.g. I'm not
-/*     sure its use in op_select is entirely safe.
-/*     
-/************************************************************************/
-
-gdb_fastprogress()   
-{
-       int i;
-       int retval=0, rc;
-       
-       for (i=0; i<gdb_mcons; i++) {
-               register CONNECTION con = &gdb_cons[i];
-               register int infd = gdb_cons[i].in.fd;
-               register int outfd = gdb_cons[i].out.fd;
-
-               if(connection_status(con) != CON_UP)
-                       continue;
-
-               gdb_conok = TRUE;
-               if ((!(con->in.flags&HCON_UNUSED))&&
-                   ((con->in.stream_buffer_remaining > 0)
-                   || FD_ISSET(infd, &last_crfds))) {
-                       rc = gdb_hcon_progress(CON_INPUT, &con->in);
-                       if (!gdb_conok) {
-                               g_stop_with_errno(con);
-                               rc = COMPLETE;
-                       }
-                       if (rc == COMPLETE)
-                               retval++;
-               }
-               if ((!(con->out.flags&HCON_UNUSED))&&
-                   (FD_ISSET(outfd, &last_cwfds))) {
-                       rc = gdb_hcon_progress(CON_OUTPUT, &con->out);
-                       if (!gdb_conok) {
-                               g_stop_with_errno(con);
-                               rc = COMPLETE;
-                       }
-                       if (rc == COMPLETE)
-                               retval++;
-               }
-       }
-       /*
-        * We've gone as far as we can, now find out how many connections
-        * have had operations complete.
-        */
-
-       return retval;
-}
-\f
-/************************************************************************/
-/*     
-/*                        g_con_progress
-/*     
-/*     Make as much progress as possible on the specified connection.
-/*     Returns NOPROGRESS if no bytes moved on either half connection,
-/*     PROGRESS, if some moved and no operations completed, or COMPLETE if
-/*     any of the operations completed.  Note that each connection
-/*     consists of two half connections, and we must make each of them
-/*     progress as far as possible.
-/*     
-/*     The nest here starts getting so deep that it's hard to pass state
-/*     around efficiently.  We  use a single global variable, gdb_conok,
-/*     to indicate whether the connection we're working on now has died.
-/*     The move data routines set this to FALSE whenever there is a 
-/*     fatal error on a connection.  We check it, and do a proper 
-/*     sever on the connection if it seems to be in trouble.
-/*     
-/************************************************************************/
-
-
-int
-g_con_progress(con_id)
-int    con_id;                                 /* index of this connection */
-                                               /* in the connection desc. */
-                                               /* arrays*/
-{
-       register CONNECTION con= (&gdb_cons[con_id]);
-                                               /* pointer to the connection */
-                                               /* data structure */
-       register int progress = NOPROGRESS;
-       register int live = TRUE;               /* true when we've seen */
-                                               /* enough to make sure we */
-                                               /* want to go around again*/
-       int rc;
-       /*
-        * Check status of connection-if it's not running, then just return.
-        */
-       if (con->status != CON_UP)
-               return NOPROGRESS;
-       /*
-        * Repeatedly make progress on each half connection until both
-        * are idle.  Important to keep trying as one may become active
-        * while the other is progressing.  
-        */
-
-       gdb_conok = TRUE;                       /* this gets set to FALSE */
-                                               /* for fatal I/O errors */
-                                               /* there may be a timing */
-                                               /* window here in use of */
-                                               /* HCON_BUSY.  Also: it is */
-                                               /* essential that errno */
-                                               /* remain valid after conok */
-                                               /* goes bad */
-       while (live) {
-               live = FALSE;                   /* until proven otherwise */
-               /*
-                * make progress on the input connection note that following
-                * logic depends on NOPROGRESS being 0
-                */
-               if (rc = gdb_hcon_progress(CON_INPUT, &con->in)) {
-                       live = TRUE;
-                       progress = max(rc, progress);
-               }
-               /*
-                * See if connection has died
-                */
-               if (!gdb_conok) {
-                       g_stop_with_errno(con);
-                       return COMPLETE;        /* dying connection always */
-                                               /* implies that the */
-                                               /* operation at the head */
-                                               /* of the queue completed */
-               }
-               /*
-                * make progress on the output connection
-                */
-               if (rc = gdb_hcon_progress(CON_OUTPUT, &con->out)) {
-                       live = TRUE;
-                       progress = max(rc, progress);
-               }
-               /*
-                * See if connection has died
-                */
-               if (!gdb_conok) {
-                       g_stop_with_errno(con);
-                       return COMPLETE;
-               }
-       }
-
-       return progress;
-}
-
-
-/************************************************************************/
-/*     
-/*                     gdb_hcon_progress
-/*     
-/*     Allows a specified half-connection to progress as much as possible,
-/*     and returns true iff at least one operation is newly completed.
-/*
-/************************************************************************/
-
-int
-gdb_hcon_progress(direction, hc)
-int    direction;                              /* CON_INPUT or CON_OUTPUT */
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-        HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-       register OPERATION op;                  /* current operation on this */
-                                               /* half connection */
-       int progress = NOPROGRESS;              /* can indicate any progress */
-                                               /* on the half con or */
-                                               /* whether any operations */
-                                               /* completed */
-       int done;                               /* true when no more progress*/
-                                               /* can be made */
-       int fcn_result;                         /* result of latest init or */
-                                               /* continue function */
-
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "hcon_progress: halfcon=0x%x dir=%s ",
-                       half_con, (direction==CON_INPUT)?"INPUT":"OUTPUT");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      See if we are being re-entered and are already working
-       /*      on this half_con.  If so, return right now.  
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (half_con->flags & HCON_BUSY) {
-               /*
-                * Write message to debugging log
-                */
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "BUSY, returning\n");
-               return NOPROGRESS;
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      See if there is an operation on this half connection.
-       /*      If not, return.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-       op = half_con->op_q_first;              /* pick up first operation */
-                                               /* in queue */
-       if (op == (OPERATION)half_con) {        /* see if end of circular */
-                                               /* list */
-               /*
-                * Write message to debugging log
-                */
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "Q EMPTY, returning\n");
-               return NOPROGRESS;              /* nothing to do on */
-                                               /* this half session */
-       }
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Loop until all operations are complete, or until no further
-       /*      progress can be made on this one.
-       /*      
-       /*      Loop invariants:
-       /*      
-       /*      1) Op contains the operation at the head of the q, or
-       /*         else is == half_con, indicating no more operationos
-       /*         to be processed.
-       /*      
-       /*      2) The operation at the head of the queue is either running
-       /*         or continuing.  As soon as one completes, it is dequeued.
-       /*      
-       /*      Progress is declared whenever an operation newly
-       /*      returns OP_COMPLETE, i.e. whenever there has been 
-       /*      an operation which went from running to complete.
-       /*      
-       /*      Done is declared whenever an operation returns anything
-       /*      other than complete, indicating that it cannot progress
-       /*      further at this time.  Loop ends.  
-       /*      
-       /*      While we're here, mark us busy so we won't try the
-       /*      same half_con on reentry.
-       /*      
-       /*----------------------------------------------------------*/
-
-       done = FALSE;                           /* this one may be able to */
-                                               /* progress */
-
-       half_con->flags |= HCON_BUSY;           /* don't try this hcon */
-                                               /* while we already doing */
-                                               /* it.  Could happen if */
-                                               /* we queue new ops */
-       half_con->flags &= ~HCON_PROGRESS;      /* gdb_move_data will */
-                                               /* indicate progress here*/
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "LOOPING\n");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Loop through the operations queued on this half con
-       /*      trying to make progress on them, in order.
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (!done &&
-              op != (OPERATION)half_con) {
-
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "\top=0x%x status%d...",
-                               op, OP_STATUS(op));
-
-               switch (op->status) {
-            /*
-             * Operation is at head of queue for first time and has
-             * never been started.  Try to start it up.
-             */
-           case OP_QUEUED:
-                       /*
-                        * Call the initialization routine for this operation
-                        */
-                       fcn_result = (*op->fcn.init)(op,half_con,op->arg);
-                       if (gdb_Debug & GDB_LOG)
-                               fprintf(gdb_log, "init result=%d\n",
-                                       fcn_result);
-
-                       switch (fcn_result) {
-                             case OP_COMPLETE:
-                             case OP_CANCELLED:
-                               op->status = fcn_result; 
-                               op = g_op_newhead(half_con);
-                               progress = COMPLETE;
-                               break;
-                             case OP_PREEMPTED:
-                               op->status = OP_QUEUED;
-                               /* fall thru */
-                             case OP_REQUEUED:
-                               /* important: don't set status on re-queued */
-                               /* op as it may already have completed in */
-                               /* its second life ! */
-                               op = half_con->op_q_first;
-                               progress = max(progress, PROGRESS);
-                               break;
-                             default:
-                               op->status = fcn_result; 
-                               done = TRUE;    /* could not get done */
-                       }
-                       break;
-            /*
-             * Operation is at head of queue and has already 
-             * started trying to run.  The only reason we could be in this
-             * state is that the last time we tried to do the requested input
-             * or output, all the data could not be moved synchronously.  
-             * We therefore try to move some more, and if it all goes now,
-             * we call the continuation routine.
-             */
-           case OP_RUNNING:
-                       /*
-                        * Try to move some more data.  If it won't all 
-                        * go now, we're done with this half connection.
-                       *
-                       * If this is a special listening connection which
-                       * has an operation queued trying to do a listen,
-                       * then do the listen.  Otherwise do an ordinary
-                       * data move.
-                        */
-                       if (half_con->flags & HCON_PENDING_LISTEN) {
-                               if (gdb_listen(half_con)==FALSE) {
-                                       if (gdb_Debug & GDB_LOG)
-                                               fprintf(gdb_log, "NO LISTEN\n");
-                                       done = TRUE;
-                                       break;
-                               }
-                       } else
-                               if (gdb_move_data(direction, half_con)==FALSE) {
-                                       done = TRUE;
-                                       if (gdb_Debug & GDB_LOG)
-                                               fprintf(gdb_log, "NO DATA\n");
-                                       break;
-                               }
-                       /* 
-                        * The pending data transmission has now completed.
-                        * Call the continuation routine for this operation
-                        */
-                       fcn_result = (*op->fcn.cont)(op,half_con,op->arg);
-                       if (gdb_Debug & GDB_LOG)
-                               fprintf(gdb_log, "cont result=%d\n",
-                                       fcn_result);
-
-                       switch (fcn_result) {
-                             case OP_COMPLETE:
-                             case OP_CANCELLED:
-                               op->status = fcn_result; 
-                               op = g_op_newhead(half_con);
-                               progress = COMPLETE;
-                               break;
-                             case OP_PREEMPTED:
-                               op->status = OP_QUEUED;
-                               /* fall thru */
-                             case OP_REQUEUED:
-                               /* important: don't set status on re-queued */
-                               /* op as it may already have completed in */
-                               /* its second life ! */
-                               op = half_con->op_q_first;
-                               progress = max(progress, PROGRESS);
-                               break;
-                             default:
-                               op->status = fcn_result; 
-                               done = TRUE;    /* could not get done */
-                       }
-                       break;
-            /*
-             * Following cases are all unexpected, at least for the
-             * moment.  (See explanation of loop invariants for this while
-             * loop.  Give up if they turn up.
-             */
-           case OP_COMPLETE:
-                       GDB_GIVEUP("gdb_hcon_progress: found OP_COMPLETE on q")
-           case OP_CANCELLED:
-                       GDB_GIVEUP("gdb_hcon_progress: found OP_CANCELLED on q")
-           case OP_CANCELLING:
-                       GDB_GIVEUP("gdb_hcon_progress: OP_CANCELLING")
-           default:
-                       GDB_GIVEUP("gdb_hcon_progress: Operation is queued, but is not runnable")
-                 }
-       }
-
-       if (progress == NOPROGRESS && (half_con->flags & HCON_PROGRESS))
-               progress = PROGRESS;
-
-       half_con->flags &= ~HCON_BUSY;
-
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "hcon_progress: returns %d\n",progress);
-
-       return progress;                        /* NOPROGRESS, PROGRESS */
-                                               /* or COMPLETE */
-}
-\f
-/************************************************************************/
-/*     
-/*                             g_op_newhead
-/*     
-/*     Dequeues the operation at the head of the queue for the
-/*     given half connection and returns the pointer to the 
-/*     new head of the queue.  If the queue is null, then a pointer
-/*     to the half_con itself is returned.  (The lists are
-/*     linked circularly.)
-/*     
-/************************************************************************/
-
-OPERATION
-g_op_newhead(hcp)
-HALF_CONNECTION hcp;
-{
-       register OPERATION newhead, oldhead;
-
-       /*
-        * Get old and new heads of chain
-        */
-       oldhead = hcp->op_q_first;
-       newhead = oldhead->next;
-       /*
-        * Make sure nobody chained a bad one on us
-        */
-       if (newhead == NULL) {
-               if (gdb_Debug & GDB_LOG) {
-                       fprintf(gdb_log,"\t\tg_op_newhead: found null link, oldhead = 0x%x newhead=0x%x halfcon=0x%x\n\t\t\t hc->first=0x%x hc->last=0x%x\n",
-                               oldhead, newhead, hcp, hcp->op_q_first,
-                               hcp->op_q_last);
-               }
-               GDB_GIVEUP("g_op_newhead: found NULL chain link")
-       }
-       /*
-        * Remove oldhead from chain, fixing up chain pointers
-        */
-       newhead->prev = oldhead->prev;
-       hcp->op_q_first = newhead;
-
-       /*
-        * Clean up pointers in the newly dequeued operation.  This is
-        * just for cleanliness and ease of debugging.
-        */
-       oldhead->next = oldhead->prev = NULL;
-       oldhead->halfcon = NULL;
-
-       return newhead;
-}
-\f
-/************************************************************************/
-/*     
-/*                             gdb_move_data
-/*     
-/*     This routine attempts to make further progress on the pending
-/*     level transmission operation pending on this half connection.
-/*     (Presumes that such an operation is pending.)  Returns TRUE
-/*     if all the requested data has been moved, else FALSE.
-/*     
-/*     We assume here that all fd's are set to non-blocking I/O, so
-/*     we can safely try reading and writing until they return 0 bytes.
-/*     
-/************************************************************************/
-
-#define FIX_BUFFER_POINTERS(hc, count) if (count>0) {hc->next_byte += count; \
-                                                    hc->remaining -= count;}
-int
-gdb_move_data(direction, hc)
-int    direction;                              /* CON_INPUT or CON_OUTPUT */
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-       register HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-       register fd_set *fdbits;                /* the mask we should adjust */
-                                               /* for this direction */
-
-       /*
-        * For safety, in case we're called when nothing is pending.
-        */
-       if (half_con->remaining == 0)
-               return TRUE;
-       /*
-        * Move the data into the user's buffer.  In the case of input
-        * data may come first from the stream buffer, then from the socket
-        * itself.
-        */
-       if (direction == CON_INPUT) {
-               gdb_transfer_from_buffer(half_con);
-              /*
-               * If remaining is greater than 0, then we emptied
-               * the stream buffer and still weren't done.  Try
-               * to read it from the pipe and re-fill the stream
-               * buffer.
-               */
-              if (half_con->remaining) {
-                      gdb_read_data_and_buffer(half_con);
-              }
-       } else {
-              gdb_write_data(half_con);
-       }
-       /*
-        * The file descriptor masks used for doing selects must be activated
-        * when and only when there is a pending operation trying to use
-        * the connection.  Update the masks for this half connection.
-        */
-       fdbits = (direction == CON_INPUT)? &gdb_crfds : &gdb_cwfds;
-       if (half_con->remaining >0 && gdb_conok)
-               FD_SET(half_con->fd, fdbits);
-       else                                    
-               FD_CLR(half_con->fd, fdbits);
-
-       return (half_con->remaining == 0);
-}
-\f
-/************************************************************************/
-/*     
-/*                     gdb_transfer_from_buffer
-/*     
-/*     Given an inbound half connection, satisfy as much as possible
-/*     of desired data from the stream buffer.
-/*     
-/************************************************************************/
-
-int
-gdb_transfer_from_buffer(hc)
-register HALF_CONNECTION hc;
-{
-       register int count;                     /* amount to move */
-
-       /*
-        * Figure out how much, if any, we'll be able to do here
-        */
-       count = min(hc->remaining, hc->stream_buffer_remaining);
-       if (count <= 0)
-               return;                         /* could not satisfy */
-                                               /* any from buffered data*/
-
-       /*
-        * Copy the data, update both stream and data buffer pointers
-        */
-
-       memcpy(hc->next_byte, hc->stream_buffer_next, count);
-
-       hc->stream_buffer_next += count;
-       hc->stream_buffer_remaining -= count;
-       FIX_BUFFER_POINTERS(hc, count)
-       
-}
-
-\f/************************************************************************/
-/*     
-/*                             gdb_write_data
-/*     
-/*     This routine implements gdb_move_data for an outbound half
-/*     connection.
-/*     
-/************************************************************************/
-
-int
-gdb_write_data(hc)
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-       register HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-       register int count;                     /* number of bytes read */
-                                               /* or written in latest */
-                                               /* attempt */
-       fd_set *fdbits;                         /* the mask we should adjust */
-                                               /* for this direction */
-       fd_set tst_bits;                        /* these are used for */
-                                               /* the select we do prior */
-                                               /* to reading which tells */
-                                               /* us whether 0 byte read */
-                                               /* means empty or closed  */
-        int selected;                          /* TRUE iff select says */
-                                               /* we should be able to */
-                                               /* progress */
-
-       /*
-        * Loop writing to the socket until it claims that no more 
-        * progress can be made.  Note that some versions of Unix report
-        * socket failure by select = 1, write count = 0.  To avoid
-        * extra selects, we try the write first, and only do the select/write
-        * sequence if write seems not to be progressing.
-        */
-       FD_ZERO(&tst_bits);
-       while(half_con->remaining>0) {
-               count = write(half_con->fd, half_con->next_byte,
-                             (int)min(half_con->remaining, 
-                                      GDB_MAX_SOCK_WRITE));
-               if (count == 0) {
-                       FD_SET(half_con->fd,&tst_bits);
-                       selected = select(gdb_mfd,
-                                         (fd_set *)NULL, &tst_bits,
-                                         (fd_set *)NULL, 
-                                         &gdb_notime);
-                       if (selected == (-1)) {
-                               gdb_conok = FALSE;
-                               break;
-                       }
-                       if (selected == 0) {
-                               count =0;
-                               break;
-                       }
-                       count = write(half_con->fd, half_con->next_byte,
-                                     (int)min(half_con->remaining, 
-                                              GDB_MAX_SOCK_WRITE));
-                       if (count==0) {
-                               if (selected == 1)
-                                 gdb_conok = FALSE;
-                               break;          /* no more data available now*/
-                       }
-               }
-               /*
-                * Count is != 0
-                */
-               if (count<0) {
-                       count = 0;
-                       if (errno != EWOULDBLOCK) {
-                               gdb_conok  = FALSE; /* tell callers */
-                               /* that con has */
-                               /* died */
-                       }
-                       break;
-               }
-
-               half_con->flags |= HCON_PROGRESS;
-               FIX_BUFFER_POINTERS(half_con, count)
-       }
-       /*
-        * The file descriptor masks used for doing selects must be activated
-        * when and only when there is a pending operation trying to use
-        * the connection.  Update the masks for this half connection.
-        */
-       fdbits =  &gdb_cwfds;
-       if (half_con->remaining >0 && gdb_conok)
-               FD_SET(half_con->fd, fdbits);
-       else                                    
-               FD_CLR(half_con->fd, fdbits);
-
-       return;
-}
-\f
-/************************************************************************/
-/*     
-/*
-/*                        gdb_read_data_and_buffer
-/*     
-/*     This routine is called only when the half_connection stream 
-/*     buffer is known to be empty and the "next-byte" buffer    
-/*     has more to be filled in.  We try in one read to finish
-/*     off the user's request and at the same time fill the stream
-/*     buffer for later.
-/*     
-/*             We assume here that all fd's are set to non-blocking I/O, so
-/*     we can safely try reading and writing until they return 0 bytes.
-/*     
-/************************************************************************/
-
-int
-gdb_read_data_and_buffer(hc)
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-       register HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-       register int count;                     /* number of bytes read */
-                                               /* or written in latest */
-                                               /* attempt */
-       fd_set *fdbits;                         /* the mask we should adjust */
-                                               /* for this direction */
-               struct iovec iov[2];                    /* we use this to hold */
-                                               /* pointers to (1) the */
-                                               /* actual user data buffer */
-                                               /* and (2) the pipe length */
-                                               /* pre-read buffer */
-       int fix_amount;                         /* amount to adjust */
-                                               /* half_con->remaining*/
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Mark the stream buffer as empty, in case we don't
-       /*      get around to filling it.
-       /*      
-       /*----------------------------------------------------------*/
-
-       half_con -> stream_buffer_next = half_con -> stream_buffer;
-       half_con -> stream_buffer_remaining = 0;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Loop trying to read data from the socket.  We scatter
-       /*      first into the user's buffer directly, then into
-       /*      the stream buffer (which helps us save system
-       /*      calls next time around.)  We stop either when:
-        /*      socket reports error/no progress or user's buffer is
-       /*      full.
-       /*      
-       /*----------------------------------------------------------*/
-
-       /*
-        * Loop until either (1) the connection reported that it could
-        * not progress any further or (2) the full count has been 
-        * satisfied.  Some versions of Unix observe the rule that 
-        * a closed connection, especially when reading, is indicated
-        * by returning a count of 0 on read when select claims that progress
-        * can be made.  We used to handle this case.  Bill Sommerfeld
-        * has introduced a performance change which leaves that checking
-        * out in the latest version.  To add it back, then ONLY in
-        * the case where read returned 0, do a select followed by another
-        * read (the order is important).  If we ever run on a system that
-        * works in this way, we may hang at close time.
-        */
-
-       while(half_con->remaining>0) {
-               /*
-                * First we try a read, and if it works, we believe it
-                */
-               iov[0].iov_base = half_con -> next_byte;
-               iov[0].iov_len =  half_con -> remaining;
-               iov[1].iov_base = half_con -> stream_buffer;
-               iov[1].iov_len =  half_con -> stream_buffer_length;
-               count = readv(half_con->fd, iov, 2);
-
-               if (count<0) {
-                       count = 0;
-                       if (errno != EWOULDBLOCK) 
-                               gdb_conok  = FALSE; /* tell callers that */
-                                                   /* con has died */
-                       break;
-
-               }
-               if (count == 0) {/* We hit EOF */
-                       gdb_conok = FALSE;
-                       break;
-               }
-                       
-               /*
-                * Count is >0, we moved some data.  Note, setting of
-                * stream_buffer_remaining can only be non-zero on last
-                * time through the loop, because that will be when 
-                * half_con->remaining goes to zero.
-                */
-               half_con->flags |= HCON_PROGRESS;
-               half_con->stream_buffer_remaining=max(0, count-iov[0].iov_len);
-               fix_amount = min(count,half_con->remaining);
-               FIX_BUFFER_POINTERS(half_con, fix_amount);
-       }
-
-       /*
-        * The file descriptor masks used for doing selects must be activated
-        * when and only when there is a pending operation trying to use
-        * the connection.  Update the masks for this half connection.
-        */
-       fdbits =  &gdb_crfds;
-       if (half_con->remaining >0)
-               FD_SET(half_con->fd, fdbits);
-       else                                    
-               FD_CLR(half_con->fd, fdbits);
-
-       return ;
-}
-\f
-/************************************************************************/
-/*     
-/*                     gdb_receive_data (gdb_receive_data)
-/*     
-/*     This routine is called by an init or continuation routine to
-/*     request that a specified amount of data be read, without 
-/*     blocking, on the supplied connection.  This routine returns
-/*     OP_COMPLETE if the entire read completed synchronously,
-/*     or OP_RUNNING if the read remains ongoing or is cancelling
-/*     due to error on the socket.
-/*     
-/************************************************************************/
-
-int
-gdb_receive_data(half_con, ptr, len)
-HALF_CONNECTION half_con;                      /* read on this connection*/
-char    *ptr;                                  /* put first byte here */
-int    len;                                    /* number of bytes to read */
-{
-       /*
-        * Fill in the initial state of the attempted receive 
-        */
-       half_con->remaining = len;
-       half_con->next_byte = ptr;
-
-       /*
-        * Now see if we can make some progress on this read, possibly
-        * even completing it synchronously.  Return appropriate
-        * result to our caller.  Note: errors are reflected as OP_RUNNING
-        * with global variable gdb_cnok set to FALSE.
-        */
-       if(gdb_move_data(CON_INPUT, half_con))
-               return OP_COMPLETE;
-       else
-               return OP_RUNNING;
-}
-
-/************************************************************************/
-/*     
-/*                     gdb_send_data (gdb_send_data)
-/*     
-/*     This routine is called by an init or continuation routine to
-/*     request that a specified amount of data be written, without 
-/*     blocking, on the supplied connection.  This routine returns
-/*     OP_COMPLETE if the entire write completed synchronously,
-/*     or OP_RUNNING if the output remains ongoing or there was an error.
-/*     
-/************************************************************************/
-
-int
-gdb_send_data(half_con, ptr, len)
-HALF_CONNECTION half_con;                      /* write on this connection*/
-char    *ptr;                                  /* put first byte here */
-int    len;                                    /* number of bytes to read */
-{
-
-       /*
-        * Fill in the initial state of the attempted receive 
-        */
-       half_con->remaining = len;
-       half_con->next_byte = ptr;
-
-       /*
-        * Now see if we can make some progress on this read, possibly
-        * even completing it synchronously.  Return appropriate
-        * result to our caller.
-        */
-       if(gdb_move_data(CON_OUTPUT, half_con))
-               return OP_COMPLETE;
-       else
-               return OP_RUNNING;
-}
-
-/************************************************************************/
-/*     
-/*                     gdb_start_a_listen
-/*     
-/*     This routine is called by an init or continuation routine to
-/*     request that a connection be done.  This routine returns
-/*     OP_COMPLETE if the accept completed synchronously,
-/*     or OP_RUNNING if the output remains ongoing or there was an error.
-/*     
-/************************************************************************/
-
-int
-gdb_start_a_listen(half_con, otherside, lenp, fdp)
-HALF_CONNECTION half_con;                      /* write on this connection*/
-char    *otherside;                            /* put first byte here */
-int    *lenp;                                  /* number of bytes to read */
-int     *fdp;
-{
-
-       /*
-        * Fill in the initial state of the attempted accept
-        */
-       half_con->accepted_len = lenp;
-       half_con->next_byte = otherside;
-       half_con->accepted_fdp = fdp;
-
-       /*
-        * Now see if we can make some progress on this read, possibly
-        * even completing it synchronously.  Return appropriate
-        * result to our caller.
-        */
-       if(gdb_listen(half_con))
-               return OP_COMPLETE;
-       else
-               return OP_RUNNING;
-}
-\f
-/************************************************************************/
-/*     
-/*                     gdb_listen (gdb_listen)
-/*     
-/*     This routine is called from gdb_start_a_listen or hcon_progress to attempt
-/*     to continue making progress in accepting a connection on a
-/*     listening connection.
-/*     
-/************************************************************************/
-
-int
-gdb_listen(hc)
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-       register HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-
-       GDB_INIT_CHECK
-
-       half_con->flags &= ~HCON_PENDING_LISTEN;/* in case we succeed */
-
-       /* 
-        * The first implementatin of this used to do a select to make sure
-        * that the accept would not block.  Bill Sommerfeld has changed this
-        * to non-blocking I/O, so the following code is commented out.
-        */
-#ifdef notdef
-       FD_ZERO(&tst_bits);
-       FD_SET(half_con->fd,&tst_bits);
-       selected = select(gdb_mfd,&tst_bits, (fd_set *)NULL, (fd_set *)NULL,
-                         &gdb_notime);
-        /*
-         * If selected==(-1), then we know there's something
-         * wrong with the socket
-         */
-        if (selected == (-1)) {
-               gdb_conok = FALSE;
-               return FALSE;
-        }
-        /*
-         * if selected==0, then we know accept won't do anything, so
-         * don't try.
-         */
-        if (selected == 0) {
-               half_con->flags |= HCON_PENDING_LISTEN;
-               FD_SET(half_con->fd, &gdb_crfds); /* we'll be looking for */
-                                                 /* this whenever we select*/
-               return FALSE;
-        }
-        /*
-         * Selected is >0.  The accept SHOULD not hang.
-         */
-#endif
-
-       /*
-        * Here is Bill's non-blocking implementation
-        */
-        *(half_con->accepted_fdp) = accept(half_con->fd,
-                           (struct sockaddr *)half_con->next_byte,
-                          half_con->accepted_len);
-       /*
-        * See whether the accept succeeded
-        */
-        if (*(half_con->accepted_fdp) < 0) {
-                if (errno != EWOULDBLOCK) {
-                        gdb_conok = FALSE;     /* error will be returned */
-                                               /* in shut-down listening con*/
-                }
-                half_con->flags |= HCON_PENDING_LISTEN;
-                FD_SET(half_con->fd, &gdb_crfds);
-                return FALSE;
-        }
-
-        FD_CLR(half_con->fd, &gdb_crfds);      /* don't select on this */
-        return TRUE;
-}
diff --git a/gdb/gdb_ugd.mss b/gdb/gdb_ugd.mss
deleted file mode 100644 (file)
index da4ce6b..0000000
+++ /dev/null
@@ -1,3045 +0,0 @@
-@device(PostScript)  
-@make(Manual)  
-@style(FontFamily "Helvetica", Size 11)  
-@style(hyphenation on)  
-@style(indent 0)  
-@style(leftmargin +4cm)  
-@style(footnotes "")  
-@modify(example,Size 10, below 1cm, above 1cm, leftmargin +3, rightmargin +0)  
-@define(F, FaceCode F, Size 11, TabExport)  
-@modify(HD1, Below .75cm, Above 1cm, indent -1cm)  
-@modify(HD1A, Below .75cm, Above 1cm)  
-@modify(HD2, Below .6cm, Above 1cm, indent -1cm)  
-@modify(HD3, Below .6cm, Above 1cm)  
-@modify(itemize, Below .5cm, Above .6cm)  
-@modify(example, Below .5cm, Above .6cm)  
-@modify(float, Below .5cm, Above .6cm)  
-@begin(titlepage)  
-@begin(titlebox)  
-@majorheading(A Guide to Using GDB)  
-@heading(Noah Mendelsohn)  
-  
-@end(titlebox)  
-Document Version: 0.4 (DRAFT)  
-For use with GDB Release: 0.4
-This draft printed on: @value(Date)  
-@copyrightnotice(MIT Project Athena)  
-@end(titlepage)  
-@Counter(ProgramNumber, Numbered <@1>, Referenced <@1>)  
-@set(ProgramNumber=1)  
-@Chapter(Introduction)  
-  
-Many of the most important computer applications involve sharing  
-information among the users of a computer system.  
-These applications may be simple to create if all users do their  
-work on a single timesharing system, but the job is much harder in  
-a @i[distributed] system, where each user has his or her own workstation.  
-The purpose of GDB Global Database system is to simplify the creation   
-of distributed applications in which information sharing is important.  
-  
-This guide is intended for prospective users of GDB who want to know  
-what GDB can do for them and need a general guide to doing the   
-job right.    
-A complete description of GDB services and interfaces is provided in  
-another document titled: "GDB C Library Reference Manual".  
-Both guides are intended for readers with a good working knowledge  
-of C and Unix@+[TM]@foot(@+[TM]Unix is a trademark of  
-AT&T Bell Laboratories) programming.    
-A short note titled: "GDB Global Databases for Project Athena" provides  
-a general introduction to GDB   
-for non-programmers.   
-The sections below are intended to answer some of the most basic  
-questions about GDB and using this guide.  
-@section(What can GDB do?)  
-Here is a brief list of the programming tasks that GDB facilitates:  
-@begin(itemize)  
-@begin(multiple)  
-@b[Sharing a relational database through a network]  
-  
-GDB includes everything needed for a program running on one machine  
-in a Berkeley Unix network to create, alter, and query the relations  
-in an RTI Ingres database stored on some other machine in the network.  
-Programs running on several machines may access the same data simultaneously,  
-and a single program may use more than one database at a time.    
-The programs may easily be ported across machine architectures, RT/PC  
-to Vax for example, and programs running on different machine types  
-may share a common database.  
-@end(multiple)  
-  
-@begin(multiple)  
-@b[Writing network servers and their clients]  
-  
-GDB handles most of the bookkeeping and error recovery needed to build  
-servers and clients in a Berkeley Unix environment.  A completely   
-functional demonstration server capable of supporting multiple clients  
-with reasonable error detection has been written in about 20 lines  
-of C code using the services of GDB (page @pageref[tfsr]).  
-Clients running on various types of machine may easily access common  
-servers, with GDB handling the necessary data conversions automatically.  
-@end(multiple)  
-  
-@begin(multiple)  
-@b[Single Process Unix Servers]  
-  
-It is customary when writing servers under Unix to fork a separate  
-server process to handle each client.    
-In addition to this traditional model, GDB provides a rich set  
-of asynchronous communication services which facilitate the  
-creation of servers in which a single process supports all clients.  
-This model is particularly appropriate to the implementation   
-of such high performance applications as network games.  
-@end(multiple)  
-  
-@begin(multiple)  
-@b[Peer-to-peer communication]  
-  
-Some communicating applications, like the Berkeley Unix @f[talk] program,  
-@index(talk)  
-don't fit naturally into a server/client model.  GDB also provides   
-services for managing connections between @i[peer] programs, of which  
-neither is viewed as master or slave.  
-@end(multiple)  
-@end(itemize)  
-  
-@section(Which Chapters in this Guide Should I Read?)  
-@Index(Chapters, guide to)  
-  
-Although GDB has a rich set of features for elaborate  
-asynchronous programming, many useful applications can be built  
-with just the simplest GDB tools.  This guide is intended to be read  
-selectively.  The following are some hints on what to read, depending  
-on the job you are trying to do:  
-  
-@begin(itemize)  
-Everyone who uses GDB should read the rest of this "Introduction",  
-and the chapter titled "Managing Structured Data".  
-  
-If you wish to use GDB to access a remote Ingres database, then the  
-only other chapter you have to read is "Creating and Using Relational  
-Databases with GDB".  If you're interested in doing database accesses  
-@i[asynchronously], allowing you to overlap your access to several  
-databases or to keep control of the local terminal while a query is  
-executing, then you should also read the chapter titled "Synchronous  
-and Asynchronous Operations".  
-  
-If you are planning to write your own servers, clients, or other   
-communicating programs, then you can skip the chapter on relational  
-databases, but you should read instead the chapter "Creating  
-Servers, Clients, and Other Communicating Programs".  This gives  
-all the information you need to use the basic communication capabilities  
-of GDB, which will be adequate for the majority of applications.  
-Asynchronous communication techniques are described in the chapter  
-"Synchronous and Asynchronous Operations".  
-@end(itemize)  
-  
-Three other chapters provide additional material which may be useful on  
-occasion.   "Hints and Tricks" has some suggestions which may be helpful  
-if you can't figure out how to make GDB do exactly what you want.  
-"Bugs" lists some of the known shortcomings in current implementations.  
-If you're having trouble, this is one of the places to look.    
-"How GDB Works" gives a general overview of GDB's internal  
-structure, information which should not be needed in writing an  
-application, but which may be of interest to serious users.  The  
-sample programs in the appendices are referenced in the appropriate  
-chapters.  
-  
-@section(What is needed to run GDB?)  
-The services of GDB are accessed through a C library.  
-You will have to insure that the appropriate C include files are available  
-on your system, and that the gdb library is available when you link your  
-application.  Your system administrator can take care of these things  
-for you.    
-@i[Note to early users:  You may receive the pieces of GDB in slightly  
-different form.  Documentation supplied with the distribution should  
-explain what to do.]  
-  
-@begin(group)  
-@blankspace(1 line)  
-Every C main program  
-that uses GDB should include the following:  
-  
-@begin(example)  
-#include <stdio.h>  
-#include "gdb.h"  
-  
-int  
-main()  
-{  
-     gdb_init();  
-     /*  
-      * Once gdb_init has been called, the services of gdb are  
-      * available.  gdb_init may be called only once.  
-      */  
-}  
-@end(example)  
-@end(group)  
-  
-Other source files should @f[#include "gdb.h"], but should @i[not]   
-@index(gdb.h)  
-invoke @f[gdb_init].  
-@index(gdb_init)  
-  
-If you are using GDB to access an Ingres database, then there are  
-several other things you must do:  
-  
-@begin(itemize)  
-@begin(multiple)  
-Make sure RTI Ingres is installed at the server site where the data   
-@index(RTI Ingres)  
-@index(Ingres)  
-is to be stored.  
-@end(multiple)  
-  
-@begin(multiple)  
-Make sure that there is an entry in the file named @f[/etc/services]  
-@index(/etc/services)  
-at both server and client sites for the service named gdb_db@index(gdb_db).  
-The entries at the server and client should be identical.    
-Talk to your system administrator if this is not the case.  
-@i[Note: as of this writing, GDB does not check @f[/etc/services] when  
-accessing Ingres, but soon it will!]  
-@end(multiple)  
-  
-@begin(multiple)  
-Make sure that the @f[dbserv] program supplied with GDB  
-@index(dbserv)  
-is started at the server site.  
-@end(multiple)  
-  
-@end(itemize)  
-  
-Once these steps have been followed, the full services of the Ingres  
-database are available to GDB clients throughout the network.  In  
-future releases of GDB, the Kerberos Authentication  
-Service@index(Kerberos) will be used to verify the identity of clients  
-and to provide some options for access control.  In the meantime, keep  
-in mind that any GDB user on the internet@index(Internet, access  
-rights from)  
-effectively inherits the access rights of the userid under which the  
-database server is running.  
-  
-@Chapter(Managing Structured Data)  
-@label(structure)  
-  
-This chapter presents a brief overview of the services that GDB  
-provides for managing structured data.    
-Although the discussion in this chapter uses relational database  
-examples, the same GDB features are used to implement servers and  
-clients of all kinds.  
-  
-When Ingres is used to retrieve data from a relational database, the  
-result of the query is known as a @i[relation]@index(relation).  Each  
-relation consists of 0 or more @i[tuples]@index(tuple), and the tuples  
-themselves consist of @i[fields]@index(field).  Informally, one may  
-think of the relation as a table containing one row for each "match"  
-found in the database.  The rows are called tuples, and each such  
-tuple contains the fields which were requested in the query.  For  
-example, a query to a database containing information on military  
-personnel might be:  
-  
-@begin(example)  
-@center[Get the name, rank, and serial number of all personal with over   
-5 years of service]  
-@end(example)  
-  
-If there were two such people, then the resulting relation would contain  
-two tuples, each with three fields.  For example:  
-  
-@begin(example)  
-          Name Rank Serial  
-          ----------------------  
-          Mary  123 876543  
-          John  121 875432  
-@end(example)  
-  
-When GDB is used to perform a query, then some standard  
-representation must be used to hold the resulting relation.  
-Furthermore, GDB must know quite a bit about the @i[types] of the  
-fields, whether they are @i[integer] or @i[real] for example, so that  
-it can do necessary conversions when transmitting between  
-incompatible machines.  Since C itself provides no convenient  
-way of doing this, GDB uses the following conventions:  
-  
-GDB has its own notion of @i[data object]@index(Data object, GDB),  
-which is slightly different from a C variable or structure.  A GDB  
-data object may be as simple as a single integer or as complex as an  
-entire relation.  Each GDB object has a @i[type]@Index(Typing of GDB  
-objects), which tells GDB what kind of object it is.  Though some of  
-the types supported by GDB are similar to those provided by the C  
-language, GDB has its own typing mechanism which is intended to  
-support the transmission and data conversion services that GDB must  
-provide.  
-  
-Every GDB object has one of the following types:  
-  
-@begin(itemize)  
-@begin(multiple)  
-INTEGER_T   
-@index[INTEGER_T]     
-  
-Usually the same as a @i[long] in C.  
-@end(multiple)  
-  
-@begin(multiple)  
-REAL_T      
-@index[REAL_T]   
-  
-Usually the same as a @i[double] in C.  
-@end(multiple)  
-  
-@begin(multiple)  
-STRING_T    
-@index[STRING_T]      
-  
-For various reasons, GDB uses counted byte strings.  The actual implementation  
-of a STRING_T is:  
-       
-@begin(example)  
-       struct {
-               char *ptr;        /* pointer to first*/
-                                 /* byte of data, or*/
-                                 /* NULL if none */
-               int length;       /* number of bytes */
-                                 /* allocated */
-       }
-@end(example)  
-  
-Though these strings are commonly used to hold C language null  
-terminated strings, that is not required.  Any null(s) must be  
-included in the length.  GDB includes library services for creating  
-and manipulating STRING_T data (page @pageref[string_data_in_gdb]).  
-Future releases of GDB may include a C_STRING_T type, which would  
-correspond directly to a C null terminated string.  @end(multiple)  
-  
-@begin(multiple)  
-DATE_T      
-@index[DATE_T]   
-  
-Used to contain a date field retrieved from Ingres.  This is implemented  
-as a 25 byte character array.  See Ingres documentation for conventions.  
-@end(multiple)  
-  
-@begin(multiple)  
-TUPLE_DESCRIPTOR_T    
-@index[TUPLE_DESCRIPTOR_T]      
-  
-Every tuple and relation is described by a tuple descriptor.  The tuple  
-descriptor contains the names of the fields, their position in the tuple,  
-and the types of the fields.  Tuple descriptors are themselves GDB objects.  
-@end(multiple)  
-  
-@begin(multiple)  
-TUPLE_T     
-@index[TUPLE_T]       
-  
-Refers to an entire tuple, including its descriptor.  An item of  
-type TUPLE_T is self-describing.  GDB can tell by inspection what  
-its structure is, as well as the names, types and contents of its fields.  
-@end(multiple)  
-  
-@begin(multiple)  
-RELATION_T       
-@index[RELATION_T]    
-  
-Refers to an entire relation, all its tuples and their descriptors.  An item of 
-
-type RELATION_T is also self-describing.  
-@end(multiple)  
-  
-@begin(multiple)  
-TUPLE_DATA_T     
-@index[TUPLE_DATA_T]       
-  
-This is for internal use of GDB. It refers to just the data part of  
-a tuple, when the description can be inferred.    
-@end(multiple)  
-  
-@begin(multiple)  
-User Defined Types  
-@Index[User defined types]  
-  
-GDB allows users to define their own types.  This can be useful for  
-sophisticated applications which want GDB to take care of transmission  
-and data conversion for unusual data structures.  Few applications  
-will actually require this flexibility, which is explained briefly under  
-"Hints and Tricks".  
-@end(multiple)  
-@end(itemize)  
-  
-Why go to all this trouble, and what does it mean to say that things  
-as simple as INTEGER_T and as complex as RELATION_T are both just types?  
-As it turns out, this convention is the basis of a very powerful scheme  
-for transmitting structured data from one computer to another.  GDB  
-includes a service called @f[send_object] which is used to transmit  
-@index(send_object)  
-information through a network, and a matching service called   
-@f[receive_object].    
-@index(receive_object)  
-Because of the uniform typing scheme outlined above, the same routine  
-used to send a single integer may be used to send an entire relation.  
-Furthermore, the typing information is just what GDB needs to do efficient  
-data conversions when two incompatible machines are communicating.  
-  
-There is one more point of confusion which should be clarified.  As  
-@Index(Types, GDB vs. C)  
-shown above, the system supplied GDB types have names like INTEGER_T,  
-STRING_T, and so on.      
-The confusion arises because these are @i[not] C language typedefs,  
-they are preprocessor constants used as indices into GDB's type  
-tables.  For each GDB type there is usually a corresponding C language  
-type.  For example, INTEGER_T is GDB's term for what C calls a  
-@f[long].  Table @ref[GDBTypes] shows the correspondence between GDB types  
-and C types:  
-  
-@begin(table)  
-@caption(GDB Types and C Types)  
-@tag[GDBTypes]  
-@tabset(.75in, 3.5in)  
-  
-@u[@\GDB Type@\C Language Type]  
-  
-@\INTEGER_T@\long  
-  
-@\REAL_T@\double  
-  
-@\STRING_T@\STRING  
-  
-@\DATE_T@\char xx[25]  
-  
-@\TUPLE_DESCRIPTOR_T@\TUPLE_DESCRIPTOR  
-  
-@\TUPLE_T@\TUPLE  
-  
-@\RELATION_T@\RELATION  
-  
-@\TUPLE_DATA@\TUPLE->   
-@\@\(i.e. a de-referenced tuple)  
-@end(table)  
-  
-All of the GDB type identifiers, as well as the C language types with  
-uppercase names are defined for you in @f[gdb.h].   
-@index(gdb.h)  
-  
-When should you use the GDB type and when should you use the C type?  
-In general, the C type is used whenever you are declaring a variable  
-to C, or casting @index[casting pointers] a pointer to a new type.  
-For example:  
-  
-@begin(example)  
-int
-main()
-{
-       TUPLE t;                        /* C declaration */
-                                       /* for a TUPLE */
-       RELATION r;                     /* C declaration */
-                                       /* for a RELATION */
-       STRING s;                       /* C declaration */
-                                       /* for a counted */
-                                       /* byte string */
-
-       string_alloc(&s,25);            /* allocate a 25 */
-                                       /* character string */
-}
-@end(example)  
-  
-The GDB types are used when you are telling @i[GDB] about the type  
-of data it's going to manipulate:  
-  
-@begin(example)  
-int
-main()
-{
-       STRING s;                       /* C declaration */
-                                       /* for a counted */
-                                       /* byte string */
-       CONNECTION c;
-
-       /*
-        * send the data in STRING s on connection c.  The
-        * STRING_T indication below tells GDB what kind of
-        * object is being sent.
-        */
-       send_object(c, &s, STRING_T);
-}
-@end(example)  
-  
-@section(Building and Using Relations)  
-  
-@index[Relations, creating] Each time you do an Ingres query, the  
-results are added to the local relation that you supply.  That means  
-that you will usually want to create an empty relation before doing a  
-query, then pass that to the @f[db_query] routine @index(db_query)  
-@index(querying Ingres databases)  
-which will fill it in with the results of the query.  Creating the  
-relation is done in two steps: (1) you create a  
-TUPLE_DESCRIPTOR@index[tuple descriptor]@index[TUPLE_DESCRIPTOR]  
-which contains information about the names and types of the fields  
-which will be in the tuples of the relation and (2) using the  
-descriptor, you create the empty relation.  Note that the same  
-descriptor may be used repeatedly to create many relations.  Here is  
-an example with one descriptor and two relations:  
-  
-@begin(example)  
-int  
-main()  
-{  
-     char *fld_names[] = {"name", "rank", "serial"};  
-     FIELD_TYPE fld_types[] = {STRING_T, INTEGER_T, INTEGER_T};  
-  
-     TUPLE_DESCRIPTOR desc;  
-     RELATION old_timers;  
-     RELATION new_recruits;  
-  
-     desc = create_tuple_descriptor(3, fld_names, fld_types);  
-  
-     old_timers = create_relation(desc);  
-     new_recruits = create_relation(desc);  
-  
-}  
-@end(example)  
-  
-GDB provides many macros and procedures for manipulating relations,  
-tuples, and fields.  Let's assume that the program goes on to do two  
-successful queries, one for old_timers and one for new_recruits.  The  
-declarations and code in Program #@ref(ProgramNumber) might be added  
-to the example to print the results of the new recruits query.  
-  
-@begin(float)  
-@index(Fields, accessing)  
-@index(Relations, tuples in)  
-@index(Tuples in relations)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-TUPLE t;  
-STRING *name;  
-int *rank;  
-int *serial;  
-/*  
- * Define symbolic names for the positions of the fields  
- * in the tuples.  There are other ways to do this,  
- * but this does work:  
- */  
-#define NAME 0  
-#define RANK 1  
-#define SERIAL 2  
-/*  
- * the following code would go after the query  
- *  
- *    the loop is executed once for each new  
- *    recruit returned by the query  
- */  
- for(t=FIRST_TUPLE_IN_RELATION(new_recruits);  
-     t != NULL;  
-     t = NEXT_TUPLE_IN_RELATION(new_recruits, t)) {  
-     /*  
-      * Get a pointer to each field in the tuple  
-      */  
-      name = (STRING *)FIELD_FROM_TUPLE(t, NAME);  
-      rank = (int *)FIELD_FROM_TUPLE(t, RANK);  
-      serial = (int *)FIELD_FROM_TUPLE(t, SERIAL);  
-     /*  
-      * print the fields  
-      */  
-      printf("name=%s rank=%d serial=%d\n",   
-          STRING_DATA(*name), *rank, *serial);            
- }  
-/*  
- * return the memory used to hold the new_recruits relation  
- */  
-delete_relation(new_recruits);  
-@end(example)  
-@end(float)  
-  
-The example illustrates several important points.  Variables  
-representing structured objects  
-like TUPLE, TUPLE_DESCRIPTOR and RELATION are actually pointers.    
-@index(Relations, pointer representation of)  
-@index(Tuples, pointer representation of)  
-@index(Relations, tuples in)  
-@index(Tuples in relations)  
-Because TUPLE is a pointer type, TUPLE variables may be used  
-as cursors in a relation.  For example, you might declare a TUPLE  
-variable called @f[ranking_recruit] and set it in the loop above to  
-the tuple of the recruit with the highest rank.    
-Lots of TUPLE variables may point into  
-the same relation, or even to the same tuple, but like any other  
-pointers, they become invalid if the corresponding structures are  
-deleted.  The C value NULL is used to represent non-existent TUPLES,  
-RELATIONS, and descriptors.  
-  
-As shown in the program, the @f[FIELD_FROM_TUPLE] macro is used to find  
-@index(Fields, accessing)  
-@index(FIELD_FROM_TUPLE)  
-a field within a tuple.  @f[FIELD_FROM_TUPLE] returns a  
-@i[pointer] to the requested field, and it is up to you to cast the  
-pointer according to the type of field being retrieved.  In the  
-program, @f(name) is of type STRING_T, so the  
-cast @f[(STRING *)] is used.  Pointer casting is a feature of  
-the C language which is explained in Kernighan and Ritchie and other C  
-programming guides.  
-  
-Note that @f[FIELD_FROM_TUPLE] refers to fields by their  
-position in the tuple, not by name.  This was done for efficiency, as  
-@f[FIELD_FROM_TUPLE] is likely to be called frequently by GDB  
-applications.  The argument supplied may be a variable,  
-but it is your responsibility to correctly interpret the type of  
-the resulting pointer.  GDB can also help you find fields by symbolic  
-name, but that takes longer.  The @f[field_index]   
-@Index(Fields, finding by name)  
-function takes  
-as its argument a tuple descriptor (@i[not] a tuple) and the string  
-name of a field;  it returns the field number of the named field.  If  
-you want to pull fields by name from several similar tuples, the  
-efficient way is to find the index once using @f[field_index],  
-then use that repeatedly in calls to @f[FIELD_FROM_TUPLE].  
-  
-A brief guide to the functions and macros provided for manipulating structured  
-data is provided in Appendix I.  
-  
-@section(STRING Data in GDB)  
-@label(string_data_in_gdb)  
-  
-@index(string)  
-@index(STRING_T)  
-As noted previously, GDB represents string data as counted fields of  
-bytes.  If you create a tuple with a field of type STRING_T, then the  
-space actually allocated in the tuple is just that needed to hold the  
-location and length of the string data, not the space for the data  
-itself.  @f[gdb.h] @index[gdb.h] contains the following definition,  
-which may be used when referring to STRING fields, or to create your  
-own variables of type STRING.  
-  
-@begin(example)  
-@index[FIELD_FROM_TUPLE]
-@index[string_alloc]
-@index[MAX_STRING_SIZE]
-@index[STRING_DATA]
-       typedef struct str_dat {
-               char *ptr;            /* pointer to first */
-                                     /* byte of data, or  */
-                                     /* NULL if none */
-               int length;           /* number of bytes of*/
-                                     /* data allocated */
-       } STRING;
-@end(example)  
-  
-If you have such a tuple and wish to initialize the string field to have  
-space for up to 100 bytes of data, then the code in Program  
-#@ref(ProgramNumber) might be used.  
-  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-       TUPLE t;
-       #define STRFIELD 3            /* index of the string*/
-                                     /* field in the tuple */
-       STRING *sp;                   /* pointer to the field*/
-
-       /*
-       * Get a pointer to the string field in the tuple
-       */
-       sp = (STRING *)FIELD_FROM_TUPLE(t,STRFIELD);
-@index[FIELD_FROM_TUPLE]
-       /*
-       * Allocate space for 100 bytes
-       */
-       string_alloc(sp, 100);
-@index[string_alloc]
-       /*
-       * Copy some text into the new buffer
-       */
-       strcpy(STRING_DATA(*sp), "Hi there");
-@index[STRING_DATA]
-       /*
-       * Note, at this point:
-       *
-       *       MAX_STRING_SIZE(*sp) == 100
-       *
-       *       strlen(STRING_DATA(*sp)) == 9
-       */
-@end(example)  
-@end(float)  
-  
-A call to @f[string_free] would free all 100 bytes of data.  Note that  
-@index(string_free)  
-a routine named @f[null_tuple_strings] frees all the strings in a given  
-@index(null_tuple_strings)  
-tuple.    
-  
-If you're writing your own servers and clients, then STRING variables  
-are a convenient way of sending uninterpreted byte strings from one  
-machine to another, as shown in Program #@ref(ProgramNumber).  
-  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-       CONNECTION con;
-       char buffer[500];
-       STRING s;
-
-       /*
-       * Set up string descriptor s as required by gdb
-       */
-
-       STRING_DATA(s) = buffer;       /* copy the pointer*/
-
-       /*
-        * For demonstration purposes, put some data into the
-        * buffer.
-        */
-       
-        strcpy(buffer, "Some string");
-        MAX_STRING_SIZE(s) = strlen(buffer)+1; 
-                                       /* include space for */
-                                       /* the null */
-
-       /*
-        * send the object through the connection.
-        * we assume that the connection is already
-        * started
-        */
-        send_object(con, &s, STRING_T);        
-@end(example)  
-@end(float)  
-  
-As of this writing, the STRING_T type is the only means GDB provides  
-for manipulating byte strings.  Future releases may also support a  
-C_STRING_T, which would more closely match C's convention of null  
-terminated strings.  The current implementation was chosen for its  
-generality and efficiency.  STRING_T may be used to hold any array of  
-bytes, including those with embedded null characters, and for long  
-strings, STRING_T avoids the overhead of searching the string to  
-compute its length.  
-  
-@Chapter(Creating and Using Relational Databases with GDB)  
-  
-@index[Relational databases]  
-GDB may be used to obtain the full services of an RTI Ingres  
-@index[RTI Ingres]  
-@index[Ingres]  
-relational database from a program running at any node in a Berkeley  
-Unix network.  In addition to most of the services provided by RTI  
-Ingres version 3, GDB supports:  
-  
-@begin(itemize)  
-Remote access from any machine in a network.  
-  
-Parallel access to multiple databases, possibly but not necessarily at  
-multiple sites.  
-  
-Transparent access from incompatible machines (e.g. RT/PC to VAX.)  
-@end(itemize)  
-  
-In fact, GDB is designed to be used with a variety of database  
-products, but RTI Ingres is the only one for which an implementation  
-exists at present.  Nevertheless, every attempt has been made to  
-isolate the Ingres dependencies in GDB.  
-GDB's current support of relational databases is based on the Ingres QUEL  
-query language, which is documented in the appropriate manuals from  
-RTI.  It is @i[essential] that you familiarize yourself with QUEL  
-before attempting to use GDB to manipulate relational databases.  A  
-knowledge of QUEL is presumed in the sections which follow.  
-  
-@section(Accessing Databases)  
-  
-The general procedure for using relational databases in GDB is:  
-  
-@begin(itemize)  
-Use @f[access_db] to initiate access to the database(s) you want to  
-@index(access_db)  
-use.  You specify the name of the database and the host in the network  
-which stores it, and GDB sets up the appropriate connection to the  
-database server.  
-  
-Use @f[perform_db_operation] and @f[db_query] to manipulate or query  
-@index(db_query)  
-@index(perform_db_operation)  
-the databases.  
-  
-Use @f[terminate_db] to sever the connection to the database server.  
-@index(terminate_db)  
-It is also acceptable for your program to exit without terminating its  
-databases, as  
-the server will notice that the connection has been severed.  
-@end(itemize)  
-  
-Because some programs require access to several databases at once, GDB  
-uses DATABASE@index[DATABASE] variables to keep track of the various  
-databases which are being used:  
-  
-@begin(example)  
-int
-main()
-{
-       DATABASE personnel, inventory;
-
-       personnel = access_db("people_data@@host1");
-       inventory = access_db("stuff_data@@host2")
-       /*
-        * Both databases are now available.  Either one
-        * may be queried or manipulated, or both may be used
-        * in parallel.
-        */
-}
-@end(example)  
-  
-Once an attempt is made to access a database, the status of the  
-corresponding database connection may be checked by using the  
-DB_STATUS@index[DB_STATUS] macro.  The values of DB_STATUS are shown in  
-table  
-@ref(DB_STATUS).  
-  
-@begin(table)  
-@caption(Database Status Values)  
-@tag(DB_STATUS)  
-@tabset(.75in, 2.5in)  
-  
-@\DB_OPEN@index[DB_OPEN]@\The connection to the database  
-@\@\appears to be intact.  Operations  
-@\@\on the database may be attempted.  
-  
-@\DB_CLOSED@index[DB_CLOSED]@\The connection to the database  
-@\@\has been lost. @f[terminate_db] is the  
-@index(terminate_db)  
-@\@\only operation which will be accepted.  
-@end(table)  
-  
-There is a distinction between a database which is @f[DB_CLOSED] and  
-@index(DB_CLOSED) one which has been explicitly terminated.  
-@f[terminate_db] allows GDB @index(terminate_db) to clean up the data  
-structures which had been used to control access to the database.  It  
-sets the supplied database variable to NULL.  @f[DB_STATUS] should not  
-be used on a database which has been @index(DB_STATUS) explicitly  
-terminated; it is intended for checking the status of a database which  
-is believed to be accessible.  @section(Performing Operations on  
-Databases) With the exception of queries, all Ingres QUEL@index[QUEL]  
-operations may be performed using the GDB @f[perform_db_operation]  
-function.  @index(perform_db_operation) Program #@ref(ProgramNumber)  
-accesses the database named @f[personnel_data] at site @f[host1],  
-creates an empty table named @f[new_recruits], and puts three entries  
-in the new table.  
-  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-int
-main()
-{
-       DATABASE personnel;
-       char     *quel_command;
-       int      retcode;
-       /*
-        * Access the database and check for errors
-        */
-       access_db("personnel@@host1", &personnel);
-       if (DB_STATUS(personnel) != DB_OPEN) {
-               fprintf(stderr,"Could not access database\n");
-               exit(4);
-       }
-       /*
-        * Create the new table by sending the appropriate QUEL
-        * command.
-        */
-       quel_command=
-           "create recruits (name=c8, rank = i4, serial=i4)");
-       retcode = perform_db_operation(personnel,quel_command);
-       if (retcode != OP_SUCCESS)  {
-               fprintf(stderr,"Could not create table.\n");
-               exit(4);
-       }
-       /*
-        * Add three rows to the table
-        */
-       quel_command=
-"append to  recruits (name=\"Mary\", rank = 123, serial=876543)";
-       retcode = perform_db_operation(personnel,quel_command);
-       if (retcode != OP_SUCCESS)  {
-               fprintf(stderr,"Could not append\n");
-               exit(8);
-       }
-       quel_command=
-"append to  recruits (name=\"John\", rank = 121, serial=875432)";
-       retcode = perform_db_operation(personnel,quel_command);
-       if (retcode != OP_SUCCESS)  {
-               fprintf(stderr,"Could not append\n");
-               exit(8);
-       }
-       quel_command=
-"append to  recruits (name=\"Noah\", rank = 1, serial=123)";
-       retcode = perform_db_operation(personnel,quel_command);
-       if (retcode != OP_SUCCESS)  {
-               fprintf(stderr,"Could not append\n");
-               exit(8);
-       }
-       /*
-        * Sever the connection to the database.  This is 
-        * optional.
-        */
-       terminate_db(&personnel);
-}
-@end(example)  
-@end(float)  
-  
-It is a complete example, with all necessary error recovery.  The  
-return code provided by @f[perform_db_operation] is the Ingres error  
-@index(perform_db_operation)  
-@index(Ingres error)  
-@index(Error, Ingres)  
-number for the operation attempted, or else the special reserved value  
-@f[OP_CANCELLED].  The latter indicates that GDB lost its connection  
-@index(OP_CANCELLED)  
-to the server either just before or just after the operation was  
-attempted.  There is no way to tell whether the operation took effect  
-before the connection was lost.  Subsequent operations on the database  
-are unlikely to work unless another @f[access_db] is done.  
-@index(access_db)  
-  
-Note that @i[any] QUEL@index[QUEL commands] command, with the  
-exception of a retrieve, may be done using @f[perform_db_operation].  
-All clients are considered to @index(perform_db_operation) have the  
-same access and update rights as the userid under which the @f[dbserv]  
-program is running.  @index(dbserv)@index(Internet, access  
-rights from)@Index(Access rights)  
-  
-Hint:  the @f[sprintf] function is a very useful means of putting  
-@index(sprintf)  
-variable information into command strings.  Just use @f[sprintf] to  
-format the QUEL command in a C character array, then pass that to  
-@f[perform_db_operation] for execution.  @f[sprintf] is found in  
-the standard Unix C library.  Try @f[man sprintf] if you don't know  
-how to use it.  
-@section(Performing Database Queries)  
-  
-@index[Retrieval from relational database]  
-@index[Querying relational databases]  
-Retrieves are different from most other QUEL commands because they  
-return query result data in addition to the usual return code.  For this  
-reason, GDB provides a special @f[db_query] function which is used to  
-@index(db_query)  
-do information retrieval from an Ingres database into a GDB relation.  
-Techniques for building an empty relation and for getting at the  
-fields of a result were discussed in Chapter @ref(structure).  All  
-that remains is to explain how the query itself is formulated and sent  
-to the server.    
-  
-@begin(multiple) The format of a GDB retrieve request is exactly the  
-same as the corresponding QUEL@index[QUEL] retrieve @i[except that the  
-target of each retrieve is specified differently].  In QUEL, the  
-command:  
-  
-@begin(example)  
-retrieve (name=recruits.name, rank=recruits.rank, 
-         serial=recruits.serial)       
-        where recruits.rank >10
-@end(example)  
-  
-would result in a table with three columns named @f[name, rank] and  
-@f[serial].  If we assume that a null GDB relation @f[result] has been created  
-with fields named @f[name, rank] and  
-@f[serial], then the following call to @f[db_query] would accomplish a  
-similar query:  
-  
-@begin(example)  
-db_query(personnel, result,  
-      "(>*name*<=recruits.name, >*rank*<=recruits.rank,   
-       >*serial*<=recruits.serial)        
-      where recruits.rank >10");  
-@end(example)  
-  
-Here are the general rules for converting a QUEL query into a GDB  
-query:  
-@end(multiple)  
-  
-@begin(itemize)  
-Create a GDB relation with fields suitable for holding the result.  
-The types of the fields must match the data to be retrieved.  
-Extra fields are OK, they will be set to null values in the retrieved  
-tuples.  You may find the extra fields useful for various purposes in  
-your program.  
-  
-Prepare a C character string which specifying the query to be  
-performed.  The string has exactly the same form as the  
-arguments to a QUEL retrieve, except that @i[each target will be the  
-name of a field in the relation, bracketed by >*...*<].  All the usual  
-syntactic rules governing QUEL retrieves apply.  In particular,  
-remember the parenthesis which are required around the target list.  
-The verb @i[retrieve] should @i[not] be specified at the beginning of  
-the string.  
-  
-Use @f[db_query] to perform the query.  
-@index(db_query)  
-@end(itemize)  
-  
-GDB sends the query request to the remote host and executes the query  
-there.  Return codes are handled in the same manner as for  
-@index(Return codes, Ingres)  
-@index(Ingres error)  
-@index(Error, Ingres)  
-@f[perform_db_operation].  In the case where no errors are found,  
-tuples resulting from the query are appended to the supplied relation.  
-If the server is running on a different type of machine than your  
-client program, GDB does any necessary data conversions to local  
-representation for you.  
-It is quite possible to get a return code of OP_SUCCESS with no tuples  
-added to the relation.  This indicates that Ingres had no trouble  
-executing the query, but found no data matching your retrieval  
-criteria.  
-  
-You may use @f[perform_db_operation] to establish range names which  
-@index(perform_db_operation)  
-may then be used in your query.  Range names are private to each user  
-of the database, and to each connection to the database.  
-  
-Program #@ref(ProgramNumber) is a copy of the sample program from  
-Chapter @ref(structure), fleshed out to show the actual retrieval.  
-For brevity, no error checking is done in this example.  In practice,  
-the return code from each GDB function should be checked.  
-  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-int
-main()
-{
-       DATABASE personnel;
-
-       char *fld_names[] = {"name", "rank", "serial"};
-       FIELD_TYPE fld_types[] = {STRING_T, INTEGER_T, INTEGER_T};
-#define NAME 0
-#define RANK 1
-#define SERIAL 2
-
-       TUPLE_DESCRIPTOR desc;
-       RELATION new_recruits;
-       TUPLE t;
-       STRING *name;
-       int *rank;
-       int *serial;
-
-       /*
-        * Access the database
-        */
-       access_db("personnel@@host1", &personnel);
-
-       /*
-        * Create a null relation to hold the results
-        */
-       desc = create_tuple_descriptor(3, fld_names, fld_types);
-       new_recruits = create_relation(desc);
-
-       /*
-        * Do the query
-        */
-       db_query(personnel, new_recruits,
-                "(>*name*<=recruits.name, >*rank*<=recruits.rank, 
-                 >*serial*<=recruits.serial)   
-                where recruits.rank >10");
-       /*
-        * print the results
-        */
-       for(t=FIRST_TUPLE_IN_RELATION(new_recruits);
-           t != NULL;
-           t = NEXT_TUPLE_IN_RELATION(new_recruits, t)) {
-               /*
-                * Get a pointer to each field in the tuple
-                */
-               name = (STRING *)FIELD_FROM_TUPLE(t, NAME);
-               rank = (int *)FIELD_FROM_TUPLE(t, RANK);
-               serial = (int *)FIELD_FROM_TUPLE(t, SERIAL);
-               /*
-                * print the fields
-                */
-               printf("name=%s rank=%d serial=%d\n", 
-                       STRING_DATA(*name), *rank, *serial);             
-       }
-}
-@end(example)  
-@end(float)  
-  
-  
-@Chapter(Creating Servers, Clients, and Other Communicating Programs)  
-@Index(Communicating programs, writing)  
-  
-One of the main purposes of GDB is to facilitate the programming of  
-servers, clients, and other communicating programs.  Many useful  
-programs can be created in just a few lines of code, but GDB also  
-allows you to write very complex asynchronous servers which support  
-many clients from a single Unix process.  This chapter outlines the various  
-techniques which may be used for writing communicating programs in  
-GDB.  
-  
-@section(Connections)  
-  
-All communication in GDB is done using connections.  The state of  
-each connection is kept in a variable of type @f[CONNECTION], or more  
-@index(CONNECTION)  
-specifically, in a structure to which the connection variable points.  
-GDB has several functions for initiating and terminating connections.  
-They are implemented using Berkeley Unix socket facilities, but  
-are intended to be much easier to use.  There are several different  
-ways to start connections, depending mainly on whether you are writing  
-a server, a client, or sets of peers.  These are described in sections  
-below.  Once successfully started, all  
-connections are full duplex, reliable, ordered data paths on which GDB  
-objects may be sent and received.    
-  
-Once it is started, each connection has a status which may be  
-determined using the @f[connection_status] macro.  Values of concern  
-@index(connection_status)  
-to users are shown in table @ref(ConnectionStatus).  
-  
-@begin(table)  
-@caption(Connection Status Values)  
-@tag(ConnectionStatus)  
-@tabset(.75in, 2.5in)  
-  
-@\CON_UP@index[CON_UP]@\Connection is operational.  
-@\@\Data transmission may be attempted.  
-  
-@\CON_STOPPING@index[CON_STOPPING]@\Connection has failed.
-
-@\@\User may check the @f[connection_errno]
-@\@\@index[connection_errno] for cause, or may call
-@\@\@f[connection_perror]@index[connection_perror] to print
-@\@\message.  In any case, user must issue a @f[sever_connection]@index[sever_connection]
-@\@\in order for the connection to be re-used by gdb.
-
-@\CON_STOPPED@index[CON_STOPPED]@\Connection has been 
-@\@\severed by the user.
-@end(table)  
-  
-Note that the routines which start connections may return NULL values
-in case of failure or they may return a connection descriptor in the
-CON_STOPPING state.  
-When a connection enters the CON_STOPPING state, the only operations which
-users may perform are to check the @f[connection_status] and the @f[connection_errno], or to sever the connection.
-
-If any connection, including a listening connection, fails due to an
-error reported by Unix on a system call, GDB records the corresponding
-Unix @f[errno]@index[errno] in the connection descriptor, and puts the
-connection in the CON_STOPPING state.  All pending operations on the
-connection are cancelled.  This errno value may be queried with the
-@f[connection_errno] macro.
-
-Users may terminate connections at any time from
-either end by using the @f[sever_connection] function.  All operations
-queued at either @index(sever_connection) end are cancelled and the
-communication path is closed.  Connection @i[variables] which have
-been severed may be re-used to start other connections.  A connection
-which has entered the @f[CON_STOPPING] @index(CON_STOPPING) state
-should be severed before its connection variable is re-used.
-  
-  
-@section(Sending and Receiving Data)  
-  
-GDB provides a @f[send_object] function which may be used to send any  
-@index(send_object)  
-GDB object on a connection, and a matching @f[receive_object]  
-@index(receive_object)  
-function.  Objects are sent in order on each connection.  Calls to  
-@f[receive_object] should match one for one with calls to  
-@f[send_object], and the types specified on the receives must  
-match those on the sends.  @i[Failure to do this will result in  
-unpredictable program failures including segmentation faults, hangs,  
-prematurely severed connections, etc.]  
-  
-Chapter @ref(structure) describes GDB's typing scheme.  
-@f[send_object] is a @i[polymorphic] routine which can transmit any  
-type of GDB object.  Each object is automatically converted to the  
-local representation of the receiving machine.  Program  
-#@ref(ProgramNumber) is a simple example which starts a connection to  
-a server, sends a single integer to the server, and gets back a  
-relation.  
-  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-int
-main{
-       CONNECTION server;
-       int i = ???somevalue???;
-       RELATION result;
-       int rc;
-
-       server = start_server_connection("serverid", "");
-
-       if (server == NULL) {
-               fprintf(stderr, "Failed to connect to server\n")
-               exit(4);
-       }
-
-       rc = send_object(server, &i, INTEGER_T);
-       if (rc == OP_CANCELLED) {
-               fprintf(stderr, "Could not send to server.\n")
-               exit(4);
-       }
-
-       rc = receive_object(server, &result, RELATION_T);
-       if (rc == OP_CANCELLED) {
-               fprintf(stderr, "Could not receive from server.\n")
-               exit(4);
-       }
-
-       sever_connection(server);
-
-}
-@end(example)  
-@end(float)  
-  
-This program is complete, if not particularly useful,   
-and it contains all testing needed to detect  
-communication related errors.  Many very useful applications employ GDB  
-in just this simple manner.  GDB takes care of locating the server  
-(naming of servers is discussed below), managing the connection,  
-converting data for transmission, and detecting errors.  
-  
-As discussed in chapter @ref(async), many GDB operations have  
-@index[Asynchronous operations]  
-asynchronous equivalents.  @f[start_sending_object] and  
-@index(start_sending_object)  
-@f[start_receiving_object] may be used to asynchronously send and  
-@index(start_receiving_object)  
-receive data on GDB connections.  GDB maintains a separate operation  
-queue for the inbound and the outbound activity on each connection.  
-If you invoke @f[start_sending_object] several times in rapid  
-succession on the same connection, the requests queue up in  
-order.  The same is true for @f[start_receiving_object], but sends  
-and receives are queued independently.  In certain cases, it may  
-be more efficient to queue several asynchronous transmissions at once  
-than to do just one at a time.    You must not change any  
-variables being sent or received until the operations have completed,  
-otherwise unpredictable results may occur.  If an ordinary @f[send_object] or  
-@f[receive_object] is invoked, then the corresponding queue is flushed  
-before the synchronous operation is attempted.  
-  
-@section(Naming Communicating Programs)  
-@Index(Naming communicating programs)  
-  
-A GDB program attempting to connect to a correspondent somewhere else  
-in the network must have some means of addressing its connection  
-request.   Network servers awaiting connections from clients must have  
-some means of establishing their own identity to the network.    The  
-appropriate form for such addresses may change over time and according  
-to the organization in which GDB is being used.  To isolate these  
-concerns in the cleanest possible manner, all GDB routines use an  
-ordinary C character string to encode any desired network or service  
-address.  Though the form of the string may change when GDB is  
-re-implemented in new environments, the number and nature of  
-parameters to GDB's functions will not.  
-  
-At present, GDB uses the naming facilities of Berkeley 4.2 or 4.3  
-Unix.  Berkeley Unix uses a file called @f[/etc/services] to define  
-@index(/etc/services)  
-the names of network services and to map them to internal addresses  
-known as port numbers.  Setting up @f[/etc/services] is a job for your  
-Unix system administrator, but you must ensure that each GDB service name  
-you intend to use has been defined in @f[/etc/services] at all  
-communicating sites to be a @i[tcp port].  Your system administrator  
-should know what that means.  Once this has been done, the service  
-name is available for use by GDB.  For example, a program intended to  
-act as a server for clients playing chess with each other might be  
-created with the GDB function:  
-  
-@begin(example)  
-                 client = create_forking_server("chess", NULL)  
-@end(example)  
-  
-where @f[chess] is a service name defined in @f[/etc/services].  
-@index(/etc/services)  
-(Other considerations in using @f[create_forking_server] are discussed  
-@index(create_forking_server)  
-below.  Here we are interested only in the service name @f[chess].)  
-  
-A client desiring a connection to this server would have to specify  
-the host at which the server was running as well as its service name.  
-The client might create the connection with:  
-  
-@begin(example)  
-          server = start_server_connection("hostname:chess", NULL)  
-@end(example)  
-  
-@Index(start_server_connection)  
-where @f[hostname] is the name of the host where the server is  
-running.  GDB takes care of finding the host, looking up the service  
-name @f[chess] in @f[/etc/services], and making the appropriate  
-connection.   
-  
-Sometimes its convenient to bypass @f[/etc/services] and specify a  
-port number directly.  GDB assumes that any service name beginning  
-with @f[#] is a port number.  For example:  
-@Index[# (Port number designator)]  
-@Index(Port numbers)  
-  
-@begin(example)  
-                 client = create_forking_server("#9502", NULL)  
-@end(example)  
-  
-creates a server at port 9502.  No checking for conflicts with  
-existing services or entries in @f[/etc/services] is done.  In  
-general, you should be sure that you and your system administrator  
-agree on any service names or port numbers you are going to use before  
-you try it.  Otherwise, you may interfere with other network services  
-at your site.  
-  
-@section(Connecting to A Server)  
-@Index(Connecting to a server)  
-  
-The code fragment:  
-  
-@begin(example)  
-       CONNECTION server;  
-  
-       server = start_server_connection("hostname:chess", NULL)  
-       if (server == NULL)   
-               fprintf(stderr, "Could not start connection.\n");  
-@end(example)  
-@Index(start_server_connection)  
-  
-may be used to start a connection to a service named @f[chess] on the  
-specified host.  If the returned connection variable is not NULL, then  
-a GDB connection has been created which may be used for sending and  
-receiving GDB objects.  The @f[sever_connection] function may be used  
-@index(sever_connection)  
-to break the connection at any time, or the client program may simply  
-exit.  A properly written server will notice that the connection has  
-failed and do the appropriate cleanup.  
-The second parameter to @f[start_server_connection] is an optional  
-parameter string which is made available to the server.  Rules for  
-using this string are established by each server.  
-There is no asynchronous form of start_server_connection at the  
-present time.  GDB delays until the request either succeeds or  
-encounters an unrecoverable error.  
-  
-@section(Writing Servers)  
-  
-There are several kinds of GDB server, each of which is discussed in a  
-separate section below.  
-  
-@subsection(Forking Servers - the simplest kind)  
-  
-@index[Forking servers]  
-The simplest kind of GDB server, which most programmers will use, is  
-called the @i[forking] server.    
-This is the traditional kind of Unix server in which a new process is  
-forked to deal with each client.  GDB does the forking for you, and  
-takes care of most of the Unix bookkeeping required in a forking  
-program.  
-Creation of forking servers is best illustrated by the simple example  
-in Program #@ref(ProgramNumber).   
-  
-@modify(example,Size 9)  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-@label(tfsr)
-{
-       CONNECTION client;      /* talk on this to client */
-       int data;               /* receive data here */
-
-       gdb_init();             /* set up gdb */
-
-       client = create_forking_server("echoserver",NULL);
-       fprintf(stderr,"forked\n");
-
-       while (TRUE) {
-               if (receive_object(client, &data, INTEGER_T) ==
-                   OP_CANCELLED) {
-                       fprintf(stderr,"Client has terminated\n");
-                       exit(4);
-               }
-               if (data >= 'a' && data <= 'z')
-                       data += 'A'-'a'; /* upcase the response */
-               if (send_object(client, &data, INTEGER_T) ==
-                   OP_CANCELLED) {
-                       fprintf(stderr,"send error\n");
-                       exit(4);
-               }
-       }
-}
-@end(example)  
-@end(float)  
-  
-This is a fully functional server capable of supporting an arbitrary  
-number of clients.  It does the trivial work of accepting a stream of  
-characters (stored in integers) converting them to uppercase, and  
-sending the result back to the client.  The @f[create_forking_server]  
-@index(create_forking_server)  
-function behaves somewhat like the Unix @f[fork] system call.  Each  
-@index(fork)  
-time a new client connects to the server, a fork is done and the  
-variable @f[client] in the child process is set to the new client  
-@index(client)  
-connection.  In other words, the code below @f[create_forking_server]  
-is automatically invoked over and over again in a new process each  
-time a connection is received from a client.  When the processing for  
-each client is done, an @f[exit] or @f[return] is all that is needed  
-@index(return)  
-@index(exit)  
-to cause the appropriate cleanup in the server.  Note that this sample  
-server detects termination of its clients by checking for errors when  
-receiving and sending.  This technique is convenient and reliable,  
-since the connection is always severed as soon as the client  
-terminates.  
-  
-@subsection(Single Process Servers)  
-  
-@index[Single process servers]  
-Though forking servers are particularly easy to write, they have the  
-disadvantage of breaking the server into a separate process for each  
-client.  In particular, forking servers are unsuited to applications  
-in which data is to be shared among the various clients.  A server  
-which implemented a bridge game, for example, might relay the bids  
-played by one client to all of the three others.  This kind of program  
-is very difficult to implement in a forking server, so GDB also allows  
-you to write servers in which all clients are handled by a single Unix  
-process.  Because so much asynchronous activity has to be coordinated  
-within a single process, these servers are generally much harder to  
-design and debug.  Nevertheless, they can be the basis of some of the  
-most exciting, high performance applications which can be written with  
-GDB.    
-  
-Chapter @ref(async) introduces the techniques  
-used to do asynchronous communication with GDB.  
-Read it now, if you have not already done so, before proceeding   
-with this section.  
-Here we show how a  
-single server process may @i[asynchronously] acquire new connections  
-from its clients.  In general, a single process server works in the  
-following manner:  
-  
-@begin(itemize)  
-@f[create_listening_connection] is used to create a special connection  
-@index(create_listening_connection)  
-on which connection requests from clients arrive.  
-  
-The asynchronous operation @f[start_accepting_client] is  
-@index(start_accepting_client)  
-queued on the listening connection.  This operation completes whenever  
-a new client requests a connection.  The server immediately issues a  
-new @f[start_accepting_client] in case another client is  
-trying to connect.  
-  
-The server examines the parameters supplied by the client, and if it  
-decides to accept the client's connection, transmits its decision  
-by using the asynchronous operation @f[start_replying_to_client].  
-@index(start_replying_to_client)  
-When this becomes OP_COMPLETE, the new client is ready for use.  
-  
-@f[start_sending_object] and @f[start_receiving_object] are used in  
-@index(start_receiving_object)  
-@index(start_sending_object)  
-the usual manner to send data to and from the clients.  
-@end(itemize)  
-  
-The typical server must be capable of doing all of these operations  
-simultaneously and in any order.  It maintains a LIST_OF_OPERATIONS  
-which includes all of the operations on which completion is awaited,  
-and it drops into an @f[op_select_any] to wait for something to  
-@index(op_select_any)  
-happen.  Based on the operation which has completed, it determines the  
-next step to perform.  If a client has sent data, it may queue a  
-response or prepare data for transmission to other clients.  If a new  
-connection request is received it must queue the appropriate response,  
-and so on.    
-  
-There are many ways to organize such a program.  A sample, which  
-performs the same character echoing function as the forking server on  
-page @PageRef(tfsr), is included in Appendix @ref(nonforkingserver).  
-Studying this sample is the best way to learn about creating  
-non-forking servers.  The GDB library routines are documented in the  
-Library Reference Manual.  
-  
-@section(Communicating Peers)  
-  
-@index[Peer to peer communication]  
-Sometimes it is useful to write communicating @i[peer] programs which  
-do not fit the client/server model.   
-When two peers communicate, neither may be presumed to start before  
-the other.  GDB provides a  
-@f[start_peer_connection]@index[start_peer_connection] function which  
-starts a connection to a peer elsewhere in the network.    
-If necessary, @f[start_peer_connection] delays indefinitely until its  
-peer is started and issues a matching @f[start_peer_connection].  Once  
-started, peer connections are used just like any others.  
-@f[start_peer_connection] is documented in the Library Reference Manual.  
-  
-@Chapter(Synchronous and Asynchronous Operations)  
-@label(async)  
-  
-  
-Most of the GDB programs discussed so far have been completely  
-@i[synchronous], meaning that they only try to do one thing  
-at a time.  The @f[perform_db_operation] and @f[db_query] routines  
-@index(db_query)  
-@index(perform_db_operation)  
-retain control until the requested operations have run to completion,  
-which makes it impossible for a program to do several queries in  
-parallel, or to continue with its own execution while a database is  
-being updated.  GDB also provides @i[asynchronous] versions of many of  
-@index(Asynchronous operations)  
-its services, allowing execution of the client to proceed while the  
-requested operation is attempted.  Asynchronous programming is usually  
-more difficult than synchronous, but it is much more flexible.  This  
-chapter describes GDB's facilities for managing asynchronous  
-activities.  
-  
-@section(Operations)  
-@index(Asynchronous operations)  
-@index(OPERATION)  
-  
-An asynchronous program may have several operations running in  
-parallel while its own local execution continues.  In order to track  
-the progress of these activities, the program uses an OPERATION  
-@index[OPERATION]  
-variable for each one, as illustrated in Program  
-#@ref(ProgramNumber).  This program fragment presumes that DATABASEs  
-@f[personnel] and @f[inventory] have been successfully accessed.  
-Several important points are illustrated by the example.  Each  
-operation variable must be initialized with the @f[create_operation]  
-@index(create_operation)  
-function.  Like most other data structures in GDB, OPERATIONS are  
-really pointer types;  @f[create_operation] allocates and initializes  
-the data structure which GDB actually uses to track the operation.    
-  
-@begin(float)  
-  
-@center(PROGRAM #@ref(ProgramNumber))  
-@set(ProgramNumber=+1)  
-@begin(example)  
-       DATABASE personnel, inventory;
-       char     *quel_command;
-       RELATION new_recruits;
-
-       OPERATION query_op, append_op;
-
-       /*
-        * Each operation must be created before it 
-        * can be used
-        */
-       query_op = create_operation();
-       append_op = create_operation();
-
-       /*
-        * Start an append to the parts database in parallel
-        * with a query to the personnel database. We assume that
-        * both DB's are accessed and the relation was created.
-        */
-       quel_command=
-   "append to  parts (type=\"resistor\", price = .12, quantity=150)";
-       retcode = start_performing_db_operation(append_op, 
-                                               personnel,
-                                               quel_command);
-       start_db_query(query_op, personnel, new_recruits,
-                "(>*name*<=recruits.name, >*rank*<=recruits.rank, 
-                 >*serial*<=recruits.serial)   
-                where recruits.rank >10");
-
-       /*
-        * Wait for both to complete.  Order of the following 
-        * two statements does NOT matter!
-        */
-       complete_operation(append_op);
-       complete_operation(query_op);
-
-       /*
-        * Check for errors
-        */
-       if(OP_RESULT(append_op) != OP_SUCCESS ||
-          OP_RESULT(query_op) != OP_SUCCESS)
-               fprintf(stderr,"Something didn't work\n");
-@end(example)  
-@end(float)  
-  
-There are many ways to check for progress or await completion of GDB  
-operations.    
-One of the simplest is @f[complete_operation], which is  
-@index(complete_operation)  
-shown in this example.  The program hangs in GDB until the specified  
-operation completes.  As noted in the program comments, the order of  
-the two calls to @f[complete_operation] is @i[not] significant.  This  
-might be surprising, as the calls seem to imply that @f[append_op]  
-must complete before @f[query_op] will proceed.  That is not the case.  
-@i[Whenever GDB is given control for any reason, it always makes  
-progress as quickly as possible on all pending operations.]  This  
-means that @f[query_op] may progress or even complete while   
-awaiting completion of  
-@f[append_op].  Should @f[query_op] complete before  
-@f[append_op], the second call to @f[complete_operation] will not delay  
-at all.  
-  
-Each operation has two types of status, which may be queried by  
-@f[OP_STATUS] and @f[OP_RESULT] respectively.  OP_STATUS is used to  
-@index(OP_RESULT)  
-@index(OP_STATUS)  
-track the progress of an operation while it is executing.  It has the  
-values shown in table @ref(OP_STATUS).  
-  
-@begin(table)  
-@caption(OP_STATUS Values)  
-@tag(OP_STATUS)  
-@tabset(.75in, 2.5in)  
-  
-@\OP_NOT_STARTED@\The operation  
-@\@\variable is not in use.  
-  
-@\OP_COMPLETE@\The operation completed  
-@\@\without any transmission  
-@\@\related errors.    
-  
-@\OP_CANCELLED@\GDB was forced to  
-@\@\give up on the operation  
-@\@\prematurely. The likeliest  
-@\@\explanation is failure of  
-@\@\the connection.  
-  
-@\other@\OP_STATUS takes on   
-@\@\several other values while  
-@\@\an operation is queued or  
-@\@\executing.  These are not  
-@\@\of concern to users of  
-@\@\the library.  
-@end(table)  
-  
-  
-The operation should be considered running until its status becomes  
-either  
-@f[OP_COMPLETE] or @f[OP_CANCELLED].  The macro @f[OP_DONE] may be  
-@index(OP_DONE)  
-@index(OP_CANCELLED)  
-@index(OP_COMPLETE)  
-@index[Return codes from GDB operations]  
-used to test for both of these.  When an operation reaches  
-@f[OP_COMPLETE] status, then the @f[OP_RESULT] macro may be used to  
-get the return code from the operation itself.  In the case of an  
-Ingres query, for example, the operation will be considered complete  
-when all results have been returned to the client.  @f[OP_STATUS] will be  
-@index(OP_STATUS)  
-@f[OP_COMPLETE] and @f[OP_RESULT] will contain the return code from Ingres.  
-If the connection fails before the query is successfully attempted,  
-@f[OP_STATUS] will be @f[OP_CANCELLED] and @f[OP_RESULT] will be  
-undefined.  The result value @f[OP_SUCCESS] is usually used to  
-indicate that an operation completed successfully.  
-  
-@f[OPERATIONS] are created in the state @f[OP_NOT_STARTED].  After  
-@index(OP_NOT_STARTED)  
-use, the state is generally @f[OP_CANCELLED] or @f[OP_COMPLETE].  It is  
-possible to re-use such an @f[OPERATION], which saves the overhead of  
-deleting and re-creating it.  You must use @f[reset_operation] to  
-prepare an operation for re-use, returning it to the state  
-@f[OP_NOT_STARTED].   
-  
-Hint: it is often handy to create arrays of operations, or to include  
-@Index(Arrays of operations)  
-operations in other C structures.  Make sure to do a  
-@f[create_operation] on each one before it is used.  
-@f[delete_operation] may be used to reclaim the space for operations  
-@index(delete_operation)  
-which have terminated and are no longer needed.  
-  
-@section(op_select_any and op_select_all)  
-  
-In certain programs you may wish to take explicit action when any of a  
-list of pending operations completes, or you may wish to monitor  
-activities on file descriptors not controlled by GDB.  Berkeley Unix  
-uses @f[select] to control asynchronous file handling, and GDB  
-@index(select)  
-provides two generalized forms which facilitate control of GDB's  
-operations.    
-  
-@f[op_select_any] has semantics similar to the select system  
-@index(op_select_any)  
-call, but in addition, it allows pending GDB operations to  
-progress.  Along with a list of file descriptors, you must give  
-@f[op_select_any] a list of the GDB operations whose completion is of  
-interest.  Like @f[select], this routine waits quietly when all  
-descriptors are blocked.  Unlike @f[select], @f[op_select_any] allows  
-processing to proceed on all GDB connections, and it returns only when  
-one of the operations specified in the list actually completes.  While  
-@f[select] would return whenever any data could be read or written on  
-a connection, @f[op_select_any] returns only when enough progress   
-been made that one of the specified operations actually completes.  One  
-may think of @f[op_select_any] as raising the level of abstraction on  
-a connection from single bytes to entire operations.  As with  
-@f[select], you may supply your own file descriptors and a timeout,  
-and GDB will treat these in the same manner as @f[select] would.  
-@f[op_select_all] is similar to @f[op_select_any], but it waits for  
-@index(op_select_all)  
-all of the specified operations to complete before returning.  
-  
-Both of these functions take as arguments a @f[LIST_OF_OPERATIONS],  
-@index(LIST_OF_OPERATIONS)  
-which may be created using the @f[create_list_of_operations] function.  
-@index(create_list_of_operations)  
-Since manipulating lists is clumsy, it is sometimes useful to create  
-one long list with all the operations you ever expect to wait for, and  
-just pass that to @f[op_select_any].  Once an operation has completed,  
-you should use @f[reset_operation] to keep it from pre-satisfying the  
-next select call.  
-The program in Appendix @ref(nonforkingserver) illustrates all of these  
-techniques.  
-  
-@chapter(Hints and Tricks)  
-@blankspace(2in)  
-@center(To be supplied.)  
-@chapter(Bugs)  
-@blankspace(2in)  
-@center(To be supplied.)  
-  
-@chapter(How GDB Works)  
-  
-The ultimate authority on this is, of course, the GDB code.    
-@index[source code organization]
-Most of it is pretty well commented (some would say over-commented,  
-but that is my style), which means that you can usually figure out  
-what's happening IF you know where to look and have some general idea  
-of how things work.  
-This chapter presents the general concepts and implementation  
-techniques which underlie GDB.  
-It is not comprehensive, but I do recommend that you read this before  
-looking at the code.  
-  
-GDB is organized into several interacting sub-components or layers.  
-Some are so trivial as to require little or no explanation.    
-Others, such as the layers which do asynchronous operations and  
-communication,  
-are much more complex.  
-The sections below describe the components of GDB and their  
-relationship to each other.  
-A thorough knowledge of Berkeley Unix, C programming, and creation and  
-manipulation of sockets is presumed.  
-It is also presumed that the reader is familiar with the other  
-chapters in this guide.  
-  
-@section(General Code Layout)  
-  
-GDB is supplied as a suite of .c source files which are compiled to  
-build the libgdb.a library archive.  The gdb.h include file is used by  
-all of these, and also by user applications.  
-@index[dbserv, compiling]
-The @f[dbserv] database server is supplied in a separate @f[dbserv.qc]  
-file, which can @i[only] be compiled on a machine which has RTI Ingres  
-installed and accessible.  See RTI's documentation for details.  
-If you are not using dbserv then there is no need to build it.  The  
-rest of GDB, including database client applications, may be compiled  
-and used on machines which do not have RTI's products installed.  
-  
-The file named gdb.c contains the routine @f[gdb_init], which is  
-@index[gdb_init]
-called first by all users of gdb.  
-Initialization of GDB data structures can be tracked by reading this  
-source.  
-This source file also contains a few utility routines.  
-Most of the other source is organized more or less by layer, with some  
-of the larger layers split into several source files.  
-The chapters below give hints, or you can grep for the name  
-of the routine in which you are interested.   
-It is always safe to grep in g*.c; this will get all of the executable  
-GDB source.  
-  
-gdb.h is organized more or less by gdb layer, with a ^L page break  
-@index[gdb.h]
-between each section.  
-You should always have the corresponding section of gdb.h handy while  
-trying to learn about a piece of GDB.  It is essential.  
-  
-@section(Memory Management)  
-  
-@index[Memory management]
-GDB makes extensive use of dynamically allocated (heap) memory.  
-ALL calls for dynamic memory are done through the two routines  
-@index[db_alloc]
-@index[db_free]
-@f[db_alloc] and @f[db_free].  These are actually defines in gdb.h  
-which cause invocation of @f[*gdb_amv] and @f[*gdb_fmv] respectively.  
-@index[gdb_amv]
-@index[gdb_fmv]
-@index[gdb_am]
-@index[gdb_fm]
-These in turn point, by default, to @f[gdb_am] and @f[gdb_fm], which  
-just call malloc and free.  
-This is all done so an application can easily replace the default  
-memory allocators.   
-The addresses of the new routines should be plugged into the vectors  
-prior to calling @f[gdb_init].  Note that the interfaces are @i[not]  
-quite the same as to malloc and free;  check the source for details.  
-  
-Many dynamically allocated GDB objects contain 4 character @f[id]  
-fields.  These are just eye catchers for debugging, initialized to  
-"REL" for relations, "TUP" for tuples, and so on.  
-Most parameters passed by users are  
-checked for these fields, which helps catch bad parameters and some  
-memory management errors.  
-  
-@section(GDB Type Management)
-@index[GDB types]
-@index[Types]
-Make sure you understand GDB types from a users point of view (Chapter  
-@ref[structure]) before continuing here.  
-  
-The primary purpose of GDB types is to support the polymorphic  
-@index[Polymorphism]
-operations @f[start_sending_object] and @f[start_receiving_object].  
-These two operations suffice to send and receive @i[any] GDB object,  
-regardless of its structure or complexity.  
-@index[Type definition]
-@index[GDB Type definition]
-Given these limited goals, GDB needs only some very basic information  
-about its types:  
-  
-@begin(itemize)  
-The length of an item as represented locally (may depend on local  
-machine type).  
-  
-Required alignment (e.g. 4 or fullword, 8 for double)  
-  
-A function to return a null value for the type.  
-This is used to initialize newly allocated variables.  
-  
-A function to encode values of this type for transmission.  
-  
-A function to decode data of this type from its transmitted form to the  
-local representation (which is usually machine dependent.)  
-  
-A function to return the length which a value would take when encoded  
-for transmission.  
-GDB calls these functions to decide how much memory to allocate for  
-the transmission buffer before calling the encode routine to fill in  
-the buffer.  
-  
-A format function which is used to format variables of this type for  
-debugging output.  
-  
-A string name for the type.  Used only for debugging output.  
-@end(itemize)   
-  
-@index[Properties]
-@index[FCN_PROPERTY]
-@index[INT_PROPERTY]
-@index[STR_PROPERTY]
-All this information is coded into the array named g_type_table.  
-The macros INT_PROPERTY, FCN_PROPERTY, and STR_PROPERTY are used by  
-the GDB code to index into the type table and pull out any desired  
-property for the given type.  
-For example, INT_PROPERTY(REAL_T, LENGTH_PROPERTY) returns the length  
-of the local representation of a real number.  
-  
-@begin(example)  
-       FCN_PROPERTY(REAL_T, ENCODE_PROPERTY) (....)  
-@end(example)  
-  
-calls the encode routine on a real number, with the supplied (....)  
-arguments.  Though the macro expansions look messy, they are designed  
-to be optimizable by a good compiler.  
-  
-The routine @f[gdb_i_stype] is used to initialize the type table,  
-@index[gdb_i_stype]
-thereby defining types.  The typing system is extensible in that new  
-types may be defined by adding entries to the type table at any time.  
-The most difficult aspect of this is writing the encode and decode  
-functions for the new type.  Note that the routines for encoding and  
-decoding structured types, like tuples and relations, generally make  
-repeated calls to the encoding routines for components.  Thus, the  
-relation encoding routine calls the tuple encoding routine, which  
-calls the routines for the various fields.  The end result is a single  
-buffer containing the entire structured datum flattened for  
-transmission.  
-  
-@subsection (The TUPLE_T and RELATION_T Structured Types)  
-  
-@index[TUPLE_T]
-@index[RELATION_T]
-The @f[TUPLE_T] and @f[RELATION_T] types are supplied with GDB; they  
-are commonly used to contain the results of a relational database  
-query, but they are also useful for transmitting other types of  
-structured data.  For brevity, we will refer simply to tuples and  
-relations.  
-  
-Both tuples and relations are self-describing.    
-Given a tuple or relation, one can determine its complete structure as  
-well as its contents.  
-A tuple is an ordered, non-extensible collection of named, typed,  
-fields, and a relation is an ordered, extensible collection of tuples.  
-Because one program, and certainly one relation, will commonly use  
-many tuples with the same structure (i.e. the same field names and  
-types), the description information for these tuples may be shared in  
-a single @f[TUPLE_DESCRIPTOR].   
-@index[Tuple descriptors]
-The tuple descriptor is allocated and initialized by  
-@f[create_tuple_descriptor] with the names and types of a set of  
-fields.  
-Internally, the descriptor is also initialized to contain the offset  
-and length of the fields within a tuple.  
-Accessing a field within a tuple is thus extremely fast, as the  
-offsets are pre-computed.  
-Note that the offsets and lengths of the fields are local properties  
-which may vary from one machine type to another.  Also, this structure  
-supports retrieval of a field whose index or name (and thus its type)  
-is variable at execution time.  
-  
-A single tuple descriptor may be shared by an arbitrary number of  
-tuples, some of which may be members of relations.    
-Also, GDB may implicitly allocate tuple descriptors for tuples and  
-relations received through the network.  
-To facilitate management of these descriptors GDB uses reference  
-counting.  Each time a descriptor is used in a tuple or  
-relation, its reference count is incremented.  Each time such a tuple  
-or relation is deleted, the reference count is decremented.    
-When the reference count goes to 0, the descriptor itself is  
-reclaimed.  
-@i[As a general rule, users should explicitly de-allocate the  
-descriptors, tuples, and relations that they create, and they should  
-de-allocate objects that they explicitly receive from the network.  
-Implicitly created descriptors will be reclaimed automatically by the  
-system.]  
-  
-@index[TUPLE]
-@index[TUPLE_DESCRIPTOR]
-@index[RELATION]
-The names @F[TUPLE, TUPLE_DESCRIPTOR] and @f[RELATION] supplied in  
-gdb.h are actually pointers and may be manipulated as such (e.g.  
-copied, passed as arguments to functions, etc.)  The create functions  
-dynamically allocate memory and fill in the pointers.  
-  
-A tuple descriptor consists of a fixed header, an array containing  
-descriptive information for each field, and then a contiguous list of  
-null terminated strings, which are the text names of the fields.  
-  
-A TUPLE is a pointer to a single contiguous chunk of memory  
-containing a header followed by the data for the tuple fields.  
-The header includes chain pointers, which are used @i[only] when the  
-tuple is contained in a relation, and a pointer to the corresponding  
-tuple descriptor.  The data follows immediately, at the offsets listed  
-in the tuple descriptor.    
-Offsets are relative to the start of the first field, not the tuple  
-header.  
-  
-Relations consist of a header structure circularly double linked to a  
-(possibly null) list of tuples.  
-The last tuple points to the relation header, as does the back pointer  
-from the first tuple.  
-A null relation has forward and back pointers to itself.  
-The queue manipulation macros like ADD_TUPLE_TO_RELATION depend on the  
-@index[ADD_TUPLE_TO_RELATION]
-fact that the next and prev fields are at the same offset in both the  
-tuple and relation header data structures;  this may not actually be  
-true on machines which allocate structures backwards, and as much, it  
-represents a non-portability.  
-  
-@section(Communications and Asynchronous Operations)  
-  
-@index[Communication services]
-@index[Asynchronous operations]
-This layer of GDB provides management for connections between programs  
-on separate hosts, and for asynchronous transmission of typed data  
-between those hosts.  It relies on the memory management and data  
-typing layers discussed above.  Due primarily to the extensive support  
-for asynchronous, non-blocking communication on multiple connections,  
-this is by far the most complicated layer of GDB.  Rather than trying  
-to discuss every detail, I will emphasize the most important general  
-concepts, and give warnings about implementation features which may be  
-difficult to follow in the code.  
-  
-@subsection(Connections)  
-  
-@index[Connections]
-A @f[connection] is an abstraction for an asynchronous, reliable,  
-full-duplex path on which GDB can transmit and receive its typed data.  
-The current implementation uses Berkeley TCP stream sockets for  
-transport.  
-  
-Unlike most GDB data structures, all connection descriptors are  
-@index[gdb_cons]
-statically allocated in the @f[gdb_cons] array.  When a new connection is  
-started, the first available slot in the array is returned as the  
-corresponding connection descriptor.  NOTE:  the actual state of each  
-connection descriptor is contained in its status field.  @f[gdb_mcons]  
-is a high water mark variable indicating the highest numbered  
-connection which has ever been used;  it provides an optimization for  
-the common case of a process which only uses one or two connections.  
-Below the water mark, the status fields must be checked to determine  
-whether a connection descriptor is actually in use.  
-@index[GDB_MAX_CONNECTIONS]
-GDB_MAX_CONNECTIONS determines the size of the array, and hence limits  
-the number of simultaneous connections which may be controlled by a  
-single process.  The GDB library may be rebuilt with a larger value if  
-desired.    
-  
-Each connection actually consists of two half connections, one for  
-each direction.   In the current implementation, they use the same  
-file descriptor, but this could be changed for other networking  
-environments.  There is also some stray code which refers to  
-out-of-band connections.  This was intended to be used for out of band  
-signalling, primarily to cancel ongoing operations.  It was never  
-implemented.  
-  
-@subsection(Operations and Half Connections)  
-  
-@index[Operations]
-@index[Half connections]
-Each transmission operation which GDB supports on a half connection is  
-fundamentally asynchronous, meaning that the application program can  
-continue to execute while the operation proceeds.    
-GDB is @i[not] signal driven;  it uses non-blocking I/O to make as  
-much progress as possible whenever it gets control, leaving 
-@index[SIGIO]
-SIGIO available to
-the application 
-programmer.  GDB does set a handler for SIGPIPE.
-@index[SIGPIPE]
-Though  
-synchronous versions are provided for most operations, these usually  
-are implemented by invoking the asynchronous version and then  
-immediately waiting for it to complete.  
-  
-Each pending operation is represented by a data structure of type  
-OPERATION (actually, OPERATION is the pointer to the data structure)  
-@i[which is queued on the corresponding half connection.]  It is thus  
-a fundamental limitation of the current version of GDB that  
-asynchronous activities exist @i[only] in the context of a connection.  
-The only reason that such an operation may ever block is due to lack  
-of progress in data transmission on the corresponding path.  GDB does  
-not provide for any more general kind of multiplexing or lightweight  
-process management.  
-  
-The operation data structure contains the complete state of the  
-pending operation.  This is summarized in a status field, which  
-indicates that the operation is either OP_QUEUED (waiting behind  
-others in a queue), OP_RUNNING (at the head of the queue and  
-proceeding as fast a data transmission will allow), OP_COMPLETE  
-(completed without GDB detected error) or OP_CANCELLED (abandoned  
-before completion, usually due to loss of the corresponding  
-connection.)  There is also a result field, which becomes valid  
-@i[only] when and if the operation reaches the OP_COMPLETE state.  It  
-is effectively the final return code, with legal values depending on the  
-operation being attempted.  In addition to these state fields, the  
-operation structure contains a pointer to a function which is to be  
-invoked the next time progress can be made (i.e. the next time the  
-communication path unblocks) and the @f[arg] field, which points to a  
-dynamically allocated structure used by the functions to contain their  
-own ongoing state.  
-  
-The operation actually running on each half connection is the one at  
-the head of the queue.  The only reason such an operation may be  
-blocked is because it has tried to send or receive data which the  
-@f[gdb_move_data] routine was unable to move immediately.  The pending state of
-this partially 
-completed  
-@index[next_byte]
-@index[remaining]
-transmission is summarized by the @f[next_byte] and @f[remaining]  
-fields of the half_connection structure.  If an operation seems not to  
-be progressing, and the @f[remaining] field is non-zero, it may be  
-that the socket is not making progress.      
-  
-The heart of GDB's transport layer is a routine called  
-@index[gdb_progress]
-@f[gdb_progress], which has the effect of making all possible progress  
-on all pending operations regardless of the connections involved.  
-This routine never blocks.    
-Instead, it cycles through the connections, trying repeatedly to make  
-progress, and returning when no further progress can be made.  
-The actual work is done by 
-@index[gdb_hcon_progress]
-@f[gdb_hcon_progress], which is one of the  
-most important (and deceptively complicated) in GDB.  
-If the operation at the head of the queue has never been run before,  
-then its initialization function (@f[*init] from the operation  
-structure) is called to start it off.  
-If the operation has been run before, then it @i[must] be blocked  
-waiting for data to be transmitted.  In this case, 
-@index[gdb_move_data]
-@f[gdb_move_data]  
-is called to move the data.  
-If that still results in blockage, then no further progress can be  
-made;  
-otherwise, the operation's continuation function (@f[*cont] from the operation  
-structure) is called to process the data or proceed in some other  
-manner.  
-  
-Most of the subtlety in this area comes from the interplay between  
-multiple connections and operations.  
-If connection 1 blocks, connection 2 may be able to proceed. By the  
-time 2 finishes, 1 may be able to progress after all.  For this  
-reason, @f[gdb_hcon_progress] is called over and over again until a  
-full sweep is made through all active connections without a report of  
-any progress at all.  Furthermore, it is sometimes the case that an  
-ongoing operation will actually create and queue new operations on  
-either the same or a different connection, which may result in a  
-recursive invocation of @f[gdb_progress].  The 
-@index[HCON_BUSY]
-@f[HCON_BUSY] flag is  
-used to avoid recursive processing of the same half connection.  
-Another subtle flag is 
-@index[HCON_PROGRESS]
-@f[HCON_PROGRESS], which is used by  
-@f[gdb_move_data] to indicate whether progress was made on a given half  
-connection.  It looks to me in hindsight like this should have been  
-passed as a parameter, perhaps there was a good reason why not.  In  
-any case, it is effectively a value returned from @f[gdb_move_data].  
-A final complication arises because an operation is allowed to  
-re-queue itself from one half connection to another.  This effectively  
-puts it back from OP_RUNNING to OP_QUEUED state, to be caught by a  
-subsequent sweep of @f[gdb_hcon_progress].  
-  
-@subsection(GDB Select Features)  
-  
-@index[Select operations]
-In a Berkeley Unix system, the customary means of waiting for I/O to  
-progress is to hang in the @f[select] system call.  
-One of the purposes of GDB is to hide byte level communication from  
-applications, which are interested only in the progress of their higher  
-level requests to GDB.  For this reason, GDB provides the new  
-selection operations @f[op_select_any] and @f[op_select_all].  The  
-former is also known by the historical name @f[op_select], which will  
-be used here for brevity.  It is also the more interesting of the  
-two, since @f[op_select_all] is built trivially from @f[op_select].  
-  
-@f[op_select] is given a list of queued and/or completed GDB  
-operations, a list of file descriptors not controlled by GDB, and a  
-timeout value in the same form as for Berkeley select.  @f[op_select]  
-returns as soon as (1) one of the operations supplied is completed or  
-cancelled (2) a select call indicates that progress can be made on one  
-of the other file descriptors or (3) the timeout is satisfied.   
-Actually, the current version of the system has a bug which  
-effectively resets the time every time any connection makes progress.  
-  
-@index[con_select]
-The real work here is done in the routine named @f[con_select].  This  
-routine contains the @i[only] significant @f[select] call in the  
-entire GDB system.  There are a few others, but those never block.  
-@f[con_select] is similar to a real select except that: (1) it  
-implicitly selects all file descriptors controlled by connections, as  
-well as those explicitly specified (2) it allows transmission and  
-receipt to progress on all connections and (3) it considers a  
-connection to be selected if and only if a transmission operation  
-which had been pending becomes complete.  One may consider that  
-@f[con_select] turns the fd's controlled by sockets into operation  
-streams rather than byte streams.  Note also that this operation  
-differs from a traditional select and op_select in that it is not  
-robust against waiting for connections with pre-completed activity.  
-This could be added, but since it's an internal routine anyway, it  
-seems not to be worthwhile.  Also, this routine presumes that all  
-possible progress has been made before con_select is invoked.  
-  
-Con_select does not know about the specific list of operations for  
-which completion is awaited.  Op_select and the other selection  
-routines call con_select repeatedly until the termination criteria are  
-satisfied.   
-  
-@index[complete_operation]
-Many simple applications use @f[complete_operation] rather  
-than the more complex selection operations to await completion of  
-asynchronous activities.  This routine merely calls con_select  
-repeatedly until the desired operation completes.  NOTE: even though  
-the user is waiting for activity on a particular operation, all  
-connections and all operations progress.  This tends to make it easier  
-for the programmer to avoid deadlocks, and it means that the order in  
-which complete_operation requests are issued is frequently  
-unimportant.  
-  
-@subsection(Connection Error Handling)  
-  
-@index[Error handling]
-For reasons beyond the control of GDB, connections may fail at any  
-time, and GDB must be prepared for this.  
-In general, all queued operations on the connection are cancelled.  
-Note that the application must still sever the connection, to indicate  
-that it is no longer using its pointers to the connection descriptor.  
-  
-GDB operations are responsible for implementing their own error  
-recovery.  
-None of the existing operations do anything elaborate, and many of  
-them cannot be cancelled at all.  It would be very difficult to  
-provide on the fly cancellation of complex operations like database  
-queries, given the asynchronous, full duplex nature of their  
-operation.  
-Right now, the only way to prematurely terminate such an operation is  
-to sever the corresponding connection and restart it.   
-This is always safe, if not convenient.  
-  
-@section(Server/Client Management)  
-  
-@index[Server/client management]
-GDB supports two general styles of communicating programs:  
-peer-to-peer, and server client.    
-Within the framework of the server/client model, GDB supports both  
-forking and non-forking servers.  The interfaces to the two server  
-types are identical, so a given client need not be aware of the style  
-of its server.  
-  
-@subsection(Non-forking servers)  
-  
-@index[Non-forking servers]
-@index[Servers, non-forking]
-GDB's asynchronous communication primitives support the creation of  
-non-forking servers, in which multiple clients are serviced by a  
-single Unix server process.  The maximum number of clients  
-which can be served by a single non-forking server process is  
-GDB_MAX_CONNECTIONS-1  (one connection is used for the "listening  
-connection", described below.)   In addition to  
-@f[start_sending_object] and @f[start_receiving_object] discussed  
-above, @f[start_accepting_client] provides a service for  
-@i[asynchronously] acquiring connections from new clients.  
-Start_accepting_client connection is an asynchronous GDB operation,  
-which may be queued @i[only] on special connections created with the  
-@f[create_listening_connection] primitive.  
-Create_listening_connection allocates a connection descriptor, creates  
-a listening Berkeley Unix Internet Stream socket, and binds a supplied  
-port address to it.  Only the inbound half connection of the  
-connection descriptor is significant.  
-  
-The structure of start_accepting_client is subtle, and it  
-serves as a good example of some of the complex ways in which GDB  
-operations can be created. At the time it is issued @i[two] operations  
-are queued on the listening connection. The first one merely does the  
-accept of a new connection, but without filling in any of the  
-connection data structures.  The second one is the one which uses the  
-operation descriptor passed by the caller.  Its init routine is  
-g_iacc, which therefore runs @i[after] the connection has been  
-acquired from the kernel.  This routine proceeds to fill in the new  
-connection descriptor so that communication may be done on the new  
-stream using GDB's services.  It also calls g_ver_iprotocol to insure  
-that both sides are running compatible versions of GDB.  
-  
-At this point, the new connection exists, but we still have to acquire  
-the client's parameters.  This too must be done asynchronously.  On  
-the new connection, a @f[start_receiving_object] is queued, and then  
-the @f[start_accepting_client] re-queues itself onto the data  
-connection.  Success of the start_accepting_client now depends on  
-completion of activity on the newly created data connection, not the  
-listening connection.  When the start_receiving_object for the client  
-data finally completes, the original start_accepting_client operation,  
-now requeued behind it, takes control again, this time in the routine  
-g_i2acc.  This merely checks to insure that the receive completed  
-successfully.  It's final status, returned to the caller as OP_STATUS,  
-is the same as that of the receive.  The net result of all this is a  
-newly allocated connection for which the accept and the acquisition of  
-the initial parameters were all done without blocking.    
-  
-At this point a tentative connection exists, but the server still has  
-three options in dealing with the new client.  These are (1) accept  
-the new client (2) refuse the client or (3) bounce the client to  
-another server.  To indicate the disposition, the server application  
-must issue the @f[start_replying_to_client] asynchronous operation,  
-indicating either @f[GDB_ACCEPTED, GDB_REFUSED,] or @f[GDB_FORWARDED].  
-@f[start_replying_to_client] creates a tuple containing the response  
-parameters to be sent to the client.  It then queues a  
-@f[start_sending_object] for that tuple on the client connection, and  
-queues itself behind that.  By the time @f[start_replying_to_client]  
-receives control again, the send of the tuple has completed.  The  
-tuple and other dynamically allocated data is freed, and the return  
-code passed back to the application.  
-  
-@subsection(Forking Servers)  
-  
-@index[Forking servers]
-@index[Servers, forking]
-GDB provides a @f[create_forking_server] routine which does most of  
-the bookkeeping required for a single server program to support an  
-arbitrary number of clients, forking once each time a new client  
-connects.  The number of simultaneous clients supported is limited  
-only by the number of processes Unix allows the server to create.  
-A GDB forking server has a single parent process, which hangs forever  
-in the @f[create_forking_server] routine, and one child for each  
-active client.  @f[create_forking_server] returns in each child the  
-connection descriptor for the corresponding client.  The usual GDB  
-communication services may then be used to communicate with the  
-client.  The supplied @f[dbserv.qc] database server is an example of a  
-forking server.  
-  
-Internally, create_forking_server begins in the parent by setting up  
-@f[gdb_reaper] as the handler for @f[SIGCHLD].  GDB thus reaps dying  
-children automatically for the application.  
-  
-In the parent, @f[create_forking_server] issues an ordinary  
-@f[create_listening_connection] to establish its own server address.  
-It then loops forever using @f[start_accepting_client] to acquire  
-sockets for new clients.    
-The application may supply a validation routine which is used to  
-determine whether a given client is to be accepted by the server.  If  
-the validation routine returns FALSE, then the  
-@f[start_replying_to_client] is used to refuse the connection.  
-Otherwise, the server forks the and the child issues a  
-@f[start_replying_to_client] to accept the connection.  In the  
-parent, the client connection is severed (to prevent file and  
-connection descriptor leakage) and the listening operation is reset  
-so that it may be used again.  @f[create_forking_server] thus  
-hides the complexity of dynamically acquiring connections, forking,  
-replying to clients, and reaping 'dead' children.  
-  
-The @f[gdb_debug] routine may be used to set a flag called  
-@f[GDB_NOFORK]. When this flag is set, @f[create_forking_server]  
-semantics are changed so that no fork is done when the first client  
-connects.  Instead, the single client is served directly by the  
-parent.  This flag is useful when using debuggers like dbx, which are  
-incapable of debugging forking programs.  
-  
-@section(Peer-to-peer Communication)  
-  
-@index[Peer-to-peer communication]
-@f[start_peer_connection] is used by programs wishing to do  
-symmetrical communication, in which neither is the server or the  
-client.  
-The current implementation tries first to connect to the other side,  
-and if that fails, it hangs in an accept.  There is a race condition  
-in which the programs may hang if both are started at the same time;  
-each tries a connect, which fails, and then each side hangs in an  
-accept.  The only solutions I know to this problem involve either (1)  
-unconditionally creating multiple connections between the two sides,  
-or (2) running randomized delay loops to re-try the connects  
-periodically.  Even option (2) will sometimes result in multiple  
-connections.  Either of these implementations is a possibility for the  
-future.  In the meantime, @f[start_peer_connection] merely fills in a  
-connection descriptor, and does connects and accepts as described  
-above.  
-A check is also made to insure that both partners are running  
-compatible versions of GDB (see g_ver_iprotocol and g_ver_oprotocol.)  
-  
-@section(Database Management)  
-  
-@index[Database management]
-GDB's database services are cleanly layered on top of the GDB 
-facilities described above.  The supplied @f[dbserv.qc] is a forking 
-server implementing a fairly complete set of database access protocols 
-for remote clients.  Client functions are provided which encapsulate 
-most of the low level GDB transmission services used for accessing the 
-server.  
-
-Database clients use operations like @f[start_db_query] and 
-@f[perform_db_operation] to manipulate the database.  
-These functions make extensive use of GDB's 
-asynchronous communication capabilities to maximize the overlap 
-between server and client processing, and to achieve pipelining of 
-data transfers for retrievals returning large quantities of data. 
-Application programmers are given asynchronous versions of most 
-database functions, allowing them to overlap their own execution with 
-GDB's access to the database.  A single application may have 
-simultaneous connections to multiple databases at multiple sites, and 
-may have parallel operations in progress to the several databases 
-simultaneously.  The current implementation allows a single client to 
-have multiple connections to a single database, with (simulated) 
-parallel activity. 
-@subsection(Database Client Operations) 
-@f[start_accessing_database] returns a pointer of type DATABASE to a 
-dynamically allocated structure used as a handle for subsequent access 
-to that database.  Stored within the structure is a pointer of type 
-CONNECTION, which is used for data transmission to and from the 
-server.  In reviewing the code I am embarrassed to note that the 
-@f[terminate_db] function described in the library reference manual 
-was never implemented.  It's function should be to sever the 
-corresponding connection and de-allocate the database descriptor.  In 
-fact, the client may safely terminate or sever the connection at 
-anytime if desired.  The server will detect the loss of the connection 
-and do the appropriate cleanup. 
-The application uses @f[start_performing_db_operation] and 
-@f[start_db_query] and their synchronous equivalents to perform 
-operations against the database.  @f[start_performing_db_operation] is 
-suitable for any Ingres QUEL operation which is expressible as a 
-single string, and which returns only an integer return code.  This is 
-in fact true of almost all QUEL statements except for retrieve, which 
-returns a relation as well as a return code.  @f[start_db_query] is 
-used for retrieval. 
-Both of these database access operations are asynchronous and full 
-duplex.  This means that an application can stream multiple requests 
-to the server, mixing regular operations in with retrievals.  The requests are transmitted 
-to the server as fast as possible, and the responses are received 
-asynchronously, but in order, as they become available. 
-
-@f[start_performing_db_operation] takes the string containing the QUEL 
-statement, converts it to the GDB type STRING_T, and queues an 
-ordinary @f[start_sending_object] for the string on the outbound half 
-connection.  It then queues a @f[start_receiving_object] of an 
-INTEGER_T on the inbound connection to receive the corresponding 
-return code, and queues itself behind that on the @i[inbound] 
-half connection.  By the time this operation takes control again, 
-the return code has been received, and cleanup can be done.  Note that 
-all phases of this activity are fully asynchronous.  In particular, 
-the outbound and inbound activities are completely independent as seen 
-at the client.  Of course, the server does not generate the return 
-code until after it has inspected the request, but the client side is 
-fully asynchronous.  If another request is issued by the application, 
-then the outbound 
-data is queued for transmission immediately, regardless of how far the 
-first operation has progressed, and the operations to receive the 
-return code are queued behind those from the first request. 
-For example, applications commonly queue in immediate succession the 
-operations to begin a transaction, do several updates, and commit 
-the transaction, waiting for completion only on the commit.  These 
-activities proceed much more rapidly than they would if each piece 
-were implemented synchronously. 
-@f[start_db_query] is similar in spirit, but it must also handle the 
-receipt of the retrieved relation. 
-In addition to sending the query string itself, the client sends a 
-copy of the tuple descriptor for the relation to be created.  This 
-allows the server to properly format tuples for transmission back to 
-the client, and it also provides type information for each field. 
-As above, a receive operation is queued for a return code, and then 
-the query operation itself is queued on the inbound half connection. 
-It receives control in function g_idbq once the return code has been 
-received.   If the return code indicates failure, then the 
-operation is complete.  If success is indicated, then the resulting 
-(possibly null) relation must be received from the server. 
-There is no way to tell at this point how many tuples must be
-received.  The server therefore prefaces each tuple transmission with
-a YES/NO flag, indicating whether another tuple is to follow.  The
-client repeatedly receives these flags, and each time a YES is
-received, it prepares to receive another TUPLE.  These tuples are then
-inserted into the application's relation.  The @f[g_cdbq] routine, which gets
-control each time a flag or tuple is received,  runs in the
-context of the OPERATION supplied by the application.  Each time it
-receives control, it preempts itself by issuing
-@f[preempt_and_start_receiving_object], effectively sticking a receive
-operation ahead of itself on the inbound half connection.  This
-continues until all of the flags and tuple data have been received.
-Note that @f[start_db_query] and the corresponding server could have 
-been written to move the entire relation as a single GDB object. 
-Though the code for this is much simpler, it means that the entire 
-relation must be prepared at the server before any transmission can 
-begin.  The current implementation provides pipelining;  each tuple is 
-sent on its way as soon as it is retrieved from Ingres.  Transmission 
-time tends to be hidden by the overhead of the Ingres retrieval loop. 
-@subsection(The dbserv.qc Database Server) 
-@index[dbserv]
-As noted above, the supplied Ingres server is an ordinary GDB forking 
-server whose purpose is to receive database requests from clients and 
-pass them on to Ingres. 
-Most of its operation is straightforward, with transmission of query 
-results being a notable exception. 
-When dbserv receives a query, it first parses the query string to 
-determine which tuple fields will be assigned by the retrieval. 
-The array named @f[offs] in the routine @f[do_query] is 
-filled in with the offset that each retrieved field occupies in the 
-tuple. 
-A query buffer is prepared containing the text of the query in the 
-form required by Ingres.  The Ingres type indicators (e.g. %i4 for 
-integer) are placed into the queries in place of the GDB field name 
-indicators.  
-Text fields are handled specially, because their lengths cannot be 
-determined until after retrieval.  do_query has a large local array of 
-character strings, into which the actual Ingres retrieval is done. 
-The routine named @f[fix_strings] is then used to copy the resulting 
-text into GDB STRING_T variables, which are assigned to the tuple 
-fields.  Copies are needed because the large text buffers may be 
-re-used for subsequent retrieves before the earlier tuples have been 
-transmitted.  
-The main retrieval loop in @f[do_query] repeatedly retrieves 
-information from Ingres into a dummy tuple.  This is promptly copied 
-to buffer it for transmission, and @f[fix_strings] is called, as noted 
-above. 
-do_query may have several transmissions outstanding at once, the maximum 
-being determined by the constant @f[OVERLAP].  The @f[pending] 
-structure array, which contains the state of each outstanding 
-transmission is used circularly.  This has the effect of insuring that 
-that the server never hangs in a @f[complete_operation] unless more 
-than @f[OVERLAP] transmissions are outstanding at a time.  At the time 
-of this writing, @f[OVERLAP] is defined as 10.  For each tuple, the 
-server sends the YES/NO flag described above, followed by the data.   
-Note that the data is sent as type TUPLE_DATA_T, rather than TUPLE_T, 
-to eliminate redundant transmissions of the tuple descriptor. 
-  
-@appendix(Functions and Macros for Manipulating Structured Data)  
-  
-Here is a partial list of the GDB functions and macros which may be  
-used to manipulate structured data.  This list is intended as a quick  
-reference guide.  All user callable GDB routines are documented in the  
-Library Reference Manual.  
-  
-@begin(description)  
-@f[descriptor_from_tuple]@\returns the tuple descriptor of the supplied tuple.  
-@index(descriptor_from_tuple)  
-  
-@f[descriptor_from_relation]@\returns the tuple descriptor of the supplied  
-@index(descriptor_from_relation)  
-relation.  
-  
-@f[create_tuple_descriptor]@\allocates a tuple descriptor.  
-@index(create_tuple_descriptor)  
-  
-@f[delete_tuple_descriptor]@\destroys a tuple descriptor, deallocating the  
-@index(delete_tuple_descriptor)  
-memory which had been used to hold it.  
-  
-@f[create_tuple]@\allocates a tuple.  
-@index(create_tuple)  
-  
-@f[null_tuple_strings]@\If a tuple contains fields of type STRING_T, then  
-@index(null_tuple_strings)  
-the memory for these is allocated separately from that used for other  
-fields in the tuple.  This routine releases the memory used for all  
-string fields in the tuple.  It should usually be called just before  
-invoking @f[delete_tuple].  
-  
-@f[delete_tuple]@\destroys a tuple, deallocating the  
-@index(delete_tuple)  
-memory which had been used to hold it.    
-  
-@f[string_alloc]@\allocates space for a STRING, filling in the pointer and  
-@index(string_alloc)  
-length fields of the string descriptor.  
-  
-@f[string_free]@\returns the memory used for a STRING.  
-@index(string_free)  
-  
-@f[db_alloc]@\Allocate memory using GDB's memory allocator.  In most   
-@index(db_alloc)  
-implementations this just calls Unix @f[malloc], but GDB's memory allocators  
-@index(malloc)  
-can be replaced by users running in unusual environments.  
-  
-@f[db_free]@\Return memory allocated by db_alloc.  
-@index(db_free)  
-  
-@f[STRING_DATA]@\Given an argument of type STRING, returns a @f[(char *)]  
-@index(STRING_DATA)  
-pointer to the string data.  This is a macro which may appear as the  
-target of an assignment statement;  you can construct your own STRING  
-by setting the STRING_DATA and MAX_STRING_SIZE.  
-  
-@f[MAX_STRING_SIZE]@\Given an argument of type STRING, returns an integer equal 
-
-@index(MAX_STRING_SIZE)  
-to the size of the allocated string data.  If the STRING is used to   
-hold a null terminated C character string, then @f[strlen] of that string  
-@index(strlen)  
-must be @f[<= MAX_STRING_SIZE].  
-  
-@f[ADD_TUPLE_TO_RELATION]@\a macro which inserts a new tuple after all the  
-@index(ADD_TUPLE_TO_RELATION)  
-others in a relation.  The tuple must share the same descriptor as the  
-relation itself.  
-  
-@f[ADD_TUPLE_AFTER_TUPLE]@\inserts a tuple into the middle of a relation.  
-@index(ADD_TUPLE_AFTER_TUPLE)  
-  
-@f[REMOVE_TUPLE_FROM_RELATION]@\the specified tuple is removed from the  
-@index(REMOVE_TUPLE_FROM_RELATION)  
-relation, but not de-allocated.  It may subsequently be inserted in  
-another relation if desired.  Each tuple may be in at most one  
-relation at a time.  
-  
-@f[FIRST_TUPLE_IN_RELATION]@\Finds the first tuple in a relation.  Returns  
-@index(FIRST_TUPLE_IN_RELATION)  
-NULL if the relation is empty.  
-
-@f[NEXT_TUPLE_IN_RELATION]@\Given a relation and a tuple which is presumed
-@index(NEXT_TUPLE_IN_RELATION)
-to be in that relation, return the tuple which follows the one
-supplied.  NULL is returned if the tuple supplied is the last one in
-the relation.
-
-@f[PREV_TUPLE_IN_RELATION]@\Given a relation and a tuple which is presumed
-@index(PREV_TUPLE_IN_RELATION)
-to be in that relation, return the tuple which preceeds the one
-supplied.  NULL is returned if the tuple supplied is the first one in
-the relation.
-
-@f[DESCRIPTOR_FROM_TUPLE]@\Given a tuple, get back its tuple descriptor.
-@index(DESCRIPTOR_FROM_TUPLE)
-
-@f[DESCRIPTOR_FROM_RELATION]@\Given a relation, get back its tuple descriptor.
-@index(DESCRIPTOR_FROM_RELATION)
-
-@f[FIELD_FROM_TUPLE]@\Given a tuple and a field index, return a pointer to the 
-@index(FIELD_FROM_TUPLE)
-field.  The results of this macro must be cast properly by the caller.
-
-@f[FIELD_TYPE_IN_TUPLE]@\Given a tuple descriptor (@i[not] a tuple) and
-@index(FIELD_TYPE_IN_TUPLE)
-the index (@i[not] the name) of a field, return the type code of the
-field.  Symbolic names for type codes, such as @f[STRING_T] and
-@Index(STRING_T)
-@f(INTEGER_T) are defined in gdb.h;  they may be stored in
-@Index(INTEGER_T)
-variables of type @f[FIELD_TYPE].
-@index(FIELD_TYPE)
-
-@f[field_index]@\Given a tuple descriptor and the name of a field, return the
-@index(field_index)
-index of that field.
-
-@end(description)
-
-The following routines are often useful for debugging GDB
-applications.  @b[Important note: each of these routines takes two
-arguments, the first is an i.d. string, the second is the object to be printed!]
-
-@begin(description)
-@f[print_tuple]@\Prints a tuple on the gdb_log file (which defaults to
-@index(print_tuple)
-stderr.)  All fields are correctly labeled and formatted according to
-their type.
-
-@f[print_relation]@\Prints an entire relation, with all of its tuples, on gdb_log.
-@index(print_relation)
-@end(description)
-@appendix(Sample Non-Forking Server)
-@label(nonforkingserver)
-@modify(example,Size 8)
-@begin(example)
-/************************************************************************/
-/*     
-/*                       tsr (test server)
-/*                       -----------------
-/*     
-/*     Author: Noah Mendelsohn (IBM T.J. Watson Research and MIT Project
-/*                              Athena)
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-/*     
-/*     PURPOSE
-/*     -------
-/*     
-/*     A GDB server program demonstrating techniques for asynchronously
-/*     communicating with an arbitrary number of clients from a single
-/*     Unix server process.  This server accepts GDB connections from
-/*     clients as requests come in (up to the arbitrary maximum
-/*     MAXCLIENTS.)  On each connection, it receives a stream of integers,
-/*     which it interprets as ASCII characters.  The characters are
-/*     converted to uppercase, and then sent back to the client from
-/*     which they came.  
-/*     
-/*     All of this is done completely asynchronously.  No client is 
-/*     locked out while characters are being echoed to another, and
-/*     new connections are accepted at any time.
-/*     
-/*     NOTES
-/*     -----
-/*     
-/*     1) The complete state of each client is kept in the array
-/*        named client.  The client[i].state variable indicates whether
-/*        client i is active, and if so, the client[i].action variable
-/*        indicates what kind of asynchronous activity the client is 
-/*        engaged in.  Note that these are local conventions, having
-/*        nothing to do with GDB or its interfaces.  
-/*     
-/*     2) Communication to each client is done over its connection,
-/*        named client[i].con.
-/*     
-/*     3) There is at most one asynchronous activity pending to 
-/*        each client at any given time, and its state is tracked
-/*        in the variable named client[i].pending_op.  The operation
-/*        may be a send, a receive, or an accept, depending on 
-/*        the contents of client[i].action.  These operations are
-/*        allocated when the server starts up, and then re-used
-/*        repeatedly.  They are the GDB analog of a lightweight process,
-/*        which is activated when queued on a connection.
-/*     
-/*     4) A special form of connection and a special listening operation
-/*        are used for asynchronously listening for new connection
-/*        requests.  These are 'listencon' and 'listenop' respectively.
-/*     
-/*     5) GDB includes a special form of select which waits for 
-/*        completion of operations as well as for activity on user
-/*        specified file descriptors.  The list of operations to be
-/*        monitored is stored in the variable
-/*        named op_list.  The call to op_select_any hangs until one
-/*        or more of these operations complete, then terminates.
-/*     
-/*     6) The main server loop acts on any new connection requests,
-/*        processes any newly completed activity on the active
-/*        clients, then drops into op_select_any to allow asynchronous
-/*        activities to progress.  
-/*     
-/*     
-/************************************************************************/
-@end(example)
-@begin(example)
-#include <stdio.h>
-#include "gdb.h"
-
-/************************************************************************/
-/*     
-/*                          DECLARATIONS
-/*     
-/************************************************************************/
-
-#define MAXCLIENTS 10
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      State of each possible client
-       /*      
-       /*----------------------------------------------------------*/
-
-struct client {
-       int state;                              /* state of this client */
-                                               /* descriptor */
-#define CL_DEAD 1                              /* client not started */
-#define CL_STARTING 2                          /* accepted, reply ongoing */
-#define CL_UP 3                                        /* ready to go */
-       int action;                             /* what are we doing now */
-#define CL_RECEIVE 4                           /* waiting for a packet */
-#define CL_SEND    5                           /* sending a packet */
-#define CL_ACCEPT  6                           /* sending a reply */
-       CONNECTION con;                         /* connection to this */
-                                               /* client, if any */
-       OPERATION pending_op;                   /* pending operation */
-                                               /* on this connection, */
-                                               /* if any */
-       int data;                               /* the character to echo */
-                                               /* goes here, expressed as */
-                                               /* an int  */
-};
-
-struct client client[MAXCLIENTS];
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Connections and operations for listening for
-       /*      new clients.
-       /*      
-       /*----------------------------------------------------------*/
-
-CONNECTION listencon;                          /* listen on this */
-                                               /* connection */
-OPERATION  listenop;                           /* this operation is used */
-                                               /* repeatedly for listening */
-                                               /* for new clients */
-
-int    nextcl = 0;                             /* index of the next client */
-                                               /* we'll accept */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Miscellaneous variables used in acquiring connections.
-       /*      These are ignored in a simple server like this;  a 
-       /*      more sophisticated server might want to validate the
-       /*      names of its clients before accepting connections.
-       /*      
-       /*----------------------------------------------------------*/
-
-TUPLE client_tuple;                            /* client request goes */
-                                               /* here */
-char otherside[100];
-int othersize;
-@end(example)
-@begin(example)
-/************************************************************************/
-/*     
-/*                             MAIN
-/*     
-/************************************************************************/
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*                     LOCAL VARIABLES
-       /*      
-       /*----------------------------------------------------------*/
-
-       register int i;                         /* loop index */
-       LIST_OF_OPERATIONS op_list;             /* for op_select_any */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Check parameters
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (argc != 2) {
-               fprintf(stderr,"Correct form is %s <servicename>\n",
-                       argv[0]);
-               exit(4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      Initialize
-       /*      
-       /*----------------------------------------------------------*/
-
-       gdb_init();                             /* set up gdb */
-       init_clients();                         /* null the client states */
-       do_listen(argv[1]);                     /* start the listening */
-                                               /* connection and queue */
-                                               /* a listening operation */
-       make_oplist(&op_list);                  /* create wait list */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*           Loop forever taking care of business.
-       /*      
-       /*      1) If any new connection requests have come in,
-       /*         accept them.
-       /*      
-       /*      2) For each client on which some activity is newly
-       /*         completed, take care of it.
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (TRUE) {
-               if (OP_DONE(listenop))
-                       new_connection();
-               for (i=0; i<MAXCLIENTS; i++) {
-                       if (OP_DONE(client[i].pending_op))
-                               do_client(i);
-               }
-               op_select_any(op_list, 0, NULL, NULL, NULL, NULL);
-       }
-}
-@end(example)
-@begin(example)
-/************************************************************************/
-/*     
-/*                             do_client
-/*     
-/*     An operation has completed on the specified client.
-/*     
-/************************************************************************/
-
-int
-do_client(id)
-int id;
-{
-       register struct client *cp = &(client[id]);
-
-       /*
-        * If there has been an error, shutdown the client.
-        */
-       if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
-               sever_connection(cp->con);
-               reset_operation(cp->pending_op);
-               cp->state = CL_DEAD;
-               cp->action = 0;
-               return;
-       }
-       /*
-        * The operation completed successfully.  Figure out what it was
-        * and do the right thing.
-        */
-       switch (cp->action) {
-             case CL_ACCEPT:
-             case CL_SEND:
-               start_receiving_object(cp->pending_op, cp->con, 
-                                      (char *)&cp->data,
-                                      INTEGER_T);
-               cp->action = CL_RECEIVE;
-               break;
-             case CL_RECEIVE:
-               if (cp->data >= 'a' && cp->data <= 'z')
-                       cp->data += 'A'-'a';    /* upcase the response */
-               start_sending_object(cp->pending_op, cp->con, 
-                                      (char *)&cp->data,
-                                      INTEGER_T);
-               cp->action = CL_SEND;
-       }
-}
-@newpage
-/************************************************************************/
-/*     
-/*                       init_clients
-/*     
-/************************************************************************/
-
-int
-init_clients()
-{
-       register struct client *c;
-
-       for (c=client; c<client+MAXCLIENTS; c++){
-               c->state = CL_DEAD;
-               c->action = 0;
-               c->con = NULL;
-               c->pending_op = create_operation();
-               reset_operation(c->pending_op);         
-       }
-}
-
-
-@end(example)
-@begin(example)
-/************************************************************************/
-/*     
-/*                     make_oplist
-/*     
-/************************************************************************/
-
-int
-make_oplist(oplp)
-LIST_OF_OPERATIONS *oplp;
-{
-       /*
-        * ugh! we've got to fix create_list_of_operations to be
-        * more flexible!!
-        */
-
-       *oplp = create_list_of_operations(MAXCLIENTS+1, listenop,
-                                         client[0].pending_op,
-                                         client[1].pending_op,
-                                         client[2].pending_op,
-                                         client[3].pending_op,
-                                         client[4].pending_op,
-                                         client[5].pending_op,
-                                         client[6].pending_op,
-                                         client[7].pending_op,
-                                         client[8].pending_op,
-                                         client[9].pending_op);
-}
-@end(example)
-@begin(example)
-/************************************************************************/
-/*     
-/*                             do_listen
-/*     
-/*     Do the one time setup for listening for clients, and
-/*     also start a listen for an actual client.
-/*     
-/************************************************************************/
-
-int
-do_listen(service)
-char *service;
-{
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Make a listening connection
-       /*      
-       /*----------------------------------------------------------*/
-
-       fprintf(stderr, "Server creating listening connection\n");
-       listencon = create_listening_connection(service);
-
-       if (listencon == NULL) {
-               fprintf(stderr,"tsr: could not create listening connection\n");
-               exit (4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      On that connection, put up an operation to listen
-       /*      for our first client.
-       /*      
-       /*----------------------------------------------------------*/
-
-       listenop = create_operation();
-
-       othersize = sizeof(otherside);
-
-       start_accepting_client(listencon, listenop, &(client[nextcl].con),
-                              (char *)otherside,
-                              &othersize, &client_tuple);
-
-}
-@end(example)
-@begin(example)
-/************************************************************************/
-/*     
-/*                     new_connection
-/*     
-/*     We have just gotten a connection for client nextcl.  
-/*     
-/************************************************************************/
-
-int
-new_connection()
-{
-       register struct client *cp = &client[nextcl];
-       /*
-        * Make sure there's been no error
-        */
-       if(OP_STATUS(listenop) != OP_COMPLETE ||
-          cp->con == NULL) {
-               fprintf(stderr,"Error on listening operation\n");
-               exit(8);
-       }
-       /*
-        * Set up the new connection and reply to the client
-        */
-       cp->state = CL_STARTING;
-       cp->action = CL_ACCEPT;
-       start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
-                                "", "");
-
-       /*
-        * Find a new free connection descriptor.  Blow up if we've used the
-        * last one
-        */
-       for (nextcl=0; nextcl<MAXCLIENTS; nextcl++)
-               if (client[nextcl].state == CL_DEAD)
-                       break;
-
-       if (nextcl == MAXCLIENTS) {
-               fprintf(stderr,"Too many clients, giving up\n");
-               exit(8);
-       }
-       /*
-        * Start listening again
-        */
-       reset_operation(listenop);
-       othersize = sizeof(otherside);
-
-       start_accepting_client(listencon, listenop, &(client[nextcl].con),
-                              (char *)otherside,
-                              &othersize, &client_tuple);
-
-
-}
-@end(example)
-
-@begin(comment)
-
-@Chapter(Hints and Tricks)
-select variants
-
-redefining GDB_GIVEUP
-
-replacing storage allocators
-
-print_relation, tuple, etc.
-
-tuples as analogs for structures.
-
-Using procedures to keep tuples up to date.
-
-Creating your own types
-
-Debug switch and the log
-
-Output from dbserv
-
-Reference counting of tuple descriptors.
-
-@Chapter(Bugs)
-Macros which require no ; after invocation
-
-/etc/services entries for database server
-
-Only one database server per site.
-@Chapter(How GDB Works)
-
-@end(comment)
diff --git a/gdb/gdb_version b/gdb/gdb_version
deleted file mode 100644 (file)
index c2d3992..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/************************************************************************/
-/*     
-/*             This file accompanies GDB version 0.4
-/*     
-/*     Versions designated 0.x are prototype releases supported
-/*     informally by the author.
-/*     
-/*     Author: Noah Mendelsohn  
-/*             IBM T.J. Watson Research Center -and- MIT Project Athena
-/*
-/*     Copyright (C) 1987 Massachusetts Institute of Technology
-/*     
-/************************************************************************/
-
diff --git a/gdb/library.mss b/gdb/library.mss
deleted file mode 100644 (file)
index 6fa1bd3..0000000
+++ /dev/null
@@ -1,1960 +0,0 @@
-@device(PostScript)
-@make(Manual)
-@style(FontFamily "Helvetica", Size 11)
-@style(hyphenation on)
-@style(indent 0)
-@style(leftmargin +4cm)
-@style(footnotes "")
-@modify(example,Size 10, below 1cm, above 1cm, leftmargin +3, rightmargin +0)
-@define(F, FaceCode F, Size 11, TabExport)
-@define(FunctionSection, leftmargin +1cm, rightmargin +1cm, size 10)
-@define(Function, leftmargin -.5cm, nofill, indent 0, break,  group,
-       above .6cm, below .4cm, blanklines kept, spread .7 line)
-@modify(HD1, Below .75cm, Above 1cm, indent -1cm)
-@modify(HD1A, Below .75cm, Above 1cm)
-@modify(HD2, Below .6cm, Above 1cm, indent -1cm)
-@modify(HD3, Below .6cm, Above 1cm)
-@modify(itemize, Below .5cm, Above .6cm)
-@modify(example, Below .5cm, Above .6cm)
-@modify(float, Below .5cm, Above .6cm)
-@begin(titlepage)
-@begin(titlebox)
-@majorheading(GDB C Library Reference Manual)
-@heading(Noah Mendelsohn)
-
-@end(titlebox)
-Document Version: 0.4 (DRAFT)
-For use with GDB Release: 0.4
-This draft printed on: @value(Date)
-@copyrightnotice(MIT Project Athena)
-@end(titlepage)
-@Counter(ProgramNumber, Numbered <@1>, Referenced <@1>)
-@set(ProgramNumber=1)
-@PrefaceSection(Preface)
-
-GDB is a set of C library routines and related utilities which
-facilitate construction of network services.  This preliminary version
-of the Library Reference Manual is based on specifications which were
-written before the code.  In some cases, it refers to design decisions
-which had yet to be made at the time of writing, or uses terminology
-which is slightly inconsistent with the other GDB documentation.  The
-tone of some of the descriptions is informal, reflecting debates over
-design philosophy which occured during development of GDB.
-Nevertheless, almost all of the services described herein are
-currently operational in Release 0.1 of GDB, and they conform very
-closely to their written specifications.  This guide is intended
-primarily for reference.  For a general introduction to programming
-with GDB, read the document titled "A Guide to Using GDB."  Please
-report any discrepancies you discover in either document to the
-author.  A more carefully edited version of this manual will accompany
-GDB Release 1.
-
-@PageHeading(Even, Right "@c[GDB Library Reference Manual]",
-                  Left "@c[@value(Page)]")
-@PageHeading(Odd, Right "@c[@value(Page)]",
-                  Left "@c[@Title(Chapter)]")
-                
-@Chapter(Introduction)
-@Index[Introduction]
-
-This document is the program interface description for a collection of
-Unix@+[TM]@foot(@+[TM]Unix is a trademark of AT&T Bell Laboratories)
-library routines which provide transparent distributed support for
-network servers, and for relational databases in particular.  The
-several libraries work together to implement a relational database
-which may be conveniently accessed from anywhere in a "Berkeley" Unix
-network, but the lower level libraries may themselves be useful for
-building other sorts of network services, or for
-transmitting other kinds of structured data.  The database access
-and transmission services support communication between incompatible
-machine architectures; data conversions are done as necessary by the
-library routines.
-
-This document contains a separate section for each of the libraries.
-Interdependencies are noted in the sections.
-
-@chapter(Using the Libraries)
-
-The sections below outline the library services provided by GDB.  
-Programs using GDB
-to access relational databases will use, directly or indirectly, the
-services of all of the GDB layers.  Programs using GDB for local management
-of structured data or as a means of writing servers, clients, or other
-communicating programs may use only some of the layers.    In any case,
-Every C main program
-that uses GDB should include the following:
-
-@begin(group)
-@begin(example)
-
-#include <stdio.h>
-#include "gdb.h"
-
-int
-main()
-{
-       gdb_init();
-       /*
-        * Once gdb_init has been called, the services of gdb are
-        * available.  gdb_init may be called only once.
-        */
-}
-@end(example)
-@end(group)
-
-Other source files should @f[#include "gdb.h"], but should @i[not] 
-@index(gdb.h)
-invoke @f[gdb_init].
-@index(gdb_init)
-
-If you are using GDB to access an Ingres database, then there are
-several other things you must do:
-
-@begin(itemize)
-@begin(multiple)
-Make sure RTI Ingres is installed at the server site where the data 
-@index(RTI Ingres)
-@index(Ingres)
-is to be stored.
-@end(multiple)
-
-@begin(multiple)
-Make sure that there is an entry in the file named @f[/etc/services]
-@index(/etc/services)
-at both server and client sites for the service named gdb_db@index(gdb_db).
-The entries at the server and client should be identical.  
-Talk to your system administrator if this is not the case.
-@i[Note: as of this writing, GDB does not check @f[/etc/services] when
-accessing Ingres, but soon it will!]
-@end(multiple)
-
-@begin(multiple)
-Make sure that the @f[dbserv] program supplied with GDB
-@index(dbserv)
-is started at the server site.
-@end(multiple)
-
-@end(itemize)
-
-Gdb produces two kinds of terminal output.  Serious error messages,
-which are always directed to stderr, and other output, which are
-directed to the file indicated by the gdb_log global variable.
-Included in the latter are the results of functions like
-@f[print_relation]@index[print_relation], which are described below.
-Users wishing to redirect @f[gdb_log]@index[gdb_log] may open any
-stream of their choice and put the resulting FILE * variable into
-gdb_log after calling gdb_init.
-
-The remainder of this manual is taken with the definitions of the
-functions provided by GDB.  The functions are organized by general
-category, but all are listed alphabetically in the index.  Each
-section is prefaced by a brief introduction, followed by the function
-definitions themselves.  In all the descriptions below, the
-pseudo-type @f[string]@Index[string] is used for @f[char *] in cases
-where a null terminated string is to be supplied.  This is just a
-documentation convention, the type string is not defined in the
-libraries.  Here is the description of the @f[gdb_init] function, the
-only one which has been introduced so far:
-
-@begin(functionsection)
-@begin(function)
-void
-@f[gdb_init]()
-@index[gdb_init]
-@end(function)
-
-Gdb_init initializes the data structures used by gdb.  Gdb_init must be called
-once and only once prior to use of any other GDB services.  No value is
-returned.
-@end(functionsection)
-
-@chapter(Database Manipulation)
-@Index(Database manipulation)
-
-This library provides most of the services of a shared, network wide,
-relational database.  It is built on the structured object
-manipulation and transmission libraries described in Chapters
-@ref(structdata) and @ref(trans).  A query, for example, returns a
-RELATION in the local process space.
-
-These routines have the following important characteristics:
-
-@begin(itemize)
-Access to databases stored on incompatible machines (e.g. RT/PC to
-Vax) is supported transparently.
-
-Pipelining of requests from client to server is encouraged.  This
-maximizes overlap in processing and minimizes server swapouts between
-repeated requests, thereby improving performance.
-
-Requests proceed asynchronously with client execution, though 
-synchronous interfaces are provided for applications where asynchrony
-is an unnecessary complication.  Asynchronous processing is managed
-by appropriate interaction with the Berkeley 'select' mechanism;
-applications can be created which drive a user's terminal
-or other I/O devices while simultaneously retrieving the results
-of a database query.  One important use of such overlap is to support
-abort operations (e.g. a screen menu selection to abort a long running
-query.)
-
-Multiple databases may be accessed simultaneously.  If desired, these
-may reside at several sites.  Using the asynchronous processing options,
-queries may be executed in parallel on the several databases.  The 
-same facilities may be used to open parallel connections to the same
-database, allowing parallel execution of independent operations.
-@end(itemize)
-
-Unfortunately, the syntax of a few of the actual library calls described
-herein is Ingres dependent.  It is hoped that one day an effective
-cannonical form will be developed, and these routines replaced with a
-suite that might be supported using a variety of database engines.  The
-Ingres dependency is isolated to a couple of routines.
-
-@section(Types Used for Database Manipulation) 
-
-The types @f[RELATION, TUPLE, and FIELD_TYPE] are inherited from the
-structured data management libary (see Chapter @ref(structdata).)  The
-following additional type is also used.
-
-@begin(table)
-@caption(Types used in Database Manipulation)
-@tabset(.75in, 2.5in)
-
-@\DATABASE@INDEX[DATABASE]@\A handle on an accessible database.
-@end(table)
-
-@Section(Routines)
-
-NOTE:  See also the "Communications and Server Management" Section of
-this specification.  This section contains only those functions
-particular to database manipulation.  General facilities for
-starting operations and querying their status are found in the other
-section. 
-
-@begin(functionsection)
-@begin(function)
-DBSTATUS
-@f[access_db](db_ident, &db_handle);
-@index[access_db]
-DATABASE db_handle;
-string db_ident;
-@end(function)
-
-Establishes a database context for future database calls.  A successful
-accessdb call must be executed before any database operations can be done.
-The return code DB_OPEN indicates that the database was successfully accessed.
-A successful call to accessdb returns a local handle which must be
-supplied to subsequent library routines to indicate the database to be
-accessed.  Most implementations support simultaneous access to several
-databases, but that is not required.  The DB_TOO_MANY_ACCESSED error is
-raised when and if implementation defined limits are exceeded.  Each
-database should be closed with a 'terminatedb' call when no longer needed.
-Failure to explicitly terminate databases may waste resources at the
-server, though most implementations will detect improper termination and
-do the necessary reclamation.  
-
-The form of the db_ident string depends on the implementation.  For
-example, in a network with nameservers, a single string such as
-'partsdata' may suffice to identify a database on the network.  When
-name resolution services are not available, a string of the form
-'databasename@@site' may be required.  There is a question of access
-rights and authorization for this operation.  I'm hoping that we can
-eventually build on Kerberos, but there may be problems.  Worst of all,
-we may have to re-invent Ingres' protection mechanism, which would
-involve a very detailed understanding of their operations.  I hope not.
-
-@begin(function)
-int
-@f[start_accessing_db](op, db_ident, &db_handle);
-@index[start_accessing_db]
-OPERATION
-DATABASE db_handle;
-string db_ident;
-@end(function)
-
-Same as accessdb, but the program continues to execute (if possible)
-while the operation is sent to the server and performed.  See
-'complete_operation' and 'op_select.'  All operations and queries are
-processed in fifo order.  The value of db_handle is undefined until the
-operation_status(pending_operation) is OP_COMPLETE and the
-operation_result(pending_operation) is DB_OPEN.
-
-@begin(function)
-DBSTATUS
-@f[terminate_db](&db_handle);
-@index[terminate_db]
-DATABASE db_handle;
-@end(function)
-
-This routine reclaims server and client resources used to access the
-database and severs any connections which may no longer be needed.  Data
-which has been retrieved and stored locally remains available.
-
-@begin(function)
-OPERATION
-@f[start_terminatedb](db_ident);
-@index[start_terminatedb]
-string db_ident;
-@end(function)
-
-Same as terminatedb, but the program continues to execute (if
-possible) while the operation is sent to the server and performed.
-See 'complete_operation' and 'op_select.'  All operations and queries
-are processed in fifo order.
-
-@begin(function)
-OPERATION
-@f[DB_STATUS](db_handle);
-@index[DB_STATUS]
-DATABASE db_handle;
-@end(function)
-
-Returns the status of the specified database.  Values returned are
-DB_OPEN@index[DB_OPEN], indicating that the database is available for use,
-or DB_CLOSED@index[DB_CLOSED], indicating that it is not.
-
-@begin(function)
-int
-@f[perform_db_operation](db_handle,request);
-@index[perform_db_operation]
-DATABASE db_handle;
-string request;
-@end(function)
-
-This routine may be used to perform any database operation which does
-not require structured data as an argument and which only returns a
-return code.  In the case of Ingres, this covers all operations except
-retrieve.  Requests are represented as null terminated strings.  In
-other words, this library routine sends a simple string command to the
-server for execution and returns an integer return code.  Any pending
-asynchronous operations on this database are completed before the
-supplied operation is attempted.
-
-@begin(function)
-int
-@f[db_query](db_handle, relation, query_string)
-@index[db_query]
-DATABASE db_handle;
-RELATION relation;
-string   query_string;
-@end(function)
-
-Executes the query specified by query string,
-appending its result to the supplied relation.
-An integer return code is returned.  OP_SUCCESS is returned for a
-successful query.  The relation is unchanged unless the query
-succeeds.  Note that it is possible to have a successful query (i.e.
-one which is well formed with respect to the database) which returns
-no data;  such a query will return OP_SUCCESS leaving the relation unchanged.
-
-Query_string has the same form as an EQUEL query, except that the
-names of returned fields are enclosed in >* ....*< brackets (we can
-change the brackets to anything that won't conflict with Ingres
-syntax.)  Note that the relation must be 'created' before it may be
-given to query_db.  This is so we know typing information for
-constructing the actual database query.  The caller may use sprintf or
-a similar function to prepare a query string containing variable data.
-The selected fields MUST match the names of fields in the relation.
-If not, a DB_BAD_FIELD_NAME error is raised before the query is
-executed.  Null values are provided for tuple fields not retrieved by
-the query.
-
-The types of the referenced fields in the supplied relation must be
-drawn from a limited set of INTEGER_T, REAL_T, STRING_T and DATE_T types
-(the exact list will be provided in a later version of this
-specification document.)  If not, a DB_BAD_FIELD_TYPE error is raised
-before the query is executed.  The query will be constructed using the
-supplied types.  If Ingres is incapable of doing the appropriate
-conversions upon retrieval, then a DB_CONVERSION_ERROR is returned.
-If the field type in the relation is STRING_T and Ingres succesfully
-converts the retrieved data to character form, then a null is appended
-iff there is room at the end.  If the supplied field is too short,
-data is quietly dropped on the right end.  The string is allocated by
-string_alloc.  The
-string may be free'd with string_free, by the routine
-'null_tuple_strings', or by the delete_relation routine.  Normally,
-space is reclaimed automatically when the corresponding tuple or
-relation is freed.  Fields not assigned by the query are set to null
-values.
-
-As specified, this routine is incapable of retrieving data of
-indeterminate structure, e.g. it cannot achieve the effect of an
-e.all retrieve in Ingres.  This sort of function could be layered
-upon the base support suggested here, by first querying the Ingres
-structure database and then issuing the appropriate second query for
-the fields actually in the relation.  This implementation is presumably
-slow, but I am reluctant to greatly complicate the design at this
-point.  Another approach would be to add a special library routine
-db_query_relation which would create a relation, making assumptions
-about field representations for the fields actually retrieved.  I'm
-inclined to put this off until we see the core of the library up and
-running.  It would (probably) not involve a major restructure.
-
-@begin(function)
-int
-@f[start_performing_db_operation](operation, db_handle,
-@index[start_performing_db_operation]
-request);
-OPERATION operation;
-DATABASE db_handle;
-string request;
-@end(function)
-
-Same as perform_db_operation, but the program continues to execute (if
-possible) while the operation is sent to the server and performed.  See
-'operation_status, operation_result, complete_operation and
-op_select.'  All operations and queries are processed in fifo order.
-Callers must insure that the request string
-remains valid until the operation completes (be careful about using local
-variables.)
-
-
-@begin(function)
-int
-@f[start_db_query](operation, db_handle, relation, 
-@index[start_db_query]
-query_string)
-OPERATION operation;
-DATABASE db_handle;
-RELATION relation;
-string   query_string;
-@end(function)
-
-Same as query_db, but the program continues to execute (if possible)
-while the operation is sent to the server and performed.  See
-'operation_status, operation_result, complete_operation and
-op_select.'  The relation is undefined during the execution of this
-operation.  It may not be referenced or free'd until the operation
-completes.  All operations and queries are processed in fifo order.
-The value of the relation is indeterminate in the case of failure,
-but it is guaranteed to be of legal structure and self-consistent.
-Callers must insure that the query string
-remains valid until the operation completes (be careful about using local
-variables.)
-@end(functionsection)
-
-@chapter(Structured Data Management at a Single Site)
-@Index(Structured data management)
-@label(structdata)
-
-These routines provide a simple, limited facility for managing
-structured data on behalf of a single process.  A basic datum is called
-a field, and it may be of arbitrary type (including user defined types.)
-Named fields may be collected into tuples, and lists of tuples may
-form relations.  These constructs are used to represent the data
-retrieved from a relational database.  A separate library (Chapter
-@ref(trans))
-supports transmission of these data structures through a
-network.  The typing scheme provided is sufficient to drive the
-transformations and re-alignment required when transmitting across
-incompatible machine architectures.  It is NOT intended as a general 
-purpose extension to the C language.
-
-@section(Type Definition and Manipulation)
-
-The information in this section is relavent to those users wishing to
-define their own types.  User defined types are NOT necessary for
-typical database retrieval and update activities.  Users desiring just
-those services need only know the names of built in system types,
-such as @f[INTEGER_T] and @f[STRING_T] which have direct counterparts in an
-Ingres database.  @i[In the likely event that you have no need to
-define your own types, skip ahead now to section @ref(structypes).]
-
-Each datum or field managed by the system must be of some specified
-type.  For each type, the system must have access to certain
-information (e.g. alignment restrictions) and to certain routines
-(initialize, encapsulate for transmission, etc.)  Limited facilities to
-support user defined types are also helpful, since they allow such
-services as transmission across heterogeneous machines to be supported
-for arbitrary user data (this notion is stolen directly from ARGUS.)
-On the other hand, we don't want to tackle the many complicated
-problems inherent in a general solution to the dynamic typing problem.
-Instead, we employ the following simple, ad hoc mechanism, which seems
-to be sufficient for our needs.  
-
-The system supports a set of types identified signed integers (e.g.
-type 1 might be STRING_T, type 2 might be DATE_T, etc.)  Out of this
-name space, the first few starting from 0 are reserved for the system
-defined types, and the rest, up to GDB_MAX_TYPES, are available for
-dynamic assignment of user defined types.  Appropriate pre-processor
-symbols, such as INTEGER_T, are provided in an include file for system
-types.
-
-For each type, certain information must be available to the system at
-execution time.  This information is coded as a two dimensional array,
-each element of which holds either an integer, a pointer to a string,
-or a function pointer.  One index selects the type, the other the
-property.  For example, property number 6 of each type might be a code
-for its alignment requirement (4 for fullword, etc.).  Using the
-example above, entry [2,6] in the type definition array would give the
-alignment rule for a field of type DATE_T.  In certain cases, the
-information to be coded is a pointer to a routine.  For example, a
-NULL value routine is provided for each type which can be used to initialize
-fields of that type.
-
-In order to create a user defined type, it is necessary to code
-functions for each of the necesary properties (e.g. the function which
-computes null values) and then use the "create_type" function to
-register the new type in the type tables.  "create_type" returns the
-integer code assigned to the new type.  WARNING:  create_type is not
-yet implemented.
-
-@subsection(Information Required for Each Type)
-
-The simple mechanism described above is sufficient to encode the
-properties of each type.  The information currently required is:
-
-@begin(itemize)
-LENGTH_PROPERTY: the length of the field 
-
-ALIGNMENT_PROPERTY: an integer code for the alignment rule for the
-type (8 for doubleword, etc., may vary by machine type.)
-
-NULL_PROPERTY: a routine to initialize a null value of the type
-
-CODED_LENGTH_PROPERTY: a routine to calculate the length of the
-field when encoded for transmission.
-
-
-ENCODE_PROPERTY: a routine to encode the field for transmission
-
-DECODE_PROPERTY: a routine to decode tranmitted data into local 
-representation
-
-FORMAT_PROPERTY: a routine to format the field (optional, for debugging)
-
-NAME_PROPERTY: a string name for the type.
-@end(itemize)
-
-For system defined types, this information is provided automatically by
-include files and libraries which initialize the system type definition
-array.  Interface specifications for the various routines will be
-provided in a later version of this specification.  For the moment, 
-the code in source file @f[gdb_stype.c]@Index[gdb_stype.c] provides a 
-useful model. 
-
-@newpage
-@section(C Typedefs Relating to Data Structuring)
-@label(structypes)
-
-The following C types are defined in include files for use with the
-routines listed below.  These should not be confused with types
-declared using the mechanisms above, which the C compiler knows nothing
-about.
-
-@begin(table)
-@caption(Typedefs for Data Structuring)
-@tabset(.75in, 2.5in)
-@\TUPLE_DESCRIPTOR@index[TUPLE_DESCRIPTOR]@\information needed to describe the structure
-@\@\of a given tuple.
-
-@\TUPLE@index[TUPLE]@\a handle on an actual tuple.  This is always
-@\@\a pointer, and it may be manipulated
-@\@\accordingly (e.g. its length may be presumed
-@\@\small, and NULL is used for non-existent
-@\@\TUPLES.)
-
-@\RELATION@index[RELATION]@\a handle on an actual relation.  This is always
-@\@\a pointer, and it may be manipulated
-@\@\accordingly.
-
-@\FIELD_TYPE@index[FIELD_TYPE]@\a type code for a field...generally
-@\@\represented as a signed integer (see above)
-@end(table)
-       
-@section(Routines)
-
-(Note some of these may be implemented as macros.  Where such
-implementation is presumed, the name is put in UPPERCASE.  This
-allusion to Unix convention is meant to suggest that the associated
-operations are extremely fast, and that they are likely to suffer/gain
-from the semantic differences which distinguish macros from C
-functions.  Note also that some of the macros contain define statements
-in C of the form @f[{}], these must be used without semicolon's or
-a syntax error will occur.)
-
-@begin(functionsection)
-@begin(function)
-TUPLE_DESCRIPTOR
-@f[create_tuple_descriptor](number_of_fields, name_list,
-@index(create_tuple_descriptor)
-                                        type_list)
-string name_list[];
-FIELD_TYPE type_list[];
-int    number_of_fields;
-@end(function)
-
-Allocates and fills in a tuple descriptor data structure.  The
-descriptor records the number of fields in the tuple, the length in
-bytes of each field, and a pointer to the type descriptor of each
-field.  Each field's offset is automatically assigned as the sum of
-the offsets of the fields preceeding it, adjusted according to the
-alignment condition found in the type descriptor.  Note that the type
-named STRING_T has a reserved meaning in some contexts (see below).
-Specifically, string data is generally stored discontiguously from the
-tuple itself; the tuple holds only control information and a pointer
-to the string.  Space for tuple descriptors is obtained using
-db_alloc.  The tuple_descriptor reference count is set to 1.
-
-@begin(function)
-void
-@f[delete_tuple_descriptor](tuple_descriptor)
-@index(delete_tuple_descriptor)
-@end(function)
-
-Decrements the reference count, and if it goes to zero,
-releases the memory occupied by the tuple descriptor.
-
-@begin(function)
-TUPLE
-@f[create_tuple](tuple_descriptor)
-@index(create_tuple)
-@end(function)
-
-Allocates space for a new tuple, and initializes its description.  The
-values of fields in the tuple are not initialized.  String types are
-not distinguished in this operation; no space is allocated for the
-target of a string pointer.  The reference count of the tuple
-descriptor is incremented.
-
-@begin(function)
-void
-@f[delete_tuple](tuple)
-@index[delete_tuple]
-TUPLE tuple;
-@end(function)
-
-Deallocates the space for the specified tuple.  Neither the tuple descriptor
-nor any of the string data which may be referenced by the tuple is
-deleted.  The reference count of the tuple descriptor is decremented,
-and if necessary, the descriptor is deleted too.
-
-@begin(function)
-void
-@f[initialize_tuple](tuple)
-@index[initialize_tuple]
-TUPLE tuple;
-@end(function)
-
-Sets each field in a tuple to its null value.
-
-@begin(function)
-void
-@f[null_tuple_strings](tuple)
-@index(null_tuple_strings)
-TUPLE tuple;
-@end(function)
-
-Reclaims the space for all fields in the tuple whose type is STRING_T.
-The value of the string itself is set to uninitialized.  The sequence
-"null_tuple_strings(t); delete_tuple(t);" may be used to reclaim all
-the space used for a tuple containing string fields.
-
-@begin(function)
-RELATION
-@f[create_relation](tuple_descriptor);
-@index[create_relation]
-TUPLE_DESCRIPTOR tuple_descriptor;
-@end(function)
-
-Creates an empty relation.  Tuples subsequently added to the relation
-must contain the fields described in the tuple descriptor at the time
-the relation is created.  Not sure yet whether this will be checked.
-May just create a generalized relation in which each tuple is
-self_describing and the consistent case is viewed as a subset.
-The tuple descriptor reference count is incremented.
-
-
-@begin(function)
-int
-@f[delete_relation](rel);
-@index[delete_relation]
-RELATION rel;
-@end(function)
-
-Reclaims the space for the specified relation, which should not be
-used again by the caller.  All tuples are deleted, along with any strings
-which have been allocated in the tuples. The caller must insure that the
-contents of any string fields are self consistent, i.e. if the string is 
-non-null, then it must refer to data which was properly allocated by gdb.
-The tuple descriptor reference count is decremented, and if necessary,
-the descriptor is deleted.
-
-@begin(function)
-void
-@f[ADD_TUPLE_TO_RELATION ]@index[ADD_TUPLE_TO_RELATION](relation, tuple)
-
-void
-@f[ADD_TUPLE_AFTER_TUPLE] (relation, new_tuple, 
-@index[ADD_TUPLE_AFTER_TUPLE]
-                            previous_tuple)
-
-RELATION relation;
-TUPLE tuple, new_tuple, previous_tuple;
-@end(function)
-
-These operations insert a new tuple into a relation.  They do NOT
-allocate storage for the tuple, because there may be times when it is
-convenient to insert an existing tuple into a relation.  These
-routines will probably be implemented as macros, hence the uppercase
-names.  ADD_TUPLE_TO_RELATION places the new tuple after all those
-already in the relation.  Each tuple may in in only one relation at a
-time.  This routine may or may not check for conformity between
-the description of the tuple and the description of the relation.  A
-given tuple may be in only one relation at a time; this is not
-checked.  Note:  to insert a tuple as the first one in the relation, 
-provide the relation pointer as the previous tuple, e.g. 
-ADD_TUPLE_AFTER_TUPLE(r, t, (TUPLE)r).
-
-@begin(function)
-TUPLE
-@f[REMOVE_TUPLE_FROM_RELATION](relation, tuple)
-@index[REMOVE_TUPLE_FROM_RELATION]
-RELATION relation;
-TUPLE tuple;
-@end(function)
-
-Removes the designated tuple from the relation (this function may 
-be implemented to remove the tuple from whichever relation it is in,
-or it may check which relation it is in, or it may presume that the
-correct relation is specified.  No checking need be done;  caller
-is responsible for insuring that the tuple is indeed in the 
-specified relation.)  The tuple is not de-allocated, merely removed
-from the relation.  It may subsequently be inserted in a different
-relation.  
-
-
-@begin(function)
-RELATION
-@f[tuples_in_relation](rel);
-@index[tuples_in_relation]
-RELATION rel;
-@end(function)
-
-Returns a count of the tuples in the supplied relation.
-
-@begin(function)
-TUPLE_DESCRIPTOR
-@f[DESCRIPTOR_FROM_TUPLE](tuple)
-@index[DESCRIPTOR_FROM_TUPLE]
-
-TUPLE_DESCRIPTOR 
-@f[DESCRIPTOR_FROM_RELATION](relation)
-
-@index[DESCRIPTOR_FROM_RELATION]
-TUPLE tuple;
-RELATION relation;
-@end(function)
-
-Given a tuple or relation, return the descriptor of its entries.
-
-@begin(function)
-int
-@f[field_index](tuple_descriptor, field_name)
-@index[field_index]
-TUPLE_DESCRIPTOR tuple_descriptor;
-string          field_name;
-@end(function)
-
-Given a tuple descriptor and the string name of a field in the tuple,
-this routine returns the 0 relative index of the field in the tuple.
-If the named field is not in the tuple, -1 is returned.
-
-@begin(function)
-(?? *)
-@f[FIELD_FROM_TUPLE](tuple, field_index);
-@index[FIELD_FROM_TUPLE]
-TUPLE  tuple;
-int    field_index;
-string         field_name;
-@end(function)
-
-Given the relative index of a field in a tuple (0 origin), return a
-pointer to the first byte of data in the field.  See also @f[field_index].
-
-@begin(function)
-int
-@f[FIELD_OFFSET_IN_TUPLE](tuple_descriptor, field_index);
-@index[FIELD_OFFSET_IN_TUPLE]
-
-FIELD_TYPE 
-@f[FIELD_TYPE_IN_TUPLE](tuple_descriptor, field_index);
-
-@index[FIELD_TYPE_IN_TUPLE]
-@end(function)
-
-Given the type descriptor for an entire tuple and the name of a field
-in the tuple, these routines return the byte offset, and the
-field_type of the named field in the tuple.  Their results are
-undefined in the case where the field_index is negative or too large.
-Note, the offset returned is from the start of the tuple data, NOT from
-the start of the tuple itself.  To address the field, the construction:
-(tup->data)+offset gives the true addresss of the first byte of the field.
-This may change in the future, since it seems to require an unnecessary
-knowledge of the tuple structure on the part of the programmer.
-
-@begin(function)
-TUPLE
-@f[FIRST_TUPLE_IN_RELATION](relation)
-@index[FIRST_TUPLE_IN_RELATION]
-
-TUPLE 
-@f[NEXT_TUPLE_IN_RELATION](relation,tuple)
-@index[NEXT_TUPLE_IN_RELATION]
-
-TUPLE 
-@f[PREV_TUPLE_IN_RELATION](relation,tuple)
-@index[PREV_TUPLE_IN_RELATION]
-
-RELATION relation;
-TUPLE tuple;
-@end(function)
-
-Returns tuples from a relation relative to the order in which they were
-inserted.  NULL is returned for the successor of the last tuple or the
-predecessor of the first tuple in a relation.
-
-@begin(function)
-void
-@f[print_relation](name, relation)
-@index[print_relation]
-
-void 
-@f[print_tuple](name, tuple)
-
-@index[print_tuple]
-
-void 
-@f[print_tuple_descriptor](name, desc)
-@index[print_tuple_descriptor]
-
-string name;
-RELATION relation;
-TUPLE    tuple;
-TUPLE_DESCRIPTOR desc;
-@end(function)
-
-These routines format the contents of the specified relation or tuple
-and write the results to the gdb logging file descriptor.  The
-supplied name, an ordinary C null terminated string, is used to label
-the printed entry in the log.  These routines are intended primarily
-for debugging.
-@end(functionsection)
-
-@chapter(Structured Data Transmission Services)
-@index(Data transmission)
-@index(Transmission of data)
-@index(Structured data transmission)
-@label(trans)
-
-These services are used to move structured data between communicating
-programs.  To provide some context for this discussion, we summarize
-here the basic techniques used to create servers and clients, and
-introduce the use of OPERATIONS for handling asynchronous activities.
-This discussion partially duplicates that of Chapter
-@ref(serverclient), which is devoted to server/client management, and
-general techniques for managing asynchronous operations in GDB.  The
-emphasis in this chapter is on transmission of structured data.
-
-@section(Background)
-
-Two styles of communicating program are supported: peer-to-peer, in which
-the two sides of the connection are considered to be symmetrical, and
-client/server, in which a server is pre-started, awaiting connections from
-one or more clients.  The following types are used by the structured data
-transmission services:
-
-@begin(itemize)
-
-@begin(multiple)
-CONNECTION
-
-represents a communication path to some other program using
-GDB.  Usually, this is a network communication path between
-programs on different machines.    Connections may
-be closed explictly by issueing a "sever_connection", and they
-are implicitly closed when the process owning the
-connection exits.       
-@end(multiple)
-
-@begin(multiple)
-OPERATION
-
-GDB is capable of managing asynchronous activities on its 
-CONNECTIONS.  When a program wishes to do asynchronous
-communication it creates an OPERATION to represent the state
-of the asynchronous activity.  GDB provides functions and
-macros for manipulating OPERATIONS.  For example, 
-OP_DONE(operation) returns true iff the operation has
-completed.
-@end(multiple)
-@end(itemize)
-
-@section(Service and Network Addresses)
-
-In the current implementation, the address of a GDB program
-running on the network has the form:
-
-@begin(example)
-               "hostname:servicename"
-@end(example)
-
-where hostname is the internet name of the host on which the program
-is running, and servicename is the name of the service as registered
-in @f[/etc/services]@index[/etc/services].  Services should be of type
-tcp.  An alternate form of servicename is #portnumber, where
-portnumber is the integer number of the Berkeley port to
-be used for the service.  Use of explicit port numbers is
-discouraged, except for testing.   Examples:
-"myhost:dbserver" or "yourhost:#1234".  All addresses are
-represented as null terminated strings in C.
-       
-       
-
-@section(Establishing Communication)
-
-As noted above, there are two general styles of communicating
-programs.  Peer-to-peer communication is started by use of the
-following function.  These services and other related routines are
-fully documented in Chapter @ref(serverclient).  The discussion here
-is intended to introduce the GDB services which transmit structured
-data.
-
-@begin(functionsection)
-
-@begin(function)
-CONNECTION
-@f[start_peer_connection](service_address)
-@index[start_peer_connection]
-string service_address;
-@end(function)
-
-Creates a connection to a peer at the designated address (see service and
-network addresses above.)  Either peer may start first.  This routine will
-hang indefinitely waiting for its peer, unless a fatal error is
-encountered.  There is currently no asynchronous form of this service.
-NULL is returned in case of an error.  Messages describing some errors are
-written to stderr, but otherwise, there is currently no way for the program
-to determine why a failure occurred. 
-@end(functionsection)
-
-Clients may request a connection to a server by using the following
-function:
-
-@begin(functionsection)
-@begin(function)
-CONNECTION
-@f[start_server_connection](service_address, parms)
-@index[start_server_connection]
-string service_address;
-string parms;
-@end(function)
-
-Rules are the same as for start_peer_connection except:  (1) The server must be
-started and listening at the time the connection is attempted, or this
-request will fail.  (2) The supplied parms are made available to the
-server, which may use them in deciding whether to accept the connection or
-how to process it.  This request will generally not hang for very long, but
-it does set up a socket and do a limited amount of communication
-synchronously.  Typical delays on a local network with no gateways are a
-fraction of a second.  Note that GDB supports several styles of server
-(e.g. forking and non-forking), but clients connect to and communicate with
-all of them in the same manner.
-
-@end(functionsection)
-
-The techniques for creating servers are described in Chapter
-@ref(serverclient).
-
-@section(Synchronous Communication)
-
-GDB is capable of transmitting data of any of the types described in
-Chapter @ref(structdata).  This means that the services below may be
-used to send data as simple as a single integer, or as complex as an
-entire relation with all of its tuples and fields.  In all cases, data
-is automatically converted to the appropriate representation when it
-is transmitted between machines of different architecture.
-
-@begin(functionsection)
-
-@begin(function)
-int
-@f[send_object](con, obj_ptr, type_id)
-@index[send_object]
-CONNECTION  con;
-char       *obj_ptr;
-FIELD_TYPE  type_id;
-@end(function)
-
-Synchronously transmits the specified data on the connection con.  Obj_ptr
-must be the address of the object to be sent, and type_id must indicate the
-type of the object to be sent.  The final status of the transmit operation
-is returned.  In general, OP_SUCCESS indicates success, OP_CANCELLED
-indicates an error.   OP_CANCELLED generally implies that the corresponding
-connection has broken and should be severed.  Examples:
-
-@begin(example)
-rc = send_object(server, &my_int, INTEGER_T);   
-                       /* send an integer */
-rc = send_object(peer, &tuple, TUPLE_T);        
-                       /* send a tuple */
-rc = send_object(peer, &rel, RELATION_T);       
-                       /* send a relation */
-@end(example)
-
-@begin(function)
-int
-@f[receive_object](con, obj_ptr, type_id)
-@index[receive_object]
-CONNECTION  con;
-char       *obj_ptr;
-FIELD_TYPE  type_id;
-@end(function)
-
-Synchronously receives the specified data on the connection con.  Obj_ptr
-must be the address of the object to be received, and type_id must indicate the
-type of the object.  The final status of the receive operation
-is returned.  In general, OP_SUCCESS indicates success, OP_CANCELLED
-indicates an error.   OP_CANCELLED generally implies that the corresponding
-connection has broken and should be severed.  Examples:
-
-@begin(example)
-rc = receive_object(server, &my_int, INTEGER_T);
-                       /* receive integer */
-rc = receive_object(peer, &tuple, TUPLE_T);     
-                       /* receive a tuple */
-rc = receive_object(peer, &rel, RELATION_T);    
-                       /* receive relation */
-@end(example)
-
-Note that receipt of certain structured objects implies that local memory
-is dynamically allocated to hold the newly received objects.  The system
-defined types for which this is the case incude: TUPLE_T, RELATION_T,
-TUPLE_DESCRIPTOR_T, and STRING_T.  TUPLE_DATA_T implies memory allocation
-only if the fields in the tuple require it.
-@end(functionsection)
-
-@section(Asynchronous communication)
-
-GDB provides a general architecture for executing asynchronous
-communication activities on a connection.  Several asynchronous operations
-are provided with the system, and sophisticated users can write their own
-(it's a little tricky, but it can be done.)   Most users will find the
-supplied operations to be sufficient.
-
-Each asynchronous activity is known as an operation.  Programmers using the
-asynchronous capabilities of GDB must declare an OPERATION to keep track of
-the state of each asynchronous activity. For example:
-
-@begin(example)
-       OPERATION send_op1, send_op2, receive_op;
-@end(example)
-
-declares 3 operations.   Before an operation can be used it must be
-"created":
-
-@begin(example)
-       send_op1 = create_operation();
-@end(example)
-
-The newly allocated 'operation' may then be used to track the state of an
-asynchronous activity, and if desired, it may later be reset and re-used
-without being re-created.  These techniques lower the cost of doing
-repeated asynchronous activities.  Many applications can create all their
-operations at start-up, resetting and re-using them as necessary.
-
-Each of the asynchronous routines described below takes an OPERATION as an
-argument.  In each case, the supplied operation should be newly created or
-reset, and in no case may it be in use by another routine;  each
-OPERATION tracks the state of one activity at a time.  The simplest way to
-synchronize asynchronous activity is with the 'complete_operation'
-function:
-
-@begin(example)
-       complete_operation@index[complete_operation](send_op1);
-       complete_operation(send_op2);
-@end(example)
-
-Note that GDB is coded to maximize throughput and avoid deadlock when
-several activities are proceeding simultaneously.  For example, the two
-calls shown above can be done in either order, since send_op2 progresses
-even while waiting for completion of send_op1.   A simple way to do
-parallel communication on several connections is to start each of the
-activities and then wait for completion of all of them.  Each progresses as
-fast as possible and as nearly in parallel as GDB can manage.  GDB uses
-Berkeley 'select' to avoid spinning when work cannot proceed.
-
-In addition to 'complete_operation', several routines are provided which
-can wait for any of a list of operations to complete, and which can combine
-a GDB wait with the facilities of a Berkeley 'select' on fd's not
-controlled by GDB.  These features are documented at the end of this
-chapter.
-
-Operations executed on a given half connection are executed in FIFO order,
-unless specifically indicated to the contrary.  (A half connection refers
-to either the inbound or outbound stream of a given connection; send and
-receive requests are queued independently.) A synchronous request as
-executed only after the completion of all prior asyncrhonous requests on
-the same half connection. 
-
-An operation which is attempted on a failed connection, or an operation
-which encounters a connection error during execution returns the status
-@f[OP_CANCELLED].   Severing a connection implicitly cancels any operations
-which are queued on that connection.  
-
-GDB generally makes as much progress as it can whenever the
-communication layer is given control.  For example, whenever a new
-operation is queued on a given connection, all connections are allowed
-to proceed as far as they can.  When a complete_operation is issued,
-all activities proceed while awaiting completion of the specified
-operation.  However, gdb only progresses when explictly given control;
-it does not use SIGIO@index[SIGIO].  For this reason, GDB programs
-should hang in a 'complete_operation' or in one of the forms of
-'op_select' when there is no work to be done, as this will allow GDB
-activities to proceed.  If the user issues his/her own select, sleep
-or a wait, GDB activities may be delayed.
-
-@subsection(Asynchronous Data Transmission)
-@label(async)
-@index(Asynchronous data transmission)
-
-The following routines are similar to send_object and receive_object, but
-they do their work asynchronously.
-
-@begin(functionsection)
-@begin(function)
-int
-@f[start_sending_object](op, con, obj_ptr, type_id)
-@index[start_sending_object]
-OPERATION op;
-CONNECTION  con;
-char       *obj_ptr;
-FIELD_TYPE  type_id;
-@end(function)
-
-Asynchronously transmits the specified data on the connection con.
-Obj_ptr must be the address of the object to be sent, and type_id must
-indicate the type of the object to be sent.  The final status
-(OP_STATUS(OP)) of the transmit operation is not available until the
-operation 'op' completes.  In general, OP_COMPLETE indicates success,
-OP_CANCELLED indicates an error.  OP_CANCELLED generally implies that
-the corresponding connection has broken and should be severed.
-OP_RESULT of a successful transmission will be OP_SUCCESS.
-Example:
-
-@begin(example)
-op1 = create_operation();
-op2 = create_operation();
-op3 = create_operation();
-start_sending_object(op1, server, &my_int, INTEGER_T); 
-start_sending_object(op2, peer, &tuple, TUPLE_T);      
-start_sending_object(op3, peer, &rel, RELATION_T);     
-compete_operation(op1);
-compete_operation(op2);
-compete_operation(op3);
-if (OP_STATUS(op1) == OP_CANCELLED ||
-    OP_STATUS(op2) == OP_CANCELLED ||
-    OP_STATUS(op2) == OP_CANCELLED)
-       printf("Couldn't do it\n");
-@end(example)
-
-@begin(function)
-int
-@f[start_receiving_object](op, con, obj_ptr, type_id)
-@index[start_receiving_object]
-OPERATION op;
-CONNECTION  con;
-char       *obj_ptr;
-FIELD_TYPE  type_id;
-@end(function)
-
-Asynchronously receives the specified data on the connection con.
-Obj_ptr must be the address of the object to be received, and type_id
-must indicate the type of the object.  The final status of the receive
-operation is not available until the operation 'op' completes.  In
-general, an OP_STATUS ofOP_COMPLETE indicates success, OP_CANCELLED
-indicates an error.  OP_CANCELLED generally implies that the
-corresponding connection has broken and should be severed.  OP_RESULT
-of a successful receipt will be OP_SUCCESS.  Example:
-
-@begin(example)
-op1 = create_operation();
-op2 = create_operation();
-op3 = create_operation();
-start_receiving_object(op1, server, &my_int, INTEGER_T); 
-start_receiving_object(op2, peer, &tuple, TUPLE_T);      
-start_receiving_object(op3, peer, &rel, RELATION_T);     
-compete_operation(op1);
-compete_operation(op2);
-compete_operation(op3);
-if (OP_STATUS(op1) == OP_CANCELLED ||
-    OP_STATUS(op2) == OP_CANCELLED ||
-    OP_STATUS(op2) == OP_CANCELLED)
-       printf("Couldn't do it\n");
-@end(example)
-@end(functionsection)
-
-@chapter(Memory Management)
-@Index(Memory management)
-@Index(Storage allocation)
-
-The following routines are provided to encapsulate calls to memory
-management services for all of the libraries defined in this
-specification.  Early implementations will just use malloc, but
-more sophisticated techniques might be used in the future.
-
-@begin(functionsection)
-@begin(function)
-(?? *)
-@f[db_alloc](bytes)
-@index[db_alloc]
-int bytes;
-@end(function)
-
-Allocates the number of bytes requested and returns the corresponding
-pointer.  The allocated space is always word aligned.
-
-@begin(function)
-void
-@f[db_free](ptr, bytes)
-@index[db_free]
-(??) *p;
-int bytes;
-@end(function)
-
-De-allocates the memory pointed to by ptr.  Some implementations by
-ignore the supplied size, requiring that ptr be a value obtained from
-db_alloc.   Others may support more flexible pool management for 
-which the size will be useful.
-@end(functionsection)
-
-@section(Overriding the default memory management routines)
-
-Two global function pointers are provided which point to the allocation
-and free routines which are actually called when db_alloc and db_free
-are used.  A user of gdb may supply his or her own memory management
-routines by replacing the supplied pointers with pointers to new routines.
-The global variables to be changed are:
-
-@begin(format)
-@tabset(.75in, 2.5in)
-@\@f[gdb_amv]@index[gdb_amv]@\vector to the allocate memory routine
-
-@\@f[gdb_fmv]@index[gdb_fmv]@\vector to the free memory routine
-@end(format)
-
-The pointers should be to routines matching the specification for
-@f[db_alloc]@index[db_alloc] and @f[db_free]@index[db_free] above.
-The pointers should be changed prior to calling
-gdb_init@index[gdb_init] to insure that all memory allocated by gdb is
-obtained using the new services.
-
-@chapter(String Management)
-@Index(String management)
-
-These routines provide allocation and de-allocation services for
-STRING_T data.   Like db_alloc and db_free, their
-primary raison d'etre is to centralize creation and deletion of
-strings.
-
-The only special TYPEDEF used for string management is @f[STRING].
-STRING describes a datum of GDB type STRING_T.  This must contain
-sufficient information to record the location of the data
-(e.g. a pointer) and the length with which the data
-was allocated (which need not be the length of null
-terminated data actually contained in the field.)
-
-@section(Routines)
-
-@begin(functionsection)
-@begin(function)
-int
-@f[string_alloc](stringp,bytes);
-@index[string_alloc]
-STRING *stringp;
-int bytes;
-@end(function)
-
-Allocates memory to contain a string of the specified length
-and returns the associated string handle.  The supplied length should
-include space for a terminating null if one is to be used, but these
-libraries make no such presumption.  A null is stored in the first byte
-of the returned data area.  
-
-@begin(function)
-void
-@f[string_free](stringp);
-@index[string_free]
-STRING *stringp;
-De-allocates the supplied string.  The length given must match that used
-to allocate the space with string_alloc (which need not be the same as
-the length of the null terminated data currently in the string.)
-@end(function)
-
-@begin(function)
-(char *)
-@f[STRING_DATA](string)
-@index[STRING_DATA]
-STRING string;
-@end(function)
-
-A macro which returns the pointer to the first byte of the referenced
-string.  NULL is returned for an uninitialized string.
-
-@begin(function)
-int
-@f[MAX_STRING_SIZE](string)
-@index[MAX_STRING_SIZE]
-STRING string;
-@end(function)
-
-A macro which returns the total number of bytes available in the string
-(which may be greater than the length of any null terminated data which
-happens to reside there at the moment.)
-@end(functionsection)
-
-@Chapter(Server and Communications Management)
-@label(serverclient)
-@Index(Server and communication management)
-
-These are routines whose purpose is to facilitate the creation of shared,
-centralized, or peer-to-peer network services in a Berkeley Unix system.
-At the server, they manage the creation of sub-processes for a given client
-or sub-service, and the allocation and use of sockets for communication to
-the clients.  A corresponding set of routines is used by clients to request
-and maintain sessions with various services.
-
-The following types are used for server and communications management:
-
-@begin(table)
-@caption(Types used in Server and Communications Management)
-@tabset(.75in, 2.5in)
-@\@f[CONNECTION]@Index[CONNECTION]@\Represents an ongoing full duplex
-@\@\connection to a central service.
-
-@\@f[CONN_STATUS]@Index[CONN_STATUS]@\a returned value indicating the
-@\@\disposition of anattempted 
-@\@\library call.
-
-@\@f[OPERATION, OPERATION_DATA]@Index[OPERATION]@Index[OPERATION_DATA]
-@\@\Represents an ongoing or completed 
-@\@\operation requested of 
-@\@\the server or transport system.
-@\@\OPERATION is a handle
-@\@\on OPERATION_DATA.
-
-@\@f[LIST_OF_OPERATIONS]@Index[LIST_OF_OPERATIONS]
-@\@\A collection of OPERATIONs.
-
-@\@f[OP_STATUS]@Index[OP_STATUS]@\A return value describing the
-@\@\progress of an asynchronous
-@\@\operation.
-@end(table)
-
-@section(Host and service names)
-@Index(Host names)
-@Index(Service names)
-@Index(Naming hosts)
-@Index(Naming services)
-@Index(Naming communicating programs)
-
-In the current implementation, the address of a GDB program running on the
-network has the form:
-
-@begin(example)
-       "hostname:servicename"
-@end(example)
-
-where hostname is the internet name of the host on which the program
-is running, and servicename is the name of the service as registered
-in @f[/etc/services]@index[/etc/services].  Services should be of type
-tcp.  An alternate form of servicename is #portnumber, where
-portnumber is the integer number of the Berkeley port to be used for
-the service.  Use of explicit port numbers is discouraged, except for
-testing.  Examples: "myhost:dbserver" or "yourhost:#1234".  All
-addresses are represented as null terminated strings in C.
-       
-The form of GDB addresses may evolve over time.  For example, host names
-may disappear when better nameservers become available.        
-
-@section(Routines for Use at Client)
-
-@begin(functionsection)
-@begin(function)
-CONNECTION
-@f[start_server_connection](server_id, parms)
-@index[start_server_connection]
-string         server_id;
-string  parms;
-@end(function)
-
-Sets up a connection to a server process at the server site.  server_id
-identifies the service; its form is specified above.  This routine
-allocates a local socket and negotiates with the server to bind it to a
-socket owned by the appropriate server process.  The parms are made
-available to the server.
-
-@begin(function)
-CONNECTION
-@f[start_peer_connection](peer_id)
-@index[start_peer_connection]
-string         peer_id;
-@end(function)
-
-Sets up a connection to a peer process, which may be at a remote site.
-peer_id identifies the process to which the connection is to be made; its
-form is specified above.    This routine allocates a
-local socket and negotiates to bind to a socket owned by the appropriate
-peer process.  Returns NULL if the connection could not be started.
-Right now, there is no way to tell why the connection attempt failed.  This
-should be fixed in subsequent versions of the spec.
-
-@begin(function)
-CONN_STATUS
-@f[connection_status](connection)
-@index[connection_status]
-CONNECTION connection;
-@end(function)
-
-Returns the status of the indicated connection.  Possible return values are:
-CONN_STOPPED (never started or severed by user), CON_UP (currentfly usable),
-CON_STARTING (transient state on way up), CON_STOPPING(transient state on
-way down--user is expected to check connection_errno and sever the connection.)
-
-@begin(function)
-int
-@f[connection_errno](connection)
-@index[connection_errno]
-CONNECTION connection;
-@end(function)
-
-Returns the Unix errno which resulted in this connection being stopped.
-While errno may be queried for any connection, it's value is meaningful
-only for a connection in the CON_STOPPING state.
-
-@begin(function)
-int
-@f[connection_perror](connection, msg)
-@index[connection_perror]
-CONNECTION connection;
-char *msg;
-@end(function)
-
-Does the equivalent of the Unix perror library routine except (1) the
-value of errno is that which caused this connection to stop and (2)
-the error message is written to gdb_log, which may or may not be
-stderr.  This routine does nothing of connection is NULL or if
-connection_status(connection) != CON_STOPPING.
-
-@begin(function)
-CONNECTION
-@f[sever_connection](connection)
-@index[sever_connection]
-CONNECTION connection;
-@end(function)
-
-Applications should use this routine to terminate a connection.  It may be
-called on any active or stopping connection.  The connection is terminated,
-all pending operations are completed or (more likely) cancelled, and the
-associated descriptor is released.  This routine always returns NULL.  It
-is the applcation's responsibility to NULL its own connection variable, which
-may conveniently be done with a construction of the form:  
-
-@begin(example)
-       peer = sever_connection(peer);
-@end(example)
-
-which has the effect of terminating the peer connection and safely nulling
-the applications pointer.  This is important because connection 
-descriptors are re-used when new connections are started.  The old value
-in a connection variable should NEVER be used after a sever.  In particular,
-the construction:
-
-@begin(example)
-               connection_status(severed_connection)
-@end(example)
-
-is safe only when the application can insure that no new connections have
-been started since the sever.
-
-Sever_connection is the inverse of start_peer_connection and
-start_server_connection.  It informs the foreign process that the client is
-done with the connection, and releases all resources associated with the
-connection.  
-@end(functionsection)
-
-@section(Routines for Use in Forking Servers)
-@Index(Forking servers)
-@Index(Servers, forking)
-
-@begin(functionsection)
-@begin(function)
-CONNECTION
-@f[create_forking_server](servicename, validate-rtn)
-@index[create_forking_server]
-string servicename;
-int *validate-rtn();
-@end(function)
-
-Turns the current process into a forking style server.  The validate
-routine, if supplied, is called before a connection is accepted to allow
-the server to screen clients.  (Interface to be documented later.)  GDB
-handles all management of connections, forking, child reaping, and the
-like.  No return is ever made in the parent, which remains under the
-control of GDB forever.  GDB will take care of terminating children
-whenever the parent is killed.  As new clients are received, GDB does the
-necessary creation of connections and returns in the child processes.  The
-connection returned by this call is to be used in communicating with the
-client.  Because a true fork is done, global data may be inherited from the
-master process.  In addition, the global variable gdb_client_tuple is 
-initialized to contain four string fields named "server_id", "parms",
-"host", and "user".
-The first is the string name of the server as passed by the client, and the
-second is the parms string supplied by the client.  The last two are the
-string names of the client host and user, as best GDB could determine them.
-In some cases, GDB may supply "????" for either of these fields if
-the true values cannot be determined. The child
-may use the full facilities of GDB to communicate with its client, and when
-communication is finished, the child should sever its connection (not
-stricly required, but it's a good thing to do) and exit.  The server will
-appropriately reap the child process.  Note that the servicename supplied
-to this routine is NOT a full network address, since the host is implicitly
-local.  See service addressing discussion above.
-
-As an aid to debugging, the GDB_NOFORK@index[GDB_NOFORK] flag may be
-set to prevent this routine from forking when a client arrives.  See
-@f[gdb_debug]@index[gdb_debug].
-@end(functionsection)
-
-@section(Routines for Use in Non-Forking Servers)
-@begin(functionsection)
-@begin(function)
-int
-@f[create_listening_connection](servicename)
-@index[create_listening_connection]
-string servicename;
-@end(function)
-
-Creates a special 'listening' connection on which start_accepting_client
-operations (see below) may be queued.  Using these two facilities together,
-a server may asynchronously wait for and acquire connections to new clients
-while continuing to service existing clients.  Servicename has the same
-forms as for create_forking_server.
-
-@begin(function)
-int
-@f[start_accepting_client_connection](listencon, op, 
-               &clientcon, &otherside
-@index[start_accepting_client_connection]
-               &othersize, &client_tuple);
-CONNECTION listencon;
-OPERATION op;
-CONNECTION clientcon;
-struct sockaddr_in otherside;
-int othersize;
-TUPLE client_tuple;
-@end(function)
-
-Begins the process of asynchronously acquiring a tentative connection from
-a client.  When this operation completes successfully, clientcon contains
-the connection to the new client, and client_tuple contains the request tuple
-(which includes the address requested and the client supplied parms).
-The otherside and othersize fields are provided for those programmers who
-need access to the Berkeley supplied address of the client.  These are the
-same as the values returned by a Berkeley 'accept' call.  Most callers will
-not need these, but it is required that appropriate parameters be supplied.
-otherside may be a character array of length 100 (less will probably do)
-and othersize should be an integer variable set to sizeof(otherside).  The
-actual size of the client address is returned, a la Berkeley accept.
-
-@begin(function)
-int
-@f[start_replying_to_client](op, con, disposition, newaddr, parms)
-@index[start_replying_to_client]
-OPERATION op;
-CONNECTION con;
-int    disposition;
-string newaddr;
-string parms;
-@end(function)
-
-The first thing a server must do after successful competion of a
-start_accepting_client is to reply to the client, indicating whether its
-request is being accepted.  The reply is sent on the new client connection
-using start_replying_to_client.  Disposition takes one of three values:
-GDB_ACCEPTED, GDB_REFUSED, or GDB_FORWARDED.  In most cases, newaddr and
-parms should be null strings ("").  GDB_ACCEPTED completes the process of
-creating the connection from client to server.  Once the start_replying
-operation is complete, the client connection is available for data
-transmission.  GDB_REFUSED indicates that the server declines to talk to
-the client, and if desired, it may indicate a reason in the parms string.
-The server should wait for completion of the start_replying_to_client, then
-sever the client connection.  GDB_FORWARDED is used to tell the client that
-the service being requested has moved, and to suggest a new address for the
-client to try.  The suggested address should be supplied in newaddr in the
-hostname:servicename form shown above.  The 'start_server_connection' which
-the client has done takes care of the forwarding request automatically and
-transparently.
-@end(functionsection)
-
-@section(Routines for Manipulating Operations)
-
-@begin(functionsection)
-@begin(function)
-OPERATION
-@f[create_operation]();
-@index[create_operation]
-@end(function)
-
-Allocates an operation descriptor and returns a pointer to it.  Note
-that the type OPERATION is just a handle, and the system assumes that
-operation data structures remain allocated for as long as they are
-needed.  Knowledgeable application programmers can allocate their own
-structures of type OPERATION_DATA and use the macro OPERATION_FROM_DATA
-to create the necessary OPERATIONS efficiently.  create_operation is
-appropriate where dynamic allocation is desired or for convenience in
-simple applications.
-
-@begin(function)
-int
-@f[delete_operation](operation)
-@index[delete_operation]
-OPERATION operation;
-@end(function)
-
-Releases space for the specified operation;
-
-@begin(function)
-OPERATION
-@f[OPERATION_FROM_DATA](op_data)
-@index[OPERATION_FROM_DATA]
-OPERATION_DATA op_data;
-@end(function)
-
-Given the operation data, this macro returns the corresponding OPERATION
-handle.
-
-@begin(function)
-Bool
-@f[OP_DONE](operation)
-@index[OP_DONE]
-OPERATION operation;
-@end(function)
-
-True iff the operation is OP_COMPLETE or OP_CANCELLED.
-
-@begin(function)
-int
-@f[OP_TAG](operation)
-@index[OP_TAG]
-@end(function)
-
-Every operation initiated by a given process has a unique integer tag
-which identifies it.  This macro returns the tag for a given operation.
-Tags are re-assigned each time the queue_op routine is called.
-Applications programmers will seldom have need to query or manipulate the
-tags directly; they are an internal mechanism used primarily to track
-operations which are being cancelled prematurely.  Applications
-programmers may occasionally find them useful as a means of generating
-operation identifiers which are guaranteed unique over the life of the
-process. 
-
-@begin(function)
-OP_STATUS
-@f[complete_operation](pending_operation)
-@index[complete_operation]
-OPERATION pending_operation;
-@end(function)
-
-Waits unconditionally for completion of the specified operation.  If
-several operations are outstanding, then waiting for a given operation
-implies a wait for all of its predecessors.  There is a separate queue
-of operations for each connection, so the term predecessor is defined
-only with respect to a given connection.  Operations pending on other
-connections DO proceed while awaiting completion of the specified
-operation.  This means that when waiting for several operations to complete,
-the calls to complete_operation may be done in any order without affecting
-the performance of the system.
-
-@begin(function)
-LIST_OF_OPERATIONS
-@f[create_list_of_operations](n, op1, op2, ..... opn)
-@index[create_list_of_operations]
-int n;
-OPERATION op1, op2 ... opn)
-@end(function)
-
-Creates and returns a list containing the supplied operation
-descriptors.  This list may then be passed to the op_select routines.
-
-@begin(function)
-void
-@f[delete_list_of_operations](op_list)
-@index[delete_list_of_operations]
-LIST_OF_OPERATIONS op_list;
-@end(function)
-
-Reclaims the space for the supplied list of operations.
-
-@begin(function)
-int
-@f[op_select_any](list_of_pending_operations, nfds, 
-@index[op_select_any]
-             &readfds, &writefds, 
-             &exceptfds, timeout)
-LIST_OF_OPERATIONS list_of_pending_operations;
-int nfds;
-fd_set readfds, writefds, exceptfds;
-struct timeval *timeout;
-@end(function)
-
-This operation has exactly the same semantics as the select system
-call, but in addition, it allows pending OPERATIONs to
-progress.  This operation hangs in a select.  If activity is discovered
-on any of the sockets controlled by the GDB library, then the
-corresponding input is read and appropriate processing is done.  If any
-of the listed pending_operations completes or terminates due to error,
-op_select returns.  op_select also returns immediately if any of the
-supplied operations is already complete. 
-
-If activity is detected on any of the file descriptors supplied by the
-user, then a count and bit fields are returned just as for select.
-(Activity on database sockets is never reflected in either count or
-bitfields.)  Timeout causes a return, as with select.  Upon return, the
-program must check for competion or termination of any of the listed
-operations, for activity on the selected file descriptors, and for
-timeouts, if requested, since any or all of these may be reported
-together.  
-
-Return values are (>0) same as for regular select, (0) timeout, (-1) only
-completion of one of the specified operations was detected.
-
-@begin(function)
-int
-@f[op_select_all](list_of_pending_operations, nfds, 
-@index[op_select_all]
-          &readfds, &writefds, 
-          &exceptfds, timeout)
-LIST_OF_OPERATIONS list_of_pending_operations;
-int nfds;
-fd_set readfds, writefds, exceptfds;
-struct timeval *timeout;
-@end(function)
-
-Same as op_select_any, except that (-1) is returned only when ALL of the
-specified operations in the list have completed.  Values (>=0) are returned
-for timeout or activity on FD's specified in the masks.
-
-@begin(function)
-int
-@f[reset_operation](operation)
-@index[reset_operation]
-OPERATION operation;
-@end(function)
-
-Sets the state of an operation back to OP_NOT_STARTED.  This is
-particularly useful for operations in a list passed to op_select_any.
-@Index(op_select_any)
-Op_select_any drops through immediately if any operation in the list
-is marked complete.  Once the operation is reset, it may be left in
-the list without detrimental effect.  reset_operation cannot be used
-on an operation which is queued or running.
-
-@begin(function)
-OP_STATUS
-@f[cancel_operation](operation)
-@index[cancel_operation]
-OPERATION operation;
-@end(function)
-
-Attempts to prematurely terminate execution of the specified operation.  If
-the operation is queued, then it is removed from the queue of the
-connection on which it resides.  If it is at the head of the queue and
-running, then an attempt is made to signal the other end of the connection
-to terminate execution.  If the operation has already completed,
-successfully or otherwise, then CANCEL_OPERATION does nothing.  In general,
-the application cannot assume that the cancellation takes effect
-immediately, or that it will always succeed.  The status of the operation
-must be checked to ascertain its true state, and if necessary, the
-application must wait for the operation to complete or terminate
-prematurely.  This call always returns immediately.  It does not wait to
-see whether the operation was indeed terminated prematurely.  There is no
-guarantee of prompt termination for any particular operation, since some
-may be uninterruptible.  The intent is to make a best effort.  Returned
-status covers only errors in the cancel operation itself.  The caller must
-still use 'complete_ operation' or 'op_select' to check for completion or
-successful cancellation of the operation.  
-
-@begin(function)
-int
-@f[OP_STATUS](operation);
-@index[OP_STATUS]
-OPERATION operation;
-@end(function)
-
-Returns a code describing the progress or completion of the operation.
-Returned values are OP_RUNNING, OP_COMPLETE or OP_COULDNT_START.  In the
-case of OP_COMPLETE OP_CANCELLING, OP_CANCELLED, or OP_COULDNT_START, the
-operation_result library routine may be used to get information about the
-success or failure of the actual operation.  Note that OP_COMPLETE applies
-to either success or failure, it merely implies that no further processing
-remains to be done on the requested operation.  OP_CANCELLED implies that
-the operation was indeed terminated prematurely by a cancellation request.
-In this case, OP_RESULT is not valid.
-
-@begin(function)
-int
-@f[OP_RESULT](operation);
-@index[OP_RESULT]
-OPERATION operation;
-@end(function)
-
-Returns detailed error information from the previous database or other
-operation request.  The possible result codes depend on the particular
-operation being performed, and they are documented along with the
-operations themselves.  The operation result is available ONLY when
-the operation is OP_COMPLETE.  Attempts to get results at other times
-may result in fatal errors.
-@end(functionsection)
-
-@section(Creating new asynchronous operations)
-
-In addition to operations like start_sending_object, which are
-supplied with GDB, it is possible for users to create their own.  This
-is a tricky business, because Unix lacks any notion of lightweight
-process.  Until proper instructions are added to the GDB Users' Guide,
-the best way to learn is to look at the source code for existing
-operations provided with GDB.  
-
-The general idea is that @f[initialize_operation] is called to fill in
-the operation descriptor with enough state to drive the operation, and
-then @f[queue_operation] is used to queue the descriptor on the
-appropriate half connection.  When the operation reaches the head of
-the queue, GDB automatically invokes the first routine of the
-operation, which was specified during initialization.  This routine
-proceeds as far as it can, updates its own state in the operation
-descriptor (and an operation specific argument appendage), and
-designates a new routine to receive control when further progress can
-be made.  The following routines are among those used in creating new
-operations: 
-
-@begin(functionsection)
-@begin(function)
-int
-@f[initialize_operation](operation, init_function, arg,
-cancel_function)
-@index[initialize_operation]
-OPERATION operation;
-int (*init_function)()
-char *arg;
-int (*cancel_function)()
-@end(function)
-
-Initializes the supplied operation with pointers to the supplied
-initialization function with the supplied argument.  The initialization
-routine will be called when and if the operation reaches the head of the
-operation queue for some connection, and it will be supplied the argument
-arg.  The cancel function, if non-null, will be called with the supplied
-argument if for any reason the operation is to be canceled.  It can do
-things like freeing the space for the argument or other associated cleanup.
-If cancel_function is NULL, then no special processing is done during
-cancellation.  The operation is put into the state OP_NOT_STARTED.
-
-@begin(function)
-OP_STATUS
-@f[queue_operation](con, direction, operation)
-@index[queue_operation]
-CONNECTION con;
-int  direction;<=  values are CON_INPUT
-                   and CON_OUTPUT
-OPERATION operation;
-@end(function)
-
-Takes the supplied operation and queues it for execution on the specified
-half connection, assigning a new unique tag for the operation.  The
-supplied operation must be in the state OP_NOT_STARTED (this may or may not
-be checked.)  If possible, execution actually begins, and in some cases,
-execution may complete by the time queue_operation returns.  Status returned
-reflects the latest known state of the operation.  Transmission on all
-connections may progress as a result of this operation.  If the connection
-is not currently operating, then it is marked as severed.  NOTE: queue 
-operation is used only by programmers creating their own asynchronous
-services.  It should NOT be called by USERS of asynchronous services.
-@end(functionsection)
-@chapter(Miscellaneous System Services)
-@Index(Miscellaneous services)
-@begin(functionsection)
-@begin(function)
-void
-@f[gdb_debug](flag)
-@index[gdb_debug]
-int    flag;
-@end(function)
-
-Toggles the specified debugging flag.  Flags currently supported are:
-@begin(itemize)
-@begin(multiple)
-@end(multiple)
-GDB_LOG@index[GDB_LOG flag]
-
-When set, this flag tells gdb to write a variety of debugging information on
-the file gdb_log.  By default, this file is set to @f[stderr]@index[stderr], 
-but users may put their own stream pointers in gdb_log.  The debugging 
-information is very detailed.  It is intended primarily for those with
-detailed knowledge of GDB's inner workings.
-@begin(multiple)
-GDB_NOFORK@index[GDB_NOFORK flag]
-
-Tells GDB not to fork when a client arrives for a forking server.  
-When this is set, the server accepts only a single client, and terminates
-when the client severs its connection.  This is useful for debugging servers
-with dbx@index[dbx] or other debuggers which are incapable of handling 
-forking programs. 
-@end(multiple)
-@end(itemize)
-Warning:  the interface to this routine is likely to change in subsequent
-releases of GDB.
-
-@end(functionsection)
-
-@Appendix(Revisions to this document)
-
-@begin(table)
-@caption(Library Reference Manual Revisions)
-@tabset(.75in, 2in)
-@\5/26/86@\Base document created
-
-@\6/23/86@\Re-define database operations for consistency
-@\@\with protocol.specification.
-
-@\7/10@\Add reset_operation
-
-@\7/18@\Added some notes in sever_connection on        
-@\@\questions relating to maintenenance of
-@\@\an out of band control stream.
-@\@\Also, added requirement to call gdb_init.
-
-@\7/25@\Considerations for re-queueing operations
-@\@\Changed names on OP_STATUS, OP_RESULT
-
-@\8/27@\General cleanup to match current state
-@\@\of implemented system
-
-@\9/2@\Correct documentation of string routines
-@\@\and show requirement for stdio.h
-
-@\9/10@\Corrections to start_db_operation and
-@\@\start_db_query
-
-@\9/17@\Added information on printing
-
-@\11/11@\Added gdb_debug and associated flags.
-
-@\11/19@\Added DB_STATUS and associated return codes.
-@\@\Fixed parm list to db_query.
-
-@\12/31@\Added host and user fields to client tuple
-
-@\1/9/87@\Fixed return values on send/receive object
-@end(table)
diff --git a/gdb/samp1.c b/gdb/samp1.c
deleted file mode 100644 (file)
index 3597ff3..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_samp1_c = "$Header$";
-#endif lint
-
-/*
- *                     sample 1
- *
- *          A simple database query program.
- *
- *     This sample program illustrates the use of the 'client library'
- *      for remote access to a relational database.  This version of
- *     the sample is about the simplest possible.  It accesses only
- *     a single database, it does the access syncrhonously, and it uses
- *     only system defined types.  Many real applications will fit this
- *     model.
- *
- *     For purposes of illustration, this program accesses a database
- *     of parts.  For each part where the value of current inventory,
- *     defined as number on hand times cost per unit, exceeds $1000,
- *     this routine prints the description of the part, a code number,
- *      the manufacturer, the cost, and the number on hand.
- *
- *     Because this program accesses the database using the client
- *     library, it may be run from any Berkeley Unix system on the internet.
- *     Necessary data conversions are done automatically if the database
- *      itself happens to live on an incompatible machine.
- *
- *     Author: Noah Mendelsohn
- */
-
-#include <stdio.h>
-#include "gdb.h"
-
-int
-main(argc, argv)
-int    argc;
-char   *argv[];
-{
-
-\f      /************************************************************
-        *                  DECLARATIONS                            *
-        ************************************************************/
-
-       /*
-        * Declare the names of fields to be retrieved and their types
-        */
-
-       int  field_count = 5;
-       char *field_names[] = {"desc",  
-                              "code",
-                              "man",
-                              "cost",
-                              "count"};
-       FIELD_TYPE field_types[] = {STRING_T,       /* desc */
-                                   INTEGER_T,      /* code */
-                                   STRING_T,       /* man */
-                                   FLOAT_T,        /* cost */
-                                   INTEGER_T};     /* count */
-
-       /*
-        * The following defines are for convenience in addressing
-        * the fields.
-        */
-
-#define DESC  0
-#define CODE  1
-#define MAN   2
-#define COST  3
-#define COUNT 4
-
-       /*
-        * Declare the relation and related data structures for
-        * storing the retrieved data.
-        */
-
-       TUPLE_DESCRIPTOR tuple_desc;
-       RELATION retrieved_data;
-
-       /*
-        *  Declare a handle to identify our session with the database
-        *  server.
-        */
-
-       DATABASE parts_data;
-
-       /*
-        * Declarations for misc. variables
-        */
-       
-       TUPLE   t;                      /* next tuple to print */
-       int     rc;                     /* A return code */     
-
-\f      /************************************************************
-        *             EXECUTION BEGINS HERE                        *
-        ************************************************************/
-
-       /*
-        * Open a connection to the database - identify session as parts_data
-        */
-
-       if (accessdb("partsdata@hostname", &parts_data) != DB_SUCCESS) {
-               printf("Cannot connect to parts database--giving up\n");
-               return;
-       }
-
-       /*
-        * Build the descriptor describing the layout of the tuples
-        * to be retrieved, and create an empty relation into which
-        * the retrieval will be done.
-        */
-
-       tuple_desc = create_tuple_descriptor(field_count, field_names,
-                                            field_types);
-       retrieved_data = create_relation(tuple_desc);
-
-       /*
-        * Do the query for parts with inventory over $1000
-        * Put results in the relation named retrieved_data.
-        */
-
-       rc = db_query(parts_data, retrieved_data,
-                     "(>*desc*< = parts.desc, 
-                       >*code*< = parts.code,
-                       >*man*<  = parts.man,
-                       >*cost*< = parts.cost,
-                       >*count*< = parts.count) 
-                      where (parts.count * parts.cost > 1000.00)");
-
-       if (rc != DB_SUCCESS) {
-               printf("Error during retrieval--giving up\n");
-               terminatedb(parts_data);
-               return;
-       }
-
-       /*
-        * Print out the results
-        */
-
-       for (t = FIRST_TUPLE_IN_RELATION(retrieved_data); t!= NULL;
-            t = NEXT_TUPLE_IN_RELATION(retrieved_data))
-               print_a_line(t);
-
-       printf("\nEnd of Report.\n\n");
-
-       /*
-        *  Clean up and leave
-        */
-
-       terminatedb(parts_data);
-       return;
-}
-
-\f/*
- *             print_a_line
- *
- *     Given a tuple with parts data, print it on standard output.
- *      NOTE: for clarity, we've left out the casts which should be
- *      done on the pointers returned from FIELD_FROM_TUPLE.
- */
-int
-print_a_line(tup)
-TUPLE  tup;
-{
-       printf("desc=%s  ",       *(FIELD_FROM_TUPLE(tup, DESC)));
-       printf("code=%d  ",       *(FIELD_FROM_TUPLE(tup, CODE)));
-       printf("manufacturer=%s ",*(FIELD_FROM_TUPLE(tup, MAN)));
-       printf("cost=%f  ",       *(FIELD_FROM_TUPLE(tup, COST)));
-       printf("count=%d\n",      *(FIELD_FROM_TUPLE(tup, COUNT)));
-}
diff --git a/gdb/samp1a.c b/gdb/samp1a.c
deleted file mode 100644 (file)
index 464326e..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_samp1a_c = "$Header$";
-#endif lint
-
-#define terminatedb(x) /* nothin doin yet */
-/*
- *                     sample 1
- *
- *          A simple database query program.
- *
- *     This sample program illustrates the use of the 'client library'
- *      for remote access to a relational database.  This version of
- *     the sample is about the simplest possible.  It accesses only
- *     a single database, it does the access syncrhonously, and it uses
- *     only system defined types.  Many real applications will fit this
- *     model.
- *
- *     For purposes of illustration, this program accesses a database
- *     of parts.  For each part where the value of current inventory,
- *     defined as number on hand times cost per unit, exceeds $1000,
- *     this routine prints the description of the part, a code number,
- *      the manufacturer, the cost, and the number on hand.
- *
- *     Because this program accesses the database using the client
- *     library, it may be run from any Berkeley Unix system on the internet.
- *     Necessary data conversions are done automatically if the database
- *      itself happens to live on an incompatible machine.
- *
- *     Author: Noah Mendelsohn
- */
-
-#include <stdio.h>
-#include "gdb.h"
-
-char *field_names[] = {"desc", 
-                      "code",
-                      "man",
-                      "cost",
-                      "cnt"};
-FIELD_TYPE field_types[] = {STRING_T,      /* desc */
-                           INTEGER_T,      /* code */
-                           STRING_T,       /* man */
-                           REAL_T,         /* cost */
-                           INTEGER_T};     /* count */
-
-int
-main(argc, argv)
-int    argc;
-char   *argv[];
-{
-
-\f      /************************************************************
-        *                  DECLARATIONS                            *
-        ************************************************************/
-
-       /*
-        * Declare the names of fields to be retrieved and their types
-        */
-
-       int  field_count = 5;
-
-
-       /*
-        * The following defines are for convenience in addressing
-        * the fields.
-        */
-
-#define DESC  0
-#define CODE  1
-#define MAN   2
-#define COST  3
-#define CNT 4
-
-       /*
-        * Declare the relation and related data structures for
-        * storing the retrieved data.
-        */
-
-       TUPLE_DESCRIPTOR tuple_desc;
-       RELATION retrieved_data;
-
-       /*
-        *  Declare a handle to identify our session with the database
-        *  server.
-        */
-
-       DATABASE parts_data;
-
-       /*
-        * Declarations for misc. variables
-        */
-       
-       TUPLE   t;                      /* next tuple to print */
-       int     rc;                     /* A return code */     
-
-\f      /************************************************************
-        *             EXECUTION BEGINS HERE                        *
-        ************************************************************/
-       /*
-        * Initialize gdb
-        */
-        gdb_init();
-
-       /*
-        * Open a connection to the database - identify session as parts_data
-        */
-
-       if (access_db("noah@menelaus", &parts_data) != DB_OPEN) {
-               printf("Cannot connect to parts database--giving up\n");
-               return;
-       }
-
-       /*
-        * Build the descriptor describing the layout of the tuples
-        * to be retrieved, and create an empty relation into which
-        * the retrieval will be done.
-        */
-
-       tuple_desc = create_tuple_descriptor(field_count, field_names,
-                                            field_types);
-       retrieved_data = create_relation(tuple_desc);
-
-       /*
-        * Do the query for parts with inventory over $1000
-        * Put results in the relation named retrieved_data.
-        */
-
-       rc = db_query(parts_data, retrieved_data,
-                     "(>*desc*< = parts.desc,>*code*< = parts.code,>*man*<  = parts.man,>*cost*< = parts.cost,>*cnt*< = parts.cnt) where (parts.cnt * parts.cost > 1000.00)");
-
-       if (rc != OP_SUCCESS) {
-               printf("Error during retrieval--giving up\n");
-               terminatedb(parts_data);
-               return;
-       }
-
-       /*
-        * Print out the results
-        */
-
-       for (t = FIRST_TUPLE_IN_RELATION(retrieved_data); t!= NULL;
-            t = NEXT_TUPLE_IN_RELATION(retrieved_data,t))
-               print_a_line(t);
-
-       printf("\nEnd of Report.\n\n");
-
-       /*
-        *  Clean up and leave
-        */
-
-       terminatedb(parts_data);
-       return;
-}
-
-\f/*
- *             print_a_line
- *
- *     Given a tuple with parts data, print it on standard output.
- *      NOTE: for clarity, we've left out the casts which should be
- *      done on the pointers returned from FIELD_FROM_TUPLE.
- */
-int
-print_a_line(tup)
-TUPLE  tup;
-{
-       printf("desc=%s  ",       STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(tup, DESC))));
-       printf("code=%d  ",       *(int *)(FIELD_FROM_TUPLE(tup, CODE)));
-       printf("manufacturer=%s ",STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(tup, MAN))));
-       printf("cost=%f  ",       *(double *)(FIELD_FROM_TUPLE(tup, COST)));
-       printf("count=%d\n",      *(int *)(FIELD_FROM_TUPLE(tup, CNT)));
-}
diff --git a/gdb/slides.mss b/gdb/slides.mss
deleted file mode 100644 (file)
index 915c967..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-@device(PostScript)
-@make(slides)
-@style(justification off)
-@style(FontFamily "TimesRoman")
-@modify(text, spread 1cm)
-@modify(heading, below 1.25in)
-@blankspace(2 in)
-@begin(center)
-@begin(majorheading)
-GDB: 
-
-Global Databases on High Speed Networks
-@end(majorheading)
-
-@heading(Noah Mendelsohn)
-
-@subheading(IBM T.J. Watson Research Center@*and@*MIT Project Athena)
-
-@blankspace(1.8 in)
-@value(Date)
-@end(center)
-@newpage
-@Heading(Problems)
-@begin(itemize)
-There are few network applications at Athena
-
-Network applications are difficult to implement
-
-Heterogeneous hardware complicates the problem
-
-Synchronization and performance issues are frequently misunderstood
-@end(itemize)
-@newpage
-@Heading(GDB Approach@*A C Library to Support:)
-@begin(Itemize)
-Shared, global relational databases
-
-Simplified implementation of servers and clients
-
-Explicit support for single process Unix servers
-@end(itemize)
-@newpage
-@heading(Potential Appplications of GDB)
-@begin(itemize)
-Subject specific databases
-
-Calendars
-
-Cooperative development environments
-
-Access to network resources (e.g. videodisc)
-
-Interactive game-like environments
-
-Discussion systems (conferences)
-@end(itemize)
-@newpage
-@Heading(GDB Database Services)
-@begin(itemize)
-Full services of RTI Ingres relational databases
-
-Available from any GDB client on internet 
-
-Machine dependencies hidden
-
-Synchronous and asynchronous flavors of most services
-
-Based on GDB data structuring facilities 
-@end(itemize)
-@newpage
-@Heading(GDB Data Structuring Services)
-@begin(itemize)
-Intended to support GDB's specific needs,  @i[not] a generalized
-extension to C language typing
-
-Explicit support for `database types' (e.g. relation, tuple)
-
-Representation may vary according to local hardware type
-
-Automatic conversion when transmitting between different architectures
-(e.g. VAX to RT/PC)
-
-Limited polymorphism
-
-Limited services for user defined types
-@end(itemize)
-@newpage
-@Heading(GDB Communication Services)
-@begin(itemize)
-CONNECTIONS:  underlying implementation is TCP byte streams, but much
-easier to use
-
-Services provided for sending and receiving GDB typed data
-
-Queuing for asynchronous operations
-
-Synchronization services
-
-All services are available to GDB applications
-
-Very low latencies can be achieved on suitable networks
-
-Asynchronous services can hide network delays from the application
-
-GDB @i[database] services are built on top of GDB communication services
-@end(itemize)
-@newpage
-@Heading(GDB Servers and Clients)
-@begin(itemize)
-@i[Forking] servers are particularly easy to implement
-
-@i[Non-forking] servers provide high performance data sharing
-
-Limited support for @i[peer-to-peer] communication is also provided
-@end(itemize)
-@newpage
-@Heading(GDB Project Status)
-@begin(itemize)
-Project started: late winter of 1986
-
-A basic, unoptimized, but 95% complete implementation of the specification
-is now available for Berkeley Unix systems
-
-Runs on both RT/PC and Vax machines, should port to others easily
-
-Preliminary versions of a User's Guide and a Library Reference Manual
-are available
-
-A few applications have been built, and several others are under development
-
-Several groups and individuals at MIT have expressed interest in the system
-@end(itemize)
-@newpage
-@Heading(Plans for the Future)
-@begin(itemize)
-Develop applications
-
-Find and support new `customers'
-
-Evaluate design, and possibly re-implement some portions based on
-experiences of users
-
-Enhancements? (e.g. automatic encapsulation of C structures as GDB types)
-
-Continue comparisons with other approaches to similar function
-(integrated distributed databases, RPC, etc.)
-@end(itemize)
diff --git a/gdb/tcl.c b/gdb/tcl.c
deleted file mode 100644 (file)
index 043b06c..0000000
--- a/gdb/tcl.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_tcl_c = "$Header$";
-#endif lint
-
-/************************************************************************/
-/*     
-/*                       tcl (test client)
-/*                       -----------------
-/*     
-/*     Author: Noah Mendelsohn (IBM T.J. Watson Research and MIT Project
-/*                              Athena)
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-/*     
-/*     PURPOSE
-/*     -------
-/*     
-/*     A simple GDB client program.  This program is the client in a
-/*     server/client pair.  It does a start server connection and then
-/*     sends characters to the server for echoing.
-/*     
-/*     NOTES
-/*     -----
-/*     
-/*     1) For simplicity, and do demonstrate the interactive response
-/*        of GDB connections, this program echoes single characters,
-/*        represented as ASCII coded integers.  Because of the polymorphism
-/*        inherent in the send_object and receive_object functions,
-/*        similar one line calls are used to transmit entire tuples
-/*        (aggregates of typed fields), relations (aggregates of tuples,
-/*        which are customarily represented by linked lists), etc.
-/*     
-/*     2) All communication done by this program and any other 
-/*        GDB based program is supported across incompatible
-/*        machine types.  For example, this program may run on an
-/*        RT/PC while the server may be running on a Vax.  Since
-/*        these machines use differing representations for integers,
-/*        GDB must do the necessary byte order conversions.
-/*     
-/*     4) Though this program is straightforward, it includes all
-/*        necessary error checking of the communication
-/*        path to the server.  For example, this program will 
-/*        terminate gracefully if the server crashes or is terminated
-/*        while this client is running.
-/*     
-/*     
-/************************************************************************/
-
-
-#include <stdio.h>
-#include <sgtty.h>
-#include "gdb.h"
-
-struct sgttyb sgtty;
-\f
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      DECLARATIONS
-       /*      
-       /*----------------------------------------------------------*/
-
-       CONNECTION server;                      /* this represents the */
-                                               /* server*/
-
-       int data;                               /* the input as typed */
-       char c;                                 /* same input as a char */
-                                               /* instead of an int */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                  EXECUTION BEGINS HERE
-       /*      
-       /*      Make sure the command line specifies the name
-       /*      of the host on which the server program is running.
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (argc != 2) {
-               /* 
-                * Tell 'em the syntax
-                */
-               fprintf(stderr, "tcl <server-host-name:service-i.d.>\n");
-               fprintf(stderr, "\tservice-i.d. is from #port number or name from /etc/services.\n");
-               fprintf(stderr, "\tShould match name service i.d. given to tsr.\n");
-               exit (4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Initialize the GDB library.
-       /*      
-       /*----------------------------------------------------------*/
-
-       gdb_init();
-\f
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Try for a connection to the server on the 
-       /*      specified host.
-       /*      
-       /*----------------------------------------------------------*/
-
-       printf("Attempting connection to server: %s\n", argv[1]);
-
-       server = start_server_connection(argv[1], "Dummy parms");
-
-        if (server == NULL) {
-               fprintf(stderr,"Could not start connection to server\n");
-               exit(8);
-       }
-
-       printf("Server connection started successfully.\n");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Put the terminal into CBREAK mode, so that we'll
-       /*      see each character as it's typed.  Also, turn off
-       /*      local character echoing, since the whole point of
-       /*      this program is to echo through the network.
-       /*      
-       /*----------------------------------------------------------*/
-
-       ioctl(0, TIOCGETP, &sgtty);             /* go into cbreak */
-       sgtty.sg_flags |= CBREAK;
-       sgtty.sg_flags &= ~ECHO;
-       ioctl(0, TIOCSETP, &sgtty);             /* go into cbreak */
-\f
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Start reading from keyboard and writing to server.
-       /*      Send each character to the server separately, and
-       /*      when it is echoed, present it on the screen.  <CRLF>
-       /*      processing is done locally.  Loop until CTRL_D (EOT)
-       /*      is entered.
-       /*      
-       /*----------------------------------------------------------*/
-
-       printf("Start typing data to be uppercased and echoed. ^D Exits.\n\n\n");
-       data = getchar();
-
-#define EOT 4
-
-       while (data != EOT) {
-               if (send_object(server, (char *)&data, INTEGER_T) ==
-                   OP_CANCELLED) {
-                           fprintf(stderr,"\n\nSend error.\n");
-                           break;
-               }
-               if (receive_object(server, (char *)&data, INTEGER_T) ==
-                   OP_CANCELLED) {
-                           fprintf(stderr,"\n\nSend error.\n");
-                           break;
-               }
-               c = data;
-               putchar(c);
-               if (c == '\r')
-                       putchar('\n');
-               data = getchar();
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Put terminal back into normal line-at-a-time with
-       /*      echoing mode.
-       /*      
-       /*----------------------------------------------------------*/
-
-       sgtty.sg_flags |= ECHO;
-       sgtty.sg_flags &= ~CBREAK;
-       ioctl(0, TIOCSETP, &sgtty);             /* go into cbreak */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Terminate the connection to the server.
-       /*      
-       /*----------------------------------------------------------*/
-
-       printf("\n\nClosing connection\n\n");
-       sever_connection(server);
-       return;
-}
-                       
diff --git a/gdb/tdbcl.c b/gdb/tdbcl.c
deleted file mode 100644 (file)
index a015d6d..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_tdbcl_c = "$Header$";
-#endif lint
-
-/************************************************************************/
-/*     
-/*                       tdbcl (test database client)
-/*                       ----------------------------
-/*     
-/*     Author: Noah Mendelsohn (IBM T.J. Watson Research and MIT Project
-/*                              Athena)
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-/*     
-/*     PURPOSE
-/*     -------
-/*     
-/*     A GDB client program which accesses a relational database
-/*     using the services of GDB.
-/*     
-/************************************************************************/
-
-
-#include <stdio.h>
-#include "gdb.h"
-
-\f
-
-int ftypes[] = {STRING_T, INTEGER_T, INTEGER_T};
-char *fnames[] = {"name", "rank", "serial"};
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      DECLARATIONS
-       /*      
-       /*----------------------------------------------------------*/
-
-       DATABASE db;                            /* this is the database */
-                                               /* we access */
-       int rc;                                 /* return code from */
-                                               /* access_db */
-       TUPLE_DESCRIPTOR tpd;
-       RELATION rel;
-#define MAX_OPS 50
-       OPERATION ops[MAX_OPS];
-       int next_op=0;                          /* next op to use */
-       int i;
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                  EXECUTION BEGINS HERE
-       /*      
-       /*      Make sure the command line specifies the name
-       /*      of the host on which the server program is running.
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (argc != 3) {
-               /* 
-                * Tell 'em the syntax
-                */
-               fprintf(stderr, "tcl <database-name@host> <query>\n");
-               exit (4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Initialize the GDB library.
-       /*      
-       /*----------------------------------------------------------*/
-
-       gdb_init();
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Create all the operations
-       /*      
-       /*----------------------------------------------------------*/
-       for (i=0; i<MAX_OPS; i++)
-               ops[i] = create_operation();
-\f
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Try for a connection to the server on the 
-       /*      specified host.
-       /*      
-       /*----------------------------------------------------------*/
-
-       printf("Attempting database: %s\n", argv[1]);
-
-       if (rc = access_db(argv[1], &db) != DB_OPEN) {
-               fprintf(stderr,"Return code from access_db is %d\n",rc);
-               exit(8);
-       }
-
-        if (db == NULL) {
-               fprintf(stderr,"Got null db after access_db reported success\n");
-               exit(8);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Try destroying and creating a table
-       /*      
-       /*----------------------------------------------------------*/
-
-       printf("Now queueing operations\n");
-
-       rc = start_performing_db_operation(ops[next_op++],db, "destroy tdbcl");
-
-       rc = start_performing_db_operation(ops[next_op++],db, "create tdbcl (name=c8, rank = i4, serial=i4)");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Append some data to the table
-       /*      
-       /*----------------------------------------------------------*/
-
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"noah\", rank = 1, serial=123)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike1\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike2\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike3\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike4\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike5\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike6\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike7\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike8\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike9\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike10\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike11\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike12\", rank = 5, serial=456)");
-       rc = start_performing_db_operation(ops[next_op++],db, "append to  tdbcl (name=\"mike13\", rank = 5, serial=456)");
-
-       
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Complete the operations and print the return codes 
-       /*      from them
-       /*      
-       /*----------------------------------------------------------*/
-
-       printf("Operations have been queued, waiting for last one to complete\n");
-       complete_operation(ops[next_op-1]);
-       for (i=0; i<=next_op; i++)
-               printf("%d: status=%d, result=%d\n", i, OP_STATUS(ops[i]),
-                      OP_RESULT(ops[i]));
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Do a query
-       /*      
-       /*----------------------------------------------------------*/
-
-       tpd = create_tuple_descriptor(3, fnames, ftypes);
-
-       rel = create_relation(tpd);
-
-       rc = db_query(db, rel, /*argv[2]*/ "(>*name*<=tdbcl.name, >*serial*<=tdbcl.serial) where tdbcl.serial>200");
-
-       printf("return code from query is %d\n",rc);
-       if (rc == 0)
-               print_relation("Query result", rel);
-
-       delete_relation(rel);
-       rel = create_relation(tpd);
-
-       rc = db_query(db, rel, /*argv[2]*/ "(>*name*<=tdbcl.name, >*serial*<=tdbcl.serial) where tdbcl.serial>200");
-
-       printf("return code from query is %d\n",rc);
-       if (rc == 0)
-               print_relation("Query result", rel);
-
-       delete_relation(rel);
-       delete_tuple_descriptor(tpd);
-
-       return;
-}
-                       
diff --git a/gdb/test.c b/gdb/test.c
deleted file mode 100644 (file)
index c88f3d3..0000000
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_test_c = "$Header$";
-#endif lint
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/************************************************************************/
-/*     
-/*                        gdb_trans2.c
-/*     
-/*           GDB - Data Transport Services Routines (Part 2)
-/*     
-/*     Author: Noah Mendelsohn
-/*     Copyright: 1986 MIT Project Athena 
-/*     
-/*     These routines implement layer 6 of the Client Library
-/*     Specification of the GDB system, as well as the facilities
-/*     outlined in the GDB Protocol Specification.  Part 2 of 2.
-/*
-/*     Some of the routines specified are actually implemented as
-/*     macros defined in gdb.h.
-/*     
-/************************************************************************/
-
-#include <sys/types.h>
-#include <errno.h>
-#include <stdio.h>
-#include "gdb.h"
-
-extern int errno;                              /* Unix error slot */
-
-/*
- * The following values are returned by g_con_progress
- */
-#define NOPROGRESS 0                           /* nothing happened on this */
-                                               /* connection--must be 0*/
-#define PROGRESS 1                             /* connection has progressed */
-#define COMPLETE 2                             /* an operation has */
-                                               /* completed on this con */
-\f
-/************************************************************************/
-/*     
-/*                          queue_operation(queue_operation)
-/*     
-/*     Add an operation to the queue for a given connection, and
-/*     then allows all connections to progress.  Returns the last
-/*     known status of the operation.
-/*     
-/************************************************************************/
-
-int
-queue_operation(con, direction, op)
-CONNECTION con;
-int     direction;
-OPERATION op;
-{
-       register HALF_CONNECTION hcon = (direction==CON_INPUT)?(&(con->in)):
-                                                              (&(con->out));
-
-       GDB_CHECK_CON(con, "queue_operation")
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "op queued: con=0x%x dir=%s op=0x%x Q was %s empty\n",
-                       con, (direction == CON_INPUT)?"INPUT":"OUTPUT",
-                       op, (hcon->op_q_first == (OPERATION)hcon)?"":"not");
-       /*
-        * Make sure connection is up
-        */
-       if (con->status != CON_UP) {
-               op->status = OP_CANCELLED;
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "\nop NOT queued\n");
-               return OP_CANCELLED;
-       }
-
-       /*
-        * Put the new operation at the end of the queue
-        */
-       op->prev = hcon->op_q_last;
-       op->next = (OPERATION)hcon;
-       hcon->op_q_last->next = op;
-       hcon->op_q_last = op;
-       /*
-        * Mark it as queued
-        */
-       op->status = OP_QUEUED;
-       op->halfcon = hcon;
-       /*
-        * Force progress on all connections
-        */
-       gdb_progress();
-
-       /*
-        * Return the last known status of the operation
-        */
-       return op->status;
-}
-/************************************************************************/
-/*     
-/*                          requeue_operation
-/*     
-/*     This routine may be called from an init or continuation routine
-/*     to cause the current operation to be requeued on a new connection.
-/*     The init routine field ofthe operation should be properly set to 
-/*     indicate the routine to receive control when the operation actually
-/*     runs on the new connection.  The caller of this routine is 
-/*     responsible for returning the status OP_REQUEUED to its caller.
-/*     
-/*     This routine returns the status of the newly queued operation.
-/*     Note, however, that even if this operation returns the status
-/*     CANCELLED, the operation itself may not continue to execute
-/*     on the old connection and it should return the status OP_REQUEUED,
-/*     NOT OP_CANCELLED (at least in this implementation.)
-/*     
-/************************************************************************/
-
-int
-requeue_operation(con, direction, op)
-CONNECTION con;
-int     direction;
-OPERATION op;
-{
-       /*
-        * Make sure the connection supplied is a legal one
-        */
-       GDB_CHECK_CON(con, "requeue_operation")
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "op requeued: new con=0x%x dir=%s op=0x%x\n",
-                       con, (direction == CON_INPUT)?"INPUT":"OUTPUT",
-                       op);
-       /*
-        * Dequeue the operation from its old half connection
-        */
-       g_op_newhead(op->halfcon);
-
-       /*
-        * Now queue it on the new one
-        */
-       return queue_operation(con, direction, op);
-}
-
-/************************************************************************/
-/*     
-/*                       g_preempt_me
-/*     
-/*     Sticks a new operation in ahead of the current one and runs it
-/*     on the current connection.  May be called only from an init or
-/*     continuation routine.  The old operation must have completely
-/*     prepared the descriptor for the new operation, i.e. it should
-/*     be in the same state as it would be for a call to queue_operation.
-/*     g_preempt_me makes it possible for operations to be built by
-/*     composition of other smaller operations, since newop runs, in
-/*     a sense, as a subroutine of oldop.  opdop must (1) reset its
-/*     initialization routine to be a routine to be called when newop
-/*     completes or cancels and (2) return the status OP_PREEMPTED to
-/*     its caller.
-/*     
-/************************************************************************/
-
-int
-g_preempt_me(oldop, newop)
-OPERATION oldop;
-OPERATION newop;
-{
-       register OPERATION old=oldop, new=newop;
-       register HALF_CONNECTION hc = old->halfcon;
-
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "op preempted: halfcon=0x%x oldop=0x%x newop=0x%x\n",
-                       oldop,newop);
-       /*
-        * link in the new operation
-        */
-       old->prev = new;
-       hc->op_q_first = new;
-       new->prev = (OPERATION)hc;
-       new->next = old;
-       /*
-        * Set the status of the new operation
-        */
-       new->status = OP_QUEUED;
-       new->halfcon = hc;
-       /*
-        * Change the status of the old operation (one could argue that
-        * this should be done in gdb_hcon_progress after the return code
-        * is detected.)
-        */
-       old->status = OP_QUEUED;
-       return OP_QUEUED;
-}
-
-
-\f
-/************************************************************************/
-/*     
-/*                        gdb_progress
-/*     
-/*     This routine should be called whenever it is suspected that
-/*     progress can be made on any connection.  This routine will
-/*     cause all connections to proceed as far as they can without 
-/*     blocking, and will make a best effort to avoid long blocks.
-/*     This routine MAY retain control for long periods when sustained
-/*     progress is possible, but it will not knowingly hang.  
-/*     
-/*     Returns: number of connections on which OPERATIONS have 
-/*     COMPLETED (not just progressed).
-/*     
-/************************************************************************/
-
-int
-
-gdb_progress()
-{
-       register int i;                         /* index to available */
-                                               /* connections */
-       register int return_value = 0;          /* the value we return */
-       int rc;                                 /* short term storage for */
-                                               /* a return code */
-       int progress_made;                      /* true when some con */
-                                               /* made progress during */
-                                               /* latest pass through list */
-       int complete_map[GDB_MAX_CONNECTIONS];  /* indicates whether a */
-                                               /* transmission operation */
-                                               /* is newly complete on */
-                                               /* corresponding connection */
-                                               /* 1 if yes else 0  */
-       int maxcon = gdb_mcons;                 /* gdb_mcons may change */
-                                               /* out from under us if */
-                                               /* connections break.  This */
-                                               /* is the initial value. */
-
-       /*
-        * Zero out the completion map for all connections.
-        */
-       for (i=0; i<maxcon; i++)
-               complete_map[i]=0;
-
-       /*
-        * Make repeated passes through all the fd's until a pass is made
-        * in which none makes any progress.  This logic is important, 
-        * because it catches the case where A is blocked, B makes progress,
-        * and A unblocks during the period where B is progressing.
-        */
-
-       do {
-               progress_made = FALSE;
-               for (i=0; i<gdb_mcons; i++) {
-                       if (rc = g_con_progress(i)) { /* note: NOPROGRESS==0 */
-                               progress_made = TRUE;
-                               if (rc == COMPLETE)
-                                       complete_map[i] = 1;
-                       }
-               }
-       } while (progress_made);
-
-       /*
-        * We've gone as far as we can, now find out how many connections
-        * have had operations complete.
-        */
-       for (i=0; i<maxcon; i++) 
-               return_value += complete_map[i];
-
-       return return_value;
-}
-\f
-/************************************************************************/
-/*     
-/*                        g_con_progress
-/*     
-/*     Make as much progress as possible on the specified connection.
-/*     Returns NOPROGRESS if no bytes moved on either half connection,
-/*     PROGRESS, if some moved and no operations completed, or COMPLETE if
-/*     any of the operations completed.  Note that each connection
-/*     consists of two half connections, and we must make each of them
-/*     progress as far as possible.
-/*     
-/*     The nest here starts getting so deep that it's hard to pass state
-/*     around efficiently.  We  use a single global variable, gdb_conok,
-/*     to indicate whether the connection we're working on now has died.
-/*     The move data routines set this to FALSE whenever there is a 
-/*     fatal error on a connection.  We check it, and do a proper 
-/*     sever on the connection if it seems to be in trouble.
-/*     
-/************************************************************************/
-
-
-int
-g_con_progress(con_id)
-int    con_id;                                 /* index of this connection */
-                                               /* in the connection desc. */
-                                               /* arrays*/
-{
-       register CONNECTION con= (&gdb_cons[con_id]);
-                                               /* pointer to the connection */
-                                               /* data structure */
-       register int progress = NOPROGRESS;
-       register int live = TRUE;               /* true when we've seen */
-                                               /* enough to make sure we */
-                                               /* want to go around again*/
-       int rc;
-       /*
-        * Check status of connection-if it's not running, then just return.
-        */
-       if (con->status != CON_UP)
-               return NOPROGRESS;
-       /*
-        * Repeatedly make progress on each half connection until both
-        * are idle.  Important to keep trying as one may become active
-        * while the other is progressing.  
-        */
-
-       gdb_conok = TRUE;                       /* this gets set to FALSE */
-                                               /* for fatal I/O errors */
-                                               /* there may be a timing */
-                                               /* window here in use of */
-                                               /* HCON_BUSY */
-       while (live) {
-               live = FALSE;                   /* until proven otherwise */
-               /*
-                * make progress on the input connection note that following
-                * logic depends on NOPROGRESS being 0
-                */
-               if (rc = gdb_hcon_progress(CON_INPUT, &con->in)) {
-                       live = TRUE;
-                       progress = max(rc, progress);
-               }
-               /*
-                * See if connection has died
-                */
-               if (!gdb_conok) {
-                       g_stop_connection(con);
-                       return COMPLETE;        /* dying connection always */
-                                               /* implies that the */
-                                               /* operation at the head */
-                                               /* of the queue completed */
-               }
-               /*
-                * make progress on the output connection
-                */
-               if (rc = gdb_hcon_progress(CON_OUTPUT, &con->out)) {
-                       live = TRUE;
-                       progress = max(rc, progress);
-               }
-               /*
-                * See if connection has died
-                */
-               if (!gdb_conok) {
-                       g_stop_connection(con);
-                       return COMPLETE;
-               }
-       }
-
-       return progress;
-}
-
-
-/************************************************************************/
-/*     
-/*                     gdb_hcon_progress
-/*     
-/*     Allows a specified half-connection to progress as much as possible,
-/*     and returns true iff at least one operation is newly completed.
-/*
-/************************************************************************/
-
-int
-gdb_hcon_progress(direction, hc)
-int    direction;                              /* CON_INPUT or CON_OUTPUT */
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-        HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-       register OPERATION op;                  /* current operation on this */
-                                               /* half connection */
-       int progress = NOPROGRESS;              /* can indicate any progress */
-                                               /* on the half con or */
-                                               /* whether any operations */
-                                               /* completed */
-       int done;                               /* true when no more progress*/
-                                               /* can be made */
-       int fcn_result;                         /* result of latest init or */
-                                               /* continue function */
-
-       /*
-        * Write message to debugging log
-        */
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "hcon_progress: halfcon=0x%x dir=%s ",
-                       half_con, (direction==CON_INPUT)?"INPUT":"OUTPUT");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      See if we are being re-entered and are already working
-       /*      on this half_con.  If so, return right now.  
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (half_con->flags & HCON_BUSY) {
-               /*
-                * Write message to debugging log
-                */
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "BUSY, returning\n");
-               return NOPROGRESS;
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      See if there is an operation on this half connection.
-       /*      If not, return.
-       /*      
-       /*----------------------------------------------------------*/
-
-
-       op = half_con->op_q_first;              /* pick up first operation */
-                                               /* in queue */
-       if (op == (OPERATION)half_con) {        /* see if end of circular */
-                                               /* list */
-               /*
-                * Write message to debugging log
-                */
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "Q EMPTY, returning\n");
-               return NOPROGRESS;              /* nothing to do on */
-                                               /* this half session */
-       }
-
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Loop until all operations are complete, or until no further
-       /*      progress can be made on this one.
-       /*      
-       /*      Loop invariants:
-       /*      
-       /*      1) Op contains the operation at the head of the q, or
-       /*         else is == half_con, indicating no more operationos
-       /*         to be processed.
-       /*      
-       /*      2) The operation at the head of the queue is either running
-       /*         or continuing.  As soon as one completes, it is dequeued.
-       /*      
-       /*      Progress is declared whenever an operation newly
-       /*      returns OP_COMPLETE, i.e. whenever there has been 
-       /*      an operation which went from running to complete.
-       /*      
-       /*      Done is declared whenever an operation returns anything
-       /*      other than complete, indicating that it cannot progress
-       /*      further at this time.  Loop ends.  
-       /*      
-       /*      While we're here, mark us busy so we won't try the
-       /*      same half_con on reentry.
-       /*      
-       /*----------------------------------------------------------*/
-
-       done = FALSE;                           /* this one may be able to */
-                                               /* progress */
-
-       half_con->flags |= HCON_BUSY;           /* don't try this hcon */
-                                               /* while we already doing */
-                                               /* it.  Could happen if */
-                                               /* we queue new ops */
-       half_con->flags &= ~HCON_PROGRESS;      /* gdb_move_data will */
-                                               /* indicate progress here*/
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "LOOPING\n");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Loop through the operations queued on this half con
-       /*      trying to make progress on them, in order.
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (!done &&
-              op != (OPERATION)half_con) {
-
-               if (gdb_Debug & GDB_LOG)
-                       fprintf(gdb_log, "\top=0x%x status%d...",
-                               op, OP_STATUS(op));
-
-               switch (op->status) {
-            /*
-             * Operation is at head of queue for first time and has
-             * never been started.  Try to start it up.
-             */
-           case OP_QUEUED:
-                       /*
-                        * Call the initialization routine for this operation
-                        */
-                       fcn_result = (*op->fcn.init)(op,half_con,op->arg);
-                       if (gdb_Debug & GDB_LOG)
-                               fprintf(gdb_log, "init result=%d\n",
-                                       fcn_result);
-
-                       switch (fcn_result) {
-                             case OP_COMPLETE:
-                             case OP_CANCELLED:
-                               op->status = fcn_result; 
-                               op = g_op_newhead(half_con);
-                               progress = COMPLETE;
-                               break;
-                             case OP_PREEMPTED:
-                               op->status = OP_QUEUED;
-                               /* fall thru */
-                             case OP_REQUEUED:
-                               /* important: don't set status on re-queued */
-                               /* op as it may already have completed in */
-                               /* its second life ! */
-                               op = half_con->op_q_first;
-                               progress = max(progress, PROGRESS);
-                               break;
-                             default:
-                               op->status = fcn_result; 
-                               done = TRUE;    /* could not get done */
-                       }
-                       break;
-            /*
-             * Operation is at head of queue and has already 
-             * started trying to run.  The only reason we could be in this
-             * state is that the last time we tried to do the requested input
-             * or output, all the data could not be moved synchronously.  
-             * We therefore try to move some more, and if it all goes now,
-             * we call the continuation routine.
-             */
-           case OP_RUNNING:
-                       /*
-                        * Try to move some more data.  If it won't all 
-                        * go now, we're done with this half connection.
-                       *
-                       * If this is a special listening connection which
-                       * has an operation queued trying to do a listen,
-                       * then do the listen.  Otherwise do an ordinary
-                       * data move.
-                        */
-                       if (half_con->flags & HCON_PENDING_LISTEN) {
-                               if (gdb_listen(half_con)==FALSE) {
-                                       if (gdb_Debug & GDB_LOG)
-                                               fprintf(gdb_log, "NO LISTEN\n");
-                                       done = TRUE;
-                                       break;
-                               }
-                       } else
-                               if (gdb_move_data(direction, half_con)==FALSE) {
-                                       done = TRUE;
-                                       if (gdb_Debug & GDB_LOG)
-                                               fprintf(gdb_log, "NO DATA\n");
-                                       break;
-                               }
-                       /* 
-                        * The pending data transmission has now completed.
-                        * Call the continuation routine for this operation
-                        */
-                       fcn_result = (*op->fcn.cont)(op,half_con,op->arg);
-                       if (gdb_Debug & GDB_LOG)
-                               fprintf(gdb_log, "cont result=%d\n",
-                                       fcn_result);
-
-                       switch (fcn_result) {
-                             case OP_COMPLETE:
-                             case OP_CANCELLED:
-                               op->status = fcn_result; 
-                               op = g_op_newhead(half_con);
-                               progress = COMPLETE;
-                               break;
-                             case OP_PREEMPTED:
-                               op->status = OP_QUEUED;
-                               /* fall thru */
-                             case OP_REQUEUED:
-                               /* important: don't set status on re-queued */
-                               /* op as it may already have completed in */
-                               /* its second life ! */
-                               op = half_con->op_q_first;
-                               progress = max(progress, PROGRESS);
-                               break;
-                             default:
-                               op->status = fcn_result; 
-                               done = TRUE;    /* could not get done */
-                       }
-                       break;
-            /*
-             * Following cases are all unexpected, at least for the
-             * moment.  (See explanation of loop invariants for this while
-             * loop.  Give up if they turn up.
-             */
-           case OP_COMPLETE:
-                       GDB_GIVEUP("gdb_hcon_progress: found OP_COMPLETE on q")
-           case OP_CANCELLED:
-                       GDB_GIVEUP("gdb_hcon_progress: found OP_CANCELLED on q")
-           case OP_CANCELLING:
-                       GDB_GIVEUP("gdb_hcon_progress: OP_CANCELLING")
-           default:
-                       GDB_GIVEUP("gdb_hcon_progress: Operation is queued, but is not runnable")
-                 }
-       }
-
-       if (progress == NOPROGRESS && (half_con->flags & HCON_PROGRESS))
-               progress = PROGRESS;
-
-       half_con->flags &= ~HCON_BUSY;
-
-       if (gdb_Debug & GDB_LOG)
-               fprintf(gdb_log, "hcon_progress: returns %d\n",progress);
-
-       return progress;                        /* NOPROGRESS, PROGRESS */
-                                               /* or COMPLETE */
-}
-\f
-/************************************************************************/
-/*     
-/*                             g_op_newhead
-/*     
-/*     Dequeues the operation at the head of the queue for the
-/*     given half connection and returns the pointer to the 
-/*     new head of the queue.  If the queue is null, then a pointer
-/*     to the half_con itself is returned.  (The lists are
-/*     linked circularly.)
-/*     
-/************************************************************************/
-
-OPERATION
-g_op_newhead(hcp)
-HALF_CONNECTION hcp;
-{
-       register OPERATION newhead, oldhead;
-
-       /*
-        * Get old and new heads of chain
-        */
-       oldhead = hcp->op_q_first;
-       newhead = oldhead->next;
-       /*
-        * Make sure nobody chained a bad one on us
-        */
-       if (newhead == NULL) {
-               if (gdb_Debug & GDB_LOG) {
-                       fprintf(gdb_log,"\t\tg_op_newhead: found null link, oldhead = 0x%x newhead=0x%x halfcon=0x%x\n\t\t\t hc->first=0x%x hc->last=0x%x\n",
-                               oldhead, newhead, hcp, hcp->op_q_first,
-                               hcp->op_q_last);
-               }
-               GDB_GIVEUP("g_op_newhead: found NULL chain link")
-       }
-       /*
-        * Remove oldhead from chain, fixing up chain pointers
-        */
-       newhead->prev = oldhead->prev;
-       hcp->op_q_first = newhead;
-
-       /*
-        * Clean up pointers in the newly dequeued operation.  This is
-        * just for cleanliness and ease of debugging.
-        */
-       oldhead->next = oldhead->prev = NULL;
-       oldhead->halfcon = NULL;
-
-       return newhead;
-}
-\f
-/************************************************************************/
-/*     
-/*                             gdb_move_data
-/*     
-/*     This routine attempts to make further progress on the pending
-/*     level transmission operation pending on this half connection.
-/*     (Presumes that such an operation is pending.)  Returns TRUE
-/*     if all the requested data has been moved, else FALSE.
-/*     
-/*     We assume here that all fd's are set to non-blocking I/O, so
-/*     we can safely try reading and writing until they return 0 bytes.
-/*     
-/************************************************************************/
-
-int
-gdb_move_data(direction, hc)
-int    direction;                              /* CON_INPUT or CON_OUTPUT */
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-       register HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-       register int count;                     /* number of bytes read */
-                                               /* or written in latest */
-                                               /* attempt */
-       fd_set *fdbits;                         /* the mask we should adjust */
-                                               /* for this direction */
-       fd_set tst_bits;                        /* these are used for */
-                                               /* the select we do prior */
-                                               /* to reading which tells */
-                                               /* us whether 0 byte read */
-                                               /* means empty or closed  */
-        int selected;                          /* TRUE iff select says */
-                                               /* we should be able to */
-                                               /* progress */
-
-       /*
-        * For safety, in case we're called when nothing is pending.
-        */
-       if (half_con->remaining == 0)
-               return TRUE;
-       /*
-        * Loop until either (1) the connection reported that it could
-        * not progress any further or (2) the full count has been 
-        * satisfied.  Some versions of Unix observe the rule that 
-        * a closed connection, especially when reading, is indicated
-        * by select claiming that there is data when read says there
-        * isn't.  Also, some other versions return errors from the
-        * select on that FD.  We test for both situations here.
-        */
-       FD_ZERO(&tst_bits);
-
-       while(half_con->remaining>0) {
-               FD_SET(half_con->fd,&tst_bits);
-               if (direction == CON_INPUT) {
-                       selected = select(gdb_mfd,&tst_bits, NULL, NULL, 
-                                         &gdb_notime);
-                       /*
-                        * If selected==(-1), then we know there's something
-                        * wrong with the socket
-                        */
-                       if (selected == (-1)) {
-                               gdb_conok = FALSE;
-                               break;
-                       }
-                       /*
-                        * if selected==0, then we know read won't do
-                        * anything, so save the extraneous system call
-                        */
-                       if (selected == 0) {
-                               count =0;
-                               break;
-                       }
-                       /*
-                        * Selected is >0.  Either the read is going to 
-                        * return 0, or this is one of those versions of
-                        * Unix that tells us the connection has died by
-                        * indicating select=1, read=0.
-                        */
-                       count = read(half_con->fd, half_con->next_byte,
-                                    half_con->remaining);
-               } else {
-                       selected = select(gdb_mfd, NULL, &tst_bits, NULL, 
-                                         &gdb_notime);
-                       if (selected == (-1)) {
-                               gdb_conok = FALSE;
-                               break;
-                       }
-                       if (selected == 0) {
-                               count =0;
-                               break;
-                       }
-                       count = write(half_con->fd, half_con->next_byte,
-                                    min(half_con->remaining, 
-                                        GDB_MAX_SOCK_WRITE));
-               }
-               /*
-                * We moved some data
-                */
-               if (count >0)
-                       half_con->flags |= HCON_PROGRESS;
-               /*
-                * rc==0 means we didn't mvoe any data, but if accompanied
-                * by select claiming there was data, it really means the 
-                * connection is dead!
-                */
-               if (count==0) {
-                       if (selected == 1)
-                               gdb_conok = FALSE;
-                       break;          /* no more data available now*/
-               }
-               if (count<0) {
-                       count = 0;
-                       if (errno != EWOULDBLOCK) {
-                               gdb_conok  = FALSE; /* tell callers that */
-                                                   /* con has died */
-                       }
-                       break;
-
-               }
-               half_con->remaining -=count;
-               half_con->next_byte +=count;
-       }
-
-       /*
-        * The file descriptor masks used for doing selects must be activated
-        * when and only when there is a pending operation trying to use
-        * the connection.  Update the masks for this half connection.
-        */
-       fdbits = (direction == CON_INPUT)? &gdb_crfds : &gdb_cwfds;
-       if (half_con->remaining >0)
-               FD_SET(half_con->fd, fdbits);
-       else                                    
-               FD_CLR(half_con->fd, fdbits);
-
-       return (half_con->remaining == 0);
-}
-\f
-/************************************************************************/
-/*     
-/*                     gdb_receive_data (gdb_receive_data)
-/*     
-/*     This routine is called by an init or continuation routine to
-/*     request that a specified amount of data be read, without 
-/*     blocking, on the supplied connection.  This routine returns
-/*     OP_COMPLETE if the entire read completed synchronously,
-/*     or OP_RUNNING if the read remains ongoing or is cancelling
-/*     due to error on the socket.
-/*     
-/************************************************************************/
-
-int
-gdb_receive_data(half_con, ptr, len)
-HALF_CONNECTION half_con;                      /* read on this connection*/
-char    *ptr;                                  /* put first byte here */
-int    len;                                    /* number of bytes to read */
-{
-       /*
-        * Fill in the initial state of the attempted receive 
-        */
-       half_con->remaining = len;
-       half_con->next_byte = ptr;
-
-       /*
-        * Now see if we can make some progress on this read, possibly
-        * even completing it synchronously.  Return appropriate
-        * result to our caller.  Note: errors are reflected as OP_RUNNING
-        * with global variable gdb_cnok set to FALSE.
-        */
-       if(gdb_move_data(CON_INPUT, half_con))
-               return OP_COMPLETE;
-       else
-               return OP_RUNNING;
-}
-
-/************************************************************************/
-/*     
-/*                     gdb_send_data (gdb_sndat)
-/*     
-/*     This routine is called by an init or continuation routine to
-/*     request that a specified amount of data be written, without 
-/*     blocking, on the supplied connection.  This routine returns
-/*     OP_COMPLETE if the entire write completed synchronously,
-/*     or OP_RUNNING if the output remains ongoing or there was an error.
-/*     
-/************************************************************************/
-
-int
-gdb_sndat(half_con, ptr, len)
-HALF_CONNECTION half_con;                      /* write on this connection*/
-char    *ptr;                                  /* put first byte here */
-int    len;                                    /* number of bytes to read */
-{
-
-       /*
-        * Fill in the initial state of the attempted receive 
-        */
-       half_con->remaining = len;
-       half_con->next_byte = ptr;
-
-       /*
-        * Now see if we can make some progress on this read, possibly
-        * even completing it synchronously.  Return appropriate
-        * result to our caller.
-        */
-       if(gdb_move_data(CON_OUTPUT, half_con))
-               return OP_COMPLETE;
-       else
-               return OP_RUNNING;
-}
-
-/************************************************************************/
-/*     
-/*                     gdb_start_a_listen
-/*     
-/*     This routine is called by an init or continuation routine to
-/*     request that a connection be done.  This routine returns
-/*     OP_COMPLETE if the accept completed synchronously,
-/*     or OP_RUNNING if the output remains ongoing or there was an error.
-/*     
-/************************************************************************/
-
-int
-gdb_start_a_listen(half_con, otherside, lenp, fdp)
-HALF_CONNECTION half_con;                      /* write on this connection*/
-char    *otherside;                            /* put first byte here */
-int    *lenp;                                  /* number of bytes to read */
-int     *fdp;
-{
-
-       /*
-        * Fill in the initial state of the attempted accept
-        */
-       half_con->accepted_len = lenp;
-       half_con->next_byte = otherside;
-       half_con->accepted_fdp = fdp;
-
-       /*
-        * Now see if we can make some progress on this read, possibly
-        * even completing it synchronously.  Return appropriate
-        * result to our caller.
-        */
-       if(gdb_listen(half_con))
-               return OP_COMPLETE;
-       else
-               return OP_RUNNING;
-}
-\f
-/************************************************************************/
-/*     
-/*                     gdb_listen (gdb_listen)
-/*     
-/*     This routine is called from gdb_start_a_listen or hcon_progress to attempt
-/*     to continue making progress in accepting a connection on a
-/*     listening connection.
-/*     
-/************************************************************************/
-
-int
-gdb_listen(hc)
-struct  half_con_data *hc;                     /* pointer to control struct */
-                                               /* for this half connection */
-{
-       register HALF_CONNECTION half_con = hc;
-                                               /* half connection pointer */
-                                               /* fast copy in register */
-
-       fd_set tst_bits;                        /* these are used for */
-                                               /* the select we do prior */
-                                               /* to reading which tells */
-                                               /* us whether 0 byte read */
-                                               /* means empty or closed  */
-        int selected;                          /* TRUE iff select says */
-                                               /* we should be able to */
-                                               /* progress */
-
-
-       GDB_INIT_CHECK
-
-       half_con->flags &= ~HCON_PENDING_LISTEN;/* in case we succeed */
-
-       FD_ZERO(&tst_bits);
-       FD_SET(half_con->fd,&tst_bits);
-       selected = select(gdb_mfd,&tst_bits, NULL, NULL, &gdb_notime);
-        /*
-         * If selected==(-1), then we know there's something
-         * wrong with the socket
-         */
-        if (selected == (-1)) {
-               gdb_conok = FALSE;
-               return FALSE;
-        }
-        /*
-         * if selected==0, then we know accept won't do anything, so
-         * don't try.
-         */
-        if (selected == 0) {
-               half_con->flags |= HCON_PENDING_LISTEN;
-               FD_SET(half_con->fd, &gdb_crfds); /* we'll be looking for */
-                                                 /* this whenever we select*/
-               return FALSE;
-        }
-        /*
-         * Selected is >0.  The accept SHOULD not hang.
-         */
-        *(half_con->accepted_fdp) = accept(half_con->fd, half_con->next_byte,
-                                          half_con->accepted_len);
-       /*
-        * See whether the accept succeeded
-        */
-        if (*(half_con->accepted_fdp) < 0) {
-               perror("gdb: start_listening: error on listen");
-               GDB_GIVEUP("Unexpected listen error");
-        }
-
-        FD_CLR(half_con->fd, &gdb_crfds);      /* don't select on this */
-        return TRUE;
-}
diff --git a/gdb/tfsr.c b/gdb/tfsr.c
deleted file mode 100644 (file)
index 60cd168..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_tfsr_c = "$Header$";
-#endif lint
-
-/************************************************************************/
-/*     
-/*                       tfsr (test forking server)
-/*                       --------------------------
-/*     
-/*     Author: Noah Mendelsohn (IBM T.J. Watson Research and MIT Project
-/*                              Athena)
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-/*     
-/*     PURPOSE
-/*     -------
-/*     
-/*     A GDB server program demonstrating techniques for asynchronously
-/*     communicating with an arbitrary number of clients by forking 
-/*     a new server process for each incoming client.
-/*     
-/*     Each forked child  receives a stream of integers,
-/*     which it interprets as ASCII characters.  The characters are
-/*     converted to uppercase, and then sent back to the client from
-/*     which they came.  
-/*     
-/*     NOTE
-/*     ----
-/*     
-/*     This program is interface compatible with tsr.c.  Clients
-/*     cannot tell which style of server they are using.
-/*     
-/************************************************************************/
-
-#include <stdio.h>
-#include "gdb.h"
-
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*                     LOCAL VARIABLES
-       /*      
-       /*----------------------------------------------------------*/
-
-       CONNECTION client;                      /* talk on this to client */
-
-       int data;                               /* receive data here */
-
-\f      /*----------------------------------------------------------*/
-       /*      
-       /*                      EXECUTION BEGINS HERE
-       /*      
-       /*                        Check parameters
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (argc != 2) {
-               fprintf(stderr,"Correct form is %s <servicename>\n",
-                       argv[0]);
-               exit(4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      Initialize
-       /*      
-       /*----------------------------------------------------------*/
-
-       gdb_init();                             /* set up gdb */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Now, turn ourselves into a forking server.
-       /*      
-       /*----------------------------------------------------------*/
-
-       client = create_forking_server(argv[1],NULL);
-       fprintf(stderr,"forked\n");
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Here we are in the child process for each client.
-       /*      Echo the characters.
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (TRUE) {
-               if (receive_object(client, &data, INTEGER_T) ==
-                   OP_CANCELLED) {
-                       fprintf(stderr,"receive error\n");
-                       exit(4);
-               }
-               if (data >= 'a' && data <= 'z')
-                       data += 'A'-'a';        /* upcase the response */
-               if (send_object(client, &data, INTEGER_T) ==
-                   OP_CANCELLED) {
-                       fprintf(stderr,"send error\n");
-                       exit(4);
-               }
-       }
-}
diff --git a/gdb/tsr.c b/gdb/tsr.c
deleted file mode 100644 (file)
index 10bc4c7..0000000
--- a/gdb/tsr.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_tsr_c = "$Header$";
-#endif lint
-
-/************************************************************************/
-/*     
-/*                       tsr (test server)
-/*                       -----------------
-/*     
-/*     Author: Noah Mendelsohn (IBM T.J. Watson Research and MIT Project
-/*                              Athena)
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-/*     
-/*     PURPOSE
-/*     -------
-/*     
-/*     A GDB server program demonstrating techniques for asynchronously
-/*     communicating with an arbitrary number of clients from a single
-/*     Unix server process.  This server accepts GDB connections from
-/*     clients as requests come in (up to the arbitrary maximum
-/*     MAXCLIENTS.)  On each connection, it receives a stream of integers,
-/*     which it interprets as ASCII characters.  The characters are
-/*     converted to uppercase, and then sent back to the client from
-/*     which they came.  
-/*     
-/*     All of this is done completely asynchronously.  No client is 
-/*     locked out while characters are being echoed to another, and
-/*     new connections are accepted at any time.
-/*     
-/*     NOTES
-/*     -----
-/*     
-/*     1) The complete state of each client is kept in the array
-/*        named client.  The client[i].state variable indicates whether
-/*        client i is active, and if so, the client[i].action variable
-/*        indicates what kind of asynchronous activity the client is 
-/*        engaged in.  Note that these are local conventions, having
-/*        nothing to do with GDB or its interfaces.  
-/*     
-/*     2) Communication to each client is done over its connection,
-/*        named client[i].con.
-/*     
-/*     3) There is at most one asynchronous activity pending to 
-/*        each client at any given time, and its state is tracked
-/*        in the variable named client[i].pending_op.  The operation
-/*        may be a send, a receive, or an accept, depending on 
-/*        the contents of client[i].action.  These operations are
-/*        allocated when the server starts up, and then re-used
-/*        repeatedly.  They are the GDB analog of a lightweight process,
-/*        which is activated when queued on a connection.
-/*     
-/*     4) A special form of connection and a special listening operation
-/*        are used for asynchronously listening for new connection
-/*        requests.  These are 'listencon' and 'listenop' respectively.
-\f/*    
-/*     5) GDB includes a special form of select which waits for 
-/*        completion of operations as well as for activity on user
-/*        specified file descriptors.  The list of operations to be
-/*        monitored is stored in the variable
-/*        named op_list.  The call to op_select_any hangs until one
-/*        or more of these operations complete, then terminates.
-/*     
-/*     6) The main server loop acts on any new connection requests,
-/*        processes any newly completed activity on the active
-/*        clients, then drops into op_select_any to allow asynchronous
-/*        activities to progress.  
-/*     
-/*     
-/************************************************************************/
-
-#include <stdio.h>
-#include "gdb.h"
-
-extern int errno;
-
-\f
-/************************************************************************/
-/*     
-/*                          DECLARATIONS
-/*     
-/************************************************************************/
-
-#define MAXCLIENTS 10
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      State of each possible client
-       /*      
-       /*----------------------------------------------------------*/
-
-struct client {
-       int state;                              /* state of this client */
-                                               /* descriptor */
-#define CL_DEAD 1                              /* client not started */
-#define CL_STARTING 2                          /* accepted, reply ongoing */
-#define CL_UP 3                                        /* ready to go */
-       int action;                             /* what are we doing now */
-#define CL_RECEIVE 4                           /* waiting for a packet */
-#define CL_SEND    5                           /* sending a packet */
-#define CL_ACCEPT  6                           /* sending a reply */
-       CONNECTION con;                         /* connection to this */
-                                               /* client, if any */
-       OPERATION pending_op;                   /* pending operation */
-                                               /* on this connection, */
-                                               /* if any */
-       int data;                               /* the character to echo */
-                                               /* goes here, expressed as */
-                                               /* an int  */
-};
-
-struct client client[MAXCLIENTS];
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Connections and operations for listening for
-       /*      new clients.
-       /*      
-       /*----------------------------------------------------------*/
-
-CONNECTION listencon;                          /* listen on this */
-                                               /* connection */
-OPERATION  listenop;                           /* this operation is used */
-                                               /* repeatedly for listening */
-                                               /* for new clients */
-
-int    nextcl = 0;                             /* index of the next client */
-                                               /* we'll accept */
-
-\f      /*----------------------------------------------------------*/
-       /*      
-       /*      Miscellaneous variables used in acquiring connections.
-       /*      These are ignored in a simple server like this;  a 
-       /*      more sophisticated server might want to validate the
-       /*      names of its clients before accepting connections.
-       /*      
-       /*----------------------------------------------------------*/
-
-TUPLE client_tuple;                            /* client request goes */
-                                               /* here */
-char otherside[100];
-int othersize;
-
-
-\f
-/************************************************************************/
-/*     
-/*                             MAIN
-/*     
-/************************************************************************/
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-       /*----------------------------------------------------------*/
-       /*      
-       /*                     LOCAL VARIABLES
-       /*      
-       /*----------------------------------------------------------*/
-
-       register int i;                         /* loop index */
-       LIST_OF_OPERATIONS op_list;             /* for op_select_any */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Check parameters
-       /*      
-       /*----------------------------------------------------------*/
-
-       if (argc != 2) {
-               fprintf(stderr,"Correct form is %s <servicename>\n",
-                       argv[0]);
-               exit(4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*                      Initialize
-       /*      
-       /*----------------------------------------------------------*/
-
-       gdb_init();                             /* set up gdb */
-       init_clients();                         /* null the client states */
-       do_listen(argv[1]);                     /* start the listening */
-                                               /* connection and queue */
-                                               /* a listening operation */
-       make_oplist(&op_list);                  /* create wait list */
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*           Loop forever taking care of business.
-       /*      
-       /*      1) If any new connection requests have come in,
-       /*         accept them.
-       /*      
-       /*      2) For each client on which some activity is newly
-       /*         completed, take care of it.
-       /*      
-       /*----------------------------------------------------------*/
-
-       while (TRUE) {
-               if (OP_DONE(listenop))
-                       new_connection();
-               for (i=0; i<MAXCLIENTS; i++) {
-                       if (OP_DONE(client[i].pending_op))
-                               do_client(i);
-               }
-               if(op_select_any(op_list, 0, NULL, NULL, NULL, NULL)==(-1)) {
-                       perror("op_select_any returned error");
-                       exit(32);
-               }
-       }
-}
-\f
-/************************************************************************/
-/*     
-/*                             do_client
-/*     
-/*     An operation has completed on the specified client.
-/*     
-/************************************************************************/
-
-int
-do_client(id)
-int id;
-{
-       register struct client *cp = &(client[id]);
-
-       /*
-        * If there has been an error, shutdown the client.
-        */
-       connection_perror(cp->con, "Unix error on send or receive"); 
-                                               /* print error if any */
-       if (connection_status(cp->con) != CON_UP ||
-           OP_STATUS(cp->pending_op) == OP_CANCELLED) {
-               sever_connection(cp->con);
-               reset_operation(cp->pending_op);
-               cp->state = CL_DEAD;
-               cp->action = 0;
-               return;
-       }
-       /*
-        * The operation completed successfully.  Figure out what it was
-        * and do the right thing.
-        */
-       switch (cp->action) {
-             case CL_ACCEPT:
-             case CL_SEND:
-               start_receiving_object(cp->pending_op, cp->con, 
-                                      (char *)&cp->data,
-                                      INTEGER_T);
-               cp->action = CL_RECEIVE;
-               break;
-             case CL_RECEIVE:
-               if (cp->data >= 'a' && cp->data <= 'z')
-                       cp->data += 'A'-'a';    /* upcase the response */
-               start_sending_object(cp->pending_op, cp->con, 
-                                      (char *)&cp->data,
-                                      INTEGER_T);
-               cp->action = CL_SEND;
-       }
-}
-\f
-/************************************************************************/
-/*     
-/*                       init_clients
-/*     
-/************************************************************************/
-
-int
-init_clients()
-{
-       register struct client *c;
-
-       for (c=client; c<client+MAXCLIENTS; c++){
-               c->state = CL_DEAD;
-               c->action = 0;
-               c->con = NULL;
-               c->pending_op = create_operation();
-               reset_operation(c->pending_op);         
-       }
-}
-
-
-
-/************************************************************************/
-/*     
-/*                     make_oplist
-/*     
-/************************************************************************/
-
-int
-make_oplist(oplp)
-LIST_OF_OPERATIONS *oplp;
-{
-       /*
-        * ugh! we've got to fix create_list_of_operations to be
-        * more flexible!!
-        */
-
-       *oplp = create_list_of_operations(MAXCLIENTS+1, listenop,
-                                         client[0].pending_op,
-                                         client[1].pending_op,
-                                         client[2].pending_op,
-                                         client[3].pending_op,
-                                         client[4].pending_op,
-                                         client[5].pending_op,
-                                         client[6].pending_op,
-                                         client[7].pending_op,
-                                         client[8].pending_op,
-                                         client[9].pending_op);
-}
-\f/************************************************************************/
-/*     
-/*                             do_listen
-/*     
-/*     Do the one time setup for listening for clients, and
-/*     also start a listen for an actual client.
-/*     
-/************************************************************************/
-
-int
-do_listen(service)
-char *service;
-{
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      Make a listening connection
-       /*      
-       /*----------------------------------------------------------*/
-
-       fprintf(stderr, "Server creating listening connection\n");
-       listencon = create_listening_connection(service);
-
-       if (listencon == NULL  || connection_status(listencon) != CON_UP) {
-               if(connection_status(listencon) == CON_STOPPING) {
-                       connection_perror(listencon, 
-                                         "Unix error creating listening connection");
-               }
-               fprintf(stderr,"tsr: could not create listening connection\n");
-               exit (4);
-       }
-
-       /*----------------------------------------------------------*/
-       /*      
-       /*      On that connection, put up an operation to listen
-       /*      for our first client.
-       /*      
-       /*----------------------------------------------------------*/
-
-       listenop = create_operation();
-
-       othersize = sizeof(otherside);
-
-       start_accepting_client(listencon, listenop, &(client[nextcl].con),
-                              (char *)otherside,
-                              &othersize, &client_tuple);
-
-}
-\f
-/************************************************************************/
-/*     
-/*                     new_connection
-/*     
-/*     We have just gotten a connection for client nextcl.  
-/*     
-/************************************************************************/
-
-int
-new_connection()
-{
-       register struct client *cp = &client[nextcl];
-       /*
-        * Make sure there's been no error
-        */
-       if(connection_status(listencon) != CON_UP) {
-               connection_perror(listencon, "Unix error on listening connection");
-               fprintf(gdb_log, "Listening connection has died.\n");
-               exit(8);
-       }
-       if(OP_STATUS(listenop) != OP_COMPLETE ||
-          cp->con == NULL || connection_status(cp->con) != CON_UP) {
-               fprintf(stderr,"Error on listening operation\n");
-               if (cp->con != NULL && 
-                   connection_status(cp->con)==CON_STOPPING) {
-                        connection_perror(cp->con, 
-                                          "Error on newly started client connection.");
-                        sever_connection(cp->con);
-                        cp->con = NULL;
-               } else
-                       exit(8);
-       } else {
-              /*
-               * Set up the new connection and reply to the client
-               */
-               cp->state = CL_STARTING;
-               cp->action = CL_ACCEPT;
-               start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
-                                        "", "");
-              /*
-               * Find a new free connection descriptor.  Blow up if
-                * we've used the last one
-               */
-               for (nextcl=0; nextcl<MAXCLIENTS; nextcl++)
-                       if (client[nextcl].state == CL_DEAD)
-                               break;
-
-               if (nextcl == MAXCLIENTS) {
-                       fprintf(stderr,"Too many clients, giving up\n");
-                       exit(8);
-               }
-       }
-       /*
-        * Start listening again
-        */
-       reset_operation(listenop);
-       othersize = sizeof(otherside);
-
-       start_accepting_client(listencon, listenop, &(client[nextcl].con),
-                              (char *)otherside,
-                              &othersize, &client_tuple);
-
-
-}
diff --git a/gdb/tst.c b/gdb/tst.c
deleted file mode 100644 (file)
index 712baf0..0000000
--- a/gdb/tst.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *     $Source$
- *     $Header$
- */
-
-#ifndef lint
-static char *rcsid_tst_c = "$Header$";
-#endif lint
-
-/************************************************************************/
-/*     
-/*                             tst.c
-/*     
-/*     A test program for the client library interface.
-/*     
-/*     Author: Noah Mendelsohn
-/*     
-/*     Copyright: 1986 MIT Project Athena
-/*     
-/************************************************************************/
-
-#include <stdio.h>
-#include "gdb.h"
-
-char *field_names[] = {"desc", 
-                      "code",
-                      "man",
-                      "cost",
-                      "count"};
-FIELD_TYPE field_types[] = {STRING_T,      /* desc */
-                           INTEGER_T,      /* code */
-                           STRING_T,       /* man */
-                           REAL_T,         /* cost */
-                           INTEGER_T};     /* count */
-
-FILE *coded_file;
-
-int
-main(argc, argv)
-int    argc;
-char   *argv[];
-{
-
-\f      /************************************************************
-        *                  DECLARATIONS                            *
-        ************************************************************/
-
-       /*
-        * Declare the names of fields to be retrieved and their types
-        */
-
-       int  field_count = 5;
-       int i;
-       /*
-        * The following defines are for convenience in addressing
-        * the fields.
-        */
-
-#define DESC  0
-#define CODE  1
-#define MAN   2
-#define COST  3
-#define COUNT 4
-
-       /*
-        * Declare the relation and related data structures for
-        * storing the retrieved data.
-        */
-
-       TUPLE_DESCRIPTOR tuple_desc;
-       RELATION retrieved_data, decoded_rel;
-
-       /*
-        * Declarations for misc. variables
-        */
-       
-       TUPLE   t;                      /* next tuple to print */
-       int coded_len;
-       char *coded_dat;
-
-       int     rc;                     /* A return code */     
-
-\f      /************************************************************
-        *             EXECUTION BEGINS HERE                        *
-        ************************************************************/
-
-       /*
-        * Build the descriptor describing the layout of the tuples
-        * to be retrieved, and create an empty relation into which
-        * the retrieval will be done.
-        */
-
-       gdb_init();                             /* initialize the global */
-                                               /* database facility */
-
-       printf("tst.c: attempting to create tuple descriptor\n");       
-
-       tuple_desc = create_tuple_descriptor(field_count, field_names,
-                                            field_types);
-
-       printf("tst.c: tuple desc created.. attempting to create relation\n");
-       retrieved_data = create_relation(tuple_desc);
-
-       printf("tst.c: relation created, formatting descriptor\n");
-
-
-       print_tuple_descriptor("Test Tuple Descriptor", tuple_desc);
-
-       printf("tst.c: descriptor formatted, formatting relation\n");
-
-       print_relation("Test Relation", retrieved_data);
-
-       printf("Creating tuples\n");
-
-       for (i=0; i<3; i++) {
-               t = create_tuple(tuple_desc);
-               
-               initialize_tuple(t);
-
-               fprintf(stderr, "Following tuple should contain null fields:\n\n");
-
-               print_tuple("A NULL TUPLE", t);
-
-               *(int *)FIELD_FROM_TUPLE(t, CODE) = i+1;
-
-               *(double *)FIELD_FROM_TUPLE(t, COST) = 12.34 * (i+1);
-               string_alloc((STRING *)FIELD_FROM_TUPLE(t,MAN), 20);
-               strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,MAN))),
-                      "Manager field data");
-               ADD_TUPLE_TO_RELATION(retrieved_data, t);               
-       }
-
-
-       printf("tst.c: relation initialized, formatting relation\n");
-
-       print_relation("Test Relation", retrieved_data);
-
-
-/*
- *  Try to encode the entire relation!!
- */
-
-       printf("Attempting to encode the relation\n");
-
-       coded_len = FCN_PROPERTY(RELATION_T, CODED_LENGTH_PROPERTY)
-             (&retrieved_data, NULL);
-
-       coded_dat = (char *)malloc(coded_len);
-
-       FCN_PROPERTY(RELATION_T, ENCODE_PROPERTY)
-         (&retrieved_data, NULL, coded_dat);
-
-       printf("Relation encoding complete, writing file \n\n");
-
-       coded_file = fopen("coded.dat", "w");
-
-       fwrite(coded_dat, 1, coded_len, coded_file);
-
-       fclose(coded_file);
-
-       printf("File written\n");
-
-       printf("Decoding relation\n\n");
-
-       FCN_PROPERTY(RELATION_T, DECODE_PROPERTY)
-         (&decoded_rel, NULL, coded_dat);
-
-       printf("Relation decoded!!  Printing it\n\n");
-
-       print_relation("Decoded Relation", decoded_rel);
-
-
-       printf("tst.c: exit\n");
-
-       return 0;
-}
index ec41c78956509608e9c8d60d5b470029df79801a..09aad020c8a68cf01801a5ab16836794d2a773fd 100644 (file)
@@ -8,8 +8,8 @@
 # Imakefile for include.
 #
 
-CODE=Imakefile gdb.h mit-copyright.h \
-       moira.h moira_site.h mr_proto.h update.h ureg_proto.h
+CODE=Imakefile mit-copyright.h \
+       moira.h moira_site.h update.h ureg_proto.h
 SRCDIR=$(SRCTOP)/include
 
 all::
diff --git a/include/gdb.h b/include/gdb.h
deleted file mode 100644 (file)
index 60a612c..0000000
+++ /dev/null
@@ -1,1462 +0,0 @@
-/*
- *     $Header$
- */
-
-/************************************************************************
- *     
- *                     gdb.h
- *     
- *     Includes for the global database facility (gdb)
- *     
- *     Author: Noah Mendelsohn
- *     Copyright: 1986 MIT Project Athena
- *     
- ************************************************************************/
-
-/*
- * Note: following include may safely be done redundantly, so it doesn't
- * matter if caller does it too.  We need it for fd_set.
- */
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <stdio.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef max
-#define max(a,b) ((a)>(b)?(a):(b))
-#endif
-
-#ifndef min
-#define min(a,b) ((a)<(b)?(a):(b))
-#endif
-
-#ifndef NFDBITS
-#define NFDBITS 32
-#endif
-#ifndef howmany
-#define        howmany(x, y)   (((x)+((y)-1))/(y))
-#endif
-#ifndef FD_SETSIZE
-#define FD_SETSIZE 256
-#endif
-#ifndef FD_SET
-#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
-#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
-#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
-#define FD_ZERO(p)      bzero(p, sizeof(*(p)))
-typedef long fd_mask;
-typedef struct fd_set {fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];} fd_set;
-#endif 
-
-/* 32-bit type for consistency in data sent across the network */
-#ifdef SIXTYFOUR
-#define int32 int
-#define uint32 u_int
-#else
-#define int32 long
-#define uint32 u_long
-#endif
-
-       /*----------------------------------------------------------*
-        *      
-        *                      GDB_GIVEUP
-        *      
-        *      This macro is called with a string argument whenever a
-        *      fatal error is encounterd.  If you re-define this
-        *      macro, you can control the disposition of fatal gdb
-        *      errors.
-        *      
-        *      The gdb library must be recompiled for the change to
-        *      take effect.  That will have to be fixed sometime.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_GIVEUP(errormsg) g_givup(errormsg);
-
-       /*----------------------------------------------------------*
-        *      
-        *                      GDB_ROUNDUP
-        *      
-        *      Round a number up to the next specified boundary.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_ROUNDUP(n,b) ((((n)+(b)-1)/(b))*(b))
-
-extern int     gdb_Options;                    /* Control optional features */
-#define GDB_OPT_KEEPALIVE      1
-extern int     gdb_Debug;                      /* debugging flags are */
-                                               /* stored here */
-extern FILE *gdb_log;                          /* file descriptor for */
-                                               /* logging gdb output */
-
-
-/*
- *                     connection failure indicator
- * 
- * This variable is used to communicate between gdb_move_data and
- * g_con_progress without passing an extra parameter through lots
- * of procedure calls.  When set to FALSE, it indicates that the 
- * connection currently being processed has encountered a fatal error
- * and should be severed.
- */
-extern int gdb_conok;                                  
-/************************************************************************
- *     
- *                         USER IDENTIFICATION
- *     
- *     gdb_init puts the user's i.d. and hostname as strings here.
- *     
- ************************************************************************/
-
-extern char *gdb_uname;                                /* user's string name */
-extern char *gdb_host;                         /* name of local host */
-                                               /* goes here */
-
-
-\f
-/************************************************************************
- *     
- *     
- *                       TYPE MANAGEMENT
- *     
- *     Declarations used to control the definition and use of 'types'
- *     as supported by the global database system.  Most of the 
- *     declarations for 'System Defined Types' will not be of concern
- *     to typical users, with the exception of the type names like
- *     INTEGER_T which are defined below.
- *     
- *     In this implementation, user defined types are added
- *     dynamically during execution by calling the appropriate
- *     functions.  The define GDB_MAX_TYPES below sets the maximum
- *     total number of types, including both system and user defined,
- *     which the system can support for any one application.  When
- *     GDB_MAX_TYPES is changed, the libary must be re-built.  Space
- *     for a two dimensional array, with one word for each property
- *     of each possible type, is allocated statically in the library.
- *     
- ************************************************************************/
-
-
-/*
- * Maximum number of types we can support, including both system and
- * user defined.
- */
-
-#define GDB_MAX_TYPES 50
-
-typedef int FIELD_TYPE;                                /* data needed to repre- */
-                                               /* sent a system or user */
-                                               /* defined data type */
-                                               /* This is actualy just */
-                                               /* a row index in the type */
-                                               /* definition table */
-
-       /*----------------------------------------------------------
-        *      
-        *              System defined types
-        *      
-        *      WARNING: Any changes to these type definitions must be
-        *      carefully matched with the initializations in the
-        *      gdb_i_stype routine in gdb_stype.c.  Mistakes in these
-        *      tables may be VERY difficult to debug.  Be careful!
-        *      
-        *----------------------------------------------------------*/
-
-/*
- * Primitive types for ingres data
- */
-
-#define INTEGER_T (0)
-#define STRING_T (1)
-#define REAL_T (2)
-#define DATE_T (3)
-
-/*
- * Structured types
- */
-
-#define TUPLE_DESCRIPTOR_T (4)
-#define TUPLE_T (5)
-#define TUPLE_DATA_T (6)
-#define RELATION_T (7)
-
-/*
- * Number of system defined types
- * 
- * This will always be equal to one more than index of last system type
- */
-
-#define SYSTEM_TYPE_COUNT 8
-
-       /*----------------------------------------------------------
-        *      
-        *              Type descriptor tables
-        *      
-        *----------------------------------------------------------*/
-
-/*
- *                     gdb_prop_union
- * 
- * Each entry in the type definition table is a union of this form,
- * which allows us to store a choice of an integer, a function 
- * pointer, or a pointer to a character string.
- */
-
-union gdb_prop_union {
-       int i;                                  /* when we want as an */
-                                               /* integer */
-       int (*f)();                             /* as a function pointer */
-       char *cp;                               /* character pointer  */
-       char *(*cpf)();                         /* string function pointer */
-};
-
-#define TYPE_PROPERTY_COUNT 8                  /* number of properties */
-                                               /* for each type*/
-
-/*
- * Uses of the type properties.  Each type has a set of properties.
- * Some are integers, some are functions.  The defines below descrive
- * respectively the 0'th,1'st, 2'nd, etc. properties of EACH type.
- * 
- * Note:  TYPE_PROPERTY_COUNT (above) must be changed when new properties
- * are added.  For system defined types, bindings for the properties
- * are done in gdb_i_stype in the gdb_stype.c source file.
- */
-
-#define LENGTH_PROPERTY 0                      /* integer */
-#define ALIGNMENT_PROPERTY 1                   /* integer */
-#define NULL_PROPERTY 2                                /* function */
-#define CODED_LENGTH_PROPERTY 3                        /* function */
-#define ENCODE_PROPERTY 4                      /* string function */
-#define DECODE_PROPERTY 5                      /* string function */
-#define FORMAT_PROPERTY 6                      /* function */
-#define NAME_PROPERTY 7                                /* char pointer */
-
-/*
- *                     gdb_type_def
- * 
- * Information to describe a single type
- */
-
-typedef union gdb_prop_union gdb_type_def[TYPE_PROPERTY_COUNT];
-
-
-/*
- *                     g_type_table
- * 
- * This is the table where the actual definitions for the types are
- * kept.
- */
-
-extern gdb_type_def g_type_table[GDB_MAX_TYPES];
-extern int gdb_n_types;                                /* number of entries in */
-                                               /* table */
-
-       /*----------------------------------------------------------
-        *      
-        *          Macros for accessing properties
-        *      
-        *----------------------------------------------------------*/
-
-#define INT_PROPERTY(type, prop) (g_type_table[type][prop].i) 
-#define STR_PROPERTY(type, prop) (g_type_table[type][prop].cp) 
-#define FCN_PROPERTY(type, prop) (*g_type_table[type][prop].f) 
-
-\f
-/************************************************************************
- *     
- *                        STRUCTURED DATA
- *     
- *     Stuff needed to declare and manage TUPLES, TUPLE_DESCRIPTORS
- *     and RELATIONS.
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *                 TUPLE_DESCRIPTOR
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_DESC_ID 0x54504400                 /* "TPD" */
-
-struct tupld_var {                             /* the variable length */
-                                               /* stuff in a tuple */
-                                               /* descriptor*/
-       char *name;                             /* string name of field */
-       FIELD_TYPE type;                        /* type of this field */
-       int  offset;                            /* byte offset of this field */
-                                               /* relative to first byte of */
-                                               /* data (not start of whole */
-                                               /* tuple) */
-       int length;                             /* Length of the actual data */
-                                               /* for this field. Note that */
-                                               /* alignment requirements of */
-                                               /* following field are NOT */
-                                               /* included in this length */
-};
-struct tupl_desc {
-       int32 id;                               /* this should say TPD\0 */
-       int ref_count;                          /* when this goes to zero, */
-                                               /* the descriptor may really */
-                                               /* be reclaimed */
-       int field_count;                        /* number of fields in */
-                                               /* the tuple*/
-       int data_len;                           /* length of the data in */
-                                               /* the actual tuple */
-       int str_len;                            /* length of the strings */
-                                               /* stored off the end of */
-                                               /* this descriptor*/
-       struct tupld_var var[1];                /* one of these for each */
-                                               /* field, but the C compiler */
-                                               /* won't accept the[] decl, */
-                                               /* because it's afraid of */
-                                               /* uncertain length*/
-};
-
-typedef struct tupl_desc *TUPLE_DESCRIPTOR;    /* use this to declare a */
-                                               /* tuple descriptor anchor */
-
-#define gdb_descriptor_length(num_flds) (sizeof(struct tupl_desc) + ((num_flds)-1) * sizeof(struct tupld_var))
-
-       /*----------------------------------------------------------
-        *      
-        *                      TUPLE
-        *      
-        *      tuple_dat is allocated by the create_tuple routine.
-        *      
-        *      TUPLE may be used in user code to declare a handle
-        *      on a tuple.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_TUP_ID 0x54555000
-
-typedef struct tuple_dat *TUPLE;               /* handle on a tuple */
-
-struct tuple_dat {
-       TUPLE next, prev;                       /* chain pointers when */
-                                               /* tuples are linked, as in */
-                                               /* a relation.  Convention is*/
-                                               /* double linked, circular.*/
-       int32 id;                               /* should say TUP\0  */
-       TUPLE_DESCRIPTOR desc;                  /* pointer to the descriptor */
-       char data[1];                           /* data goes here, word */
-                                               /* aligned.  Should be [] */
-                                               /* if compiler would allow */
-};
-
-
-       /*----------------------------------------------------------
-        *      
-        *                    RELATION
-        *      
-        *      rel_dat is allocated by the create_relation
-        *      routine.
-        *      
-        *      RELATION may be used in user code to declare a handle
-        *      on a relation.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_REL_ID 0x52454c00
-
-struct rel_dat {
-       TUPLE first, last;                      /* chain pointers to tuples */
-                                               /* note that first->prev and */
-                                               /* last->next are both == */
-                                               /* &rel-dat.  Maintenance is */
-                                               /* simplified by keeping */
-                                               /* as the first fields in */
-                                               /* both rel_dat and tuple_dat*/
-                                               /* a minor non-portability */
-       int32 id;                               /* should contain REL\0  */
-       TUPLE_DESCRIPTOR desc;                  /* descriptor for the tuples */
-                                               /* in this relation. Should */
-                                               /* == that in each tuple */
-
-};
-
-typedef struct rel_dat *RELATION;              /* handle on a relation */
-\f
-/************************************************************************
- *     
- *                   transport LAYER DECLARATIONS
- *     
- *     Declares the state maintenance structures for full duplex 
- *     connections with asynchronous transmission capability.  Most
- *     users need only know that the type CONNECTION is defined, and
- *     that it may be treated as a pointer for most purposes (i.e. it
- *     is compact, and copying it does not actually copy the connection
- *     state.)
- *     
- ************************************************************************/
-
-#define GDB_PROTOCOL_VERSION 0x01              /* version of the gdb */
-                                               /* protocols that we're */
-                                               /* observing */
-#define GDB_STREAM_BUFFER_SIZE 4096            /* amount to read in */
-                                               /* one chunk from tcp stream*/
-#define GDB_PORT htons(9425)                   /* temporary until we use */
-                                               /* services properly */
-#define GDB_BIND_RETRY_COUNT 5                 /* number of times to */
-                                               /* retry a bind before */
-                                               /* giving up.  Used when */
-                                               /* accepting connections */
-#define GDB_BIND_RETRY_INTERVAL 10             /* Number of seconds to wait */
-                                               /* between attempts to bind */
-                                               /* the listening socket */
-#define GDB_MAX_CONNECTIONS 40                 /* maximum number of */
-                                               /* connections that */
-                                               /* any one process can */
-                                               /* control simultaneously */
-/*
- * Circumvent bug in ACIS 4.2 socket support
- */
-#ifdef ibm032
-#define GDB_MAX_SOCK_WRITE 2047                        /* rt can't do socket */
-                                               /* writes longer than this */
-                                               /* gives errno 40*/
-#else
-#define GDB_MAX_SOCK_WRITE 0x00ffffff
-#endif
-
-       /*----------------------------------------------------------
-        *      
-        *           Declarations for HALF_CONNECTIONS
-        *      
-        *      Each full duplex connection has associated with it 
-        *      two simplex half-connections, each of which 
-        *      has its own queue of pending operations.  The
-        *      following describes the state of a half-connection.
-        *      
-        *----------------------------------------------------------*/
-
-struct half_con_data {
-       /*
-        * these two must be first to match position in OPERATION
-        */
-       struct oper_data *op_q_first;           /* first item in q of pending*/
-                                               /* operations for this */
-                                               /* half-connection. (chained */
-                                               /* circularly to half con, */
-                                               /* NOT the con. */
-       struct oper_data *op_q_last;            /* last item in q of pending*/
-                                               /* operations for this */
-                                               /* half-connection*/
-       int status;                             /* values are of type */
-                                               /* OPSTATUS. tells whether */
-                                               /* transmit/receive is */
-                                               /* pending.*/
-       int32 flags;                            /* bit flags */
-#define HCON_PROGRESS 0x00000001               /* used by selection */
-                                               /* routines to detect */
-                                               /* progress */
-#define HCON_LISTEN   0x00000002               /* indicates that this is */
-                                               /* a special half connection */
-                                               /* used only for listenting */
-                                               /* to incoming connection */
-                                               /* requests */
-#define HCON_UNUSED   0x00000004               /* on a one-way connection, */
-                                               /* this flag marks an unused */
-                                               /* half */
-#define HCON_PENDING_LISTEN 0x00000008         /* a queued op on this half */
-                                               /* connection is actually */
-                                               /* trying to listen */
-#define HCON_BUSY     0x00000010               /* we are currently making */
-                                               /* progress on this half */
-                                               /* connection.  Used to */
-                                               /* detect re-entrance of */
-                                               /* hcon_progress */
-       int fd;                                 /* main half duplex file */
-                                               /* descriptor for this h_conn*/
-       int oob_fd;                             /* file descriptor for */
-                                               /* out of band signals*/
-       char *next_byte;                        /* next byte to send/recv */
-       int remaining;                          /* number of bytes remaining */
-                                               /* to send/receive */
-       char *stream_buffer;                    /* points to a buffer */
-                                               /* used to pre-read/write */
-                                               /* the stream to avoid */
-                                               /* window thrashing */
-       int stream_buffer_length;               /* length of the stream */
-                                               /* buffer */
-       char *stream_buffer_next;               /* next byte to read in */
-                                               /* stream buffer */
-       int stream_buffer_remaining;            /* number of bytes currently */
-                                               /* in use in stream buffer*/
-       int *accepted_fdp;                      /* used only for listening */
-                                               /* connections.  latest */
-                                               /* accepted fd is put where*/
-                                               /* this points */
-       int *accepted_len;                      /* ptr to length of 'from' */
-                                               /* data on accept  */
-
-};
-
-typedef struct half_con_data *HALF_CONNECTION;
-
-
-       /*----------------------------------------------------------
-        *      
-        *           Declarations for CONNECTIONS
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_CON_ID 0x434f4e00 /*"CON"*/
-
-struct con_data {
-       int32   id;                             /* should contain CON\0  */
-       int status;                             /* See definitions below. */
-                                               /* Do not confuse with */
-                                               /* the status sub-fields of */
-                                               /* in and out half-cons. */
-       int version;                            /* the version of the */
-                                               /* protocol being observed */
-                                               /* on this connection */
-       int errno;                              /* the real errno gets */
-                                               /* copied here if it causes */
-                                               /* the connection to die */
-       int (*oob_fcn)();                       /* pointer to function to */
-                                               /* call when something */
-                                               /* arrives on the out of */
-                                               /* band channel */
-       struct half_con_data in, out;           /* states of the inbound */
-                                               /* and outbound half */
-                                               /* sessions.*/
-};
-
-typedef struct con_data *CONNECTION;           /* the only externally */
-                                               /* visible handle on a */
-                                               /* connection*/
-
-/*
- * Definitions of status fields.
- * 
- * WARNING: If you change any of the following, there are coordinated
- * changes to be made in gdb_debug.c
- */
-
-#define CON_STOPPED 1                          /* never started, terminated */
-#define CON_UP 2                               /* ready to use */
-#define CON_STARTING 3                         /* trying to start */
-#define CON_STOPPING 4                         /* trying to stop */
-
-/*
- * The following are used as keywords when distinguishing input from output
- * half connections.
- */
-#define CON_INPUT 1                            /* this is an input half */
-                                               /* session*/
-#define CON_OUTPUT 2                           /* this is an output half */
-                                               /* session*/
-
-
-       /*----------------------------------------------------------
-        *      
-        *                      gdb_cons
-        *      
-        *      This is the array of connection control data 
-        *      structures for gdb.  Every connection has its 
-        *      structure stored here, but they are in no 
-        *      particular order.  Because the connection data
-        *      itself cannot be moved (due to possible dangling
-        *      pointers), there may be some unused connections 
-        *      in the middle of this array.  gdb_mcons is the
-        *      1 based number of the highest connection which is
-        *      actually in use at this time.  This is a considerable
-        *      optimization for the typical case where very few
-        *      are in use, and turnover is low.
-        *      
-        *      These are externs for globals defined in gdb_lib.h
-        *      and included by gdb.c.
-        *      
-        *----------------------------------------------------------*/
-
-extern int  gdb_mcons;                         /* one based number of the */
-                                               /* highest connection */
-                                               /* descriptor we're using */
-                                               /* at the moment */
-
-extern int  gdb_mfd;                           /* number of the highest */
-                                               /* file descriptor in use */
-                                               /* for a connection */
-extern struct con_data gdb_cons[GDB_MAX_CONNECTIONS];
-                                               /* actual connection data */
-                                               /* is stored here */
-
-extern fd_set gdb_crfds, gdb_cwfds, gdb_cefds; /* connection related file */
-                                               /* descriptor maps to be */
-                                               /* used in select */
-extern fd_set last_crfds, last_cwfds, last_cefds;/* these file desc. bit */
-                                               /* masks are set up */
-                                               /* for each select call */
-                                               /* to include the user */
-                                               /* supplied and the */
-                                               /* connection related */
-                                               /* fd's */
-
-       /*----------------------------------------------------------
-        *      
-        *                      OPERATIONS
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_OP_ID 0x4f505200
-
-struct oper_data {
-       struct oper_data *next, *prev;          /* forward and back chain */
-       int32 id;                               /* should contain OPR\0  */
-       int tag;                                /* unique identifier for */
-                                               /* this operation */
-       int status;                             /* current state of this */
-                                               /* oaperation*/
-       int flags;
-#define OPF_MARKED_COMPLETE 0x00000001         /* operation was already */
-                                               /* complete when opsel was */
-                                               /* called*/
-#define OPF_MARKED_CANCELLED 0x00000002                /* operation was already */
-                                               /* cancelled when opsel was */
-                                               /* called*/
-       int result;                             /* when the operation */
-                                               /* completes, this field is */
-                                               /* set to reflect its dispos-*/
-                                               /* ition. Contents of this */
-                                               /* field will depend on the */
-                                               /* operation being performed */
-       HALF_CONNECTION halfcon;                /* the half connection on */
-                                               /* which this operation is */
-                                               /* queued */
-                                               /* May be meaningless if not */
-                                               /* queued..*/
-       char *arg;                              /* pointer to user data */
-       union fcn {
-               int (*init)();                  /* pointer to routine to */
-                                               /* call to start this */
-                                       
-       /* operation*/
-               int (*cont)();                  /* pointer to function to */
-                                               /* be called when this */
-                                               /* logical operation */
-                                               /* continues*/
-       } fcn;
-
-       int (*cancel)();                        /* this routine gets called */
-                                               /* to handle a cancel request*/
-                                               /* this field is normally */
-                                               /* set to NULL when the */
-                                               /* operation is queued and */
-                                               /* updated as required by */
-                                               /* the init and cont funcs. */
-};
-
-typedef struct oper_data OPERATION_DATA;       /* an actual operation */
-                                               /* descritor, creator is */
-                                               /* responsible for making */
-                                               /* sure that memory is not */
-                                               /* freed while in use */
-typedef OPERATION_DATA *OPERATION;             /* a handle on an operation */
-                                               /* this is what most */
-                                               /* applications will use */
-
-       /*----------------------------------------------------------
-        *      
-        *                STATES OF AN OPERATION
-        *      
-        *      These represent the state of an asynchronous, queued
-        *      operation.  For convenience of the application programmer,
-        *      some of these are folded together when queried through the
-        *      operation_status routine.  In particular, operation status
-        *      returns only one of:
-        *      
-        *      OP_NOT_RUNNING, OP_RUNNING, OP_COMPLETE,  or 
-        *      OP_CANCELLED.
-        *      
-        *      Any other status is reported as OP_RUNNING.  This is
-        *      done on the assumption that it makes correct coding
-        *      of applications less error-prone, as there are fewer
-        *      cases to check, and most of them would not be of 
-        *      interest anyway.
-        *      
-        *      Note that OP_CANCELLED may be generated by the system
-        *      even when no explicit request for cancellation has been
-        *      issued.  For example, this may occur when a connection
-        *      is severed unexpectedly.
-        *      
-        *      WARNING:  If you change any of the following, be sure
-        *      to make the equivalent changes to gdb_debug.c.
-        *      
-        *      We also define here certain standard values of OP_RESULT,
-        *      since some return conventions presume that op_status 
-        *      and op_result values are orthogonal.
-        *      
-        *----------------------------------------------------------*/
-
-#define OP_SUCCESS     0                       /* this value is actually */
-                                               /* used only in result */
-                                               /* fields, but it is */
-                                               /* sometimes convenient to */
-                                               /* have status and result */
-                                               /* have orthogonal values */
-#define OP_NOT_STARTED 1                       /* this operation has been */
-                                               /* initialized but is not on */
-                                               /* any connection's queue */
-#define OP_QUEUED 2                            /* this operation is on */
-                                               /* some connection's queue */
-                                               /* but it has not yet */
-                                               /* reached the head of the q */
-#define OP_RUNNING 3                           /* op is at head of q trying */
-                                               /* to progress */
-#define OP_COMPLETE 4                          /* operation has run to */
-                                               /* completion.  result field */
-                                               /* is now valid */
-#define OP_CANCELLING 5                                /* we are in the process of */
-                                               /* (trying to) cancel this */
-                                               /* operation */
-#define OP_CANCELLED 6                         /* operation was prematurely */
-                                               /* terminated.  result field */
-                                               /* is NOT valid. */
-#define OP_MARKED 7                            /* used by op_select_all */
-#define OP_REQUEUED 8                          /* returned by an init or */
-                                               /* continuation routine to */
-                                               /* indicate that the */
-                                               /* operation has requeued */
-                                               /* itself */
-#define OP_PREEMPTED 9                         /* returned by an init or */
-                                               /* continuation routine to */
-                                               /* indicate that the op has */
-                                               /* preempted itself by */
-                                               /* queueing a new operation */
-                                               /* ahead of itself */
-
-       /*----------------------------------------------------------
-        *      
-        *                   LIST_OF_OPERATIONS
-        *      
-        *----------------------------------------------------------*/
-
-struct oper_list {
-       int     count;                          /* number of operations */
-                                               /* in the list */
-       OPERATION op[1];                        /* really op[n], but */
-                                               /* structs must have a */
-                                               /* definite length */
-};
-
-typedef struct oper_list *LIST_OF_OPERATIONS;  /* handle on a list */
-
-#define size_of_list_of_operations(n)                                  \
-               (sizeof(struct oper_list) + (n-1)*sizeof(OPERATION))
-
-       /*----------------------------------------------------------
-        *      
-        *                      gdb_notime
-        *      
-        *      Pass this to select when doing a poll.
-        *      
-        *----------------------------------------------------------*/
-
-extern struct timeval gdb_notime;
-
-\f
-/************************************************************************
- *     
- *             CHECKING ROUTINES IMPLEMENTED AS MACROS
- *     
- ************************************************************************/
-
-extern char g_errstr[150];                     /* build emsgs here */
-
-#define GDB_INIT_CHECK g_chk_init();           /* make sure gdb_init */
-                                               /* was called */
-
-#define GDB_CHECK_CON(con, where) if ((con)->id != GDB_CON_ID) \
-       { (void) sprintf(g_errstr, "Invalid connection descriptor passed to \"%s\"\n", where); \
-       GDB_GIVEUP(g_errstr) }
-
-
-#define GDB_CHECK_TUP(tup, where) if ((tup)->id != GDB_TUP_ID) \
-       { (void) sprintf(g_errstr, "Invalid tuple passed to \"%s\"\n", where); \
-       GDB_GIVEUP(g_errstr) }
-
-
-#define GDB_CHECK_TPD(tpd, where) if ((tpd)->id != GDB_DESC_ID) \
-       { (void) sprintf(g_errstr, "Invalid tuple descriptor passed to \"%s\"\n", where); \
-       GDB_GIVEUP(g_errstr) }
-
-
-#define GDB_CHECK_REL(rel, where) if ((rel)->id != GDB_REL_ID) \
-       { (void) sprintf(g_errstr, "Invalid relation passed to \"%s\"\n", where); \
-       GDB_GIVEUP(g_errstr) }
-
-#define GDB_CHECK_OP(op, where) if ((op)->id != GDB_OP_ID) \
-       { (void) sprintf(g_errstr, "Invalid operation passed to \"%s\"\n", where); \
-       GDB_GIVEUP(g_errstr) }
-
-#define GDB_CHECK_DB(db, where) if (db->id != GDB_DB_ID) \
-       { (void) sprintf(g_errstr, "Invalid database handle passed to \"%s\"\n", where); \
-       GDB_GIVEUP(g_errstr) }
-
-
-
-\f
-/************************************************************************
- *     
- *             TRANSPORT ROUTINES IMPLEMENTED AS MACROS
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *                 connection_status
-        *      
-        *      Returns the status of the indicated connection.
-        *      Possible return values are:
-        *      
-        *              CON_STOPPED     never started or terminated
-        *              CON_UP          currently usable
-        *              CON_STARTING    transient state on way up
-        *              CON_STOPPING    transient state on way down
-        *      
-        *----------------------------------------------------------*/
-
-#define connection_status(con) ((con)->status)
-
-       /*----------------------------------------------------------
-        *      
-        *                 connection_errno
-        *      
-        *      When a connection dies due to an error on a system
-        *      call, the corresponding errno is recorded in the 
-        *      connection descriptor.  This macro returns that value.
-        *      
-        *----------------------------------------------------------*/
-
-#define connection_errno(con) ((con)->errno)
-
-
-\f
-/************************************************************************
- *     
- *                    SERVER/CLIENT MANAGEMENT
- *     
- *     Definitions used in starting and maintaining communication 
- *     between servers and clients (as opposed to peers.)
- *     
- ************************************************************************/
-
-#define GDB_MAX_SERVER_RETRIES 3               /* maximum number of times */
-                                               /* clients will accept */
-                                               /* forwarding requests from */
-                                               /* a given server */
-
-
-extern TUPLE_DESCRIPTOR gdb_tosrv;             /* descriptor for request */
-                                               /* tuples sent to the */
-                                               /* server during negotiation*/
-
-extern TUPLE_DESCRIPTOR gdb_fmsrv;             /* descriptor for request */
-                                               /* tuples sent from the */
-                                               /* server during negotiation*/
-
-#define GDB_MAX_SERVER_ID_SIZE 255             /* longest name of a server */
-                                               /* that we can handle */
-#define GDB_MAX_SERVER_PARMS_SIZE 1023         /* longest parm string we */
-                                               /* can exchange between */
-                                               /* server and client*/
-
-       /*----------------------------------------------------------
-        *      
-        *      The following are values returned in the disposition
-        *      field of the response tuple to indicate what the
-        *      server has decided to do about the connection 
-        *      request.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_ACCEPTED 1
-#define GDB_REFUSED  2
-#define GDB_FORWARDED 3
-
-       /*----------------------------------------------------------
-        *      
-        *      Global variables inherited by a child from a server
-        *      parent.
-        *      
-        *----------------------------------------------------------*/
-
-extern TUPLE gdb_client_tuple;                 /* request tuple sent from */
-                                               /* the client */
-
-extern char gdb_sockaddr_of_client[100];       /* this should really be */
-                                               /* sockaddr_in, but I don't */
-                                               /* want everyone to have */
-                                               /* to include all those */
-                                               /* big .h files */
-extern int gdb_socklen;                                /* length of above */
-
-
-\f
-/************************************************************************
- *     
- *                     DATABASE MANAGEMENT
- *     
- *     This layer of GDB provides access to the services of a relational
- *     database from anywhere in a GDB network.
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *                      GDB_DB_SERVICE
-        *      
-        *      The name of the service, as found in /etc/services,
-        *      for GDB database servers.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_DB_SERVICE "#9420"
-
-       /*----------------------------------------------------------
-        *      
-        *                      DATABASE
-        *      
-        *      Describes a client's active connection to a database.
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_DB_ID 0x44420000                   /* eye catcher */
-
-struct db_struct {
-       int32 id;                               /* eye catcher */
-       CONNECTION connection;                  /* the GDB connection */
-                                               /* used to get at this */
-                                               /* database */
-       int status;                             /* status of this */
-                                               /* database connection */
-#define DB_OPEN 1                              /* database opened */
-                                               /* successfully */
-#define DB_CLOSED 2                            /* not open */
-       char *name;                             /* pointer to string name */
-                                               /* of the database, for */
-                                               /* debugging */
-       char *server;                           /* pointer to the i.d. */
-                                               /* of the server, for */
-                                               /* debugging */
-};
-
-typedef struct db_struct *DATABASE;
-
-       /*----------------------------------------------------------
-        *      
-        *      Return codes from DB operations
-        *      
-        *----------------------------------------------------------*/
-
-#define DB_NO_SUCH_OP 3
-
-       /*----------------------------------------------------------
-        *      
-        *      Parameters which limit sizes of things
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_MAX_QUERY_SIZE 2048                        /* length of the longest */
-                                               /* substituted query */
-                                               /* string we can make */
-#define GDB_MAX_QUERY_FIELDS 100               /* maximum number of fields */
-                                               /* we can retrieve in one */
-                                               /* query */
-#define GDB_SIZE_OF_INGRES_TEXT 2001           /* number of chars in */
-                                               /* largest ingres text */
-                                               /* field */
-#define GDB_MAX_RETRIEVED_TEXT_FIELDS 60       /* maximum number of text */
-                                               /* type fields we can */
-                                               /* retrieve in a single */
-                                               /* query.  we hold this */
-                                               /* down because stack space */
-                                               /* is taken for max size of */
-                                               /* each during query. */
-
-       /*----------------------------------------------------------
-        *      
-        *      Return codes from database operations
-        *      
-        *----------------------------------------------------------*/
-
-#define DB_PARSE_FAIL (-3)                     /* couldn't parse */
-                                               /* the request string*/
-
-\f
-/************************************************************************
- *     
- *                     DATABASE OPERATIONS IMPLEMENTED
- *                             AS MACROS
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *                      DB_STATUS
-        *      
-        *----------------------------------------------------------*/
-
-#define DB_STATUS(dbhandle) ((dbhandle)->status)
-
-
-
-\f
-/************************************************************************
- *     
- *                     STRING MANAGEMENT
- *     
- *     To allow dynamic manipulation of strings in gdb without
- *     excessive memory re-allocation, we define a string as a
- *     counted byte space.  Though this space will frequently be used
- *     to store a standard null terminated string, that is not
- *     required.
- *     
- *     Current representation for a string is a pointer followed by
- *     an integer length.  A null pointer indicates a null string, in
- *     which case the length is arbitrary.  Any other pointer is to
- *     memory which was allocated by db_alloc in which must be free'd
- *     eventually with db_free.
- *     
- ************************************************************************/
-
-typedef struct str_dat {
-       char *ptr;                              /* pointer to the data */
-       int length;                             /* length of the allocated */
-                                               /* memory (not necessarily */
-                                               /* length of null-term'd */
-                                               /* string stored there) */
-} STRING;
-
-       /*----------------------------------------------------------
-        *      
-        *      Macros for manipulating strings.  These return
-        *      the actual data from the string and the size of
-        *      the data space respectively.  To get the length of
-        *      the null terminated string which might be stored 
-        *      there, use strlen(STRING_DATA(string)).
-        *      
-        *----------------------------------------------------------*/
-
-
-#define STRING_DATA(str) ((str).ptr)
-#define MAX_STRING_SIZE(str) ((str).length)
-
-
-/************************************************************************
- *     
- *                     MEMORY ALLOCATION
- *     
- *     db_alloc and db_free are the externally visible names of
- *     the memory allocation services.  These actually call the 
- *     routines pointed to by the vectors gdb_amv and gdb_fmv, which
- *     default to the supplied routines gdb_am and gdb_fm.  Users
- *     may supply their own memory allocation by storing over the
- *     vectors.  This may be done prior to calling gdb_init to 
- *     insure that all dynamic memory is controlled by the user.
- *     
- ************************************************************************/
-
-#define db_alloc (*gdb_amv)
-#define db_free  (*gdb_fmv)
-
-extern char *gdb_am();
-extern int  gdb_fm();
-
-extern char *((*gdb_amv)());
-extern int  (*gdb_fmv)();
-
-\f
-/************************************************************************
- *     
- *           STRUCTURED DATA ROUTINES IMPLEMENTED AS MACROS
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *                   ADD_TUPLE_TO_RELATION
-        *      
-        *----------------------------------------------------------*/
-
-#define ADD_TUPLE_TO_RELATION(relation, tuple)                         \
-       {                                                       \
-                (tuple)->prev    = (relation)->last;            \
-               (tuple)->next    = (TUPLE)(relation);           \
-               (relation)->last = tuple;                       \
-               (tuple)->prev->next = tuple;                    \
-        }
-
-       /*----------------------------------------------------------
-        *      
-        *                   ADD_TUPLE_AFTER_TUPLE
-        *      
-        *----------------------------------------------------------*/
-
-#define ADD_TUPLE_AFTER_TUPLE(relation, tuple, prev_tuple)     \
-       {                                                               \
-                (tuple)->prev    = (prev_tuple)->next->prev;            \
-               (tuple)->next    = (prev_tuple)->next;                  \
-               (tuple)->next->prev = tuple;                            \
-               (prev_tuple)->next = tuple;                             \
-        }
-
-       /*----------------------------------------------------------
-        *      
-        *                REMOVE_TUPLE_FROM_RELATION
-        *      
-        *----------------------------------------------------------*/
-
-#define REMOVE_TUPLE_FROM_RELATION(relation, tuple)                    \
-       {                                                               \
-               (tuple)->prev->next = (tuple)->next;                    \
-               (tuple)->next->prev = (tuple)->prev;                    \
-        }
-
-
-       /*----------------------------------------------------------
-        *      
-        *                 DESCRIPTOR_FROM_TUPLE
-        *      
-        *----------------------------------------------------------*/
-
-#define DESCRIPTOR_FROM_TUPLE(tuple) ((tuple)->desc)
-
-       /*----------------------------------------------------------
-        *      
-        *                 DESCRIPTOR_FROM_RELATION
-        *      
-        *----------------------------------------------------------*/
-
-#define DESCRIPTOR_FROM_RELATION(relation) ((relation)->desc)
-
-       /*----------------------------------------------------------
-        *      
-        *                 REFERENCE_TUPLE_DESCRIPTOR
-        *      
-        *      Bumps the reference count for a tuple descriptor.
-        *      Intended only for internal use of GDB.
-        *      
-        *----------------------------------------------------------*/
-
-#define REFERENCE_TUPLE_DESCRIPTOR(tpd) (++((tpd)->ref_count))
-
-       /*----------------------------------------------------------
-        *      
-        *                 UNREFERENCE_TUPLE_DESCRIPTOR
-        *      
-        *      Decrements the reference count for a tuple descriptor.
-        *      Intended only for internal use of GDB.  Warning: it
-        *      is the user's responsibility to use delete_tuple_descriptor
-        *      instead of this macro in any situation in which the
-        *      reference count might go to zero.
-        *      
-        *----------------------------------------------------------*/
-
-#define UNREFERENCE_TUPLE_DESCRIPTOR(tpd) (--((tpd)->ref_count))
-
-       /*----------------------------------------------------------
-        *      
-        *                       FIELD_FROM_TUPLE
-        *      
-        *----------------------------------------------------------*/
-
-#define FIELD_FROM_TUPLE(tuple, field_index)                           \
-       (((tuple)->data) + (((tuple)->desc)->var[field_index].offset))
-
-       /*----------------------------------------------------------
-        *      
-        *                      FIELD_OFFSET_IN_TUPLE
-        *      
-        *----------------------------------------------------------*/
-
-#define FIELD_OFFSET_IN_TUPLE(tuple_descriptor, field_index)           \
-       ((tuple_descriptor)->var[field_index].offset)
-
-       /*----------------------------------------------------------
-        *      
-        *                      FIELD_TYPE_IN_TUPLE
-        *      
-        *----------------------------------------------------------*/
-
-#define FIELD_TYPE_IN_TUPLE(tuple_descriptor, field_index)             \
-       ((tuple_descriptor)->var[field_index].type)
-
-       /*----------------------------------------------------------
-        *      
-        *                    FIRST_TUPLE_IN_RELATION
-        *      
-        *----------------------------------------------------------*/
-
-#define FIRST_TUPLE_IN_RELATION(relation)                              \
-       (((relation)->first) == (TUPLE)relation ? NULL : (relation)-> first)
-
-       /*----------------------------------------------------------
-        *      
-        *                      NEXT_TUPLE_IN_RELATION
-        *      
-        *----------------------------------------------------------*/
-
-#define NEXT_TUPLE_IN_RELATION(relation, prev)                         \
-       (((prev)->next) == (TUPLE)relation ? NULL : prev->next )
-
-       /*----------------------------------------------------------
-        *      
-        *                      PREV_TUPLE_IN_RELATION
-        *      
-        *----------------------------------------------------------*/
-
-#define PREV_TUPLE_IN_RELATION(relation, next)                         \
-       (((next)->prev) == (TUPLE) relation ? NULL : next->prev)
-
-
-
-\f
-/************************************************************************
- *     
- *     TRANSPORT and OPERATION SERVICES IMPLEMENTED AS MACROS
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *                   OPERATION_FROM_DATA
-        *      
-        *      Given OPERATION_DATA, return the corresponding handle
-        *      of type OPERATION.  Currently, OPERATION is just
-        *      implemented as a pointer to OPERATION_DATA.
-        *      
-        *----------------------------------------------------------*/
-
-#define OPERATION_FROM_DATA(op_data)                                   \
-       ((OPERATION)&(op_data))
-
-       /*----------------------------------------------------------
-        *      
-        *                       OP_TAG
-        *      
-        *      Return the tag for a given operation.
-        *      
-        *----------------------------------------------------------*/
-
-#define OP_TAG(operation) ((operation)->tag)
-
-       /*----------------------------------------------------------
-        *      
-        *                     OP_STATUS
-        *      
-        *      Return the status of a given operation.  Note that
-        *      status describes an operations progress through 
-        *      execution.  It has the same values for all operations.
-        *      Result describes the final outcome of an operation.
-        *      It's values depend on the particular operation which
-        *      was attempted.  
-        *      
-        *----------------------------------------------------------*/
-
-#define OP_STATUS(operation) ((operation)->status)
-
-       /*----------------------------------------------------------
-        *      
-        *                      OP_DONE
-        *      
-        *      True iff the operation is either OP_COMPLETE or
-        *      OP_CANCELLED.
-        *      
-        *----------------------------------------------------------*/
-
-#define OP_DONE(op) ((op)->status == OP_COMPLETE || (op)->status == OP_CANCELLED)
-
-       /*----------------------------------------------------------
-        *      
-        *                     OP_RESULT
-        *      
-        *      Return the result of a given operation.  Note that
-        *      status describes an operations progress through 
-        *      execution.  It has the same values for all operations.
-        *      Result describes the final outcome of an operation.
-        *      It's values depend on the particular operation which
-        *      was attempted. The special result value -1 is used 
-        *      to indicate an invalid value for result.  Generally,
-        *      -1 is returned when result is accidently queried at
-        *      a time when OP_STATUS != OPERATION_COMPLETE.
-        *      
-        *----------------------------------------------------------*/
-
-#define OP_RESULT(operation) ((operation)->result)
-
-\f
-/************************************************************************
- *     
- *                     Debugging Interfaces
- *     
- ************************************************************************/
-
-       /*----------------------------------------------------------
-        *      
-        *      The following operation codes my be passed to 
-        *      gdb_debug to set special debugging modes of operation.
-        *      
-        *      Note that most of these are toggles
-        *      
-        *----------------------------------------------------------*/
-
-#define GDB_LOG        0x00000001              /* turn on tracing to */
-                                               /* log file */
-#define GDB_NOFORK     0x00000002              /* don't fork forking */
-                                               /* servers */
-
-\f
-/************************************************************************
- *     
- *     Things which have to be at the end because they require
- *     the various types to be defined first.
- *     
- ************************************************************************/
-
-
-#ifdef DUMB_7_CHAR_LOADER
-       /*----------------------------------------------------------
-        *      
-        *                Long Names for Routines
-        *      
-        *      External names in Unix must generally be unique
-        *      within the first 7 characters or so, at least for
-        *      some versions of ld.  To account for this without
-        *      making all our routine names terribly short and
-        *      cryptic, we use the following defines.
-        *      
-        *----------------------------------------------------------*/
-
-#define string_alloc                   gdb_sta
-#define string_free                    gdb_stf
-
-#define create_tuple_descriptor        gdb_ctd
-#define delete_tuple_descriptor        gdb_dtd
-#define field_index                    gdb_fi
-#define create_tuple                   gdb_ctup
-#define delete_tuple                   gdb_dtup
-#define initialize_tuple               gdb_itup
-#define null_tuple_strings             gdb_ntps
-
-#define create_relation                        gdb_crel
-#define delete_relation                        gdb_drel
-#define tuples_in_relation              gdb_trel
-
-
-/*
- * Transport layer
- */
-#define create_operation               gdb_crop
-#define delete_operation               gdb_dop
-#define initialize_operation           gdb_inop
-#define reset_operation                        gdb_rsop
-#define cancel_operation               gdb_cnop
-
-#define create_list_of_operations      gdb_clop
-#define delete_list_of_operations      gdb_dlop
-
-#define op_select                      gdb_opsel
-#define op_select_any                  gdb_opsel
-#define op_select_all                  gdb_aopsel
-#define con_select                     gdb_cnsel
-
-#define gdb_receive_data               gdb_rcdat        
-#define gdb_send_data                  gdb_sndat        
-#define gdb_start_listening            gdb_stl
-#define start_accepting_client         gdb_stac
-
-
-#define gdb_listen                     gdb_lis
-
-/*
- * Connection management
- */
-#define start_peer_connection          gdb_spconn
-#define sever_connection               gdb_svconn
-#define start_server_connection                gdb_stsrv
-#define create_listening_connection    gdb_clc
-#define start_replying_to_client       gdb_strtc
-#define create_forking_server          gdb_cfs
-
-
-/*
- * Asynchronous operations
- */
-#define start_sending_object           gdb_snobj
-#define start_receiving_object                 gdb_rcobj
-#define preempt_and_start_receiving_object             gdb_prcobj
-
-#define queue_operation                        gdb_qop
-
-#define requeue_operation              g_req_op
-
-#define complete_operation             gdb_cmpo
-/*
- * Synchronous operations
- */
-#define send_object                    gdb_sobj
-#define receive_object                 gdb_robj
-/*
- * Database operations
- */
-#define access_db                      gdb_adb
-#define start_accessing_db             gdb_sadb
-#define perform_db_operation           gdb_pdbo
-#define db_query                       gdb_dbq
-#define start_performing_db_operation  gdb_spdb
-#define   start_db_query                       gdb_sdbq
-#else
-#define op_select_any  op_select
-#endif /* DUMB_7_CHAR_LOADER */
-
-extern char *string_alloc();
-extern int   string_free();
-extern TUPLE_DESCRIPTOR create_tuple_descriptor();
-extern int  delete_tuple_descriptor();
-extern int  field_index();
-extern TUPLE create_tuple();
-extern int   delete_tuple();
-extern int   initialize_tuple();
-extern int   null_tuple_strings();
-extern RELATION create_relation();
-extern int delete_relation();
-extern OPERATION create_operation();
-extern LIST_OF_OPERATIONS create_list_of_operations();
-extern OPERATION g_op_newhead();
-extern CONNECTION start_peer_connection();
-extern CONNECTION sever_connection();
-extern CONNECTION start_server_connection();
-extern CONNECTION create_listening_connection();
-extern CONNECTION create_forking_server();
-extern int start_sending_object();
-extern int start_receiving_object();
-extern int preempt_and_start_receiving_object();
-extern int queue_operation();
-extern int requeue_operation();
-extern int complete_operation();
-extern int send_object();
-extern int receive_object();
-
-
-       /*----------------------------------------------------------
-        *      
-        *      Other routines requiring extern to avoid forward
-        *      reference to non integer type functions.
-        *      
-        *----------------------------------------------------------*/
-
-extern CONNECTION g_make_con();
diff --git a/include/mr_proto.h b/include/mr_proto.h
deleted file mode 100644 (file)
index 565c385..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* $Id$
- *
- * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
- *
- */
-
-#include <stdio.h>
-#include <gdb.h>
-#include <moira.h>
-
-typedef struct mr_params {
-       uint32 mr_size;
-       uint32 mr_version_no;
-       union {
-               u_long procno;  /* for call */
-               u_long status;  /* for reply */
-       } u;
-#define mr_procno u.procno
-#define mr_status u.status
-       int mr_argc;
-       char **mr_argv;
-       int *mr_argl;
-       char *mr_flattened;
-       int mr_state;
-} mr_params;
-
-int mr_start_send(OPERATION op, HALF_CONNECTION hcon, struct mr_params *arg);
-int mr_start_recv(OPERATION op, HALF_CONNECTION hcon, struct mr_params **argp);
-void mr_destroy_reply(mr_params *reply);
index 1f07c136de2eba85d5b982e7038a230fda45e282..b6790dc8057d9b1acd003cf949468955e324b0d5 100644 (file)
@@ -4,12 +4,17 @@
 #define log_ERROR 3
 
 #define SERVICE_NAME "moira_update"
-#define        UPDATE_BUFSIZ   BUFSIZ
+/* For unknown reasons, we're running des_pcbc_encrypt in DEcrypt mode,
+   not ENcrypt, so we need to guarantee that the block size is a multiple
+   of 8 to prevent the data from being zero-padded. */
+#define UPDATE_BUFSIZ ((BUFSIZ + 7) & ~7)
 
-int send_file(char *pathname, char *target_path, int encrypt);
-int send_auth(char *hostname);
-int execute(char *path);
-void send_quit(void);
+int send_file(int conn, char *pathname, char *target_path, int encrypt);
+int send_auth(int conn, char *hostname);
+int execute(int conn, char *path);
+void send_quit(int conn);
 
 #include <krb.h>
 int get_mr_update_ticket(char *host, KTEXT ticket);
+
+extern char *whoami;
index 2f6028367dab78b62674a414a29b3839a8621b3c..e0d53b5b939fcaf9e024fcb4e8bff0f7b0590618 100644 (file)
@@ -10,7 +10,7 @@ AFSLIBS=$(AFSDIR)/lib/afs/libprot.a    $(AFSDIR)/lib/afs/libauth.a \
 SRCS = afs.c ksrvtgt.c
 CODE = $(SRCS)
 CFLAGS = -I../include -I../lib -I$(AFSDIR)/include -I/usr/athena/include $(DBG)
-LIBS = -L../lib -L../gdb -L/usr/athena/lib -lmoira -lzephyr -lmrgdb -lcom_err -lhesiod -lkrb -ldes
+LIBS = -L../lib -L/usr/athena/lib -lmoira -lzephyr -lcom_err -lhesiod -lkrb -ldes
 SRCDIR = $(SRCTOP)/incremental
 
 program(afs.incr,afs.o,,${AFSLIBS} ${LIBS},${PROGDIR})
index db3ee265a0a1beee25064307a5f322844d66d718..36ecc3cb03ad2e4fb59cb3079ce930fb9189ea0c 100644 (file)
@@ -8,13 +8,13 @@
 # Imakefile for GDB library.
 #
 
-SRCS = mr_auth.c mr_call.c mr_connect.c mr_data.c mr_init.c \
-       mr_query.c mr_param.c mr_access.c mr_ops.c \
+SRCS = mr_auth.c mr_call.c mr_connect.c mr_init.c \
+       mr_query.c mr_access.c mr_ops.c \
        fixname.c strs.c fixhost.c nfsparttype.c sq.c hash.c \
        idno.c critical.c gdss_convert.c kname_unparse.c
 
-OBJECTS        = mr_auth.o mr_call.o mr_connect.o mr_data.o mr_init.o \
-       mr_query.o mr_param.o mr_access.o mr_ops.o \
+OBJECTS        = mr_auth.o mr_call.o mr_connect.o mr_init.o \
+       mr_query.o mr_access.o mr_ops.o \
        fixname.o strs.o fixhost.o nfsparttype.o sq.o hash.o \
        idno.o critical.o mr_et.o ureg_err.o krb_et.o gdss_et.o \
        gdss_convert.o kname_unparse.o
index 711754a7fd274b7ab755b485123485a0e1b7ec9a..ac70e3e79149dc1bab626c31b3ee48d0a786f4b2 100644 (file)
 
 RCSID("$Header$");
 
-int mr_access_internal(int argc, char **argv);
-
 /*
  * Check access to a named query.
  */
 int mr_access(char *name, int argc, char **argv)
 {
-  char **nargv = malloc(sizeof(char *) * (argc + 1));
-  int status = 0;
-
-  if (!nargv)
-    return ENOMEM;
-  nargv[0] = name;
-  memcpy(nargv + 1, argv, sizeof(char *) * argc);
-  status = mr_access_internal(argc + 1, nargv);
-  free(nargv);
-  return status;
-}
-
-/*
- * Check access to a named query, where the query name is argv[0]
- * and the arguments are the rest of argv[].
- */
-int mr_access_internal(int argc, char **argv)
-{
+  mr_params params, reply;
   int status;
-  mr_params params_st;
-  mr_params *params = NULL;
-  mr_params *reply = NULL;
 
   CHECK_CONNECTED;
 
-  params = &params_st;
-  params->mr_version_no = sending_version_no;
-  params->mr_procno = MR_ACCESS;
-  params->mr_argc = argc;
-  params->mr_argl = NULL;
-  params->mr_argv = argv;
+  params.u.mr_procno = MR_ACCESS;
+  params.mr_argc = argc + 1;
+  params.mr_argv = malloc(sizeof(char *) * (argc + 1));
+  if (!params.mr_argv)
+    return ENOMEM;
+  params.mr_argv[0] = name;
+  memcpy(params.mr_argv + 1, argv, sizeof(char *) * argc);
+  params.mr_argl = NULL;
 
-  if ((status = mr_do_call(params, &reply)) == 0)
-    status = reply->mr_status;
+  if ((status = mr_do_call(&params, &reply)) == MR_SUCCESS)
+    status = reply.u.mr_status;
 
   mr_destroy_reply(reply);
+  free(params.mr_argv);
 
   return status;
 }
index aabd780de7b47fd090ca460fc44b28748165e845..c70cced5edda59bf4d401c586e7916244c42211e 100644 (file)
@@ -12,6 +12,7 @@
 #include "mr_private.h"
 
 #include <ctype.h>
+#include <stdio.h>
 #include <string.h>
 
 #include <krb.h>
@@ -25,19 +26,14 @@ RCSID("$Header$");
 int mr_auth(char *prog)
 {
   int status;
-  mr_params params_st;
+  mr_params params, reply;
   char *args[2];
   int argl[2];
   char realm[REALM_SZ], host[BUFSIZ], *p;
-  mr_params *params = &params_st;
-  mr_params *reply = NULL;
   KTEXT_ST auth;
 
   CHECK_CONNECTED;
 
-  /* Build a Kerberos authenticator. */
-
-  memset(host, 0, sizeof(host));
   if ((status = mr_host(host, sizeof(host) - 1)))
     return status;
 
@@ -55,21 +51,17 @@ int mr_auth(char *prog)
       status += ERROR_TABLE_BASE_krb;
       return status;
     }
-  params->mr_version_no = sending_version_no;
-  params->mr_procno = MR_AUTH;
-  params->mr_argc = 2;
-  params->mr_argv = args;
-  params->mr_argl = argl;
-  params->mr_argv[0] = (char *)auth.dat;
-  params->mr_argl[0] = auth.length;
-  params->mr_argv[1] = prog;
-  params->mr_argl[1] = strlen(prog) + 1;
-
-  if (sending_version_no == MR_VERSION_1)
-    params->mr_argc = 1;
+  params.u.mr_procno = MR_AUTH;
+  params.mr_argc = 2;
+  params.mr_argv = args;
+  params.mr_argl = argl;
+  params.mr_argv[0] = (char *)auth.dat;
+  params.mr_argl[0] = auth.length;
+  params.mr_argv[1] = prog;
+  params.mr_argl[1] = strlen(prog) + 1;
 
-  if ((status = mr_do_call(params, &reply)) == 0)
-    status = reply->mr_status;
+  if ((status = mr_do_call(&params, &reply)) == MR_SUCCESS)
+    status = reply.u.mr_status;
 
   mr_destroy_reply(reply);
 
index 893163274b32609a81822d67bc0b35db42afef5d..d5d287d82a9fc99fff6cb90ee0e3bcc1df289fe0 100644 (file)
 #include <moira.h>
 #include "mr_private.h"
 
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
 RCSID("$Header$");
 
-int mr_do_call(struct mr_params *params, struct mr_params **reply)
+/* Moira RPC format:
+
+   4-byte total length (including these 4 bytes)
+   4-byte version number (MR_VERSION_2 == 2)
+   4-byte opcode (from client) or status (from server)
+   4-byte argc
+
+   4-byte len, followed by null-terminated string, padded to 4-byte boundary
+     (the len doesn't include the padding)
+   ...
+
+   (followed by more packets if status was MR_MORE_DATA)
+
+   All numbers are in network byte order.
+*/
+
+int mr_do_call(struct mr_params *params, struct mr_params *reply)
 {
+  int status;
+
   CHECK_CONNECTED;
 
-  if (!_mr_send_op)
-    _mr_send_op = create_operation();
+  status = mr_send(_mr_conn, params);
+  if (status == MR_SUCCESS)
+    status = mr_receive(_mr_conn, reply);
+
+  if (status)
+    mr_disconnect();
+
+  return status;
+}
+
+int mr_send(int fd, struct mr_params *params)
+{
+  u_long length, written;
+  int i, *argl;
+  char *buf, *p;
+
+  length = 16; /* length + version + opcode/status + argc */
+
+  if (params->mr_argl)
+    {
+      argl = params->mr_argl;
+      for (i = 0; i < params->mr_argc; i++)
+       length += 8 + argl[i];
+    }
+  else
+    {
+      argl = malloc(params->mr_argc * sizeof(int));
+      if (params->mr_argc && !argl)
+       return ENOMEM;
+      for (i = 0; i < params->mr_argc; i++)
+       {
+         argl[i] = strlen(params->mr_argv[i]) + 1;
+         length += 8 + argl[i];
+       }
+    }
+
+  buf = malloc(length);
+  if (!buf)
+    {
+      if (!params->mr_argl)
+       free(argl);
+      return ENOMEM;
+    }
+  memset(buf, 0, length);
+
+  putlong(buf + 4, MR_VERSION_2);
+  putlong(buf + 8, params->u.mr_procno);
+  putlong(buf + 12, params->mr_argc);
 
-  if (!_mr_recv_op)
-    _mr_recv_op = create_operation();
+  for (i = 0, p = buf + 16; i < params->mr_argc; i++)
+    {
+      putlong(p, argl[i]);
+      memcpy(p += 4, params->mr_argv[i], argl[i]);
+      p += argl[i] + (4 - argl[i] % 4) % 4;
+    }
+  length = p - buf;
+  putlong(buf, length);
+
+  written = write(fd, buf, length);
+  free(buf);
+  if (!params->mr_argl)
+    free(argl);
 
-  initialize_operation(_mr_send_op, mr_start_send, (char *)params, NULL);
-  queue_operation(_mr_conn, CON_OUTPUT, _mr_send_op);
+  if (written != length)
+    return MR_ABORTED;
+  else
+    return MR_SUCCESS;
+}
+
+int mr_receive(int fd, struct mr_params *reply)
+{
+  u_long length, data;
+  ssize_t size, more;
+  char *p;
+  int i;
 
-  initialize_operation(_mr_recv_op, mr_start_recv, (char *)reply, NULL);
-  queue_operation(_mr_conn, CON_INPUT, _mr_recv_op);
+  memset(reply, 0, sizeof(struct mr_params));
 
-  /* Block until operation done. */
-  complete_operation(_mr_send_op);
-  complete_operation(_mr_recv_op);
-  /* Look at results */
-  if ((OP_STATUS(_mr_send_op) != OP_COMPLETE) ||
-      (OP_STATUS(_mr_recv_op) != OP_COMPLETE))
+  size = read(fd, &data, 4);
+  if (size != 4)
+    return size ? MR_ABORTED : MR_NOT_CONNECTED;
+  length = ntohl(data) - 4;
+  reply->mr_flattened = malloc(length);
+  if (!reply->mr_flattened)
+    return ENOMEM;
+
+  for (size = 0; size < length; size += more)
+    {
+      more = read(fd, reply->mr_flattened + size, length - size);
+      if (!more)
+       break;
+    }
+  if (size != length)
     {
-      mr_disconnect();
+      mr_destroy_reply(*reply);
       return MR_ABORTED;
     }
-  return 0;
+
+  getlong(reply->mr_flattened, data);
+  if (data != MR_VERSION_2)
+    {
+      mr_destroy_reply(*reply);
+      return MR_VERSION_MISMATCH;
+    }
+
+  getlong(reply->mr_flattened + 4, reply->u.mr_status);
+  getlong(reply->mr_flattened + 8, reply->mr_argc);
+  reply->mr_argv = malloc(reply->mr_argc * sizeof(char *));
+  reply->mr_argl = malloc(reply->mr_argc * sizeof(int));
+  if (reply->mr_argc && (!reply->mr_argv || !reply->mr_argl))
+    {
+      mr_destroy_reply(*reply);
+      return ENOMEM;
+    }
+
+  for (i = 0, p = reply->mr_flattened + 12; i < reply->mr_argc; i++)
+    {
+      getlong(p, reply->mr_argl[i]);
+      reply->mr_argv[i] = p + 4;
+      p += 4 + reply->mr_argl[i] + (4 - reply->mr_argl[i] % 4) % 4;
+    }
+
+  return MR_SUCCESS;
+}
+
+void mr_destroy_reply(mr_params reply)
+{
+  free(reply.mr_argl);
+  free(reply.mr_argv);
+  free(reply.mr_flattened);
 }
index 5fe7d8a512033ecf1ca4639c129c9f3d2a602ed3..0ebeca1ac5a1b17ba6906e9ffa15d3e52027cc39 100644 (file)
 #include <moira_site.h>
 #include "mr_private.h"
 
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <hesiod.h>
 
 RCSID("$Header$");
 
-static char *mr_server_host = 0;
+int _mr_conn = 0;
+static char *mr_server_host = NULL;
+
+/* mrgdb compatibility magic
+
+   The data looks like this:
+
+   client -> server
+     00000036                          [length of rest of packet]
+     00000004                          [number of fields]
+     01 01 01 01                       [types of fields: 4 strings]
+     "server_id\0parms\0host\0user\0"  [field names]
+     00000001                          [length of null-terminated server_id]
+     "\0"                              [server_id: ignored anyway]
+     00000001                          [length of null-terminated parms]
+     "\0"                              [parms: ignored anyway]
+     00000001                          [length of null-terminated client host]
+     "\0"                              [host: ignored anyway]
+     00000001                          [length of null-terminated client name]
+     "\0"                              [user: ignored anyway]
+
+   server -> client
+     00000031                          [length of rest of packet]
+     00000003                          [number of fields]
+     00 01 01                          [types of fields: int and 2 strings]
+     "disposition\0server_id\0parms\0" [field names]
+     00000001                          [GDB_ACCEPTED]
+     00000001                          [length of null-terminated server_id]
+     "\0"                              [server_id: ignored anyway]
+     00000001                          [length of null-terminated parms]
+     "\0"                              [parms: ignored anyway]
+
+*/
+
+static char challenge[58] = "\0\0\0\066\0\0\0\004\001\001\001\001server_id\0parms\0host\0user\0\0\0\0\001\0\0\0\0\001\0\0\0\0\001\0\0\0\0\001\0";
+static char response[53] = "\0\0\0\061\0\0\0\003\0\001\001disposition\0server_id\0parms\0\0\0\0\001\0\0\0\001\0\0\0\0\001\0";
 
 /*
- * Open a connection to the mr server.  Looks for the server name
+ * Open a connection to the moira server.  Looks for the server name
  * 1) passed as an argument, 2) in environment variable, 3) by hesiod
- * 4) compiled in default (from moira_site.h).
+ * 4) compiled in default
  */
 
 int mr_connect(char *server)
 {
-  char *p, **pp, *sbuf = NULL;
+  char *port, **pp, *sbuf = NULL;
+  struct hostent *shost;
 
-  if (!mr_inited)
-    mr_init();
   if (_mr_conn)
     return MR_ALREADY_CONNECTED;
+  if (!mr_inited)
+    mr_init();
 
   if (!server || (strlen(server) == 0))
     server = getenv("MOIRASERVER");
@@ -53,50 +96,104 @@ int mr_connect(char *server)
   if (!server || (strlen(server) == 0))
     server = MOIRA_SERVER;
 
-  if (!strchr(server, ':'))
+  shost = gethostbyname(server);
+  if (!shost)
+    return MR_CANT_CONNECT;
+
+  if (strchr(server, ':'))
     {
-      p = strchr(MOIRA_SERVER, ':');
-      p++;
-      sbuf = malloc(strlen(server) + strlen(p) + 2);
-      if (!sbuf)
-       return ENOMEM;
-      sprintf(sbuf, "%s:%s", server, p);
+      int len = strcspn(server, ":");
+      sbuf = malloc(len + 1);
+      strncpy(sbuf, server, len);
+      sbuf[len - 1] = '\0';
       server = sbuf;
+      port = strchr(server, ':') + 1;
+    }
+  else
+    port = strchr(MOIRA_SERVER, ':') + 1;
+
+  _mr_conn = mr_connect_internal(server, port);
+  free(sbuf);
+  if (!_mr_conn)
+    return MR_CANT_CONNECT;
+
+  /* stash hostname for later use */
+  mr_server_host = strdup(shost->h_name);
+  return MR_SUCCESS;
+}
+
+int mr_connect_internal(char *server, char *port)
+{
+  int fd, size, more;
+  struct sockaddr_in target;
+  struct hostent *shost;
+  char actualresponse[53];
+
+  shost = gethostbyname(server);
+  if (!shost)
+    return 0;
+
+  if (port[0] == '#')
+    target.sin_port = atoi(port + 1);
+  else
+    {
+      struct servent *s;
+      s = getservbyname(port, "tcp");
+      if (s)
+       target.sin_port = s->s_port;
+      else
+       return 0;
     }
 
-  errno = 0;
-  _mr_conn = start_server_connection(server, "");
-  if (_mr_conn == NULL)
-    return errno;
-  if (connection_status(_mr_conn) == CON_STOPPED)
+  memcpy(&target.sin_addr, shost->h_addr, shost->h_length);
+  target.sin_family = shost->h_addrtype;
+
+  fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (fd < 0)
+    return 0;
+
+  if (connect(fd, (struct sockaddr *)&target, sizeof(target)) < 0)
     {
-      int status = connection_errno(_mr_conn);
-      if (!status)
-       status = MR_CANT_CONNECT;
-      mr_disconnect();
-      return status;
+      close(fd);
+      return 0;
     }
 
-  /*
-   * stash hostname for later use
-   */
+  /* Do magic mrgdb initialization */
+  size = write(fd, challenge, sizeof(challenge));
+  if (size != sizeof(challenge))
+    {
+      close(fd);
+      return 0;
+    }
+  for (size = 0; size < sizeof(actualresponse); size += more)
+    {
+      more = read(fd, actualresponse + size, sizeof(actualresponse) - size);
+      if (!more)
+       break;
+    }
+  if (size != sizeof(actualresponse))
+    {
+      close(fd);
+      return 0;
+    }
+  if (memcmp(actualresponse, response, sizeof(actualresponse)))
+    {
+      close(fd);
+      return 0;
+    }
 
-  if (!sbuf)
-    sbuf = strdup(server);
-  mr_server_host = sbuf;
-  if ((p = strchr(mr_server_host, ':')))
-    *p = '\0';
-  mr_server_host = canonicalize_hostname(mr_server_host);
-  return 0;
+  /* You win */
+  return fd;
 }
 
 int mr_disconnect(void)
 {
   CHECK_CONNECTED;
-  _mr_conn = sever_connection(_mr_conn);
+  close(_mr_conn);
+  _mr_conn = 0;
   free(mr_server_host);
-  mr_server_host = 0;
-  return 0;
+  mr_server_host = NULL;
+  return MR_SUCCESS;
 }
 
 int mr_host(char *host, int size)
@@ -105,28 +202,127 @@ int mr_host(char *host, int size)
 
   /* If we are connected, mr_server_host points to a valid string. */
   strncpy(host, mr_server_host, size);
-  return 0;
+  host[size - 1] = '\0';
+  return MR_SUCCESS;
 }
 
 int mr_noop(void)
 {
   int status;
-  mr_params param_st;
-  struct mr_params *params = NULL;
-  struct mr_params *reply = NULL;
+  mr_params params, reply;
 
   CHECK_CONNECTED;
-  params = &param_st;
-  params->mr_version_no = sending_version_no;
-  params->mr_procno = MR_NOOP;
-  params->mr_argc = 0;
-  params->mr_argl = NULL;
-  params->mr_argv = NULL;
+  params.u.mr_procno = MR_NOOP;
+  params.mr_argc = 0;
+  params.mr_argl = NULL;
+  params.mr_argv = NULL;
 
-  if ((status = mr_do_call(params, &reply)) == 0)
-    status = reply->mr_status;
+  if ((status = mr_do_call(&params, &reply)) == MR_SUCCESS)
+    status = reply.u.mr_status;
 
   mr_destroy_reply(reply);
 
   return status;
 }
+
+
+/* Server side */
+
+int mr_listen(char *port)
+{
+  struct sockaddr_in sin;
+  int s, on = 1;
+
+  memset(&sin, 0, sizeof(sin));
+  if (port[0] == '#')
+    sin.sin_port = atoi(port + 1);
+  else
+    {
+      struct servent *s;
+      s = getservbyname(port, "tcp");
+      if (s)
+       sin.sin_port = s->s_port;
+      else
+       return -1;
+    }
+
+  s = socket(AF_INET, SOCK_STREAM, 0);
+  if (s < 0)
+    return -1;
+  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0)
+    {
+      close(s);
+      return -1;
+    }
+  if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+    {
+      close(s);
+      return -1;
+    }
+  if (listen(s, 5) < 0)
+    {
+      close(s);
+      return -1;
+    }
+
+  return s;
+}
+
+int mr_accept(int s, struct sockaddr_in *sin)
+{
+  int conn, addrlen = sizeof(struct sockaddr_in);
+  char lbuf[4], *buf;
+  long len, size, more;
+
+  conn = accept(s, (struct sockaddr *)sin, &addrlen);
+  if (conn < 0)
+    return -1;
+
+  /* Now do mrgdb accept protocol */
+  /* XXX timeout */
+
+  if (read(conn, lbuf, 4) != 4)
+    {
+      close(conn);
+      return -1;
+    }
+  getlong(lbuf, len);
+
+  buf = malloc(len);
+  if (!buf || len < 54)
+    {
+      close(conn);
+      free(buf);
+      return -1;
+    }
+
+  for (size = 0; size < len; size += more)
+    {
+      more = read(conn, buf + size, len - size);
+      if (!more)
+       break;
+    }
+  if (size != len)
+    {
+      close(conn);
+      free(buf);
+      return 0;
+    }
+
+  if (memcmp(buf, challenge + 4, 34))
+    {
+      close(conn);
+      free(buf);
+      return 0;
+    }
+
+  /* good enough */
+  free(buf);
+
+  if (write(conn, response, sizeof(response)) != sizeof(response))
+    {
+      close(conn);
+      return -1;
+    }
+  return conn;
+}
diff --git a/lib/mr_data.c b/lib/mr_data.c
deleted file mode 100644 (file)
index 1fc2b8b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* $Id$
- *
- * A few variables
- *
- * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
- */
-
-#include <mit-copyright.h>
-#include <moira.h>
-#include "mr_private.h"
-
-RCSID("$Header$");
-
-CONNECTION _mr_conn;
-
-OPERATION _mr_send_op, _mr_recv_op;
-
-int sending_version_no = MR_VERSION_2;
-
index ce7440b23b1aab5633358f0cbb02613443dc4618..00f6c1d2c2c3881a988b568087e553c9e3f11796 100644 (file)
@@ -15,18 +15,14 @@ RCSID("$Header$");
 
 int mr_inited = 0;
 
-/* the reference to link_against_the_moira_version_of_gdb is to make
- * sure that this is built with the proper libraries.
- */
 void mr_init(void)
 {
-  extern int link_against_the_moira_version_of_gdb;
   if (mr_inited)
     return;
 
-  gdb_init();
   initialize_sms_error_table();
   initialize_krb_error_table();
-  link_against_the_moira_version_of_gdb = 0;
+  initialize_gdss_error_table();
+  initialize_ureg_error_table();
   mr_inited = 1;
 }
index 015d5449898df67ff544ca52113ba5cc591fe2b1..1d7f6c41ea3e0d3383b027c9f17d0f23190a45e1 100644 (file)
@@ -24,20 +24,16 @@ RCSID("$Header$");
 int mr_do_update(void)
 {
   int status;
-  mr_params param_st;
-  struct mr_params *params = NULL;
-  struct mr_params *reply = NULL;
+  mr_params params, reply;
 
   CHECK_CONNECTED;
-  params = &param_st;
-  params->mr_version_no = sending_version_no;
-  params->mr_procno = MR_DO_UPDATE;
-  params->mr_argc = 0;
-  params->mr_argl = NULL;
-  params->mr_argv = NULL;
+  params.u.mr_procno = MR_DO_UPDATE;
+  params.mr_argc = 0;
+  params.mr_argl = NULL;
+  params.mr_argv = NULL;
 
-  if ((status = mr_do_call(params, &reply)) == 0)
-    status = reply->mr_status;
+  if ((status = mr_do_call(&params, &reply)) == MR_SUCCESS)
+    status = reply.u.mr_status;
 
   mr_destroy_reply(reply);
 
@@ -52,55 +48,41 @@ int mr_do_update(void)
 int mr_motd(char **motd)
 {
   int status;
-  mr_params param_st;
-  struct mr_params *params = NULL;
-  struct mr_params *reply = NULL;
+  mr_params params, reply;
   static char *buffer = NULL;
 
   *motd = NULL;
   CHECK_CONNECTED;
-  params = &param_st;
-  params->mr_version_no = sending_version_no;
-  params->mr_procno = MR_MOTD;
-  params->mr_argc = 0;
-  params->mr_argl = NULL;
-  params->mr_argv = NULL;
-
-  if ((status = mr_do_call(params, &reply)))
+  params.u.mr_procno = MR_MOTD;
+  params.mr_argc = 0;
+  params.mr_argl = NULL;
+  params.mr_argv = NULL;
+
+  if ((status = mr_do_call(&params, &reply)))
     goto punt;
 
-  while ((status = reply->mr_status) == MR_MORE_DATA)
+  while ((status = reply.u.mr_status) == MR_MORE_DATA)
     {
-      if (reply->mr_argc > 0)
+      if (reply.mr_argc > 0)
        {
-         buffer = realloc(buffer, reply->mr_argl[0] + 1);
+         buffer = realloc(buffer, reply.mr_argl[0] + 1);
          if (!buffer)
            {
              mr_disconnect();
              return ENOMEM;
            }
-         strcpy(buffer, reply->mr_argv[0]);
+         strcpy(buffer, reply.mr_argv[0]);
          *motd = buffer;
        }
       mr_destroy_reply(reply);
-      reply = NULL;
-
-      initialize_operation(_mr_recv_op, mr_start_recv, &reply, NULL);
-      queue_operation(_mr_conn, CON_INPUT, _mr_recv_op);
-
-      complete_operation(_mr_recv_op);
-      if (OP_STATUS(_mr_recv_op) != OP_COMPLETE)
+      if (mr_receive(_mr_conn, &reply) != MR_SUCCESS)
        {
          mr_disconnect();
-         status = MR_ABORTED;
-         return status;
+         return MR_ABORTED;
        }
     }
 punt:
   mr_destroy_reply(reply);
-  /* for backwards compatability */
-  if (status == MR_UNKNOWN_PROC)
-    return 0;
-  else
-    return status;
+
+  return status;
 }
diff --git a/lib/mr_param.c b/lib/mr_param.c
deleted file mode 100644 (file)
index 8f07b0b..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/* $Id$
- *
- * Deal with mrgdb (bleah!)
- *
- * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
- *
- */
-
-#include <mit-copyright.h>
-#include <moira.h>
-#include "mr_private.h"
-
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-RCSID("$Header$");
-
-/*
- * GDB operations to send and recieve RPC requests and replies.
- */
-
-/*
- * This doesn't get called until after the actual buffered write completes.
- * In a non-preflattening version of this, this would then queue the
- * write of the next bunch of data.
- */
-
-int mr_cont_send(OPERATION op, HALF_CONNECTION hcon, struct mr_params *arg)
-{
-  op->result = OP_SUCCESS;
-  free(arg->mr_flattened);
-  arg->mr_flattened = NULL;
-
-  return OP_COMPLETE;
-}
-
-int mr_start_send(OPERATION op, HALF_CONNECTION hcon,
-                 struct mr_params *arg)
-{
-  int i, len;
-  unsigned int mr_size;
-  int *argl;
-  char *buf, *bp;
-
-  /*
-   * This should probably be split into several routines.
-   * It could also probably be made more efficient (punting most
-   * of the argument marshalling stuff) by doing I/O directly
-   * from the strings.  Anyone for a scatter/gather mr_send_data?
-   *
-   * that would look a lot like the uio stuff in the kernel..  hmm.
-   */
-
-  /*
-   * Marshall the entire data right now..
-   * We are sending the version number,
-   * total request size, request number,
-   * argument count, and then each argument.
-   * At least for now, each argument is a string, which is
-   * sent as a count of bytes followed by the bytes
-   * (including the trailing '\0'), padded
-   * to a 32-bit boundary.
-   */
-
-  mr_size = 4 * sizeof(int32);
-
-  argl = malloc(sizeof(int) * arg->mr_argc);
-
-  /*
-   * For each argument, figure out how much space is needed.
-   */
-
-  for (i = 0; i < arg->mr_argc; ++i)
-    {
-      if (arg->mr_argl)
-       argl[i] = len = arg->mr_argl[i];
-      else
-       argl[i] = len = strlen(arg->mr_argv[i]) + 1;
-      mr_size += sizeof(int32) + len;
-      /* Round up to next 32-bit boundary.. */
-      mr_size = sizeof(int32) * howmany(mr_size, sizeof(int32));
-    }
-
-  arg->mr_flattened = buf = malloc(mr_size);
-
-  memset(arg->mr_flattened, 0, mr_size);
-
-  arg->mr_size = mr_size;
-
-  ((int32 *)buf)[0] = htonl(mr_size);
-  ((int32 *)buf)[1] = htonl(arg->mr_version_no);
-  ((int32 *)buf)[2] = htonl(arg->mr_procno);
-  ((int32 *)buf)[3] = htonl(arg->mr_argc);
-
-  /*
-   * bp is a pointer into the point in the buffer to put
-   * the next argument.
-   */
-
-  bp = (char *)(((int32 *)buf) + 4);
-
-  for (i = 0; i < arg->mr_argc; ++i)
-    {
-      len = argl[i];
-      *((int32 *)bp) = htonl(len);
-      bp += sizeof(int32);
-      memcpy(bp, arg->mr_argv[i], len);
-      bp += sizeof(int32) * howmany(len, sizeof(int32));
-    }
-  op->fcn.cont = mr_cont_send;
-  arg->mr_size = mr_size;
-
-  free(argl);
-
-  if (gdb_send_data(hcon, arg->mr_flattened, mr_size) == OP_COMPLETE)
-    return mr_cont_send(op, hcon, arg);
-  else
-    return OP_RUNNING;
-}
-
-int mr_cont_recv(OPERATION op, HALF_CONNECTION hcon, mr_params **argp)
-{
-  int done = FALSE;
-  char *cp;
-  int *ip;
-  int i;
-  mr_params *arg = *argp;
-
-  while (!done)
-    {
-      switch (arg->mr_state)
-       {
-       case S_RECV_START:
-         arg->mr_state = S_RECV_DATA;
-         if (gdb_receive_data(hcon, (caddr_t)&arg->mr_size,
-                              sizeof(int32)) == OP_COMPLETE)
-           continue;
-         done = TRUE;
-         break;
-       case S_RECV_DATA:
-         fflush(stdout);
-         /* Should validate that length is reasonable */
-         arg->mr_size = ntohl(arg->mr_size);
-         if (arg->mr_size > 65536)
-           return OP_CANCELLED;
-         arg->mr_flattened = malloc(arg->mr_size);
-         arg->mr_state = S_DECODE_DATA;
-         memcpy(arg->mr_flattened, (caddr_t)&arg->mr_size, sizeof(int32));
-
-         if (gdb_receive_data(hcon, arg->mr_flattened + sizeof(int32),
-                              arg->mr_size - sizeof(int32))
-             == OP_COMPLETE)
-           continue;
-         done = TRUE;
-         break;
-       case S_DECODE_DATA:
-         cp = arg->mr_flattened;
-         ip = (int *) cp;
-         /* we already got the overall length.. */
-         for (i = 1; i < 4; i++)
-           ip[i] = ntohl(ip[i]);
-         arg->mr_version_no = ip[1];
-         if (arg->mr_version_no != MR_VERSION_1 &&
-             arg->mr_version_no != MR_VERSION_2)
-           arg->mr_status = MR_VERSION_MISMATCH;
-         else arg->mr_status = ip[2];
-         arg->mr_argc = ip[3];
-         cp += 4 * sizeof(int);
-         arg->mr_argv = malloc(arg->mr_argc * sizeof(char *));
-         arg->mr_argl = malloc(arg->mr_argc * sizeof(int));
-
-         for (i = 0; i < arg->mr_argc; ++i)
-           {
-             u_short nlen = ntohl(*(int *)cp);
-             cp += sizeof(int32);
-             if (cp + nlen > arg->mr_flattened + arg->mr_size)
-               {
-                 free(arg->mr_flattened);
-                 arg->mr_flattened = NULL;
-                 return OP_CANCELLED;
-               }
-             arg->mr_argv[i] = malloc(nlen);
-             memcpy(arg->mr_argv[i], cp, nlen);
-             arg->mr_argl[i] = nlen;
-             cp += sizeof(int32) * howmany(nlen, sizeof(int32));
-           }
-         free(arg->mr_flattened);
-         arg->mr_flattened = NULL;
-         return OP_COMPLETE;
-       }
-    }
-  return OP_RUNNING;
-}
-
-
-int mr_start_recv(OPERATION op, HALF_CONNECTION hcon, struct mr_params **argp)
-{
-  mr_params *arg = *argp;
-  if (!arg)
-    {
-      *argp = arg = malloc(sizeof(mr_params));
-      arg->mr_argl = NULL;
-      arg->mr_argv = NULL;
-      arg->mr_flattened = NULL;
-    }
-  arg->mr_state = S_RECV_START;
-  op->fcn.cont = mr_cont_recv;
-  return mr_cont_recv(op, hcon, argp);
-}
-
-void mr_destroy_reply(mr_params *reply)
-{
-  int i;
-  if (reply)
-    {
-      if (reply->mr_argl)
-       free(reply->mr_argl);
-      reply->mr_argl = NULL;
-      if (reply->mr_flattened)
-       free(reply->mr_flattened);
-      reply->mr_flattened = NULL;
-      if (reply->mr_argv)
-       {
-         for (i = 0; i < reply->mr_argc; i++)
-           {
-             if (reply->mr_argv[i])
-               free (reply->mr_argv[i]);
-             reply->mr_argv[i] = NULL;
-           }
-         free(reply->mr_argv);
-       }
-      reply->mr_argv = NULL;
-      free(reply);
-    }
-}
index f5d69587b58250ff9accf156f9c9be6d4e987bd6..7ce271096f8d05a17fea2bee5e0e6d9caab14807 100644 (file)
@@ -7,35 +7,42 @@
  * <mit-copyright.h>.
  */
 
-#include "mr_proto.h"
+#include <mit-copyright.h>
+#include <moira.h>
 
-extern CONNECTION _mr_conn;
-extern OPERATION _mr_send_op, _mr_recv_op;
+#include <sys/types.h>
 
-extern int mr_inited;
-extern int sending_version_no;
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
-/*
- * You are in a maze of twisty little FSM's, all different.
- */
+extern int _mr_conn, mr_inited;
 
-#define S_RECV_START 1
-#define S_RECV_DATA 2
-#define S_DECODE_DATA 3
+typedef struct mr_params {
+  union {
+    u_long mr_procno;     /* for call */
+    u_long mr_status;     /* for reply */
+  } u;
+  int mr_argc;
+  char **mr_argv;
+  int *mr_argl;
+  unsigned char *mr_flattened;
+} mr_params;
 
-#define EVER (;;)
+#define CHECK_CONNECTED if (!_mr_conn) return MR_NOT_CONNECTED
 
-#define CHECK_CONNECTED {if (!_mr_conn) return MR_NOT_CONNECTED;}
+#define getlong(cp, l) l = ((((unsigned char *)cp)[0] * 256 + ((unsigned char *)cp)[1]) * 256 + ((unsigned char *)cp)[2]) * 256 + ((unsigned char *)cp)[3]
+#define putlong(cp, l) do { ((unsigned char *)cp)[0] = l >> 24; ((unsigned char *)cp)[1] = l >> 16; ((unsigned char *)cp)[2] = l >> 8; ((unsigned char *)cp)[3] = l; } while(0);
 
 /* prototypes from mr_call.h */
-int mr_do_call(struct mr_params *params, struct mr_params **reply);
+int mr_do_call(struct mr_params *params, struct mr_params *reply);
+int mr_send(int fd, struct mr_params *params);
+int mr_receive(int fd, struct mr_params *params);
+void mr_destroy_reply(mr_params reply);
+
+/* prototypes from mr_connect.h */
+int mr_accept(int s, struct sockaddr_in *sin);
+int mr_connect_internal(char *server, char *port);
+int mr_listen(char *port);
 
 /* prototypes from mr_init.c */
 void mr_init(void);
-
-/* prototypes from mr_ops.c */
-int mr_complete_operation(OPERATION op);
-
-/* prototypes from mr_params.c */
-int mr_cont_send(OPERATION op, HALF_CONNECTION hcon, struct mr_params *arg);
-int mr_cont_recv(OPERATION op, HALF_CONNECTION hcon, mr_params **argp);
index af22ef891f5e265fb86e42151a94b92ffdc29d17..820c9108a51d9daf70631a899aff83141acf9558 100644 (file)
@@ -18,9 +18,6 @@
 
 RCSID("$Header$");
 
-int mr_query_internal(int argc, char **argv,
-                     int (*callback)(int, char **, void *), void *callarg);
-
 /*
  * This routine is the primary external interface to the mr library.
  *
@@ -32,77 +29,45 @@ static int level = 0;
 int mr_query(char *name, int argc, char **argv,
             int (*callproc)(int, char **, void *), void *callarg)
 {
-  char **nargv = malloc(sizeof(char *) * (argc + 1));
-  int status = 0;
-
-  if (!nargv)
-    return ENOMEM;
-  nargv[0] = name;
-  memcpy(nargv + 1, argv, sizeof(char *) * argc);
-  status = mr_query_internal(argc + 1, nargv, callproc, callarg);
-  free(nargv);
-  return status;
-}
-
-/*
- * This routine makes a Moira query.
- *
- * argv[0] is the query name.
- * argv[1..argc-1] are the query arguments.
- *
- * callproc is called once for each returned value, with arguments
- * argc, argv, and callarg.
- * If it returns a non-zero value, further calls to it are not done, and
- * all future data from the server is ignored (there should be some
- * way to send it a quench..)
- */
-
-int mr_query_internal(int argc, char **argv,
-                     int (*callproc)(int, char **, void *), void *callarg)
-{
-  int status;
-  mr_params params_st;
-  mr_params *params = NULL;
-  mr_params *reply = NULL;
-  int stopcallbacks = 0;
+  int status, stopcallbacks = 0;
+  mr_params params, reply;
 
+  CHECK_CONNECTED;
   if (level)
     return MR_QUERY_NOT_REENTRANT;
 
-  CHECK_CONNECTED;
-  level++;
-
-  params = &params_st;
-  params->mr_version_no = sending_version_no;
-  params->mr_procno = MR_QUERY;
-  params->mr_argc = argc;
-  params->mr_argl = NULL;
-  params->mr_argv = argv;
+  params.u.mr_procno = MR_QUERY;
+  params.mr_argc = argc + 1;
+  params.mr_argl = NULL;
+  params.mr_argv = malloc(sizeof(char *) * (argc + 1));
+  if (!params.mr_argv)
+    return ENOMEM;
+  params.mr_argv[0] = name;
+  memcpy(params.mr_argv + 1, argv, sizeof(char *) * argc);
 
-  if ((status = mr_do_call(params, &reply)))
+  level++;
+  if ((status = mr_do_call(&params, &reply)))
     goto punt;
 
-  while ((status = reply->mr_status) == MR_MORE_DATA)
+  while ((status = reply.u.mr_status) == MR_MORE_DATA)
     {
-      if (!stopcallbacks && callproc)
-       stopcallbacks = (*callproc)(reply->mr_argc, reply->mr_argv, callarg);
+      if (!stopcallbacks)
+       stopcallbacks = (*callproc)(reply.mr_argc, reply.mr_argv, callarg);
       mr_destroy_reply(reply);
-      reply = NULL;
-
-      initialize_operation(_mr_recv_op, mr_start_recv, &reply, NULL);
-      queue_operation(_mr_conn, CON_INPUT, _mr_recv_op);
 
-      complete_operation(_mr_recv_op);
-      if (OP_STATUS(_mr_recv_op) != OP_COMPLETE)
+      if (mr_receive(_mr_conn, &reply) != MR_SUCCESS)
        {
          mr_disconnect();
          status = MR_ABORTED;
          goto punt_1;
        }
     }
+
 punt:
   mr_destroy_reply(reply);
 punt_1:
   level--;
+  free(params.mr_argv);
+
   return status;
 }
index 8fec176c7a72f9c5409c8c2966043b95d2161117..dac1e50719d73d14a75580273551e113a70d0a63 100644 (file)
@@ -92,7 +92,7 @@ those described in this man page, but they are not intended to be used
 directly. Instead, they are called by the routines that are described.
 
 Be sure to link your application against these libraries:
--lmoira -lmrgdb -lcom_err -lkrb -ldes
+-lmoira -lcom_err -lkrb -ldes
 .TP
 Protocol functions
 All protocol routines return 0 on success, or a value from 
index 6796812b6909307116d849d4ff13a9f2e080bad3..cad93f878b37180e28588e9ef9bcdb9255a7e575 100644 (file)
@@ -12,5 +12,5 @@ SRCS= startreg.c reg_svr.c requests.c reg_svr.h
 CODE=$(SRCS)
 OBJS=requests.o reg_svr.o
 
-program(reg_svr, $(OBJS),,../server/libmrglue.a -lkadm $(LIBGDSS) $(CLIBS) $(SQL_LIB), ${PROGDIR})
+program(reg_svr, $(OBJS),,-lkadm $(LIBGDSS) $(CLIBS) $(SQL_LIB), ${PROGDIR})
 program(startreg, startreg.o,,,${PROGDIR})
index b1341b24e9521363bd89ad64a1ad5f778dd9948e..daef5ab7646d6301471ce42a43b2388e648a0d1d 100644 (file)
@@ -35,6 +35,9 @@ RCSID("$Header$");
 
 extern char admin_errmsg[];
 
+FILE *journal;
+char *whoami;
+
 int parse_encrypted(struct msg *message, struct db_data *data);
 int parse_encrypted(struct msg *message, struct db_data *data);
 int db_callproc(int argc, char **argv, void *queue);
index c14272e4e291286cd4a7b050db84acd63e7e8f24..6cd73bc0657a13d37f0980160ea6388965b200a2 100644 (file)
 GDSS_INC=$(GDSSINC)
 
 SRCS = startmoira.c mr_main.c mr_sauth.c mr_scall.c \
-       mr_srvdata.c mr_shutdown.c mr_util.c \
+       mr_shutdown.c mr_util.c \
        mr_server.h query.h qrtn.h qrtn.c \
        qsupport.c qsubs.c queries2.c increment.c \
        cache.c mr_glue.c qvalidate.c qaccess.c qsetup.c \
        qfollow.c
 CODE= startmoira.c mr_main.c mr_sauth.c mr_scall.c \
-       mr_srvdata.c mr_shutdown.c mr_util.c \
+       mr_shutdown.c mr_util.c \
        mr_server.h query.h qrtn.h qrtn.pc \
        qsupport.pc qsubs.c queries2.c increment.pc \
        cache.pc mr_glue.c qvalidate.pc Imakefile \
        qaccess.pc qsetup.pc qfollow.pc
-SRVOBJ=mr_main.o mr_sauth.o mr_scall.o mr_srvdata.o mr_shutdown.o \
+SRVOBJ=mr_main.o mr_sauth.o mr_scall.o mr_shutdown.o \
        mr_util.o qrtn.o queries2.o qsupport.o qsubs.o \
        increment.o cache.o qvalidate.o \
        qaccess.o qsetup.o qfollow.o
 GLUOBJS=mr_glue.o qrtn.o queries2.o qsupport.o qsubs.o \
-       ../lib/mr_et.o mr_sauth.o mr_srvdata.o \
+       ../lib/mr_et.o mr_sauth.o \
        ../lib/krb_et.o mr_util.o increment.o cache.o \
        qvalidate.o qaccess.o qsetup.o qfollow.o
 SRCDIR = $(SRCTOP)/server
 sqlrule()
 
-program(moirad, ${SRVOBJ},${MR_LIBDEP} ${GDB_LIBDEP},\
+program(moirad, ${SRVOBJ},${MR_LIBDEP},\
        -L/usr/athena/lib .././lib/libmoira.a -lzephyr \
-       .././gdb/libmrgdb.a  -lcom_err $(LIBGDSS)\
+       -lcom_err $(LIBGDSS)\
        -lkrb -ldes -lhesiod ${SQL_LIB}, ${PROGDIR})
-program(startmoira, startmoira.o,${MR_LIBDEP} ${GDB_LIBDEP},\
+program(startmoira, startmoira.o,${MR_LIBDEP},\
        -L/usr/athena/lib .././lib/libmoira.a -lzephyr \
-       .././gdb/libmrgdb.a -lcom_err -lkrb -ldes -lhesiod,\
+       -lcom_err -lkrb -ldes -lhesiod,\
        ${PROGDIR})
 library_obj_rule()
 install_library_target(mrglue,$(GLUOBJS),$(SRCS))
index 352b1a697ab70131597910c2af648afc32523857..72d2f9f9999bad70528d8488bdd14f0b2edcffee 100644 (file)
@@ -363,6 +363,7 @@ void flush_name(char *name, enum tables type)
          i->next->prev = i->prev;
          i->prev->next = i->next;
          free(i);
+         break;
        }
     }
 }
index 5b86c29b06776214f2c454b2895cc775344e6c2a..27f540e6eb8acdeb7bfeedf08232e148a1b974fe 100644 (file)
@@ -13,6 +13,7 @@
 #include "qrtn.h"
 
 #include <signal.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
index 80c9ccc230458b1f8a5672e7635d0db05fcabaed..b1ee8f94c67dfbc1fe84cf261a15482064b8d648 100644 (file)
@@ -86,7 +86,6 @@ int mr_noop(void)
 int mr_auth(char *prog)
 {
   struct passwd *pw;
-  extern char *krb_realm;
   char buf[1024];
 
   CHECK_CONNECTED;
@@ -95,7 +94,7 @@ int mr_auth(char *prog)
     return KDC_PR_UNKNOWN + ERROR_TABLE_BASE_krb;
   strcpy(pseudo_client.kname.name, pw->pw_name);
   krb_get_lrealm(pseudo_client.kname.realm, 1);
-  krb_realm = pseudo_client.kname.realm;
+  krb_get_lrealm(krb_realm, 1);
 
   strcpy(buf, pw->pw_name);
   strcat(buf, "@");
@@ -105,8 +104,6 @@ int mr_auth(char *prog)
   name_to_id(pseudo_client.kname.name, USERS_TABLE, &pseudo_client.users_id);
   pseudo_client.client_id = pseudo_client.users_id;
   strncpy(pseudo_client.entity, prog, 8);
-  pseudo_client.args = malloc(sizeof(mr_params));
-  pseudo_client.args->mr_version_no = MR_VERSION_2;
   return 0;
 }
 
index aaa4896a11cf5e330ca121a55d828884cf57577f..591eabc15f2079fcea04539e9db81d4106c6aad9 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+#include <krb.h>
+
 RCSID("$Header$");
 
 extern char *krb_get_lrealm(char *, int);
 
-extern CONNECTION newconn, listencon;
-
-extern int nclients;
-extern client **clients, *cur_client;
+client *cur_client;
 
-extern OPERATION listenop;
-extern LIST_OF_OPERATIONS op_list;
+char *whoami;
+char *takedown;
+FILE *journal;
 
-extern struct sockaddr_in client_addr;
-extern int client_addrlen;
-extern TUPLE client_tuple;
+time_t now;
 
-extern char *whoami;
-extern char buf1[BUFSIZ];
-extern char *takedown;
-extern FILE *journal;
+char *host;
+char krb_realm[REALM_SZ];
 
-extern time_t now;
+/* Client array and associated data. This needs to be global for _list_users */
+client **clients;
+int nclients, clientssize;
 
-char *host;
+int dormant;
 
 void reapchild(int x);
 void godormant(int x);
 void gowakeup(int x);
-int do_listen(char *port);
-void do_reset_listen(void);
 void clist_append(client *cp);
-void oplist_append(LIST_OF_OPERATIONS *oplp, OPERATION op);
-void oplist_delete(LIST_OF_OPERATIONS oplp, OPERATION op);
 void mr_setup_signals(void);
-int new_connection(void);
 
 /*
  * Main Moira server loop.
@@ -73,20 +66,20 @@ int new_connection(void);
 
 int main(int argc, char **argv)
 {
-  int status, i;
+  int status, i, listener;
   time_t tardy;
   char *port, *p;
   extern char *database;
   struct stat stbuf;
   struct utsname uts;
+  fd_set readfds, writefds, xreadfds, xwritefds;
+  int nfds, counter = 0;
 
   whoami = argv[0];
   /*
    * Error handler init.
    */
-  initialize_sms_error_table();
-  initialize_krb_error_table();
-  initialize_gdss_error_table();
+  mr_init();
   set_com_err_hook(mr_com_err);
   setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
@@ -111,17 +104,6 @@ int main(int argc, char **argv)
        }
     }
 
-  /*
-   * GDB initialization.
-   */
-  if (gdb_init() != 0)
-    {
-      com_err(whoami, 0, "GDB initialization failed.");
-      exit(1);
-    }
-  gdb_debug(0); /* this can be patched, if necessary, to enable */
-               /* GDB level debugging .. */
-  krb_realm = malloc(REALM_SZ);
   krb_get_lrealm(krb_realm, 1);
 
   /*
@@ -132,7 +114,7 @@ int main(int argc, char **argv)
     {
       if ((status = mr_open_database()))
        {
-         com_err(whoami, status, " when trying to open database.");
+         com_err(whoami, status, "trying to open database.");
          exit(1);
        }
       sanity_check_database();
@@ -165,27 +147,30 @@ int main(int argc, char **argv)
    * Set up client array handler.
    */
   nclients = 0;
-  clients = malloc(0);
+  clientssize = 10;
+  clients = malloc(clientssize * sizeof(client *));
 
   mr_setup_signals();
 
   journal = fopen(JOURNAL, "a");
   if (!journal)
     {
-      com_err(whoami, errno, " while opening journal file");
+      com_err(whoami, errno, "opening journal file");
       exit(1);
     }
 
   /*
    * Establish template connection.
    */
-  if ((status = do_listen(port)))
+  if (!(listener = mr_listen(port)))
     {
-      com_err(whoami, status, " while trying to create listening connection");
+      com_err(whoami, status, "trying to create listening connection");
       exit(1);
     }
-
-  op_list = create_list_of_operations(1, listenop);
+  FD_ZERO(&xreadfds);
+  FD_ZERO(&xwritefds);
+  FD_SET(listener, &xreadfds);
+  nfds = listener + 1;
 
   com_err(whoami, 0, "started (pid %d)", getpid());
   com_err(whoami, 0, rcsid);
@@ -200,10 +185,11 @@ int main(int argc, char **argv)
   while (!takedown)
     {
       int i;
-      /*
-       * Block until something happens.
-       */
-      if (dormant == SLEEPY)
+      struct timeval timeout;
+
+      /* If we're supposed to go down and we can, do it */
+      if ((dormant == AWAKE) && (nclients == 0) &&
+         (stat(MOIRA_MOTD_FILE, &stbuf) == 0))
        {
          mr_close_database();
          com_err(whoami, 0, "database closed");
@@ -211,104 +197,138 @@ int main(int argc, char **argv)
          send_zgram("MOIRA", "database closed");
          dormant = ASLEEP;
        }
-      else if (dormant == GROGGY)
-       {
-         mr_open_database();
-         com_err(whoami, 0, "database open");
-         mr_setup_signals();
-         send_zgram("MOIRA", "database open again");
-         dormant = AWAKE;
-       }
 
-      errno = 0;
-      status = op_select_any(op_list, 0, NULL, NULL, NULL, NULL);
-      if (status == -1)
+      /* Block until something happens. */
+      memcpy(&readfds, &xreadfds, sizeof(readfds));
+      memcpy(&writefds, &xwritefds, sizeof(writefds));
+      /* XXX set timeout */
+      if (select(nfds, &readfds, &writefds, NULL, NULL) == -1)
        {
          if (errno != EINTR)
-           com_err(whoami, errno, " error from op_select");
+           com_err(whoami, errno, "in select");
          if (!inc_running || now - inc_started > INC_TIMEOUT)
            next_incremental();
          continue;
        }
-      else if (status != -2)
-       {
-         com_err(whoami, 0, " wrong return from op_select_any");
-         continue;
-       }
+
       if (takedown)
        break;
       time(&now);
       if (!inc_running || now - inc_started > INC_TIMEOUT)
        next_incremental();
+      tardy = now - 30 * 60;
+
+      /* If we're asleep and we should wake up, do it */
+      if ((dormant == ASLEEP) && (stat(MOIRA_MOTD_FILE, &stbuf) == -1) &&
+         (errno == ENOENT))
+       {
+         mr_open_database();
+         com_err(whoami, 0, "database open");
+         mr_setup_signals();
+         send_zgram("MOIRA", "database open again");
+         dormant = AWAKE;
+       }
 
-      /*
-       * Handle any new connections; this comes first so
-       * errno isn't tromped on.
-       */
-      if (OP_DONE(listenop))
+      /* Handle any new connections */
+      if (FD_ISSET(listener, &readfds))
        {
-         if (OP_STATUS(listenop) == OP_CANCELLED)
+         int newconn;
+         struct sockaddr_in addr;
+         client *cp;
+
+         newconn = mr_accept(listener, &addr);
+         if (newconn == -1)
+           com_err(whoami, errno, "accepting new connection");
+         else if (newconn > 0)
            {
-             if (errno == EWOULDBLOCK)
-               do_reset_listen();
-             else
+             if (newconn + 1 > nfds)
+               nfds = newconn + 1;
+             FD_SET(newconn, &xreadfds);
+
+             /* Add a new client to the array */
+             nclients++;
+             if (nclients > clientssize)
                {
-                 static int count = 0;
-                 com_err(whoami, errno, " error (%d) on listen", count);
-                 if (count++ > 10)
-                   exit(1);
+                 clientssize = 2 * clientssize;
+                 clients = xrealloc(clients, clientssize * sizeof(client *));
                }
-           }
-         else if ((status = new_connection()))
-           {
-             com_err(whoami, errno, " Error on listening operation.");
-             /*
-              * Sleep here to prevent hosing?
-              */
-           }
-         /* if the new connection is our only connection,
-          * and the server is supposed to be down, then go
-          * down now.
-          */
-         if ((dormant == AWAKE) && (nclients == 1) &&
-             (stat(MOIRA_MOTD_FILE, &stbuf) == 0))
-           {
-             com_err(whoami, 0, "motd file exists, slumbertime");
-             dormant = SLEEPY;
-           }
-         /* on new connection, if we are no longer supposed
-          * to be down, then wake up.
-          */
-         if ((dormant == ASLEEP) && (stat(MOIRA_MOTD_FILE, &stbuf) == -1) &&
-             (errno == ENOENT))
-           {
-             com_err(whoami, 0, "motd file no longer exists, waking up");
-             dormant = GROGGY;
+
+             clients[nclients - 1] = cp = xmalloc(sizeof(client));
+             memset(cp, 0, sizeof(client));
+             cp->con = newconn;
+             cp->id = counter++;
+             cp->last_time_used = now;
+             cp->haddr = addr;
+             cp->tuplessize = 1;
+             cp->tuples = xmalloc(sizeof(mr_params));
+             memset(cp->tuples, 0, sizeof(mr_params));
+
+             cur_client = cp;
+             com_err(whoami, 0,
+                     "New connection from %s port %d (now %d client%s)",
+                     inet_ntoa(cp->haddr.sin_addr),
+                     (int)ntohs(cp->haddr.sin_port),
+                     nclients, nclients != 1 ? "s" : "");
            }
        }
-      /*
-       * Handle any existing connections.
-       */
-      tardy = now - 30 * 60;
 
+      /* Handle any existing connections. */
       for (i = 0; i < nclients; i++)
        {
          cur_client = clients[i];
-         if (OP_DONE(clients[i]->pending_op))
+
+         if (FD_ISSET(clients[i]->con, &writefds))
+           {
+             client_write(clients[i]);
+             if (!clients[i]->ntuples)
+               {
+                 FD_CLR(clients[i]->con, &xwritefds);
+                 /* Now that we're done writing we can read again */
+                 FD_SET(clients[i]->con, &xreadfds);
+               }
+             clients[i]->last_time_used = now;
+           }
+
+         if (FD_ISSET(clients[i]->con, &readfds))
            {
-             cur_client->last_time_used = now;
-             do_client(cur_client);
+             client_read(clients[i]);
+             if (clients[i]->ntuples)
+               FD_SET(clients[i]->con, &xwritefds);
+             clients[i]->last_time_used = now;
            }
-         else if (clients[i]->last_time_used < tardy)
+
+         if (clients[i]->last_time_used < tardy)
            {
              com_err(whoami, 0, "Shutting down connection due to inactivity");
-             shutdown(cur_client->con->in.fd, 2);
+             clients[i]->done = 1;
+           }
+
+         if (clients[i]->done)
+           {
+             client *old;
+
+             com_err(whoami, 0, "Closed connection (now %d client%s, "
+                     "%d queries)", nclients - 1, nclients != 2 ? "s" : "",
+                     newqueries);
+
+             shutdown(clients[i]->con, 2);
+             close(clients[i]->con);
+             FD_CLR(clients[i]->con, &xreadfds);
+             FD_CLR(clients[i]->con, &xwritefds);
+             for (; clients[i]->ntuples; clients[i]->ntuples--)
+               mr_destroy_reply(clients[i]->tuples[clients[i]->ntuples - 1]);
+             free(clients[i]->tuples);
+             old = clients[i];
+             clients[i] = clients[--nclients];
+             free(old);
            }
+
          cur_client = NULL;
          if (takedown)
            break;
        }
     }
+
   com_err(whoami, 0, "%s", takedown);
   if (dormant != ASLEEP)
     mr_close_database();
@@ -316,192 +336,6 @@ int main(int argc, char **argv)
   return 0;
 }
 
-/*
- * Set up the template connection and queue the first accept.
- */
-
-int do_listen(char *port)
-{
-  listencon = create_listening_connection(port);
-
-  if (!listencon)
-    return errno;
-
-  listenop = create_operation();
-  client_addrlen = sizeof(client_addr);
-
-  start_accepting_client(listencon, listenop, &newconn, (char *)&client_addr,
-                        &client_addrlen, &client_tuple);
-  return 0;
-}
-
-
-void do_reset_listen(void)
-{
-  client_addrlen = sizeof(client_addr);
-  start_accepting_client(listencon, listenop, &newconn, (char *)&client_addr,
-                        &client_addrlen, &client_tuple);
-}
-
-/*
- * This routine is called when a new connection comes in.
- *
- * It sets up a new client and adds it to the list of currently active clients.
- */
-int new_connection(void)
-{
-  client *cp;
-  static counter = 0;
-
-  /*
-   * Make sure there's been no error
-   */
-  if (OP_STATUS(listenop) != OP_COMPLETE)
-    return errno;
-
-  if (!newconn)
-    return MR_NOT_CONNECTED;
-
-  /*
-   * Set up the new connection and reply to the client
-   */
-  cp = malloc(sizeof(client));
-  memset(cp, 0, sizeof(*cp));
-  cp->action = CL_ACCEPT;
-  cp->con = newconn;
-  cp->id = counter++;
-  cp->args = NULL;
-  cp->clname[0] = '\0';
-  cp->reply.mr_argv = NULL;
-  cp->first = NULL;
-  cp->last = NULL;
-  cp->last_time_used = now;
-  newconn = NULL;
-
-  cp->pending_op = create_operation();
-  reset_operation(cp->pending_op);
-  oplist_append(&op_list, cp->pending_op);
-  cur_client = cp;
-
-  /*
-   * Add a new client to the array..
-   */
-  clist_append(cp);
-
-  /*
-   * Let him know we heard him.
-   */
-  start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED, "", "");
-
-  cp->haddr = client_addr;
-
-  /*
-   * Log new connection.
-   */
-  com_err(whoami, 0, "New connection from %s port %d (now %d client%s)",
-         inet_ntoa(cp->haddr.sin_addr), (int)ntohs(cp->haddr.sin_port),
-         nclients, nclients != 1 ? "s" : "");
-
-  /*
-   * Get ready to accept the next connection.
-   */
-  reset_operation(listenop);
-  client_addrlen = sizeof(client_addr);
-
-  start_accepting_client(listencon, listenop, &newconn, (char *)&client_addr,
-                        &client_addrlen, &client_tuple);
-  return 0;
-}
-
-/*
- * Add a new client to the known clients.
- */
-void clist_append(client *cp)
-{
-  client **clients_n;
-
-  nclients++;
-  clients_n = malloc(nclients * sizeof(client *));
-  memcpy(clients_n, clients, (nclients - 1) * sizeof(cp));
-  clients_n[nclients - 1] = cp;
-  free(clients);
-  clients = clients_n;
-  clients_n = NULL;
-}
-
-
-void clist_delete(client *cp)
-{
-  client **clients_n, **scpp, **dcpp; /* source and dest client ptr ptr */
-
-  int found_it = 0;
-
-  clients_n = malloc((nclients - 1) * sizeof(client *));
-  for (scpp = clients, dcpp = clients_n; scpp < clients + nclients; )
-    {
-      if (*scpp != cp)
-       *dcpp++ = *scpp++;
-      else
-       {
-         scpp++;
-         if (found_it)
-           abort();
-         found_it = 1;
-       }
-    }
-  --nclients;
-  free(clients);
-  clients = clients_n;
-  clients_n = NULL;
-  oplist_delete(op_list, cp->pending_op);
-  reset_operation(cp->pending_op);
-  delete_operation(cp->pending_op);
-  sever_connection(cp->con);
-  free(cp);
-}
-
-/*
- * Add a new operation to a list of operations.
- *
- * This should be rewritten to use realloc instead, since in most
- * cases it won't have to copy the array.
- */
-
-void oplist_append(LIST_OF_OPERATIONS *oplp, OPERATION op)
-{
-  int count = (*oplp)->count + 1;
-  LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS)
-    db_alloc(size_of_list_of_operations(count));
-  memcpy(newlist, *oplp, size_of_list_of_operations((*oplp)->count));
-  newlist->count++;
-  newlist->op[count - 1] = op;
-  db_free(*oplp, size_of_list_of_operations(count - 1));
-  *oplp = newlist;
-}
-
-void oplist_delete(LIST_OF_OPERATIONS oplp, OPERATION op)
-{
-  OPERATION *s;
-  int c;
-
-  for (s = oplp->op, c = oplp->count; c; --c, ++s)
-    {
-      if (*s == op)
-       {
-         while (c > 0)
-           {
-             *s = *(s + 1);
-             ++s;
-             --c;
-           }
-         oplp->count--;
-         return;
-       }
-    }
-  abort();
-}
-
-
 void reapchild(int x)
 {
   int status, pid;
index d2c61e248af2be16cf0a2610e9a77359e3af07cd..817888c775759a3621a40f40c93931a88100c594 100644 (file)
@@ -39,7 +39,7 @@ replay_cache *rcache = NULL;
  * cl->cl_name.
  */
 
-void do_auth(client *cl)
+void do_auth(client *cl, mr_params req)
 {
   KTEXT_ST auth;
   AUTH_DAT ad;
@@ -47,17 +47,16 @@ void do_auth(client *cl)
   replay_cache *rc, *rcnew;
   time_t now;
 
-  auth.length = cl->args->mr_argl[0];
-  memcpy(auth.dat, cl->args->mr_argv[0], auth.length);
+  auth.length = req.mr_argl[0];
+  memcpy(auth.dat, req.mr_argv[0], auth.length);
   auth.mbz = 0;
 
-  if ((status = krb_rd_req (&auth, MOIRA_SNAME, host,
-                           cl->haddr.sin_addr.s_addr, &ad, "")))
+  if ((status = krb_rd_req(&auth, MOIRA_SNAME, host,
+                          cl->haddr.sin_addr.s_addr, &ad, "")))
     {
       status += ERROR_TABLE_BASE_krb;
-      cl->reply.mr_status = status;
-      if (log_flags & LOG_RES)
-       com_err(whoami, status, " (authentication failed)");
+      client_reply(cl, status);
+      com_err(whoami, status, " (authentication failed)");
       return;
     }
 
@@ -78,7 +77,7 @@ void do_auth(client *cl)
                  inet_ntoa(cl->haddr.sin_addr),
                  kname_unparse(ad.pname, ad.pinst, ad.prealm));
          com_err(whoami, KE_RD_AP_REPEAT, " (authentication failed)");
-         cl->reply.mr_status = KE_RD_AP_REPEAT;
+         client_reply(cl, KE_RD_AP_REPEAT);
          return;
        }
     }
@@ -117,22 +116,16 @@ void do_auth(client *cl)
   status = set_krb_mapping(cl->clname, ad.pname, ok,
                           &cl->client_id, &cl->users_id);
 
-  if (cl->args->mr_version_no == MR_VERSION_2)
-    {
-      strncpy(cl->entity, cl->args->mr_argv[1], 8);
-      cl->entity[8] = 0;
-    }
-  else
-    strcpy(cl->entity, "???");
+  strncpy(cl->entity, req.mr_argv[1], 8);
+  cl->entity[8] = 0;
+
   memset(&ad, 0, sizeof(ad));  /* Clean up session key, etc. */
 
-  if (log_flags & LOG_RES)
-    {
-      com_err(whoami, 0, "Auth to %s using %s, uid %d cid %d",
-             cl->clname, cl->entity, cl->users_id, cl->client_id);
-    }
-  if (status != MR_SUCCESS)
-    cl->reply.mr_status = status;
-  else if (cl->users_id == 0)
-    cl->reply.mr_status = MR_USER_AUTH;
+  com_err(whoami, 0, "Auth to %s using %s, uid %d cid %d",
+         cl->clname, cl->entity, cl->users_id, cl->client_id);
+
+  if (status != MR_SUCCESS || cl->users_id != 0)
+    client_reply(cl, status);
+  else
+    client_reply(cl, MR_USER_AUTH);
 }
index acf17e470e61c75924971074fecf6c1eebfd48b0..82cfed56e1c6010177b3bfaedf7033fb3bcafa20 100644 (file)
 
 RCSID("$Header$");
 
-extern char buf1[];
 extern int nclients;
+extern client **clients;
 extern char *whoami;
 
 extern int dbms_errno, mr_errcode;
-static int row_count;
 
 void do_call(client *cl);
 void free_rtn_tuples(client *cp);
-int retr_callback(int argc, char **argv, void *p_cp);
-int list_users(int (*callbk)(int, char **, void *), char *callarg);
-void do_retr(client *cl);
-void do_access(client *cl);
+int retr_callback(int argc, char **argv, void *p_cl);
+int list_users(client *cl);
+void do_retr(client *cl, mr_params req);
+void do_access(client *cl, mr_params req);
 void get_motd(client *cl);
 
 /* Put this in a variable so that we can patch it if necessary */
 int max_row_count = 4096;
 
-/*
- * Welcome to the (finite state) machine (highest level).
- */
-void do_client(client *cp)
-{
-  struct stat stbuf;
-
-  free_rtn_tuples(cp);
-  if (OP_STATUS(cp->pending_op) == OP_CANCELLED)
-    {
-      com_err(whoami, 0,
-             "Closed connection (now %d client%s, %d new queries, %d old)",
-             nclients - 1, nclients != 2 ? "s" : "", newqueries, oldqueries);
-      clist_delete(cp);
-      /* if we no longer have any clients, and we're supposed to
-       * go down, then go down now.
-       */
-      if ((dormant == AWAKE) && (nclients == 0) &&
-         (stat(MOIRA_MOTD_FILE, &stbuf) == 0))
-       {
-         com_err(whoami, 0, "motd file exists, slumbertime");
-         dormant = SLEEPY;
-       }
-      return;
-    }
-  switch (cp->action)
-    {
-    case CL_ACCEPT:
-    case CL_SEND:
-      /* Start recieving next request */
-      initialize_operation(cp->pending_op, mr_start_recv,
-                          (char *)&cp->args, NULL);
-      queue_operation(cp->con, CON_INPUT, cp->pending_op);
-      cp->action = CL_RECEIVE;
-      break;
-    case CL_RECEIVE:
-      /* Data is here. Process it & start it heading back */
-      do_call(cp); /* This may block for a while. */
-      mr_destroy_reply(cp->args);
-      cp->args = NULL;
-      initialize_operation(cp->pending_op, mr_start_send,
-                          (char *)&cp->reply, NULL);
-      queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
-      cp->action = CL_SEND;
-      break;
-    }
-}
-
 char *procnames[] = {
   "noop",
   "auth",
@@ -102,33 +53,35 @@ char *procnames[] = {
   "motd",
 };
 
+int newqueries;
 
-void do_call(client *cl)
+void client_read(client *cl)
 {
-  int pn;
-  cl->reply.mr_argc = 0;
-  cl->reply.mr_status = 0;
-  cl->reply.mr_version_no = cl->args->mr_version_no;
-  if (((pn = cl->args->mr_procno) < 0) || (pn > MR_MAX_PROC))
+  mr_params req;
+  int status, pn;
+
+  status = mr_receive(cl->con, &req);
+  if (status != MR_SUCCESS)
     {
-      com_err(whoami, 0, "procno out of range");
-      cl->reply.mr_status = MR_UNKNOWN_PROC;
+      cl->done = 1;
+      if (status != MR_NOT_CONNECTED)
+       com_err(whoami, status, "while reading from socket");
       return;
     }
-  if (log_flags & LOG_ARGS)
+
+  pn = req.u.mr_procno;
+  if (pn < 0 || pn > MR_MAX_PROC)
     {
-      log_args(procnames[pn], cl->args->mr_version_no,
-              cl->args->mr_argc, cl->args->mr_argv);
+      com_err(whoami, 0, "procno out of range");
+      client_reply(cl, MR_UNKNOWN_PROC);
+      return;
     }
-  else if (log_flags & LOG_REQUESTS)
-    com_err(whoami, 0, "%s", procnames[pn]);
+  log_args(procnames[pn], 2, req.mr_argc, req.mr_argv);
 
-  if ((dormant == ASLEEP || dormant == GROGGY) &&
-      pn != MR_NOOP && pn != MR_MOTD)
+  if (dormant == ASLEEP && pn != MR_NOOP && pn != MR_MOTD)
     {
-      cl->reply.mr_status = MR_DOWN;
-      if (log_flags & LOG_RES)
-       com_err(whoami, MR_DOWN, "(query refused)");
+      client_reply(cl, MR_DOWN);
+      com_err(whoami, MR_DOWN, "(query refused)");
       return;
     }
 
@@ -138,19 +91,19 @@ void do_call(client *cl)
   switch (pn)
     {
     case MR_NOOP:
-      cl->reply.mr_status = 0;
+      client_reply(cl, MR_SUCCESS);
       return;
 
     case MR_AUTH:
-      do_auth(cl);
+      do_auth(cl, req);
       return;
 
     case MR_QUERY:
-      do_retr(cl);
+      do_retr(cl, req);
       return;
 
     case MR_ACCESS:
-      do_access(cl);
+      do_access(cl, req);
       return;
 
     case MR_SHUTDOWN:
@@ -158,7 +111,7 @@ void do_call(client *cl)
       return;
 
     case MR_DO_UPDATE:
-      trigger_dcm(NULL, NULL, cl);
+      client_reply(cl, MR_PERM);
       return;
 
     case MR_MOTD:
@@ -167,223 +120,195 @@ void do_call(client *cl)
     }
 }
 
-void free_rtn_tuples(client *cp)
+/* Set the final return status for a query. We always keep one more
+   free slot in cl->tuples[] than we're using so that this can't fail */
+void client_reply(client *cl, long status)
 {
-  returned_tuples *temp;
-  for (temp = cp->first; temp && OP_DONE(temp->op); )
-    {
-      returned_tuples *t1 = temp;
-      temp = t1->next;
-      if (t1 == cp->last)
-       cp->last = NULL;
-
-      mr_destroy_reply(t1->retval);
-      delete_operation(t1->op);
-      free(t1);
-    }
-  cp->first = temp;
+  cl->tuples[cl->ntuples].u.mr_status = status;
+  cl->tuples[cl->ntuples].mr_argc = 0;
+  cl->tuples[cl->ntuples].mr_argl = NULL;
+  cl->tuples[cl->ntuples].mr_argv = NULL;
+  cl->ntuples++;
 }
 
-int retr_callback(int argc, char **argv, void *p_cp)
+void client_return_tuple(client *cl, int argc, char **argv)
 {
-  client *cp = p_cp;
-  mr_params *arg_tmp;
-  returned_tuples *tp;
-  OPERATION op_tmp;
-  char **nargv;
-  int i;
+  if (cl->done || dbms_errno)
+    return;
 
-  if (row_count++ >= max_row_count)
+  if (cl->ntuples == max_row_count)
     {
       dbms_errno = mr_errcode = MR_NO_MEM;
-      return MR_ABORT;
+      return;
     }
 
-  /*
-   * This takes too much advantage of the fact that
-   * serialization of the data happens during the queue operation.
-   */
-  arg_tmp = malloc(sizeof(mr_params));
-  tp = malloc(sizeof(returned_tuples));
-  nargv = malloc(argc * sizeof(char *));
-
-  op_tmp = create_operation();
-
-  if (mr_trim_args(argc, argv) == MR_NO_MEM)
-    com_err(whoami, MR_NO_MEM, "while trimming args");
-  if (log_flags & LOG_RESP)
-    log_args("return: ", cp->args->mr_version_no, argc, argv);
-
-  tp->op = op_tmp;
-  tp->retval = arg_tmp;
-  tp->next = NULL;
-
-  arg_tmp->mr_status = MR_MORE_DATA;
-  arg_tmp->mr_version_no = cp->args->mr_version_no;
-  arg_tmp->mr_argc = argc;
-  arg_tmp->mr_argv = nargv;
-  for (i = 0; i < argc; i++)
+  if (cl->ntuples == cl->tuplessize - 1)
     {
-      int len = strlen(argv[i]) + 1;
-      nargv[i] = malloc(len);
-      memcpy(nargv[i], argv[i], len);
+      int newsize = (cl->tuplessize + 4) * 2;
+      mr_params *newtuples;
+
+      newtuples = realloc(cl->tuples, newsize * sizeof(mr_params));
+      if (!newtuples)
+       {
+         free_rtn_tuples(cl);
+         dbms_errno = mr_errcode = MR_NO_MEM;
+         return;
+       }
+      cl->tuplessize = newsize;
+      cl->tuples = newtuples;
     }
-  arg_tmp->mr_flattened = NULL;
-  arg_tmp->mr_argl = NULL;
 
-  if (cp->last)
-    {
-      cp->last->next = tp;
-      cp->last = tp;
-    } else
-      cp->last = cp->first = tp;
-
-  reset_operation(op_tmp);
-  initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp, NULL);
-  queue_operation(cp->con, CON_OUTPUT, op_tmp);
-  return MR_CONT;
+  cl->tuples[cl->ntuples].u.mr_status = MR_MORE_DATA;
+  cl->tuples[cl->ntuples].mr_argc = argc;
+  cl->tuples[cl->ntuples].mr_argl = NULL;
+  cl->tuples[cl->ntuples].mr_argv = mr_copy_args(argv, argc);
+  cl->ntuples++;
 }
 
-int list_users(int (*callbk)(int, char **, void *), char *callarg)
+void client_write(client *cl)
 {
-  char *argv[6];
-  char buf[30];
-  char buf1[30];
-  int i;
-  extern client **clients;
-  char *cp;
+  int status;
 
-  for (i = 0; i < nclients; i++)
+  status = mr_send(cl->con, &cl->tuples[cl->nexttuple]);
+  if (status)
     {
-      client *cl = clients[i];
-      if (cl->clname)
-       argv[0] = cl->clname;
-      else argv[0] = "unauthenticated";
-
-      argv[1] = inet_ntoa(cl->haddr.sin_addr);
-      argv[2] = buf;
-      sprintf(buf, "port %d", ntohs(cl->haddr.sin_port));
-      argv[3] = ctime(&cl->last_time_used);
-      cp = strchr(argv[3], '\n');
-      if (cp)
-       *cp = '\0';
-      argv[4] = buf1;
-      sprintf(buf1, "[#%d]", cl->id);
-      (*callbk)(5, argv, callarg);
+      com_err(whoami, status, "writing to socket");
+      cl->done = 1;
+    }
+  else
+    {
+      cl->nexttuple++;
+      if (cl->nexttuple == cl->ntuples)
+       free_rtn_tuples(cl);
     }
-  return 0;
 }
 
-void do_retr(client *cl)
+void free_rtn_tuples(client *cl)
 {
-  char *queryname;
+  for (cl->ntuples--; cl->ntuples >= 0; cl->ntuples--)
+    free_argv(cl->tuples[cl->ntuples].mr_argv,
+             cl->tuples[cl->ntuples].mr_argc);
+  free(cl->tuples);
+
+  cl->tuples = xmalloc(sizeof(mr_params));
+  cl->tuplessize = 1;
+  cl->ntuples = cl->nexttuple = 0;
+}
 
-  cl->reply.mr_argc = 0;
-  cl->reply.mr_status = 0;
-  row_count = 0;
+void do_retr(client *cl, mr_params req)
+{
+  char *queryname;
+  int status;
 
-  if (cl->args->mr_argc < 1)
+  if (req.mr_argc < 1)
     {
-      cl->reply.mr_status = MR_ARGS;
+      client_reply(cl, MR_ARGS);
       com_err(whoami, MR_ARGS, "got nameless query");
       return;
     }
-  queryname = cl->args->mr_argv[0];
-
-  if (cl->args->mr_version_no == MR_VERSION_2)
-    newqueries++;
-  else
-    oldqueries++;
+  queryname = req.mr_argv[0];
+  newqueries++;
 
   if (!strcmp(queryname, "_list_users"))
-    cl->reply.mr_status = list_users(retr_callback, (char *)cl);
+    status = list_users(cl);
   else
+    status = mr_process_query(cl, queryname, req.mr_argc - 1, req.mr_argv + 1,
+                             retr_callback, cl);
+
+  client_reply(cl, status);
+
+  if (cl->ntuples >= max_row_count)
     {
-      cl->reply.mr_status = mr_process_query(cl, queryname,
-                                            cl->args->mr_argc - 1,
-                                            cl->args->mr_argv + 1,
-                                            retr_callback, cl);
-    }
-  if (row_count >= max_row_count)
-    {
-      critical_alert("moirad", "attempted query %s with %d rows\n",
-                    queryname, row_count);
+      critical_alert("moirad", "attempted query %s with too many rows\n",
+                    queryname);
     }
 
-  if (log_flags & LOG_RES)
-    com_err(whoami, 0, "Query complete.");
+  com_err(whoami, 0, "Query complete.");
+}
+
+int retr_callback(int argc, char **argv, void *p_cl)
+{
+  client *cl = p_cl;
+
+  mr_trim_args(argc, argv);
+  client_return_tuple(cl, argc, argv);
 }
 
-void do_access(client *cl)
+void do_access(client *cl, mr_params req)
 {
-  if (cl->args->mr_argc < 1)
+  int status;
+
+  if (req.mr_argc < 1)
     {
-      cl->reply.mr_status = MR_ARGS;
+      client_reply(cl, MR_ARGS);
       com_err(whoami, MR_ARGS, "got nameless access");
       return;
     }
-  cl->reply.mr_argc = 0;
 
-  cl->reply.mr_status = mr_check_access(cl, cl->args->mr_argv[0],
-                                       cl->args->mr_argc - 1,
-                                       cl->args->mr_argv + 1);
+  status = mr_check_access(cl, req.mr_argv[0], req. mr_argc - 1,
+                          req.mr_argv + 1);
+  client_reply(cl, status);
 
   com_err(whoami, 0, "Access check complete.");
 }
 
-
-/* trigger_dcm is also used as a followup routine to the
- * set_server_host_override query, hence the two dummy arguments.
- */
-
-struct query pseudo_query = {
-  "trigger_dcm",
-  "tdcm",
-};
-
-int trigger_dcm(struct query *q, char *argv[], client *cl)
+void get_motd(client *cl)
 {
-  int pid;
-  char prog[128];
-
-  cl->reply.mr_argc = 0;
-
-  if ((cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl)))
-    return cl->reply.mr_status;
+  int motd;
+  char *buffer;
+  struct stat statb;
 
-  sprintf(prog, "%s/startdcm", BIN_DIR);
-  pid = vfork();
-  switch (pid)
+  if (stat(MOIRA_MOTD_FILE, &statb) == -1)
     {
-    case 0:
-      execl(prog, "startdcm", 0);
-      exit(1);
-
-    case -1:
-      cl->reply.mr_status = errno;
-      return 0;
+      client_reply(cl, MR_SUCCESS);
+      return;
+    }
+  
+  buffer = malloc(statb.st_size + 1);
+  if (!buffer)
+    {
+      client_reply(cl, MR_NO_MEM);
+      return;
+    }
 
-    default:
-      return 0;
+  motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
+  if (motd)
+    {
+      read(motd, buffer, statb.st_size);
+      close(motd);
+      buffer[statb.st_size] = '\0';
+      client_return_tuple(cl, 1, &buffer);
+      client_reply(cl, MR_SUCCESS);
     }
-}
+  else
+    client_reply(cl, errno);
 
+  free(buffer);
+}
 
-void get_motd(client *cl)
+int list_users(client *cl)
 {
-  int motd, len;
-  char buffer[1024];
-  char *arg[1];
+  char *argv[5];
+  char buf[30];
+  char buf1[30];
+  int i;
+  char *cp;
 
-  arg[0] = buffer;
-  cl->reply.mr_status = 0;
-  motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
-  if (motd < 0)
-    return;
-  len = read(motd, buffer, sizeof(buffer) - 1);
-  close(motd);
-  buffer[len] = 0;
-  row_count = 0;
-  retr_callback(1, arg, cl);
-  cl->reply.mr_status = 0;
+  for (i = 0; i < nclients; i++)
+    {
+      client *c = clients[i];
+      argv[0] = c->clname;
+      argv[1] = inet_ntoa(c->haddr.sin_addr);
+      argv[2] = buf;
+      sprintf(buf, "port %d", ntohs(c->haddr.sin_port));
+      argv[3] = ctime(&c->last_time_used);
+      cp = strchr(argv[3], '\n');
+      if (cp)
+       *cp = '\0';
+      argv[4] = buf1;
+      sprintf(buf1, "[#%d]", c->id);
+      client_return_tuple(cl, 5, argv);
+    }
+  return MR_SUCCESS;
 }
+
index 80306cb3cf5819d17d98b20d2609503795178d36..6d9d10ef349845d2732c580e88b7f062397151ff 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include <moira.h>
-#include <mr_proto.h>
+#include <mr_private.h>
 #include <moira_site.h>
 
 #include <netinet/in.h>
 
 #include <krb.h>
 
-typedef struct returned_tuples {
-  struct returned_tuples *next;
-  OPERATION op;
-  mr_params *retval;
-} returned_tuples;
-
-/*
- * This should be in the kerberos header file.
- */
+/* This should be in the kerberos header file. */
 
 struct krbname {
   char name[ANAME_SZ];
@@ -37,53 +29,23 @@ struct krbname {
  */
 
 typedef struct _client {
-  OPERATION pending_op;                /* Primary pending operation */
-  CONNECTION con;              /* Connection to the client */
-  int action;                  /* what action is pending? */
-  mr_params *args, reply;
+  int con;                     /* Connection to the client */
   int id;                      /* Unique id of client */
   struct sockaddr_in haddr;    /* IP address of client */
   char clname[MAX_K_NAME_SZ];  /* Name client authenticated to */
   struct krbname kname;        /* Parsed version of the above */
+  char entity[9];              /* client program being used */
   int users_id;                        /* Moira-internal ID of authenticated user */
-  int client_id;               /* Moira-internal ID of client for modby field */
-  returned_tuples *first, *last;
+  int client_id;               /* Moira-internal ID of client */
   time_t last_time_used;       /* Last time connection used */
-  char entity[9];              /* entity on other end of the connection */
+  mr_params *tuples;           /* Tuples waiting to send back to client */
+  int ntuples;                 /* Number of tuples waiting */
+  int tuplessize;              /* Current size of tuple array */
+  int nexttuple;               /* Next tuple to return */
+  int done;                    /* Close up next time through loop */
 } client;
 
-/*
- * States
- */
-
-#define CL_DEAD 0
-#define CL_STARTING 1
-
-/*
- * Actions.
- */
-
-#define CL_ACCEPT 0
-#define CL_RECEIVE 1
-#define CL_SEND 2
-
-extern char *krb_realm;
-
-/*
- * Debugging options.
- */
-
-extern int log_flags;
-
-#define LOG_CONNECT            0x0001
-#define LOG_REQUESTS           0x0002
-#define LOG_ARGS               0x0004
-#define LOG_RESP               0x0008
-#define LOG_RES                        0x0010
-#define LOG_VALID              0x0020
-#define LOG_SQL                        0x0040
-#define LOG_GDSS               0x0080
-
+extern char krb_realm[REALM_SZ];
 
 /* max length of query argument allowed */
 #define ARGLEN 257
@@ -91,7 +53,7 @@ extern int log_flags;
 #define QMAXARGS       22
 
 /* statistics on number of queries by version number */
-extern int newqueries, oldqueries;
+extern int newqueries;
 
 /* Maximum and minimum values that will ever be chosen for IDs */
 #define MAX_ID_VALUE   31999
@@ -117,19 +79,6 @@ struct query;
 struct validate;
 struct valobj;
 
-/* prototypes from gdb */
-int gdb_init(void);
-int gdb_debug(int flag);
-void start_accepting_client(CONNECTION, OPERATION, CONNECTION *,
-                            char *, int *, TUPLE *);
-int initialize_operation(OPERATION, int (*init_function)(OPERATION, HALF_CONNECTION, void *),
-                        char *, int (*cancel_function)(HALF_CONNECTION, void *));
-int reset_operation(OPERATION);
-int delete_operation(OPERATION);
-int start_replying_to_client(OPERATION, CONNECTION, int, char *, char *);
-int op_select(LIST_OF_OPERATIONS, int, fd_set *, fd_set *, fd_set *,
-             struct timeval *);
-
 /* prototypes from increment.dc */
 void incremental_init(void);
 void next_incremental(void);
@@ -164,11 +113,14 @@ int convert_wildcards(char *arg);
 void clist_delete(client *cp);
 
 /* prototypes from mr_sauth.c */
-void do_auth(client *cl);
+void do_auth(client *cl, mr_params req);
 
 /* prototypes from mr_scall.c */
-void do_client(client *cp);
-int trigger_dcm(struct query *q, char *argv[], client *cl);
+void do_client(client *cl);
+void client_reply(client *cl, long status);
+void client_return_tuple(client *cl, int argc, char **argv);
+void client_read(client *cl);
+void client_write(client *cl);
 
 /* prototypes from mr_shutdown.c */
 void sigshut(int);
@@ -180,6 +132,8 @@ void log_args(char *tag, int version, int argc, char **argv);
 void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar);
 int mr_trim_args(int argc, char **argv);
 char **mr_copy_args(char **argv, int argc);
+void *xmalloc(size_t);
+void *xrealloc(void *, size_t);
 
 /* prototypes from qaccess.pc */
 int access_user(struct query *q, char *argv[], client *cl);
@@ -244,6 +198,7 @@ int set_nfsphys_modtime(struct query *q, char *argv[], client *cl);
 int set_filesys_modtime(struct query *q, char *argv[], client *cl);
 int set_zephyr_modtime(struct query *q, char *argv[], client *cl);
 int _sdl_followup(struct query *q, char *argv[], client *cl);
+int trigger_dcm(struct query *q, char *argv[], client *cl);
 
 /* prototypes from qsetup.pc */
 int prefetch_value(struct query *q, char *argv[], client *cl);
index 5f3e3caf0c2a97df086398ca82496b7b5863bf68..4bf27a820c5b893480f87a135ab260143bc060bf 100644 (file)
@@ -26,6 +26,6 @@ void do_shutdown(client *cl)
    * This feature is no longer supported.  Sorry.
    */
   com_err(whoami, 0, "Shutdown request by %s rejected", cl->clname);
-  cl->reply.mr_status = EACCES;
+  client_reply(cl, EACCES);
 }
 
diff --git a/server/mr_srvdata.c b/server/mr_srvdata.c
deleted file mode 100644 (file)
index dcca3c8..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/* $Id$
- *
- * Global variables inside the Moira server.
- *
- * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
- */
-
-#include <mit-copyright.h>
-#include "mr_server.h"
-
-RCSID("$Header$");
-
-/*
- * Connections & clients:
- *
- * The template and most recently connected connection:
- */
-CONNECTION listencon, newconn;
-/*
- * The template listen operation.
- */
-OPERATION listenop;
-/*
- * The list of operations corresponding to the I/O being done by the
- * currently connected clients.
- */
-LIST_OF_OPERATIONS op_list;
-/*
- * The current number of connected clients, an array of them, and the
- * "current" client, if any.
- */
-int nclients = 0;
-client **clients, *cur_client;
-/*
- * Socket address of the most recently connected client.
- */
-struct sockaddr_in client_addr;
-int client_addrlen;
-/*
- * Additional data sent at connect time by the client
- * (provided by GDB; ignored by Moira)
- */
-TUPLE client_tuple;
-
-/*
- * Name server was invoked as.
- */
-char *whoami;
-/*
- * Buffer for use in error messages.
- */
-char buf1[BUFSIZ];
-
-/*
- * If non-null, reason for shutdown.  (Moira will be going down shortly
- * if this is non-null)
- */
-char *takedown = NULL;
-
-/* States for putting the server to sleep & waking it up again. */
-int dormant = AWAKE;
-
-/*
- * The name of the local Kerberos realm
- */
-
-char *krb_realm = NULL;
-/*
- * Logging levels.
- */
-
-int log_flags = LOG_CONNECT|LOG_REQUESTS|LOG_ARGS|LOG_RES;
-
-/*
- * Time of last time through main loop.
- */
-time_t now;
-
-
-/*
- * Statistics on number of queries of each version that have been attempted
- */
-
-int newqueries = 0;
-int oldqueries = 0;
-
-
-/* Journalling file */
-FILE *journal = NULL;
-
index 04b528b62ffeea11a1f6aa5cb7dd58e5e3fa34a9..433f1893b4037aa8064cd8ae1d58fdf9e7192659 100644 (file)
@@ -9,6 +9,7 @@
 #include "mr_server.h"
 
 #include <ctype.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -83,8 +84,10 @@ void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar)
        fprintf(stderr, "[#%d]", cur_client->id);
       fputs(": ", stderr);
     }
-  if (code)
+  if (code) {
     fputs(error_message(code), stderr);
+    fputs(" ", stderr);
+  }
   if (fmt)
     vfprintf(stderr, fmt, pvar);
   putc('\n', stderr);
@@ -145,3 +148,27 @@ char **mr_copy_args(char **argv, int argc)
     a[i] = strdup(argv[i]);
   return a;
 }
+
+
+/* malloc or die! */
+void *xmalloc(size_t bytes)
+{
+  void *buf = malloc(bytes);
+
+  if (buf)
+    return buf;
+
+  critical_alert("moirad", "Out of memory");
+  exit(1);
+}
+
+void *xrealloc(void *ptr, size_t bytes)
+{
+  void *buf = realloc(ptr, bytes);
+
+  if (buf)
+    return buf;
+
+  critical_alert("moirad", "Out of memory");
+  exit(1);
+}
index 50d5b4cb09071c1c57686f6bd011784c146d8820..713ebfb2b5cdb2ff16dd9f070d37b98acad2ebe2 100644 (file)
@@ -13,6 +13,7 @@
 #include "query.h"
 #include "qrtn.h"
 
+#include <errno.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
@@ -371,16 +372,10 @@ int followup_guax(struct query *q, struct save_queue *sq, struct validate *v,
          kname_parse(si.pname, si.pinst, si.prealm, kname);
          free(kname);
          si.rawsig = (unsigned char *)strdup(rsig);
-         if (log_flags & LOG_GDSS)
-           com_err(whoami, 0, "rawsig length = %d, sig=\"%s\"",
-                   strlen(si.rawsig), si.rawsig);
          GDSS_Recompose(&si, sigbuf);
          free(si.rawsig);
          free(argv[U_SIGNATURE]);
          argv[U_SIGNATURE] = strdup(sigbuf);
-         if (log_flags & LOG_GDSS)
-           com_err(whoami, 0, "generated signature length %d",
-                   strlen(sigbuf));
        }
 #endif /* GDSS */
       (*action)(q->vcnt, argv, actarg);
@@ -451,11 +446,7 @@ int followup_ausr(struct query *q, char *argv[], client *cl)
          timestamp = si.timestamp;
         }
       else
-       {
-         if (log_flags & LOG_GDSS)
-           hex_dump(argv[U_SIGNATURE]);
-         return gdss2et(status);
-       }
+       return gdss2et(status);
     }
   else
     {
@@ -548,11 +539,7 @@ int followup_uuac(struct query *q, char *argv[], client *cl)
          timestamp = si.timestamp;
         }
       else
-       {
-         if (log_flags & LOG_GDSS)
-           hex_dump(argv[U_SIGNATURE + 1]);
-         return gdss2et(status);
-       }
+       return gdss2et(status);
     }
   else
     {
@@ -912,6 +899,7 @@ int followup_gqot(struct query *q, struct save_queue *sq, struct validate *v,
       free(argv[idx]);
       argv[idx] = malloc(256);
       name = argv[idx];
+      memset(name, 0, 256);
       if (id == 0)
        {
          label = argv[0];
@@ -1234,11 +1222,7 @@ int followup_gsha(struct query *q, struct save_queue *sq, struct validate *v,
 
 int _sdl_followup(struct query *q, char *argv[], client *cl)
 {
-  int i;
-  i = atoi(argv[0]);
-  log_flags = i;
-
-  if (i & LOG_SQL)
+  if (atoi(argv[0]))
     EXEC SQL ALTER SESSION SET SQL_TRACE TRUE;
   else
     EXEC SQL ALTER SESSION SET SQL_TRACE FALSE;
@@ -1247,46 +1231,23 @@ int _sdl_followup(struct query *q, char *argv[], client *cl)
 }
 
 
-static void hex_dump(unsigned char *p)
+int trigger_dcm(struct query *q, char *argv[], client *cl)
 {
-  fprintf(stderr, "Size: %d\n", strlen(p));
-  while (strlen(p) >= 8)
-    {
-      fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-      p += 8;
-    }
-  switch (strlen(p))
+  pid_t pid;
+  char prog[128];
+
+  sprintf(prog, "%s/startdcm", BIN_DIR);
+  pid = vfork();
+  switch (pid)
     {
-    case 7:
-      fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x\n",
-             p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
-      break;
-    case 6:
-      fprintf(stderr, "%02x %02x %02x %02x %02x %02x\n",
-             p[0], p[1], p[2], p[3], p[4], p[5]);
-      break;
-    case 5:
-      fprintf(stderr, "%02x %02x %02x %02x %02x\n",
-               p[0], p[1], p[2], p[3], p[4]);
-      break;
-    case 4:
-      fprintf(stderr, "%02x %02x %02x %02x\n",
-             p[0], p[1], p[2], p[3]);
-       break;
-    case 3:
-      fprintf(stderr, "%02x %02x %02x\n",
-             p[0], p[1], p[2]);
-      break;
-    case 2:
-      fprintf(stderr, "%02x %02x\n",
-             p[0], p[1]);
-      break;
-    case 1:
-      fprintf(stderr, "%02x\n",
-             p[0]);
-      break;
+    case 0:
+      execl(prog, "startdcm", 0);
+      exit(1);
+
+    case -1:
+      return errno;
+
     default:
-      return;
+      return MR_SUCCESS;
     }
 }
index 4f0f9fecb47dc242a7e220729bba49c8ee0a81f0..ddf924be57ed9f5daeb201c3d1103bee5bb12ba6 100644 (file)
@@ -13,6 +13,7 @@
 #include "qrtn.h"
 #include "query.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -134,7 +135,7 @@ int mr_check_access(client *cl, char *name, int argc, char *argv_ro[])
   dbms_errno = 0;
   mr_errcode = 0;
 
-  q = get_query_by_name(name, cl->args->mr_version_no);
+  q = get_query_by_name(name);
   if (!q)
     return MR_NO_HANDLE;
 
@@ -162,7 +163,7 @@ int mr_process_query(client *cl, char *name, int argc, char *argv_ro[],
   /* list queries command */
   if (!strcmp(name, "_list_queries"))
     {
-      list_queries(cl->args->mr_version_no, action, actarg);
+      list_queries(action, actarg);
       return MR_SUCCESS;
     }
 
@@ -171,7 +172,7 @@ int mr_process_query(client *cl, char *name, int argc, char *argv_ro[],
     {
       if (argc < 1)
        return MR_ARGS;
-      q = get_query_by_name(argv_ro[0], cl->args->mr_version_no);
+      q = get_query_by_name(argv_ro[0]);
       if (!q)
        return MR_NO_HANDLE;
       help_query(q, action, actarg);
@@ -179,7 +180,7 @@ int mr_process_query(client *cl, char *name, int argc, char *argv_ro[],
     }
 
   /* get query structure, return error if named query does not exist */
-  q = get_query_by_name(name, cl->args->mr_version_no);
+  q = get_query_by_name(name);
   if (!q)
     return MR_NO_HANDLE;
   v = q->validate;
@@ -391,7 +392,7 @@ out:
 
              fprintf(journal, "%% %s %s %s",
                      cl->clname, cl->entity, ctime(&now));
-             fprintf(journal, "%s[%ld] ", q->name, cl->args->mr_version_no);
+             fprintf(journal, "%s ", q->name);
              for (i = 0; i < argc; i++)
                {
                  if (i != 0)
@@ -413,7 +414,7 @@ out:
     }
   cache_commit(); /* commit following abort is safe */
 
-  if (status != MR_SUCCESS && log_flags & LOG_RES)
+  if (status != MR_SUCCESS)
     com_err(whoami, status, " (Query failed)");
   return status;
 }
@@ -519,7 +520,7 @@ int mr_verify_query(client *cl, struct query *q, int argc, char *argv_ro[])
        return MR_ARG_TOO_LONG;
       *to = '\0';
 
-      if (*--to == '\\')
+      if (to > Argv[i] && *--to == '\\')
        return MR_BAD_CHAR;
     }
 
@@ -875,8 +876,7 @@ int set_next_object_id(char *object, enum tables table, int limit)
        }
     }
 
-  if (LOG_RES)
-    com_err(whoami, 0, "setting ID %s to %d", object, value);
+  com_err(whoami, 0, "setting ID %s to %d", object, value);
   EXEC SQL UPDATE numvalues SET value = :value WHERE name = :obj;
   return MR_SUCCESS;
 }
index 05dd1821da90741c04161e0f7dfe06395e65a37b..68785888cdb19813f7d121f148bba74930aac476 100644 (file)
@@ -849,21 +849,28 @@ int prefetch_filesys(struct query *q, char **argv, client *cl)
 int setup_ahst(struct query *q, char **argv, client *cl)
 {
   EXEC SQL BEGIN DECLARE SECTION;
-  char *name;
+  char *name, oldname[41], vendor[17], model[25], os[17];
   int value, id, saddr, mask, high, low, cnt;
   EXEC SQL END DECLARE SECTION;
   int row;
   struct in_addr addr;
 
   if (!strcmp(q->shortname, "uhst"))
-    row = 1;
+    {
+      row = 1;
+      EXEC SQL SELECT name, vendor, model, os
+       INTO :oldname, :vendor, :model, :os
+       FROM machine WHERE mach_id = :id;
+    }
   else
     row = 0;
 
+  id = *(int *)argv[0];
+
   /* sanity check name: must start with a letter, contain only
    * letters, numerals, and hyphen, and not end with a hyphen.
    */
-  if (row == 0 || strcmp(argv[1], cl->args->mr_argv[1]))
+  if (row == 0 || strcmp(argv[1], oldname))
     {
       char *p = argv[row];
 
@@ -882,7 +889,7 @@ int setup_ahst(struct query *q, char **argv, client *cl)
   /* sanity check host vendor: must start with a letter, contain only
    * letters, numerals, and hyphen, and end with an alphanumeric.
    */
-  if (*argv[row + 1] && (row == 0 || strcmp(argv[2], cl->args->mr_argv[2])))
+  if (*argv[row + 1] && (row == 0 || strcmp(argv[2], vendor)))
     {
       char *p = argv[row + 1];
 
@@ -901,7 +908,7 @@ int setup_ahst(struct query *q, char **argv, client *cl)
   /* sanity check host type: must start with a letter, contain only
    * letters, numerals, and hyphen, and end with an alphanumeric.
    */
-  if (*argv[row + 2] && (row == 0 || strcmp(argv[3], cl->args->mr_argv[3])))
+  if (*argv[row + 2] && (row == 0 || strcmp(argv[3], model)))
     {
       char *p = argv[row + 2];
 
@@ -917,10 +924,10 @@ int setup_ahst(struct query *q, char **argv, client *cl)
        return MR_BAD_CHAR;
     }
 
-  /* sanity check host vendor: must start with a letter, contain only
+  /* sanity check host os: must start with a letter, contain only
    * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
    */
-  if (*argv[row + 3] && (row == 0 || strcmp(argv[4], cl->args->mr_argv[4])))
+  if (*argv[row + 3] && (row == 0 || strcmp(argv[4], os)))
     {
       char *p = argv[row + 3];
 
index 3933041bfa9f6c9c6d4fe04dc83614b890297e13..e26643d9da718fbc42e67ea9fbd97902e81bf7d7 100644 (file)
@@ -18,7 +18,7 @@ extern int QueryCount2;
 
 int qcmp(const void *q1, const void *q2);
 
-struct query *get_query_by_name(char *name, int version)
+struct query *get_query_by_name(char *name)
 {
   struct query *q;
   int i;
@@ -48,8 +48,7 @@ struct query *get_query_by_name(char *name, int version)
   return NULL;
 }
 
-void list_queries(int version, int (*action)(int, char *[], void *),
-                 void *actarg)
+void list_queries(int (*action)(int, char *[], void *), void *actarg)
 {
   struct query *q;
   int i;
index 797cc2e91b9746d564db0233ff49b06673bf818b..58f05050880c71bab00731fa5b98a44bf8704ca9 100644 (file)
@@ -1659,7 +1659,7 @@ static struct valobj ashi_valobj[] = {
   {V_NAME, 0, SERVERS_TABLE, NAME, 0, MR_SERVICE},
   {V_LOCK, 0, SERVERHOSTS_TABLE, 0, MACH_ID, MR_DEADLOCK},
   {V_ID, 1, MACHINE_TABLE, NAME, MACH_ID, MR_MACHINE},
-  {V_CHAR, 0, SERVERHOSTS_TABLE, NAME},
+  {V_CHAR, 0, SERVERHOSTS_TABLE, SERVICE},
   {V_LEN, 5, SERVERHOSTS_TABLE, "value3"},
 };
 
index 8cb6b777cbc2ed084bf4d88d9b71be4403a55bc2..ee5c05afc9b3ca976e8c086877a629c506d744ef 100644 (file)
@@ -89,16 +89,13 @@ void incremental_clear_before(void);
 void incremental_after(enum tables table, char *qualx, char **argv);
 void incremental_clear_after(void);
 
-/* prototypes from qfollow.dc */
-int set_pobox_modtime(struct query *q, char *argv[], client *cl);
-
 /* prototypes from qrtn.dc */
 int check_query_access(struct query *q, char *argv[], client *cl);
 int set_next_object_id(char *objectx, enum tables table, int limit);
 
 /* prototypes from qsubs.c */
-void list_queries(int version, int (*action)(int, char *[], void *),
+void list_queries(int (*action)(int, char *[], void *),
                  void *actarg);
 void help_query(struct query *q, int (*action)(int, char *[], void *),
                void *actarg);
-struct query *get_query_by_name(char *name, int version);
+struct query *get_query_by_name(char *name);
index aed6f96b4beb3182d32b6e2bdce2472671390a5c..797980f63cb96df6030c0fa3005299b4b12906f3 100644 (file)
@@ -57,10 +57,6 @@ int validate_row(struct query *q, char *argv[], struct validate *v)
   /* build where clause */
   build_qual(v->qual, v->argc, argv, qual);
 
-  if (log_flags & LOG_VALID)
-    /* tell the logfile what we're doing */
-    com_err(whoami, 0, "validating row: %s", qual);
-
   /* look for the record */
   sprintf(stmt_buf, "SELECT COUNT (*) FROM %s WHERE %s",
          table_name[q->rtable], qual);
@@ -85,59 +81,30 @@ int validate_fields(struct query *q, char *argv[], struct valobj *vo, int n)
       switch (vo->type)
        {
        case V_NAME:
-         if (log_flags & LOG_VALID)
-           {
-             com_err(whoami, 0, "validating %s in %s: %s",
-                     vo->namefield, table_name[vo->table], argv[vo->index]);
-           }
          status = validate_name(argv, vo);
          break;
 
        case V_ID:
-         if (log_flags & LOG_VALID)
-           {
-             com_err(whoami, 0, "validating %s in %s: %s",
-                     vo->idfield, table_name[vo->table], argv[vo->index]);
-           }
          status = validate_id(q, argv, vo);
          break;
 
        case V_TYPE:
-         if (log_flags & LOG_VALID)
-           {
-             com_err(whoami, 0, "validating %s type: %s",
-                     table_name[vo->table], argv[vo->index]);
-           }
          status = validate_type(argv, vo);
          break;
 
        case V_TYPEDATA:
-         if (log_flags & LOG_VALID)
-           {
-             com_err(whoami, 0, "validating typed data (%s): %s",
-                     argv[vo->index - 1], argv[vo->index]);
-           }
          status = validate_typedata(q, argv, vo);
          break;
 
        case V_RENAME:
-         if (log_flags & LOG_VALID)
-           {
-             com_err(whoami, 0, "validating rename %s in %s",
-                     argv[vo->index], table_name[vo->table]);
-           }
          status = validate_rename(argv, vo);
          break;
 
        case V_CHAR:
-         if (log_flags & LOG_VALID)
-           com_err(whoami, 0, "validating chars: %s", argv[vo->index]);
          status = validate_chars(argv, vo);
          break;
 
        case V_LEN:
-         if (log_flags & LOG_VALID)
-           com_err(whoami, 0, "validating length: %s", argv[vo->index]);
          status = validate_len(argv, vo);
          break;
 
index 1521bf11c6f4cfe75fedcff15cb63431027f890d..43d9b31f7d91e6de95a78b4c5aefd4e0e8d50d4f 100644 (file)
@@ -9,13 +9,13 @@
 #
 
 SRCS=  auth_002.c checksum.c client.c config.c exec_002.c \
-       get_file.c log.c send_file.c ticket.c \
+       get_file.c sendrecv.c send_file.c ticket.c \
        update_server.c update_test.c xfer_002.c xfer_003.c
 SRCDIR=${SRCTOP}/update
 CODE=${SRCS} Imakefile
 SOBJS = auth_002.o checksum.o config.o exec_002.o get_file.o \
-       log.o update_server.o xfer_002.o xfer_003.o
-COBJS= checksum.o client.o send_file.o ticket.o
+       update_server.o xfer_002.o xfer_003.o sendrecv.o
+COBJS= checksum.o client.o send_file.o ticket.o sendrecv.o
 
 #ifdef HAS_VSPRINTF
 DEFINES= -DHAS_VSPRINTF
@@ -31,5 +31,5 @@ moira_update.o: ${COBJS}
        ${LD} -r -o moira_update.o ${COBJS}
 #endif
 
-program(update_server, ${SOBJS},${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${ETCDIR})
-program(update_test, update_test.o ${COBJS}, ${MR_LIBDEP} ${GDB_LIBDEP}, ${CLIBS},${BINDIR})
+program(update_server, ${SOBJS},${MR_LIBDEP}, ${CLIBS},${ETCDIR})
+program(update_test, update_test.o ${COBJS}, ${MR_LIBDEP}, ${CLIBS},${BINDIR})
index 28c11dc297bc6a3bc6b8e83d6cade5c0e73f22ff..f598ba9af7e17daf73c79cc56027b03307675db1 100644 (file)
 #include <errno.h>
 #include <stdio.h>
 
-#include <gdb.h>
 #include <krb.h>
 
 RCSID("$Header$");
 
-extern char buf[BUFSIZ];
-extern int have_authorization;
-extern CONNECTION conn;
-extern int code;
 static char service[] = "rcmd";
 static char master[] = "sms";
 static char qmark[] = "???";
-extern C_Block session;
+extern des_cblock session;
 
 /*
  * authentication request auth_002:
@@ -41,30 +36,32 @@ extern C_Block session;
  *
  */
 
-int auth_002(char *str)
+void auth_002(int conn, char *str)
 {
-  STRING data;
   char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ];
   AUTH_DAT ad;
-  char *p, *first;
+  char *p, *first, *data;
+  size_t size;
   KTEXT_ST ticket_st;
-  struct utsname name;
   des_key_schedule sched;
-  C_Block nonce, nonce2;
+  des_cblock nonce, nonce2;
+  long code;
 
-  if (send_ok())
-    lose("sending okay for authorization (auth_002)");
-  code = receive_object(conn, (char *)&data, STRING_T);
-  if (code)
+  send_ok(conn);
+  
+  recv_string(conn, &data, &size);
+  if (size > sizeof(ticket_st.dat))
     {
-      code = connection_errno(conn);
-      lose("awaiting Kerberos authenticators");
+      code = KE_RD_AP_UNDEC;
+      com_err(whoami, code, ": authenticator too large");
+      send_int(conn, code);
+      return;
     }
-  uname(&name);
+  memcpy(ticket_st.dat, data, size);
+  free(data);
   ticket_st.mbz = 0;
-  ticket_st.length = MAX_STRING_SIZE(data);
-  memcpy(ticket_st.dat, STRING_DATA(data), MAX_STRING_SIZE(data));
-  code = krb_rd_req(&ticket_st, service, krb_get_phost(name.nodename), 0,
+  ticket_st.length = size;
+  code = krb_rd_req(&ticket_st, service, krb_get_phost(hostname), 0,
                    &ad, KEYFILE);
   if (code)
     {
@@ -106,41 +103,26 @@ int auth_002(char *str)
       strcmp(arealm, ad.prealm))
     goto auth_failed;
 
-  if (send_ok())
-    lose("sending preliminary approval of authorization");
+  send_ok(conn);
 
   /* replay protection */
   des_random_key(&nonce);
-  STRING_DATA(data) = (char *)nonce;
-  MAX_STRING_SIZE(data) = 8;
-  if (send_object(conn, (char *)&data, STRING_T))
-    lose("sending nonce");
-  code = receive_object(conn, (char *)&data, STRING_T);
-  if (code)
-    {
-      code = connection_errno(conn);
-      goto auth_failed;
-    }
+  send_string(conn, (char *)nonce, sizeof(nonce));
+  recv_string(conn, &data, &size);
   des_key_sched(ad.session, sched);
-  des_ecb_encrypt(STRING_DATA(data), nonce2, sched, 0);
+  des_ecb_encrypt(data, nonce2, sched, 0);
+  free(data);
   if (memcmp(nonce, nonce2, sizeof(nonce)))
     goto auth_failed;
+  send_ok(conn);
 
-  if (send_ok())
-    lose("sending approval of authorization");
   have_authorization = 1;
   /* Stash away session key */
   memcpy(session, ad.session, sizeof(session));
-  return 0;
+  return;
+
 auth_failed:
-  sprintf(buf, "auth for %s.%s@%s failed: %s",
-         ad.pname, ad.pinst, ad.prealm, error_message(code));
-  {
-    int rc;
-    rc = send_object(conn, (char *)&code, INTEGER_T);
-    code = rc;
-  }
-  if (code)
-    lose("sending rejection of authenticator");
-  return EPERM;
+  com_err(whoami, code, "auth for %s.%s@%s failed",
+         ad.pname, ad.pinst, ad.prealm);
+  send_int(conn, code);
 }
index 5a2323dcc9c584921a337506529d7595a3ba737f..4389054688dd9f297012fe2e0f93b88c229b4a42 100644 (file)
@@ -18,9 +18,9 @@ RCSID("$Header$");
  * returns 24-bit checksum of bytes in file
  */
 
-int checksum_file(char *path)
+long checksum_file(char *path)
 {
-  int sum;
+  long sum;
   int ch;
   FILE *f;
 
index f982fdf3fa1e11ca02368b1b51698211d89b42c8..f5197b798c1632fdd7d65f8cf4682a2b72904955 100644 (file)
 #include <moira.h>
 #include "update.h"
 
+#include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <des.h>
-#include <gdb.h>
 #include <krb.h>
 
 RCSID("$Header$");
 
-extern int dbg;
-extern C_Block session;
+extern des_cblock session;
 
-CONNECTION conn;
-
-int send_auth(char *host_name)
+int send_auth(int conn, char *host_name)
 {
   KTEXT_ST ticket_st;
-  KTEXT ticket = &ticket_st;
-  STRING data;
-  int code;
-  int response;
-  int auth_version = 2;
+  int code, auth_version = 2;
+  long response;
 
-  code = get_mr_update_ticket(host_name, ticket);
+  code = get_mr_update_ticket(host_name, &ticket_st);
   if (code)
     return code;
-  STRING_DATA(data) = "AUTH_002";
-  MAX_STRING_SIZE(data) = 9;
-  code = send_object(conn, (char *)&data, STRING_T);
+  code = send_string(conn, "AUTH_002", 9);
   if (code)
-    return connection_errno(conn);
-  code = receive_object(conn, (char *)&response, INTEGER_T);
+    return code;
+  code = recv_int(conn, &response);
   if (code)
-    return connection_errno(conn);
+    return code;
   if (response)
     {
-      STRING_DATA(data) = "AUTH_001";
-      MAX_STRING_SIZE(data) = 9;
-      code = send_object(conn, (char *)&data, STRING_T);
+      code = send_string(conn, "AUTH_001", 9);
       if (code)
-       return connection_errno(conn);
-      code = receive_object(conn, (char *)&response, INTEGER_T);
+       return code;
+      code = recv_int(conn, &response);
       if (code)
-       return connection_errno(conn);
+       return code;
       if (response)
        return response;
       auth_version = 1;
     }
-  STRING_DATA(data) = (char *)ticket->dat;
-  MAX_STRING_SIZE(data) = ticket->length;
-  code = send_object(conn, (char *)&data, STRING_T);
+  code = send_string(conn, (char *)ticket_st.dat, ticket_st.length);
   if (code)
-    return connection_errno(conn);
-  code = receive_object(conn, (char *)&response, INTEGER_T);
+    return code;
+  code = recv_int(conn, &response);
   if (code)
-    return connection_errno(conn);
+    return code;
   if (response)
     return response;
 
@@ -74,19 +63,21 @@ int send_auth(char *host_name)
     {
       des_key_schedule sched;
       C_Block enonce;
+      char *data;
+      size_t size;
 
-      code = receive_object(conn, (char *)&data, STRING_T);
+      code = recv_string(conn, &data, &size);
       if (code)
-       return connection_errno(conn);
+       return code;
       des_key_sched(session, sched);
-      des_ecb_encrypt(STRING_DATA(data), enonce, sched, 1);
-      STRING_DATA(data) = enonce;
-      code = send_object(conn, (char *)&data, STRING_T);
+      des_ecb_encrypt(data, enonce, sched, 1);
+      free(data);
+      code = send_string(conn, (char *)enonce, sizeof(enonce));
       if (code)
-       return connection_errno(conn);
-      code = receive_object(conn, (char *)&response, INTEGER_T);
+       return code;
+      code = recv_int(conn, &response);
       if (code)
-       return connection_errno(conn);
+       return code;
       if (response)
        return response;
     }
@@ -94,32 +85,35 @@ int send_auth(char *host_name)
   return MR_SUCCESS;
 }
 
-int execute(char *path)
+int execute(int conn, char *path)
 {
-  int response;
-  STRING data;
+  long response;
+  char *data;
   int code;
 
-  string_alloc(&data, BUFSIZ);
-  sprintf(STRING_DATA(data), "EXEC_002 %s", path);
-  code = send_object(conn, (char *)&data, STRING_T);
+  data = malloc(10 + strlen(path));
+  if (!data)
+    return ENOMEM;
+  sprintf(data, "EXEC_002 %s", path);
+  code = send_string(conn, data, strlen(data) + 1);
+  free(data);
   if (code)
-    return connection_errno(conn);
-  code = receive_object(conn, (char *)&response, INTEGER_T);
+    return code;
+  code = recv_int(conn, &response);
   if (code)
-    return connection_errno(conn);
+    return code;
   if (response)
     return response;
+
   return MR_SUCCESS;
 }
 
-void send_quit(void)
+void send_quit(int conn)
+{
+  send_string(conn, "quit", 5);
+}
+
+void fail(int conn, int err, char *msg)
 {
-  STRING str;
-  if (!conn)
-    return;
-  string_alloc(&str, 5);
-  strcpy(STRING_DATA(str), "quit");
-  send_object(conn, (char *)&str, STRING_T);
-  string_free(&str);
+  return;
 }
index 0f7b35c18474c19d526a07f3237ac2abb3bd3728..b40670a092381ecc6a410aa38be178dc2e19e69f 100644 (file)
@@ -17,6 +17,7 @@
 #include <sys/stat.h>
 
 #include <ctype.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -40,12 +41,11 @@ RCSID("$Header$");
 static char *config_buf = NULL;
 static char **config_keys, **config_values;
 
-
 static int init(void)
 {
   int fd, count = 0;
   struct stat st;
-  char *p;
+  char *p, *start;
 
   /* Only execute once */
   if (config_buf)
@@ -56,14 +56,19 @@ static int init(void)
     {
       config_buf = "";
       config_keys = malloc(sizeof(char *) * 2);
+      if (!config_keys)
+       return ENOMEM;
       config_keys[0] = config_keys[1] = NULL;
       return MR_SUCCESS;
     }
+
   if (fstat(fd, &st) < 0)
     return MR_INTERNAL;
+
   config_buf = malloc(st.st_size + 2);
   if (!config_buf)
-    return MR_NO_MEM;
+    return ENOMEM;
+
   if (read(fd, config_buf, st.st_size) < st.st_size)
     {
       free(config_buf);
@@ -83,13 +88,17 @@ static int init(void)
   if (!config_keys || !config_values)
     {
       free(config_buf);
+      free(config_keys);
+      free(config_values);
       config_buf = NULL;
-      return MR_NO_MEM;
+      return ENOMEM;
     }
+
   count = 0;
   for (p = strtok(config_buf, "\n"); p; p = strtok(NULL, "\n"))
     config_keys[count++] = p;
   config_keys[count] = NULL;
+
   for (count = 0; config_keys[count]; count++)
     {
       config_values[count] = "";
index aeec495c18d5634077fa16aadbbfa05b38c6fcce..77e1c23f827529902240823ee82a0650861dce03 100644 (file)
 #include <stdio.h>
 #include <unistd.h>
 
-#include <gdb.h>
-
 RCSID("$Header$");
 
-extern CONNECTION conn;
-extern int code, uid, log_priority, have_authorization;
-extern char *whoami;
-
-int exec_002(char *str)
+void exec_002(int conn, char *str)
 {
-  int waitb;
+  int waitb, n;
   sigset_t mask, oldmask;
-  int n, pid;
+  pid_t pid;
+  long code;
 
   if (!have_authorization)
     {
-      reject_call(MR_PERM);
-      return 0;
+      send_int(conn, MR_PERM);
+      return;
     }
   if (config_lookup("noexec"))
     {
-      code = EPERM;
-      send_object(conn, (char *)&code, INTEGER_T);
-      com_err(whoami, code, "Not allowed to execute");
-      return 0;
+      send_int(conn, EPERM);
+      com_err(whoami, EPERM, "Not allowed to execute");
+      return;
     }
+
   str += 8;
   while (*str == ' ')
     str++;
@@ -55,12 +50,12 @@ int exec_002(char *str)
     case -1:
       n = errno;
       sigprocmask(SIG_UNBLOCK, &oldmask, &mask);
-      log_priority = log_ERROR;
-      com_err(whoami, errno, ": can't fork to run install script");
-      code = send_object(conn, (char *)&n, INTEGER_T);
+      com_err(whoami, n, ": can't fork to run install script");
+      code = send_int(conn, n);
       if (code)
        exit(1);
-      return 0;
+      return;
+
     case 0:
       if (setuid(uid) < 0)
        {
@@ -71,19 +66,19 @@ int exec_002(char *str)
       execlp(str, str, NULL);
       n = errno;
       sigprocmask(SIG_UNBLOCK, &oldmask, &mask);
-      log_priority = log_ERROR;
       com_err(whoami, n, ": %s", str);
-      send_object(conn, (char *)&n, INTEGER_T);
+      send_int(conn, n);
       exit(1);
+
     default:
       do
        n = wait(&waitb);
       while (n != -1 && n != pid);
+
       sigprocmask(SIG_UNBLOCK, &oldmask, &mask);
       if ((WIFEXITED(waitb) && (WEXITSTATUS(waitb) != 0)) ||
          WIFSIGNALED(waitb))
        {
-         log_priority = log_ERROR;
          if (WIFSIGNALED(waitb))
            {
              n = MR_COREDUMP;
@@ -96,16 +91,16 @@ int exec_002(char *str)
              com_err(whoami, n, " child exited with status %d",
                      WEXITSTATUS(waitb));
            }
-         code = send_object(conn, (char *)&n, INTEGER_T);
+         code = send_int(conn, n);
          if (code)
            exit(1);
        }
       else
        {
-         code = send_ok();
+         code = send_ok(conn);
          if (code)
            exit(1);
        }
     }
-  return 0;
+  return;
 }
index 04053504d60b0cfe52308a68869fea9911bd3fb8..ff8023979bff7f4b857d3f9f97ac695f141c868f 100644 (file)
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #include <des.h>
-#include <gdb.h>
 
 RCSID("$Header$");
 
@@ -24,18 +24,11 @@ RCSID("$Header$");
 #define MIN(a, b)    (((a) < (b)) ? (a) : (b))
 #endif /* MIN */
 
-extern CONNECTION conn;
-extern char buf[BUFSIZ];
-
-extern int code, uid;
-extern char *whoami;
-
-extern int have_authorization, have_file, done;
-extern C_Block session;
 static des_key_schedule sched;
 static des_cblock ivec;
+extern des_cblock session;
 
-static int get_block(int fd, int max_size, int encrypt);
+static int get_block(int conn, int fd, int max_size, int encrypt);
 
 /*
  * get_file()
@@ -69,24 +62,24 @@ static int get_block(int fd, int max_size, int encrypt);
  *
  */
 
-int get_file(char *pathname, int file_size, int checksum,
+int get_file(int conn, char *pathname, int file_size, int checksum,
             int mode, int encrypt)
 {
-  int fd, n_written;
+  int fd, n_written, code;
   int found_checksum;
+  char buf[BUFSIZ];
 
   if (!have_authorization)
     {
-      reject_call(MR_PERM);
+      send_int(conn, MR_PERM);
       return 1;
     }
-  if (done)                    /* re-initialize data */
-    initialize();
   if (setuid(uid) < 0)
     {
       com_err(whoami, errno, "Unable to setuid to %d\n", uid);
       exit(1);
     }
+
   /* unlink old file */
   if (!config_lookup("noclobber"))
     unlink(pathname);
@@ -95,10 +88,8 @@ int get_file(char *pathname, int file_size, int checksum,
   if (fd == -1)
     {
       code = errno;
-      sprintf(buf, "%s: creating file %s (get_file)",
-             error_message(code), pathname);
-      mr_log_error(buf);
-      report_error("reporting file creation error (get_file)");
+      com_err(whoami, errno, "creating file %s (get_file)", pathname);
+      send_int(conn, code);
       if (setuid(0) < 0)
        {
          com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
@@ -106,6 +97,7 @@ int get_file(char *pathname, int file_size, int checksum,
        }
       return 1;
     }
+
   /* check to see if we've got the disk space */
   n_written = 0;
   while (n_written < file_size)
@@ -115,14 +107,15 @@ int get_file(char *pathname, int file_size, int checksum,
       if (n_wrote == -1)
        {
          code = errno;
-         sprintf(buf, "%s: verifying free disk space for %s (get_file)",
-                 error_message(code), pathname);
-         mr_log_error(buf);
+         com_err(whoami, code, "verifying free disk space for %s (get_file)",
+                 pathname);
+         send_int(conn, code);
+
          /* do all we can to free the space */
          unlink(pathname);
          ftruncate(fd, 0);
          close(fd);
-         report_error("reporting test-write error (get_file)");
+
          if (setuid(0) < 0)
            {
              com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
@@ -132,18 +125,21 @@ int get_file(char *pathname, int file_size, int checksum,
        }
       n_written += n_wrote;
     }
+
   lseek(fd, 0, SEEK_SET);
-  if (send_ok())
-    lose("sending okay for file transfer (get_file)");
+  send_ok(conn);
+
   if (encrypt)
     {
       des_key_sched(session, sched);
       memcpy(ivec, session, sizeof(ivec));
     }
+
   n_written = 0;
-  while (n_written < file_size && code == 0)
+  while (n_written < file_size)
     {
-      int n_got = get_block(fd, file_size - n_written, encrypt);
+      int n_got = get_block(conn, fd, file_size - n_written, encrypt);
+
       if (n_got == -1)
        {
          /* get_block has already printed a message */
@@ -157,31 +153,20 @@ int get_file(char *pathname, int file_size, int checksum,
        }
       n_written += n_got;
       if (n_written != file_size)
-       {
-         if (send_ok())
-           lose("receiving data");
-       }
-    }
-  if (code)
-    {
-      code = connection_errno(conn);
-      report_error("reading file (get_file)");
-      if (setuid(0) < 0)
-       {
-         com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
-         exit(1);
-       }
-      return 1;
+       send_ok(conn);
     }
+
   fsync(fd);
   ftruncate(fd, file_size);
   fsync(fd);
   close(fd);
+
   if (setuid(0) < 0)
     {
       com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
       exit(1);
     }
+
   /* validate checksum */
   found_checksum = checksum_file(pathname);
   if (checksum != found_checksum)
@@ -189,62 +174,56 @@ int get_file(char *pathname, int file_size, int checksum,
       code = MR_MISSINGFILE;
       com_err(whoami, code, ": expected = %d, found = %d",
              checksum, found_checksum);
-      report_error("checksum error");
-      return 1;
-    }
-  /* send ack or nack */
-  have_file = 1;
-  if (send_ok())
-    {
-      code = connection_errno(conn);
-      unlink(pathname);
-      lose("sending ok after file transfer (get_file)");
+      send_int(conn, code);
       return 1;
     }
+
+  send_ok(conn);
   return 0;
 }
 
-static int get_block(int fd, int max_size, int encrypt)
+static int get_block(int conn, int fd, int max_size, int encrypt)
 {
-  STRING data;
-  unsigned char dst[UPDATE_BUFSIZ + 8], *src;
-  int n_read, n, i;
+  char *data;
+  size_t len;
+  int n_read, n, i, code;
 
-  code = receive_object(conn, (char *)&data, STRING_T);
-  if (code)
-    {
-      code = connection_errno(conn);
-      lose("receiving data file (get_file)");
-    }
+  recv_string(conn, &data, &len);
 
   if (encrypt)
     {
-      src = (unsigned char *)STRING_DATA(data);
-      n = MAX_STRING_SIZE(data);
-      des_pcbc_encrypt(src, dst, n, sched, ivec, 1);
+      char *unenc = malloc(len);
+
+      if (!unenc)
+       {
+         send_int(conn, ENOMEM);
+         return -1;
+       }
+
+      des_pcbc_encrypt(data, unenc, len, sched, ivec, 1);
       for (i = 0; i < 8; i++)
-       ivec[i] = src[n - 8 + i] ^ dst[n - 8 + i];
-      memcpy(STRING_DATA(data), dst, n);
+       ivec[i] = data[len - 8 + i] ^ unenc[len - 8 + i];
+      free(data);
+      data = unenc;
     }
 
-  n_read = MIN(MAX_STRING_SIZE(data), max_size);
+  n_read = MIN(len, max_size);
   n = 0;
   while (n < n_read)
     {
       int n_wrote;
-      n_wrote = write(fd, STRING_DATA(data) + n, n_read - n);
+      n_wrote = write(fd, data + n, n_read - n);
       if (n_wrote == -1)
        {
          code = errno;
-         sprintf(buf, "%s: writing file (get_file)", error_message(code));
-         mr_log_error(buf);
-         string_free(&data);
-         report_error("reporting write error (get_file)");
+         com_err(whoami, errno, "writing file (get_file)");
+         send_int(conn, code);
+         free(data);
          close(fd);
          return -1;
        }
       n += n_wrote;
     }
-  string_free(&data);
+  free(data);
   return n;
 }
diff --git a/update/log.c b/update/log.c
deleted file mode 100644 (file)
index b4e921d..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* $Id$
- *
- * handle logging for dcm and update server
- *
- * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
- */
-
-#include <mit-copyright.h>
-#include <moira.h>
-#include "update_server.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "update.h"
-
-#ifdef use_syslog
-#include <syslog.h>
-#else
-#define use_tty
-#endif
-
-RCSID("$Header$");
-
-void mr_update_com_err_hook(const char *whoami, long code,
-                           const char *fmt, va_list args);
-
-#ifdef use_syslog
-int syslog_prio[] = {
-  LOG_DEBUG,
-  LOG_INFO,
-  LOG_WARNING,
-  LOG_ERR
-};
-#endif
-extern int log_priority;
-extern char *whoami;
-
-void mr_update_com_err_hook(const char *whoami, long code,
-                           const char *fmt, va_list args)
-{
-  char buf[BUFSIZ], *cp;
-
-#ifndef use_syslog
-  strcpy(buf, whoami);
-  for (cp = buf; *cp; cp++)
-    ;
-  *cp++ = ':';
-  *cp++ = ' ';
-#else
-  cp = buf;
-  *cp = '\0';
-#endif
-  if (code)
-    {
-      strcpy(cp, error_message(code));
-      while (*cp)
-       cp++;
-    }
-  vsprintf(cp, fmt, args);
-#ifdef use_syslog
-  syslog(syslog_prio[log_priority], "%s", buf);
-#endif
-#ifdef use_tty
-  puts(buf);
-#endif
-}
-
-void mr_update_initialize(void)
-{
-  static int initialized = 0;
-  if (initialized)
-    return;
-#ifdef use_syslog
-  openlog(whoami, LOG_PID, LOG_DAEMON);
-#endif
-  set_com_err_hook(mr_update_com_err_hook);
-  log_priority = log_INFO;
-  initialized = 1;
-}
-
-
-static char fmt[] = "[%s] %s";
-
-#define        def(name, level, prio) \
-void name(char *msg)\
-{\
-   int old_prio; \
-   old_prio = log_priority; \
-   mr_update_initialize(); \
-   com_err(whoami, 0, fmt, level, msg); \
-   log_priority = old_prio; \
-}
-
-def(mr_log_error, "error", log_ERROR)
-def(mr_log_warning, "warning", log_WARNING)
-def(mr_log_info, "info", log_INFO)
-def(mr_debug, "debug", log_DEBUG)
index 5e12ef81d6e42fbd7638ec8c6bae924ccfe0b5e3..9a0960b2c42b25370b3e109ff8916d8cc7f191d9 100644 (file)
 #include <unistd.h>
 
 #include <des.h>
-#include <gdb.h>
 #include <update.h>
 
 RCSID("$Header$");
 
-extern CONNECTION conn;
-char buf[BUFSIZ];
-extern C_Block session;
-extern char *whoami;
+extern des_cblock session;
 
 /*
  * syntax:
@@ -45,11 +41,11 @@ extern char *whoami;
  *  1 on error (file not found, etc)
  */
 
-int send_file(char *pathname, char *target_path, int encrypt)
+int send_file(int conn, char *pathname, char *target_path, int encrypt)
 {
   int n, fd, code, n_to_send, i;
-  STRING data;
-  unsigned char dst[UPDATE_BUFSIZ + 8], *src;
+  char data[UPDATE_BUFSIZ], enc[UPDATE_BUFSIZ];
+  long response;
   struct stat statb;
   des_key_schedule sched;
   des_cblock ivec;
@@ -69,44 +65,42 @@ int send_file(char *pathname, char *target_path, int encrypt)
     }
   n_to_send = statb.st_size;
 
-  string_alloc(&data, UPDATE_BUFSIZ);
-  sprintf(STRING_DATA(data), "XFER_00%c %d %d %s",
-         (encrypt ? '3' : '2'), n_to_send,
+  sprintf(data, "XFER_00%c %d %d %s", (encrypt ? '3' : '2'), n_to_send,
          checksum_file(pathname), target_path);
-  code = send_object(conn, (char *)&data, STRING_T);
+  code = send_string(conn, data, strlen(data) + 1);
   if (code)
     {
-      com_err(whoami, connection_errno(conn), " sending XFER request");
+      com_err(whoami, code, "sending XFER request");
       close(fd);
-      return connection_errno(conn);
+      return code;
     }
-  code = receive_object(conn, (char *)&n, INTEGER_T);
+  code = recv_int(conn, &response);
   if (code)
     {
-      com_err(whoami, connection_errno(conn),
-             " getting reply from XFER request");
+      com_err(whoami, code, "getting reply from XFER request");
       close(fd);
-      return connection_errno(conn);
+      return code;
     }
-  if (n)
+  if (response)
     {
-      com_err(whoami, n, " transfer request (XFER) rejected");
+      com_err(whoami, response, "transfer request (XFER) rejected");
       close(fd);
-      return n;
+      return response;
     }
 
-  code = receive_object(conn, (char *)&n, INTEGER_T);
+  code = recv_int(conn, &response);
   if (code)
     {
-      com_err(whoami, connection_errno(conn), ": lost connection");
+      com_err(whoami, code, ": lost connection");
       close(fd);
-      return connection_errno(conn);
+      return code;
     }
-  if (n)
+  if (response)
     {
-      com_err(whoami, n, " from remote server: can't update %s", pathname);
+      com_err(whoami, response, " from remote server: can't update %s",
+             pathname);
       close(fd);
-      return n;
+      return response;
     }
 
   if (encrypt)
@@ -117,70 +111,69 @@ int send_file(char *pathname, char *target_path, int encrypt)
 
   while (n_to_send > 0)
     {
-      n = read(fd, STRING_DATA(data), UPDATE_BUFSIZ);
+      n = read(fd, data, sizeof(data));
       if (n < 0)
        {
-         com_err(whoami, errno, " reading %s for transmission", pathname);
+         com_err(whoami, errno, "reading %s for transmission", pathname);
          close(fd);
          return MR_ABORTED;
        }
-      MAX_STRING_SIZE(data) = n;
       if (encrypt)
        {
-         src = (unsigned char *)STRING_DATA(data);
-         memmove(dst, src, n);
-         memset(dst + n, 0, 7);
-         /* encrypt! */
-         des_pcbc_encrypt(dst, src, n, sched, ivec, 0);
+         memset(data + n, 0, sizeof(data) -n);
+         des_pcbc_encrypt(data, enc, n, sched, ivec, 0);
          /* save vector to continue chaining */
          for (i = 0; i < 8; i++)
-           ivec[i] = dst[n - 8 + i] ^ src[n - 8 + i];
+           ivec[i] = data[n - 8 + i] ^ enc[n - 8 + i];
          /* round up to multiple of 8 */
-         data.length = (data.length + 7) & 0xfffffff8;
+         n = (n + 7) & ~7;
+         code = send_string(conn, enc, n);
        }
-      code = send_object(conn, (char *)&data, STRING_T);
+      else
+       code = send_string(conn, data, n);
       if (code)
        {
-         com_err(whoami, connection_errno(conn), " transmitting file %s",
-                 pathname);
+         com_err(whoami, code, "transmitting file %s", pathname);
          close(fd);
-         return connection_errno(conn);
+         return code;
        }
+
       n_to_send -= n;
-      code = receive_object(conn, (char *)&n, INTEGER_T);
+      code = recv_int(conn, &response);
       if (code)
        {
-         com_err(whoami, connection_errno(conn),
-                 " awaiting ACK remote server during transmission of %s",
+         com_err(whoami, code, "awaiting ACK during transmission of %s",
                  pathname);
          close(fd);
-         return connection_errno(conn);
+         return code;
        }
-      if (n)
+      if (response)
        {
-         com_err(whoami, n, " from remote server during transmission of %s",
+         com_err(whoami, response,
+                 "from remote server during transmission of %s",
                  pathname);
          close(fd);
-         return n;
+         return response;
        }
     }
+
   if (statb.st_size == 0)
     {
-      code = receive_object(conn, (char *)&n, INTEGER_T);
+      code = recv_int(conn, &response);
       if (code)
        {
-         com_err(whoami, connection_errno(conn),
-                 " awaiting ACK remote server after transmission of %s",
+         com_err(whoami, code, "awaiting ACK after transmission of %s",
                  pathname);
          close(fd);
-         return connection_errno(conn);
+         return code;
        }
-      if (n)
+      if (response)
        {
-         com_err(whoami, n, " from remote server after transmission of %s",
+         com_err(whoami, response,
+                 "from remote server after transmission of %s",
                  pathname);
          close(fd);
-         return n;
+         return response;
        }
     }
   close(fd);
diff --git a/update/sendrecv.c b/update/sendrecv.c
new file mode 100644 (file)
index 0000000..7321319
--- /dev/null
@@ -0,0 +1,108 @@
+/* $Id$
+ *
+ * socket layer for update_server
+ *
+ * Copyright (C) 1997-1998 by the Massachusetts Institute of Technology
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <moira.h>
+
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+RCSID("$Header$");
+
+#define putlong(cp, l) { cp[0] = l >> 24; cp[1] = l >> 16; cp[2] = l >> 8; cp[3] = l; }
+#define getlong(cp, l) l = ((cp[0] * 256 + cp[1]) * 256 + cp[2]) * 256 + cp[3]
+
+extern void fail(int conn, int err, char *msg);
+
+int send_int(int conn, long data)
+{
+  char buf[8];
+
+  putlong(buf, 4);
+  putlong((buf + 4), data);
+  if (write(conn, buf, 8) == 8)
+    return 0;
+  else
+    {
+      fail(conn, errno, "sending integer");
+      return errno;
+    }
+}
+
+int recv_int(int conn, long *data)
+{
+  char buf[8];
+
+  if (read(conn, buf, 8) != 8)
+    {
+      fail(conn, errno, "reading integer");
+      return errno;
+    }
+  getlong((buf + 4), *data);
+  return 0;
+}
+
+
+int send_string(int conn, char *buf, size_t len)
+{
+  char fulllen[4], stringlen[4];
+  struct iovec iov[3];
+
+  putlong(fulllen, (len + 4));
+  putlong(stringlen, len);
+  iov[0].iov_base = fulllen;
+  iov[0].iov_len = 4;
+  iov[1].iov_base = stringlen;
+  iov[1].iov_len = 4;
+  iov[2].iov_base = buf;
+  iov[2].iov_len = len;
+
+  if (writev(conn, iov, 3) == -1)
+    {
+      fail(conn, errno, "sending string");
+      return errno;
+    }
+  else
+    return 0;
+}
+
+int recv_string(int conn, char **buf, size_t *len)
+{
+  char tmp[4];
+
+  if (read(conn, tmp, 4) != 4)
+    {
+      fail(conn, errno, "reading string");
+      return errno;
+    }
+  if (read(conn, tmp, 4) != 4)
+    {
+      fail(conn, errno, "reading string");
+      return errno;
+    }
+  getlong(tmp, *len);
+
+  *buf = malloc(*len);
+  if (!*buf)
+    {
+      fail(conn, ENOMEM, "reading string");
+      return ENOMEM;
+    }
+  if (read(conn, *buf, *len) != *len)
+    {
+      free(buf);
+      fail(conn, errno, "reading string");
+      return errno;
+    }
+
+  return 0;
+}
index f482c597d4c841034b33de1de2e70ced7993e931..f0cdf80522386dc9a4564b1f8c343bc509f2d9ee 100644 (file)
@@ -26,7 +26,7 @@ char insecure[] =
 int main(int argc, char **argv)
 {
   int fd;
-  C_Block key;
+  des_cblock key;
   char *tty;
   tty = ttyname(0);
   if (!tty || strcmp(tty, "/dev/console"))
index 155fa9de4ad257b2c5d01863f6d9fd387dbfb547..26502f3b8d1a20196daf2b2865c44f6e67dc2139 100644 (file)
 
 RCSID("$Header$");
 
-extern char *whoami;
-
-/* too bad we can't set the pathname easily */
 static char *srvtab = KEYFILE; /* default == /etc/srvtab */
 static char realm[REALM_SZ];
 static char master[INST_SZ] = "sms";
 static char service[ANAME_SZ] = "rcmd";
-C_Block session;
-
-int get_mr_tgt(void);
-
-static void init(void)
-{
-  static int initialized = 0;
-
-  if (!initialized)
-    {
-      if (krb_get_lrealm(realm, 1))
-       strcpy(realm, KRB_REALM);
-      initialize_krb_error_table();
-      initialized = 1;
-    }
-}
+des_cblock session;
 
+static int get_mr_tgt(void);
 
 int get_mr_update_ticket(char *host, KTEXT ticket)
 {
-  int code;
-  int pass;
+  int code, pass;
   char phost[BUFSIZ];
   CREDENTIALS cr;
 
   pass = 1;
-  init();
+  if (krb_get_lrealm(realm, 1))
+    strcpy(realm, KRB_REALM);
   strcpy(phost, (char *)krb_get_phost(host));
+
 try_it:
   code = krb_mk_req(ticket, service, phost, realm, (long)0);
   if (code)
@@ -81,12 +65,11 @@ try_it:
   return code;
 }
 
-int get_mr_tgt(void)
+static int get_mr_tgt(void)
 {
   int code;
   char linst[INST_SZ], kinst[INST_SZ];
 
-  init();
   linst[0] = '\0';
   strcpy(kinst, "krbtgt");
   code = krb_get_svc_in_tkt(master, linst, realm, kinst, realm,
index a739a3f8d6e8186b6ca822651365b29e91f6ac62..22c26f69ec428b0ac96d15dd180e310616e6f5a8 100644 (file)
 #include "update_server.h"
 
 #include <sys/stat.h>
+#include <sys/utsname.h>
 
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <errno.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <des.h>
-#include <gdb.h>
 #include "update.h"
 
 RCSID("$Header$");
 
-extern int errno;
-
-CONNECTION conn;
-int code, log_priority;
-char *whoami;
+char *whoami, *hostname;
 
 int have_authorization = 0;
-C_Block session;
-int have_file = 0;
-int done = 0;
+des_cblock session;
 int uid = 0;
 
-#define send_int(n) \
-     (_send_int = (n), send_object(conn, (char *)&_send_int, INTEGER_T))
-int _send_int;
-
 struct _dt {
   char *str;
-  int (*proc)(char *);
+  void (*proc)(int, char *);
 } dispatch_table[] = {
   { "AUTH_002", auth_002 },
   { "XFER_002", xfer_002 },
   { "XFER_003", xfer_003 },
   { "EXEC_002", exec_002 },
   { "quit", quit },
-  { NULL, (int (*)(char *))abort }
+  { NULL, (void (*)(int, char *))abort }
 };
 
-/* general scratch space -- useful for building error messages et al... */
-char buf[BUFSIZ];
-
 int main(int argc, char **argv)
 {
-  STRING str;
+  char *str, *p;
+  size_t len;
   struct _dt *d;
-  char *p;
+  struct utsname name;
+  int s, conn;
 
   whoami = strrchr(argv[0], '/');
   if (whoami)
@@ -79,22 +72,12 @@ int main(int argc, char **argv)
        exit(0);
       setsid();
     }
-  else
-    gdb_debug(GDB_NOFORK);
 
-  umask(0022);
-  initialize_sms_error_table();
-  initialize_krb_error_table();
-  mr_update_initialize();
+  uname(&name);
+  hostname = name.nodename;
 
-  /* wait for connection */
-  gdb_init();
-  /* If the config file contains a line "port portname", the daemon
-   * will listen on the named port rather than SERVICE_NAME "moira_update"
-   */
-  if (!(p = config_lookup("port")))
-    p = SERVICE_NAME;
-  conn = create_forking_server(p, 0);
+  umask(0022);
+  mr_init();
 
   /* If the config file contains a line "user username", the
    * daemon will run with that user's UID.
@@ -111,6 +94,39 @@ int main(int argc, char **argv)
       uid = pw->pw_uid;
     }
 
+  /* If the config file contains a line "port portname", the daemon
+   * will listen on the named port rather than SERVICE_NAME ("moira_update")
+   */
+  if (!(p = config_lookup("port")))
+    p = SERVICE_NAME;
+
+  s = mr_listen(p);
+  if (s == -1)
+    {
+      com_err(whoami, errno, "creating listening socket");
+      exit(1);
+    }
+
+  /* now loop waiting for connections */
+  while (1)
+    {
+      struct sockaddr_in client;
+      long len;
+      char *buf;
+
+      conn = mr_accept(s, &client);
+      if (conn == -1)
+       {
+         com_err(whoami, errno, "accepting on listening socket");
+         exit(1);
+       }
+      else if (conn == 0)
+       continue;
+
+      if (config_lookup("nofork") || (fork() <= 0))
+       break;
+    }
+
   /* If the config file contains a line "chroot /dir/name", the
    * daemon will run chrooted to that directory.
    */
@@ -123,67 +139,49 @@ int main(int argc, char **argv)
        }
     }
 
-  if (!conn)
-    {
-      com_err(whoami, errno, "can't get connection");
-      exit(1);
-    }
-  if (connection_status(conn) == CON_STOPPED)
-    {
-      com_err(whoami, connection_errno(conn), ": can't get connection");
-      exit(1);
-    }
+  com_err(whoami, 0, "got connection");
 
-  mr_log_info("got connection");
-  /* got a connection; loop forever */
   while (1)
     {
-      char *cp;
-      code = receive_object(conn, (char *)&str, STRING_T);
+      char *cp, *str;
+      size_t len;
+      int code;
+
+      code = recv_string(conn, &str, &len);
       if (code)
        {
-         com_err(whoami, connection_errno(conn), "receiving command");
-         sever_connection(conn);
+         com_err(whoami, code, "receiving command");
+         close(conn);
          exit(1);
        }
-      cp = strchr(STRING_DATA(str), ' ');
+
+      cp = strchr(str, ' ');
       if (cp)
        *cp = '\0';
       for (d = dispatch_table; d->str; d++)
        {
-         if (!strcmp(d->str, STRING_DATA(str)))
+         if (!strcmp(d->str, str))
            {
              if (cp)
                *cp = ' ';
-             (d->proc)(STRING_DATA(str));
+             (d->proc)(conn, str);
              goto ok;
            }
        }
-      sprintf(buf, "unknown request received: %s\n", STRING_DATA(str));
-      mr_log_error(buf);
-      code = send_int(MR_UNKNOWN_PROC);
+      com_err(whoami, 0, "unknown request received: %s", str);
+      code = send_int(conn, MR_UNKNOWN_PROC);
       if (code)
-       com_err(whoami, connection_errno(conn), "sending UNKNOWN_PROC");
+       com_err(whoami, code, "sending UNKNOWN_PROC");
     ok:
-      string_free(&str);
+      free(str);
     }
 }
 
-int send_ok(void)
-{
-  static int zero = 0;
-  return code = send_object(conn, (char *)&zero, INTEGER_T);
-}
-
-
-void initialize(void)
+int send_ok(int conn)
 {
-  /* keep have_authorization around */
-  have_file = 0;
-  done = 0;
+  return send_int(conn, 0);
 }
 
-
 /*
  * quit request:
  *
@@ -195,53 +193,18 @@ void initialize(void)
  * function:
  *     closes connection from MR
  */
-int quit(char *str)
+
+void quit(int conn, char *str)
 {
-  send_ok();
-  sever_connection(conn);
-  mr_log_info("Closing connection.");
+  send_ok(conn);
+  close(conn);
+  com_err(whoami, 0, "Closing connection.");
   exit(0);
 }
 
-
-/*
- * lose(msg)
- *
- * put <msg> to log as error, break connection, and exit
- */
-
-void lose(char *msg)
+void fail(int conn, int err, char *msg)
 {
-  com_err(whoami, code, msg);
-  if (conn)
-    sever_connection(conn);
+  com_err(whoami, err, msg);
+  close(conn);
   exit(1);
 }
-
-/*
- * report_error(msg)
- *
- * send back (external) <code>; if error, punt big with <lose(msg)>
- */
-
-void report_error(char *msg)
-{
-  code = send_object(conn, (char *)&code, INTEGER_T);
-  if (code)
-    {
-      code = connection_errno(conn);
-      lose(msg);
-    }
-}
-
-/*
- * reject_call(c)
- *
- * set (external) <code> to <c> and call <report_error>
- */
-
-void reject_call(int c)
-{
-  code = c;
-  report_error("call rejected");
-}
index 0ed98dc255b1cf90ef2fa9e580c607306c3015f8..a61307942268cfdf7af67d5d34a3d2dd2caa3eb1 100644 (file)
@@ -1,18 +1,18 @@
 /* prototypes for the update_server */
 
-int auth_002(char *str);
-int exec_002(char *str);
-int xfer_002(char *str);
-int xfer_003(char *str);
+void auth_002(int conn, char *str);
+void exec_002(int conn, char *str);
+void xfer_002(int conn, char *str);
+void xfer_003(int conn, char *str);
 
 /* from checksum.c */
-int checksum_file(char *path);
+long checksum_file(char *path);
 
 /* from config.c */
 char *config_lookup(char *key);
 
 /* from get_file.c */
-int get_file(char *pathname, int file_size, int checksum,
+int get_file(int conn, char *pathname, int file_size, int checksum,
             int mode, int encrypt);
 
 /* from log.c */
@@ -24,8 +24,11 @@ void mr_debug(char *msg);
 
 /* from update_server.c */
 void initialize(void);
-int send_ok(void);
-int quit(char *str);
+int send_ok(int conn);
+void quit(int conn, char *str);
 void lose(char *msg);
 void report_error(char *msg);
 void reject_call(int c);
+
+extern char *whoami, *hostname;
+extern int have_authorization, uid;
index 1e10dd1aa794c9b52143e608694b86aab31ceae4..1f6a883714940893153bcf2a484577df060639fe 100644 (file)
 #include <moira.h>
 #include <update.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <gdb.h>
-
 void usage(void);
 
-CONNECTION conn;
 char *whoami;
 
 int main(int argc, char **argv)
 {
-  char *host, service_address[256], *file, *rfile, buf[256];
-  int code, i;
+  char *host, *file, *rfile, *ibuf = NULL;
+  int code, i, count = 0, conn;
 
   whoami = argv[0];
-  initialize_sms_error_table();
-  initialize_krb_error_table();
-  gdb_init();
+  mr_init();
 
   if (argc < 2)
     usage();
   host = argv[1];
 
-  sprintf(service_address, "%s:%s", host, SERVICE_NAME);
-  conn = start_server_connection(service_address, "");
-  if (!conn || (connection_status(conn) == CON_STOPPED))
+  conn = mr_connect_internal(host, SERVICE_NAME);
+  if (!conn)
     {
-      com_err(whoami, connection_errno(conn),
-             " can't connect to update %s", service_address);
-      return MR_CANT_CONNECT;
+      com_err(whoami, errno, ": can't connect to %s:%s", host, SERVICE_NAME);
+      exit(1);
     }
-  code = send_auth(host);
+
+  code = send_auth(conn, host);
   if (code)
-    com_err(whoami, code, " authorization attempt failed");
+    com_err(whoami, code, "attempting authorization");
 
   for (i = 2; i < argc; i++)
     {
@@ -59,7 +54,7 @@ int main(int argc, char **argv)
          file = argv[++i];
          rfile = argv[++i];
          fprintf(stderr, "Sending file %s to %s as %s\n", file, host, rfile);
-         send_file(file, rfile, 0);
+         send_file(conn, file, rfile, 0);
          break;
        case 'S':
          if (i + 2 >= argc)
@@ -68,31 +63,41 @@ int main(int argc, char **argv)
          rfile = argv[++i];
          fprintf(stderr, "Sending (encrypted) file %s to %s as %s\n",
                  file, host, rfile);
-         send_file(file, rfile, 1);
+         send_file(conn, file, rfile, 1);
          break;
        case 'i':
          if (i + 1 >= argc)
            usage();
          file = argv[++i];
-         strcpy(buf, "/tmp/moira-updateXXXXX");
-         mktemp(buf);
+         ibuf = strdup("/tmp/moira-updateXXXXX");
+         if (!ibuf)
+           {
+             com_err(whoami, ENOMEM, "sending instructions");
+             exit(1);
+           }
+         mktemp(ibuf);
          fprintf(stderr, "Sending instructions %s to %s as %s\n",
-                 file, host, buf);
-         send_file(file, buf, 0);
+                 file, host, ibuf);
+         send_file(conn, file, ibuf, 0);
          break;
        case 'I':
          if (i + 2 >= argc)
            usage();
          file = argv[++i];
-         rfile = argv[++i];
-         strcpy(buf, rfile);
+         ibuf = argv[++i];
+         strcpy(ibuf, rfile);
          fprintf(stderr, "Sending instructions %s to %s as %s\n",
-                 file, host, buf);
-         send_file(file, buf, 0);
+                 file, host, ibuf);
+         send_file(conn, file, ibuf, 0);
          break;
        case 'x':
-         fprintf(stderr, "Executing instructions %s on %s\n", buf, host);
-         code = execute(buf);
+         if (!ibuf)
+           {
+             fprintf(stderr, "No instructions sent.");
+             usage();
+           }
+         fprintf(stderr, "Executing instructions %s on %s\n", ibuf, host);
+         code = execute(conn, ibuf);
          if (code)
            com_err(whoami, code, "executing");
          break;
@@ -101,7 +106,7 @@ int main(int argc, char **argv)
            usage();
          file = argv[++i];
          fprintf(stderr, "Executing instructions %s on %s\n", file, host);
-         code = execute(file);
+         code = execute(conn, file);
          if (code)
            com_err(whoami, code, "executing");
          break;
@@ -111,8 +116,8 @@ int main(int argc, char **argv)
          usage();
        }
     }
-  send_quit();
-  conn = sever_connection(conn);
+  send_quit(conn);
+  close(conn);
   exit(code);
 }
 
index 32562c03d4eaf599a5d441d19cf83fda1ed61f23..df000a0466dfe1e0829675f36280c6651c01d887 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include <gdb.h>
-
 RCSID("$Header$");
 
-extern CONNECTION conn;
-extern char buf[BUFSIZ];
-
-extern int code;
-
-extern int have_authorization, have_file, done;
-
 /*
  *
  * syntax:
@@ -46,11 +37,10 @@ extern int have_authorization, have_file, done;
  * of all at once; use checksums
  */
 
-int xfer_002(char *str)
+void xfer_002(int conn, char *str)
 {
-  int file_size;
-  int checksum;
-  char *pathname;
+  int file_size, checksum, code;
+  char *pathname, *p;
 
   str += 8;
   while (*str == ' ')
@@ -58,40 +48,46 @@ int xfer_002(char *str)
   if (!*str)
     {
     failure:
-      reject_call(MR_ARGS);
-      return 0;
+      send_int(conn, MR_ARGS);
+      return;
     }
-  file_size = atoi(str);
-  while (isdigit(*str))
-    str++;
+
+  file_size = strtol(str, &p, 10);
+  if (p == str)
+    {
+      send_int(conn, MR_ARGS);
+      return;
+    }
+  else
+    str = p;
   while (*str == ' ')
     str++;
-  checksum = atoi(str);
-  while (isdigit(*str))
-    str++;
+
+  checksum = strtol(str, &p, 10);
+  if (p == str)
+    {
+      send_int(conn, MR_ARGS);
+      return;
+    }
+  else
+    str = p;
   while (*str == ' ')
     str++;
+
   if (*str != '/')
     goto failure;
   pathname = str;
+
   if (!have_authorization)
     {
-      reject_call(MR_PERM);
-      return 0;
+      send_int(conn, MR_PERM);
+      return;
     }
-  if (done)                    /* re-initialize data */
-    initialize();
-  code = send_ok();
-  if (code)
-    lose("sending ok for file xfer (2)");
-  code = get_file(pathname, file_size, checksum, 0700, 0);
+
+  send_ok(conn);
+  code = get_file(conn, pathname, file_size, checksum, 0700, 0);
   if (!code)
-    {
-      char buf[BUFSIZ];
-      have_file = 1;
-      strcpy(buf, "transferred file ");
-      strcat(buf, pathname);
-      mr_log_info(buf);
-    }
-  return 0;
+    com_err(whoami, 0, "Transferred file %s", pathname);
+
+  return;
 }
index 2138128633f3c6135d787fa2ad9a898b95a47350..5205460655fa0a8bb7be0b85b8229e95ee374d0a 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#include <gdb.h>
-
 RCSID("$Header$");
 
-extern CONNECTION conn;
-extern char buf[BUFSIZ];
-
-extern int code;
-
-extern int have_authorization, have_file, done;
-
 /*
  *
  * syntax:
@@ -44,11 +35,10 @@ extern int have_authorization, have_file, done;
  * this version of transfer encrypts the file being transferred.
  */
 
-int xfer_003(char *str)
+void xfer_003(int conn, char *str)
 {
-  int file_size;
-  int checksum;
-  char *pathname;
+  int file_size, checksum, code;
+  char *pathname, *p;
 
   str += 8;
   while (*str == ' ')
@@ -56,40 +46,46 @@ int xfer_003(char *str)
   if (!*str)
     {
     failure:
-      reject_call(MR_ARGS);
-      return 0;
+      send_int(conn, MR_ARGS);
+      return;
     }
-  file_size = atoi(str);
-  while (isdigit(*str))
-    str++;
+
+  file_size = strtol(str, &p, 10);
+  if (p == str)
+    {
+      send_int(conn, MR_ARGS);
+      return;
+    }
+  else
+    str = p;
   while (*str == ' ')
     str++;
-  checksum = atoi(str);
-  while (isdigit(*str))
-    str++;
+
+  checksum = strtol(str, &p, 10);
+  if (p == str)
+    {
+      send_int(conn, MR_ARGS);
+      return;
+    }
+  else
+    str = p;
   while (*str == ' ')
     str++;
+
   if (*str != '/')
     goto failure;
   pathname = str;
+
   if (!have_authorization)
     {
-      reject_call(MR_PERM);
-      return 0;
+      send_int(conn, MR_PERM);
+      return;
     }
-  if (done)                    /* re-initialize data */
-    initialize();
-  code = send_ok();
-  if (code)
-    lose("sending ok for file xfer (2)");
-  code = get_file(pathname, file_size, checksum, 0444, 1);
+
+  send_ok(conn);
+  code = get_file(conn, pathname, file_size, checksum, 0444, 1);
   if (!code)
-    {
-      char buf[BUFSIZ];
-      have_file = 1;
-      strcpy(buf, "transferred file ");
-      strcat(buf, pathname);
-      mr_log_info(buf);
-    }
-  return 0;
+    com_err(whoami, 0, "Transferred file %s", pathname);
+
+  return;
 }
index 62f88d7257b38c08a3d5de11206ec7df0c749fe2..a96d79f5352f19a9c43074d173eda44c7fc8913f 100644 (file)
@@ -128,9 +128,6 @@ GDSSINC= -DGDSS -I$(BUILDTOP)/util/gdss/include
 
 MR_LIB=$(BUILDTOP)/lib/libmoira.a
 MR_LIBDEP=$(MR_LIB)
-GDB_LIB=$(BUILDTOP)/gdb/libmrgdb.a
-GDB_LIBDEP=$(GDB_LIB)
-
 
 /*
  * The name of a command which compiles error tables.
@@ -160,9 +157,9 @@ LLIB = -L/usr/athena/lib
 
 /* libraries most Moira programs use */
 #ifdef HESIOD
-CLIBS= $(MR_LIB) $(GDB_LIB) $(LLIB) $(LZEPHYR) $(COM_ERR) -lkrb -ldes -lhesiod
+CLIBS= $(MR_LIB) $(LLIB) $(LZEPHYR) $(COM_ERR) -lkrb -ldes -lhesiod
 #else
-CLIBS= $(MR_LIB) $(GDB_LIB) $(LLIB) $(LZEPHYR) $(COM_ERR) -lkrb -ldes
+CLIBS= $(MR_LIB) $(LLIB) $(LZEPHYR) $(COM_ERR) -lkrb -ldes
 #endif
 
 /* libraries SQL programs need */
This page took 1.149952 seconds and 5 git commands to generate.