From d25f90acdcd86223a00d398527773b72bab166f3 Mon Sep 17 00:00:00 2001 From: chatty Date: Tue, 27 Jul 1993 13:54:48 +0000 Subject: Included changes from mbl@prl and mbl@europarc --- comm/OLD/portserv.cc | 598 +++++++++++++++++++++++++++++++++++---------------- 1 file 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 ServList; +CcuListOf 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 iter (ServList); + CcuListIterOf 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 iter (ServList); + CcuListIterOf 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 iter (ServList); - CcuListIterOf trailing_iter (ServList); + CcuListIterOf iter (ServList); + CcuListIterOf 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 iter (ServList); + CcuListIterOf 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 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 iter (ServList); + CcuListIterOf 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 iter (ServList); + CcuListIterOf 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 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 (®_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; } -- cgit v1.1