summaryrefslogtreecommitdiff
path: root/comm
diff options
context:
space:
mode:
authorchatty1993-07-27 13:54:48 +0000
committerchatty1993-07-27 13:54:48 +0000
commitd25f90acdcd86223a00d398527773b72bab166f3 (patch)
treeb51f6116889bbb821584fdeafa94898fa9b22e51 /comm
parentaf836c3ead39838720801f5364d92ca62672f0db (diff)
downloadivy-league-d25f90acdcd86223a00d398527773b72bab166f3.zip
ivy-league-d25f90acdcd86223a00d398527773b72bab166f3.tar.gz
ivy-league-d25f90acdcd86223a00d398527773b72bab166f3.tar.bz2
ivy-league-d25f90acdcd86223a00d398527773b72bab166f3.tar.xz
Included changes from mbl@prl and mbl@europarc
Diffstat (limited to 'comm')
-rw-r--r--comm/OLD/portserv.cc598
1 files changed, 409 insertions, 189 deletions
diff --git a/comm/OLD/portserv.cc b/comm/OLD/portserv.cc
index 5470fe3..bbbeec8 100644
--- a/comm/OLD/portserv.cc
+++ b/comm/OLD/portserv.cc
@@ -15,7 +15,9 @@
#include "PortServerReq.h"
#include "PortServer.h"
#include "error.h"
+#include "Multiplexer.h"
#include "Datagram.h"
+#include "Signal.h"
#include "ccu/List.h"
#include "ccu/RegExp.h"
#include "ccu/String.h"
@@ -41,8 +43,19 @@ int SaveTime = 0;
int Mod = 0;
int NbEntries = 0;
bool Trace = FALSE;
+UchMultiplexer* Mpx = 0;
const char* LoadFile;
+#ifndef DEFAGENTLIB
+#define DEFAGENTLIB "/usr/local/lib/agents"
+#endif
+char DefLoadFile [256];
+
+#ifndef DEFAGENTBIN
+#define DEFAGENTBIN "/usr/local/lib/agents/bin"
+#endif
+const char* BinDir = 0;
+
//---------------- constants
// if an auto-launch server has not registered for REG_TIME seconds
// and somebody inquires its address, it is killed and restarted.
@@ -55,7 +68,7 @@ const char* LoadFile;
#define ALR_TIME 30000
#define ALR_STR "30 seconds"
-struct Serv {
+struct Service {
CcuString Key;
lword Host;
sword Port;
@@ -70,14 +83,14 @@ struct Serv {
};
#ifndef CPLUS_BUG19
-CcuListOf <Serv> ServList;
+CcuListOf <Service> ServList;
#else
CcuList ServList;
#endif
//---------------- auto-launch stuff
char**
-Parse (char* line)
+ParseConfigLine (char* line)
{
enum WHERE { IN_SPACE, IN_WORD, IN_QUOTE };
char quote = '\0';
@@ -154,7 +167,7 @@ Parse (char* line)
}
void
-AutoLaunch (Serv* s)
+AutoLaunch (Service* s)
{
// s->RunCmd [0] service name
// s->RunCmd [1] directory
@@ -173,9 +186,13 @@ AutoLaunch (Serv* s)
close (i);
// detach from controlling terminal
setsid ();
+ // change directory. "-" is default
+ const char* dir = s->RunCmd [1];
+ if (strcmp (dir, "-") == 0)
+ dir = BinDir;
// change directory
- if (chdir (s->RunCmd [1]) < 0)
- SysError (ErrFatal, s->RunCmd [1]);
+ if (chdir (dir) < 0)
+ SysError (ErrFatal, dir);
// exec server
if (execvp (s->RunCmd [2], s->RunCmd + 3) < 0)
SysError (ErrFatal, s->RunCmd [2]);
@@ -184,14 +201,8 @@ AutoLaunch (Serv* s)
}
void
-LoadConfig ()
+LoadConfigFile ()
{
- char* l = getlogin ();
- if (! l)
- l = cuserid (0);
- if (! l)
- Error (ErrFatal, "LoadConfig", "getlogin failed");
-
FILE* f = fopen (LoadFile, "r");
if (!f)
SysError (ErrFatal, LoadFile);
@@ -207,15 +218,15 @@ LoadConfig ()
line [strlen (line) -1] = 0;
char* nline = new char [strlen (line) + 1];
strcpy (nline, line);
- char** words = Parse (nline);
+ char** words = ParseConfigLine (nline);
if (! words) {
- Error (ErrWarn, "LoadConfig", "incorrect line ignored in file");
+ Error (ErrWarn, "LoadConfigFile", "incorrect line ignored in file");
delete nline;
continue;
}
- Serv* s = new Serv;
- char key [256]; // portserv:mbl:audioserver
- sprintf (key, "portserv:%s:%s", l, words [0]);
+ Service* s = new Service;
+ char key [256]; // agent:audio
+ sprintf (key, "agent:%s", words [0]);
s->Key = key;
s->Host = 0;
s->Port = 0;
@@ -227,49 +238,49 @@ LoadConfig ()
s->CmdLine = nline;
s->RunCmd = words;
ServList.Append (s);
-// Log ("LoadConfig", "defined auto-launch server %s dir=%s exec=%s",
+// Log ("LoadConfigFile", "defined auto-launch server %s dir=%s exec=%s",
// s->RunCmd [0], s->RunCmd [1], s->RunCmd [2]);
}
fclose (f);
}
void
-KillProcesses ()
+KillProcesses (bool all)
{
// kill all processes that have been autolaunched,
// assuming that their id is their pid.
- Serv* s;
+ Service* s;
#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
+ CcuListIterOf <Service> iter (ServList);
while (s = *++iter) {
#else
CcuListIter iter (ServList);
- while (s = (Serv*) *++iter) {
+ while (s = (Service*) *++iter) {
#endif
- if (s->AutoLaunch && s->Ident) {
+ if ((all || s->AutoLaunch) && s->Ident) {
// Log ("KillProcesses", "killing %s pid=%d", s->RunCmd [2], (void*) s->Ident);
kill (s->Ident, SIGTERM);
}
}
}
-Serv*
-Register (const char* key, lword host, sword port, int id)
+Service*
+RegisterService (const char* key, lword host, sword port, int id)
{
- Serv* s = 0;
+ Service* s = 0;
#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
+ CcuListIterOf <Service> iter (ServList);
while (s = *++iter) {
#else
CcuListIter iter (ServList);
- while (s = (Serv*) *++iter) {
+ while (s = (Service*) *++iter) {
#endif
if (strcmp (key, s->Key) == 0)
break;
}
if (! s) {
- s = new Serv;
+ s = new Service;
s->Key = key;
s->AutoLaunch = FALSE;
s->LastRun = 0;
@@ -287,12 +298,12 @@ Register (const char* key, lword host, sword port, int id)
}
bool
-Remove (const char* key, lword host, sword port, int id)
+RemoveService (const char* key, lword host, sword port, int id)
{
- Serv*s;
+ Service* s;
#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
- CcuListIterOf <Serv> trailing_iter (ServList);
+ CcuListIterOf <Service> iter (ServList);
+ CcuListIterOf <Service> trailing_iter (ServList);
#else
CcuListIter iter (ServList);
CcuListIter trailing_iter (ServList);
@@ -301,7 +312,7 @@ Remove (const char* key, lword host, sword port, int id)
#ifndef CPLUS_BUG19
s = *iter;
#else
- s = (Serv*) *iter;
+ s = (Service*) *iter;
#endif
if (host == s->Host && port == s->Port && id == s->Ident && strcmp (key, s->Key) == 0) {
if (s->AutoLaunch) {
@@ -324,12 +335,12 @@ Remove (const char* key, lword host, sword port, int id)
return FALSE;
}
-Serv*
-Inquire (const char* key)
+Service*
+InquireService (const char* key)
{
- Serv*s;
+ Service* s;
#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
+ CcuListIterOf <Service> iter (ServList);
#else
CcuListIter iter (ServList);
#endif
@@ -337,7 +348,7 @@ Inquire (const char* key)
#ifndef CPLUS_BUG19
s = *iter;
#else
- s = (Serv*) *iter;
+ s = (Service*) *iter;
#endif
if (strcmp (key, s->Key) != 0)
@@ -366,50 +377,12 @@ Inquire (const char* key)
}
-void
-Match (const char* key, UchDatagram& portserv)
-{
- UchMsgBuffer buf (256);
- UchPortServerReq ans (PortServMatch);
- int nb = 0;
-
- CcuRegExp re (key);
- if (re.Compile ()) {
- Serv*s;
-#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
- while (++iter) {
- s = *iter;
-#else
- CcuListIter iter (ServList);
- while (++iter) {
- s = (Serv*) *iter;
-#endif
- if (re.Match (s->Key)) {
-if (Trace) printf ("Match: %s\n", (const char*) s->Key);
- ans.Host = s->Host;
- ans.Port = s->Port;
- ans.SetKey (s->Key);
- buf.Append (ans);
- portserv.Reply (buf);
- nb++;
- }
- }
- } else
- nb = -1;
- ans.Type = PortServEndMatch;
- ans.Ident = nb;
- ans.SetKey (0);
- buf.Append (ans);
- portserv.Reply (buf);
-}
-
int
Dump ()
{
- Serv*s;
+ Service* s;
#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
+ CcuListIterOf <Service> iter (ServList);
#else
CcuListIter iter (ServList);
#endif
@@ -417,7 +390,7 @@ Dump ()
#ifndef CPLUS_BUG19
s = *iter;
#else
- s = (Serv*) *iter;
+ s = (Service*) *iter;
#endif
printf ("<%s> 0x%lx:%d (%d)\n", (const char*) s->Key, s->Host, s->Port, s->Ident);
}
@@ -425,7 +398,7 @@ Dump ()
}
int
-DumpFile ()
+DumpToFile ()
{
if (Trace) printf ("dumping\n");
int fd = SaveFileIsFd;
@@ -435,9 +408,9 @@ if (Trace) printf ("dumping\n");
}
UchFilDes Fd (fd);
char buf [256];
- Serv*s;
+ Service* s;
#ifndef CPLUS_BUG19
- CcuListIterOf <Serv> iter (ServList);
+ CcuListIterOf <Service> iter (ServList);
#else
CcuListIter iter (ServList);
#endif
@@ -445,7 +418,7 @@ if (Trace) printf ("dumping\n");
#ifndef CPLUS_BUG19
s = *iter;
#else
- s = (Serv*) *iter;
+ s = (Service*) *iter;
#endif
sprintf (buf, "0x%lx:%d %s\n", s->Host, s->Port, (const char*) s->Key);
Fd.Write ((byte*) buf, strlen (buf));
@@ -454,18 +427,31 @@ if (Trace) printf ("dumping\n");
return 1;
}
-// for handlers
+// for signal handlers
//
void
-SigDump (int)
+SigDump (int, int)
{
Dump ();
}
void
-SigDumpFile (int)
+SigDumpFile (int, int)
+{
+ DumpToFile ();
+}
+
+class RegistrationChannel : public UchDatagram {
+protected:
+ void Match (const char*);
+public:
+ RegistrationChannel (sword);
+ void HandleRead ();
+};
+
+RegistrationChannel :: RegistrationChannel (sword port)
+: UchDatagram (new UchInetAddress (ANYADDR, port), 0)
{
- DumpFile ();
}
void
@@ -478,11 +464,277 @@ Modified ()
}
if (SaveTime < 0) {
Mod++;
- DumpFile ();
+ DumpToFile ();
}
}
void
+RegistrationChannel :: HandleRead ()
+{
+ UchMsgBuffer buf (256);
+ UchPortServerReq req;
+
+ if (Trace) printf ("HandleRead\n");
+ buf.Flush ();
+ int n = Receive (buf);
+ if (n <= 0) {
+ SysError (ErrFatal, "Receive", EINTR);
+ return;
+ }
+
+ if (! buf.Get (&req)) {
+ Error (ErrWarn, "Receive", "could not read message");
+ return;
+ }
+
+ // respond
+ switch (req.Type) {
+ case PortServRegister:
+ if (Trace) printf ("register\n");
+ RegisterService (req.Key, req.Host, req.Port, int (req.Ident));
+ Modified ();
+ break;
+
+ case PortServRemove:
+ if (Trace) printf ("remove\n");
+ RemoveService (req.Key, req.Host, req.Port, int (req.Ident));
+ Modified ();
+ break;
+
+ case PortServInquire:
+ {
+ if (Trace) printf ("inquire\n");
+ UchPortServerReq ans;
+ Service* inq = InquireService (req.Key);
+ if (inq) {
+ ans.Type = PortServAnswer;
+ ans.Host = inq->Host;
+ ans.Port = inq->Port;
+ } else {
+ ans.Type = PortServFail;
+ ans.Host = 0;
+ ans.Port = 0;
+ }
+ buf.Flush ();
+ buf.Append (ans);
+ if (Reply (buf) < 0)
+ SysError (ErrWarn, "reply");
+ }
+ break;
+
+ case PortServMatch:
+ if (Trace) printf ("match\n");
+ Match (req.Key);
+ break;
+
+ case PortServDump:
+ if (Trace) printf ("dump\n");
+ Dump ();
+ break;
+
+ case PortServQuit:
+ if (Trace) printf ("quit\n");
+ if (SaveTime)
+ DumpToFile ();
+ KillProcesses (TRUE);
+ Mpx->Close ();
+ break;
+
+ default:
+if (Trace) printf ("unknown\n");
+ Error (ErrWarn, "Receive", "unknown request");
+
+ }
+}
+
+void
+RegistrationChannel :: Match (const char* key)
+{
+ UchMsgBuffer buf (256);
+ UchPortServerReq ans (PortServMatch);
+ int nb = 0;
+
+ CcuRegExp re (key);
+ if (re.Compile ()) {
+ Service* s;
+#ifndef CPLUS_BUG19
+ CcuListIterOf <Service> iter (ServList);
+ while (++iter) {
+ s = *iter;
+#else
+ CcuListIter iter (ServList);
+ while (++iter) {
+ s = (Service*) *iter;
+#endif
+ if (re.Match (s->Key)) {
+if (Trace) printf ("Match: %s\n", (const char*) s->Key);
+ ans.Host = s->Host;
+ ans.Port = s->Port;
+ ans.SetKey (s->Key);
+ buf.Append (ans);
+ Reply (buf);
+ nb++;
+ }
+ }
+ } else
+ nb = -1;
+ ans.Type = PortServEndMatch;
+ ans.Ident = nb;
+ ans.SetKey (0);
+ buf.Append (ans);
+ Reply (buf);
+}
+
+//---------------- BroadcastChannel
+
+class BroadcastChannel : public UchDatagram {
+protected:
+ sword p;
+ pUchAddress bcast;
+ UchMsgBuffer registerBuf;
+ UchMsgBuffer removeBuf;
+ UchMsgBuffer answerBuf;
+
+static lword BroadCastAddress ();
+ void Answer ();
+
+public:
+ BroadcastChannel (sword, UchInetAddress*);
+ bool SetUp ();
+ void HandleRead ();
+ void RegisterMe () { printf ("RegisterMe: %d\n", Send (registerBuf, *bcast, TRUE /*peek*/)); }
+ void RemoveMe () { Send (removeBuf, *bcast, TRUE /*peek*/); printf ("sending remove\n"); }
+};
+
+lword
+BroadcastChannel :: BroadCastAddress ()
+{
+// *** can't get broadcast to work on DECstation !!!
+ char* bcast = getenv ("BroadcastChannel");
+ unsigned int b1, b2, b3, b4;
+ sscanf (bcast, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
+ printf ("bacst = %d.%d.%d.%d\n", b1, b2, b3, b4);
+// return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+ return (((b1 * 256U) + b2) * 256U + b3) * 256U + b4;
+}
+
+BroadcastChannel :: BroadcastChannel (sword port, UchInetAddress* reg_addr)
+: UchDatagram (new UchInetAddress (ANYADDR, port), 0)
+{
+ lword broadcast = BroadCastAddress ();
+ bcast = new UchInetAddress (broadcast, port);
+
+ const char* l = getlogin ();
+ if (! l)
+ l = cuserid (0);
+ if (! l)
+ Error (ErrFatal, "BroadcastChannel", "getlogin failed");
+
+ /* prepare answerBuf for future requests */
+ char key [32];
+ sprintf (key, "BroadcastChannel:%s:", l);
+ lword reg_host = reg_addr->Host ();
+ sword reg_port = reg_addr->Port ();
+ int pid = getpid ();
+ UchPortServerReq reg (PortServRegister, reg_host, reg_port, pid, key);
+ registerBuf.Append (reg);
+ UchPortServerReq rem (PortServRemove, reg_host, reg_port, pid, key);
+ removeBuf.Append (rem);
+ UchPortServerReq ans (PortServAnswer, reg_host, reg_port, pid, key);
+ answerBuf.Append (ans);
+}
+
+bool
+BroadcastChannel :: SetUp ()
+{
+ int on = 1;
+ if (! UchDatagram::Setup ())
+ return FALSE;
+ if (setsockopt (FilDes (), SOL_SOCKET, SO_BROADCAST, (const char*) &on, sizeof (on)) < 0)
+ return FALSE;
+ return TRUE;
+}
+
+void
+BroadcastChannel :: Answer ()
+{
+ int res = Send (answerBuf, *bcast, TRUE /*peek*/);
+ printf ("AnswerMe: %d\n", res);
+}
+
+void
+BroadcastChannel :: HandleRead ()
+{
+ // handle requests
+ //
+ UchMsgBuffer buf (256);
+ UchPortServerReq req;
+
+ buf.Flush ();
+ int n = Receive (buf);
+ if (n <= 0) {
+ SysError (ErrFatal, "BroadcastChannel", EINTR);
+ return;
+ }
+ if (! buf.Get (&req)) {
+ Error (ErrWarn, "BroadcastChannel", "could not read message");
+ return;
+ }
+
+ // respond
+ switch (req.Type) {
+ case PortServRegister:
+ RegisterService (req.Key, req.Host, req.Port, int (req.Ident));
+ Modified ();
+ printf ("received registration %s 0x%x %d %d\n", req.Key, req.Host, req.Port, req.Ident);
+ // when somebody else registers, we send our address
+ Answer ();
+ break;
+
+ case PortServInquire:
+ printf ("received inquiry\n");
+ Answer ();
+ break;
+
+ case PortServAnswer:
+ RegisterService (req.Key, req.Host, req.Port, int (req.Ident));
+ Modified ();
+ printf ("received answer %s 0x%x %d %d\n", req.Key, req.Host, req.Port, req.Ident);
+ break;
+
+ case PortServRemove:
+ RemoveService (req.Key, req.Host, req.Port, int (req.Ident));
+ Modified ();
+ break;
+
+ default:
+ Error (ErrWarn, "main", "unknown request");
+ }
+}
+
+// main
+//
+
+sword
+GetPortNumber (const char* servname, int dflt)
+{
+ /* first try services database */
+ struct servent* service = getservbyname (servname, 0);
+ if (service)
+ return ntohs (service->s_port);
+
+ /* then, environment variable */
+ char* portno = getenv (servname);
+ if (portno) {
+ int servport = atoi (portno);
+ return servport;
+ }
+
+ /* then default value (may be zero)*/
+ return dflt;
+}
+
+void
Usage ()
{
Error (ErrUsage, "portserv", "[-t] [-s service] [-quit] [-save file [time]] [-load file]");
@@ -495,6 +747,7 @@ main (int argc, const char** argv)
bool qflag = FALSE;
ProgramName (argv [0]);
+ LoadFile = getenv ("AGENTMGRCF");
while (--argc) {
++argv;
if (strcmp (*argv, "-quit") == 0) {
@@ -530,7 +783,7 @@ main (int argc, const char** argv)
Usage ();
}
- // special case: portserv -quit
+ // special case: portService -quit
// send a PortServQuit message to
// the portserver that is running
if (qflag) {
@@ -541,113 +794,80 @@ main (int argc, const char** argv)
exit (0);
}
- sword servport;
-
- // get service name
- //
- struct servent* service = getservbyname (servname, 0);
- if (service)
- servport = ntohs (service->s_port);
- else {
- const char* portno = getenv (servname);
- if (portno) {
- servport = atoi (portno);
- } else
- Error (ErrFatal, servname, "service not available");
+ if (! LoadFile) {
+ const char* agentlib = getenv ("AGENTLIB");
+ if (!agentlib)
+ agentlib = DEFAGENTLIB;
+ strcpy (DefLoadFile, agentlib);
+ strcat (DefLoadFile, "/agentman.cf");
+ if (access (DefLoadFile, R_OK) == 0)
+ LoadFile = DefLoadFile;
}
-
- // load file
+
+ // load config file
//
+ if (! BinDir) {
+ BinDir = getenv ("AGENTBIN");
+ if (! BinDir)
+ BinDir = DEFAGENTBIN;
+ }
if (LoadFile)
- LoadConfig ();
+ LoadConfigFile ();
+
+
+ UchMultiplexer mpx;
+ Mpx = &mpx;
+
+
+ // get port
+ //
+ sword reg_port = GetPortNumber (servname, 3003);
+ if (! reg_port)
+ Error (ErrFatal, servname, "service not available");
+
// open dgram socket
//
-if (Trace) printf ("opening\n");
- UchDatagram portserv (new UchInetAddress (ANYADDR, servport), 0);
- if (! portserv.Setup ())
-// Error (ErrFatal, "main", "Setup failed");
- SysError (ErrFatal, "main");
-
- signal (SIGHUP, SigDump);
+ if (Trace) printf ("opening\n");
+ RegistrationChannel reg_chan (reg_port);
+ if (! reg_chan.Setup ())
+ SysError (ErrFatal, "main, creating portserv");
+ reg_chan.SetMode (IORead);
+ mpx.Add (&reg_chan);
+
+ // open dgram broadcast socket for communicating between port servers
+ //
+ sword bc_port = GetPortNumber ("superman", 0);
+ BroadcastChannel* bc_chan = 0;
+ if (bc_port) {
+ bc_chan = new BroadcastChannel (bc_port, (UchInetAddress*) reg_chan.BoundTo ());
+ if (! bc_chan->Setup ()) {
+ SysError (ErrWarn, "main, creating broadcast channel");
+ delete bc_chan;
+ bc_chan = 0;
+ } else {
+ Error (ErrLog, "main", "created broadcast channel");
+ bc_chan->SetMode (IORead);
+ bc_chan->RegisterMe ();
+ mpx.Add (bc_chan);
+ }
+ }
+
+ // auto-dump stuff
+ //
+ UchSignalHandler h (mpx, SigHup, SigDump);
if (SaveTime > 0)
- signal (SIGALRM, SigDumpFile);
+ new UchSignalHandler (mpx, SigAlrm, SigDumpFile);
- // handle requests
+ // run the multiplexer
//
- UchMsgBuffer buf (256);
- UchPortServerReq req;
+ mpx.LoopScan ();
-if (Trace) printf ("looping\n");
- while (running) {
- buf.Flush ();
- int n = portserv.Receive (buf);
- if (n <= 0) {
- SysError (ErrFatal, "Receive", EINTR);
- continue;
- }
-if (Trace) printf ("received\n");
- if (! buf.Get (&req)) {
- Error (ErrWarn, "Receive", "could not read message");
- continue;
- }
-
- // respond
- switch (req.Type) {
- case PortServRegister :
-if (Trace) printf ("register\n");
- Register (req.Key, req.Host, req.Port, int (req.Ident));
- Modified ();
- break;
-
- case PortServRemove :
-if (Trace) printf ("remove\n");
- Remove (req.Key, req.Host, req.Port, int (req.Ident));
- Modified ();
- break;
-
- case PortServInquire :
- {
-if (Trace) printf ("inquire\n");
- UchPortServerReq ans;
- Serv* inq = Inquire (req.Key);
- if (inq) {
- ans.Type = PortServAnswer;
- ans.Host = inq->Host;
- ans.Port = inq->Port;
- } else {
- ans.Type = PortServFail;
- ans.Host = 0;
- ans.Port = 0;
- }
- buf.Flush ();
- buf.Append (ans);
- portserv.Reply (buf);
- }
- break;
-
- case PortServMatch :
-if (Trace) printf ("match\n");
- Match (req.Key, portserv);
- break;
-
- case PortServDump :
-if (Trace) printf ("dump\n");
- Dump ();
- break;
-
- case PortServQuit :
-if (Trace) printf ("quit\n");
- if (SaveTime)
- DumpFile ();
- KillProcesses ();
- running = 0; ////////dangerous
- break;
-
- default:
-if (Trace) printf ("unknown\n");
- Error (ErrWarn, "Receive", "unknown request");
- }
- }
+ // when quitting, notify other agent mgrs
+ //
+ if (bc_chan)
+ bc_chan->RemoveMe ();
+
+ return 0;
}