summaryrefslogtreecommitdiff
path: root/comm/OLD/TextStream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'comm/OLD/TextStream.cc')
-rw-r--r--comm/OLD/TextStream.cc564
1 files changed, 332 insertions, 232 deletions
diff --git a/comm/OLD/TextStream.cc b/comm/OLD/TextStream.cc
index 65f461c..445add6 100644
--- a/comm/OLD/TextStream.cc
+++ b/comm/OLD/TextStream.cc
@@ -22,6 +22,308 @@
#include <stdio.h>
#include <ctype.h>
+extern int windex (const char* list, const char* word);
+
+#ifdef __osf__
+extern "C" {
+ int socket (int, int, int);
+}
+#endif
+
+/*?
+Construct a \typ{UchTextStream}.
+?*/
+UchTextStream :: UchTextStream ()
+: UchBufStream ()
+{
+}
+
+/*?
+Protected destructor.
+\fun{Close} must be used instead to properly close down a \typ{UchTextStream}
+?*/
+UchTextStream :: ~UchTextStream ()
+{
+}
+
+/*?
+This virtual function is called by \fun{HandleRead} when an end of file
+is read (the argument is then \var{true}), or when an error occured while
+reading (the argument is then \var{false}).
+The default action is to call \fun{Close}.
+?*/
+void
+UchTextStream :: Closing (bool)
+{
+ Close ();
+}
+
+/*?
+Read and decode input. When a complete line (terminated either by
+a newline or cr-newline) is in the input buffer, it is parsed.
+If parsing is successful, \fun{Execute} is called with the line as argument.
+If \fun{Execute} returns \var{isCmdUnknown}, \fun{TryPredefined} is called
+to decode the predefined commands.
+Finally, \fun{ProcessCmdResult} is called and the line is flushed from
+the input buffer.
+Note that since the parsed line passed to \fun{Execute} contains pointers
+to the input buffer, \fun{Execute} {\em must not} keep copies of these
+pointers, but copy the contents instead.
+?*/
+void
+UchTextStream :: HandleRead ()
+{
+ if (ReadInput () <= 0)
+ return;
+
+ Process (InBuffer);
+}
+
+void
+UchTextStream :: Process (UchMsgBuffer& buf)
+{
+ // scan buffer for complete commands
+ char* start = (char*) buf.Buffer ();
+ char* stop = start + buf.BufLength ();
+ for (char* p = start; p < stop; p++) {
+ if (*p == '\n') {
+ *p = '\0';
+ // check cr-nl sequence
+ if (p > start && *(p-1) == '\r')
+ *(p-1) = '\0';
+ // parse line, lookup command
+ UchTextLine line;
+ cmd_res res = isCmdUnknown;
+ if (line.Parse (start)) {
+ if (line.NumWords () == 0)
+ res = isCmdOk;
+ else
+ res = Execute (line);
+ if (res == isCmdUnknown)
+ res = TryPredefined (line);
+ } else
+ res = isCmdSyntax;
+ ProcessCmdResult (res, line);
+ // reset for scanning rest of buffer
+ start = p+1;
+ buf.Flush ((byte*) start);
+ }
+ }
+}
+
+/*?
+Process the result \var{res} of the execution of the line \var{line}.
+If \var{res} is one of \var{isCmdSyntax}, \var{isCmdUnknown}, \var{isCmdError},
+a warning message is issued.
+If \var{res} is \var{isCmdClose} (resp. \var{isCmdQuit}), the virtual function
+\fun{Close} (resp. \fun{Quit}) is called.
+If \var{res} is \var{isCmdTerminate} (resp. \var{isCmdAbort}),
+the global function \fun{MpxTerminate} (resp. \fun{MpxAbort}) is called.
+If \var{res} is \var{isCmdExit}, \fun{exit(1)} is called.
+Finally, if \var{res} is \var{isCmdOk}, nothing happens.
+?*/
+void
+UchTextStream :: ProcessCmdResult (cmd_res res, const UchTextLine& line)
+{
+ const char* msg = 0;
+ switch (res) {
+ case isCmdSyntax:
+ msg = "syntax error in <%s>";
+ break;
+ case isCmdUnknown:
+ msg = "unknown command: <%s>";
+ break;
+ case isCmdOk:
+ return;
+ case isCmdError:
+ msg = "error while executing command <%s>";
+ break;
+ case isCmdClose:
+ // like eof (but smarter for the session)
+ Close ();
+ return;
+ case isCmdQuit:
+ //quit application
+ Quit ();
+ return;
+ case isCmdTerminate:
+ // terminate the multiplexer
+ if (Mpx)
+ Mpx->Close ();
+ return;
+ case isCmdAbort:
+ // abort the multiplexer
+ if (Mpx)
+ Mpx->Abort ();
+ return;
+ case isCmdExit:
+ exit (1);
+ }
+ if (msg) {
+ char buf [64];
+ line.Unparse (buf, sizeof (buf));
+ fprintf (stderr, "UchTextStream::ProcessCmdResult\n", msg, buf);
+ }
+}
+
+/*?
+If \var{line} is one of the words
+\com{Close}, \com{Quit}, \com{Terminate}, \com{Abort}, \com{Exit},
+the corresponding code is returned (\var{isCmdClose}, etc.),
+otherwise, \var{isCmdUnknown} is returned.
+?*/
+UchTextStream::cmd_res
+UchTextStream :: TryPredefined (const UchTextLine& line)
+{
+ const char* cname = line [0];
+
+ if (line.NumWords () != 1)
+ return isCmdUnknown;
+ switch (windex (":Close:Quit:Terminate:Abort:Exit:", cname)) {
+ case 1: return isCmdClose;
+ case 2: return isCmdQuit;
+ case 3: return isCmdTerminate;
+ case 4: return isCmdAbort;
+ case 5: return isCmdExit;
+ }
+ return isCmdUnknown;
+}
+
+void
+UchTextStream :: Send (const char* l, bool flush)
+{
+ OutBuffer.Append (l, false);
+ if (flush || Sync || OutBuffer.BufLength () >= OutSize)
+ Flush ();
+}
+
+void
+UchTextStream :: Send (const UchTextLine& l, bool flush)
+{
+ l.Unparse (&OutBuffer);
+ OutBuffer.WriteChar ('\n');
+ if (flush || Sync || OutBuffer.BufLength () >= OutSize)
+ Flush ();
+}
+
+/*?
+By default, it writes the output buffer on the stream.
+?*/
+void
+UchTextStream :: Flush ()
+{
+ Write (OutBuffer);
+}
+
+/*?
+This virtual function is called by \fun{ProcessCmdResult} when a \com{close}
+command has been received.
+It can be called directly by the application to close down the connection
+(remember that the destructor is private and cannot be called directly).
+By default it calls \fun{MpxRemoveChannel} to unregister this stream from the
+multiplexer.
+This will trigger deletion of the stream is the multiplexer holds the last
+smart pointer to it.
+Derived classes can redefine this function, but the redefinition
+should call the default implementation.
+?*/
+void
+UchTextStream :: Close ()
+{
+ Mpx->Remove (*this);
+}
+
+/*?
+This virtual function is called by \fun{ProcessCmdResult} when a \com{quit}
+command has been received.
+By default is calls \fun{MpxTerminate}.
+Derived classes can redefine this function if they want to terminate more
+gracefully.
+?*/
+void
+UchTextStream :: Quit ()
+{
+ Mpx->Close ();
+}
+
+
+void
+UchTextStream :: Emit (lword l)
+{
+
+ char c [1];
+ sprintf (c, "%d", l);
+ OutBuffer << c;
+}
+
+void
+UchTextStream :: Emit (sword s)
+{
+ char c [1];
+ sprintf (c, "%d", s);
+ OutBuffer << c;
+}
+
+void
+UchTextStream :: Emit (byte b)
+{
+ char c [1];
+ sprintf (c, "%d", b);
+ OutBuffer << c;
+}
+
+void
+UchTextStream :: Emit (char c)
+{
+ OutBuffer << c;
+}
+
+void
+UchTextStream :: Emit (const char* s)
+{
+ OutBuffer << s;
+}
+
+
+
+void
+UchTextStream :: Receive (lword& l)
+{
+ InBuffer >> l;
+}
+
+void
+UchTextStream :: Receive (sword& s)
+{
+ InBuffer >> s;
+}
+
+void
+UchTextStream :: Receive (byte& b)
+{
+ InBuffer >> b;
+}
+
+void
+UchTextStream :: Receive (char& c)
+{
+ InBuffer >> c;
+}
+
+void
+UchTextStream :: Receive (char* s)
+{
+ InBuffer >> s;
+}
+
+void
+UchTextStream :: Receive (CcuString& s)
+{
+ InBuffer >> s;
+}
+
+
+
// list is a set of words
// the separator must be the first and last char of the string:
// e.g. :yes:no: /foo/bar/toto/
@@ -243,8 +545,8 @@ UchTextLine :: Parse (char* line)
if (where != IN_SPACE)
AddWord (word);
if (where == IN_QUOTE)
- return FALSE;
- return TRUE;
+ return false;
+ return true;
}
// decompile line into buffer
@@ -329,13 +631,13 @@ UchTextLine :: Unparse (UchMsgBuffer* buf) const
}
}
if (*quotes)
- buf->Append (quotes [0]);
- buf->Append (sa, FALSE /*no newline*/);
+ buf->WriteChar (quotes [0]);
+ buf->Append (sa, false /*no newline*/);
if (*quotes)
- buf->Append (quotes [1]);
+ buf->WriteChar (quotes [1]);
// separator with next one
if (i < Num -1)
- buf->Append (' ');
+ buf->WriteChar (' ');
}
return start;
}
@@ -344,10 +646,10 @@ bool
UchTextLine :: Match (const char* cmdname, const char* profile) const
{
if (Num <= 0)
- return FALSE; // no word on line
+ return false; // no word on line
const char* myname = Words [0];
if (! myname || cmpname (myname, cmdname) != 0)
- return FALSE; // wrong command name
+ return false; // wrong command name
// check the profile, if it is non null.
// each letter in the profile corresponds to one argument:
@@ -361,17 +663,17 @@ UchTextLine :: Match (const char* cmdname, const char* profile) const
// *** we'll probably add features for repeated arguments,
// *** enums (mapping strings to ints), etc.
if (! profile)
- return TRUE;
+ return true;
const char* p = profile;
for (int i = 1; i < Num; i++) {
switch (*p) {
case 'i':
if (! Words [i].IsInt ())
- return FALSE;
+ return false;
break;
case 's':
if (! Words [i].IsString ())
- return FALSE;
+ return false;
break;
case 'b':
{
@@ -385,25 +687,25 @@ UchTextLine :: Match (const char* cmdname, const char* profile) const
Words[i].SetVal (0);
break;
}
- return FALSE;
+ return false;
}
case '+':
if (*(p+1)) // not at end of profile
fprintf (stderr, "UchTextLine::Match, invalid command profile: <%s>\n", profile);
- return TRUE;
+ return true;
case '\0':
// profile shorter than arg list
- return FALSE;
+ return false;
default:
fprintf (stderr, "UchTextLine::Match, invalid command profile: <%s>\n", profile);
- return FALSE;
+ return false;
}
p++;
}
if (*p)
- return FALSE; // arg list shorter than profile
- return TRUE;
+ return false; // arg list shorter than profile
+ return true;
}
// return -1 if word is not in the line, otherwise return its index
@@ -427,7 +729,7 @@ UchTextLine :: Index (int value) const
int i = 0;
for (; i < Num; i++, w++)
- if (w->IsInt () && *w == value)
+ if (w->IsInt () && value == int (*w))
return i;
return -1;
}
@@ -447,208 +749,6 @@ UchTextLine :: Index (int value) const
#define RETRY_TIME 2
#define MAX_RETRIES 5
-/*?
-Construct a \typ{UchTextStream}.
-?*/
-UchTextStream :: UchTextStream ()
-: UchStream (),
- InBuffer (256),
- OutBuffer (256)
-{
-}
-
-/*?
-Protected destructor.
-\fun{Close} must be used instead to properly close down a \typ{UchTextStream}
-?*/
-UchTextStream :: ~UchTextStream ()
-{
- // nothing
-}
-
-/*?
-This virtual function is called by \fun{HandleRead} when an end of file
-is read (the argument is then \var{TRUE}), or when an error occured while
-reading (the argument is then \var{FALSE}).
-The default action is to call \fun{Close}.
-?*/
-void
-UchTextStream :: Closing (bool)
-{
- Close ();
-}
-
-/*?
-Read and decode input. When a complete line (terminated either by
-a newline or cr-newline) is in the input buffer, it is parsed.
-If parsing is successful, \fun{Execute} is called with the line as argument.
-If \fun{Execute} returns \var{isCmdUnknown}, \fun{TryPredefined} is called
-to decode the predefined commands.
-Finally, \fun{ProcessCmdResult} is called and the line is flushed from
-the input buffer.
-Note that since the parsed line passed to \fun{Execute} contains pointers
-to the input buffer, \fun{Execute} {\em must not} keep copies of these
-pointers, but copy the contents instead.
-?*/
-void
-UchTextStream :: HandleRead ()
-{
- InBuffer.NeedSize (128);
- int n = Read (InBuffer);
- if (n <= 0) {
- Closing (n < 0 ? FALSE : TRUE);
- return;
- }
-
- // scan buffer for complete commands
- char* start = (char*) InBuffer.Buffer ();
- char* stop = start + InBuffer.BufLength ();
- for (char* p = start; p < stop; p++) {
- if (*p == '\n') {
- *p = '\0';
- // check cr-nl sequence
- if (p > start && *(p-1) == '\r')
- *(p-1) = '\0';
- // parse line, lookup command
- UchTextLine line;
- cmd_res res = isCmdUnknown;
- if (line.Parse (start)) {
- if (line.NumWords () == 0)
- res = isCmdOk;
- else
- res = Execute (line);
- if (res == isCmdUnknown)
- res = TryPredefined (line);
- } else
- res = isCmdSyntax;
- ProcessCmdResult (res, line);
- // reset for scanning rest of buffer
- start = p+1;
- InBuffer.Flush ((byte*) start);
- }
- }
-}
-
-/*?
-Process the result \var{res} of the execution of the line \var{line}.
-If \var{res} is one of \var{isCmdSyntax}, \var{isCmdUnknown}, \var{isCmdError},
-a warning message is issued.
-If \var{res} is \var{isCmdClose} (resp. \var{isCmdQuit}), the virtual function
-\fun{Close} (resp. \fun{Quit}) is called.
-If \var{res} is \var{isCmdTerminate} (resp. \var{isCmdAbort}),
-the global function \fun{MpxTerminate} (resp. \fun{MpxAbort}) is called.
-If \var{res} is \var{isCmdExit}, \fun{exit(1)} is called.
-Finally, if \var{res} is \var{isCmdOk}, nothing happens.
-?*/
-void
-UchTextStream :: ProcessCmdResult (cmd_res res, const UchTextLine& line)
-{
- const char* msg = 0;
- switch (res) {
- case isCmdSyntax:
- msg = "syntax error in <%s>";
- break;
- case isCmdUnknown:
- msg = "unknown command: <%s>";
- break;
- case isCmdOk:
- return;
- case isCmdError:
- msg = "error while executing command <%s>";
- break;
- case isCmdClose:
- // like eof (but smarter for the session)
- Close ();
- return;
- case isCmdQuit:
- //quit application
- Quit ();
- return;
- case isCmdTerminate:
- // terminate the multiplexer
- if (Mpx)
- Mpx->Close ();
- return;
- case isCmdAbort:
- // abort the multiplexer
- if (Mpx)
- Mpx->Abort ();
- return;
- case isCmdExit:
- exit (1);
- }
- if (msg) {
- char buf [64];
- line.Unparse (buf, sizeof (buf));
- fprintf (stderr, "UchTextStream::ProcessCmdResult\n", msg, buf);
- }
-}
-
-/*?
-If \var{line} is one of the words
-\com{Close}, \com{Quit}, \com{Terminate}, \com{Abort}, \com{Exit},
-the corresponding code is returned (\var{isCmdClose}, etc.),
-otherwise, \var{isCmdUnknown} is returned.
-?*/
-UchTextStream::cmd_res
-UchTextStream :: TryPredefined (const UchTextLine& line)
-{
- const char* cname = line [0];
-
- if (line.NumWords () != 1)
- return isCmdUnknown;
- switch (windex (":Close:Quit:Terminate:Abort:Exit:", cname)) {
- case 1: return isCmdClose;
- case 2: return isCmdQuit;
- case 3: return isCmdTerminate;
- case 4: return isCmdAbort;
- case 5: return isCmdExit;
- }
- return isCmdUnknown;
-}
-
-/*?
-This virtual function is called by the members that send commands on the stream.
-By defaults, it writes the output buffer on the stream.
-Derived classes can redefine this function.
-?*/
-void
-UchTextStream :: DoSend ()
-{
- Write (OutBuffer);
-}
-
-/*?
-This virtual function is called by \fun{ProcessCmdResult} when a \com{close}
-command has been received.
-It can be called directly by the application to close down the connection
-(remember that the destructor is private and cannot be called directly).
-By default it calls \fun{MpxRemoveChannel} to unregister this stream from the
-multiplexer.
-This will trigger deletion of the stream is the multiplexer holds the last
-smart pointer to it.
-Derived classes can redefine this function, but the redefinition
-should call the default implementation.
-?*/
-void
-UchTextStream :: Close ()
-{
- Mpx->Remove (*this);
-}
-
-/*?
-This virtual function is called by \fun{ProcessCmdResult} when a \com{quit}
-command has been received.
-By default is calls \fun{MpxTerminate}.
-Derived classes can redefine this function if they want to terminate more
-gracefully.
-?*/
-void
-UchTextStream :: Quit ()
-{
- Mpx->Close ();
-}
-
//---------------- ServiceStarter
class UchServiceStarter : public UchBaseTimeOut {
@@ -718,7 +818,7 @@ UchTextService :: UchTextService ()
: UchTextStream (),
StatusFlag (isLost),
Starter (0),
- Closed (FALSE),
+ Closed (false),
User (),
Service (),
Host ()
@@ -733,7 +833,7 @@ UchTextService :: UchTextService (UchBaseMultiplexer& mpx, const char* s, const
: UchTextStream (),
StatusFlag (isLost),
Starter (0),
- Closed (FALSE),
+ Closed (false),
User (),
Service (),
Host ()
@@ -803,7 +903,7 @@ UchTextService :: Restart ()
ConnectTo (addr);
bool wasopened = Fd.Opened ();
- bool setup = TRUE;
+ bool setup = true;
if (wasopened) {
// we are in trouble because a stream socket can be connected
// only once and a channel is immutable...
@@ -814,7 +914,7 @@ UchTextService :: Restart ()
int nfd = socket (ConnectedTo () ->Family (), SockType (), 0);
// fprintf (stderr, "UchTextService::Restart, reopening socket: %d -> %d\n", (void*) ofd, (void*) nfd);
if (nfd < 0) {
- setup = FALSE;
+ setup = false;
} else if (nfd != ofd) {
dup2 (nfd, ofd);
close (nfd);
@@ -905,8 +1005,8 @@ void
UchTextService :: GotServer ()
{
Mpx->SetMode (*this, IORead);
- if (OutBuffer.BufLength ())
- DoSend ();
+ if (OutBuffer.BufLength () != 0)
+ Flush ();
}
/*?
@@ -937,7 +1037,7 @@ UchTextService :: Execute (const UchTextLine&)
}
/*?
-This implementation of the protected virtual function \fun{UchTextStream::DoSend}
+This implementation of the protected virtual function \fun{UchBufStream::Flush}
writes the output buffer only if the state of the connection is
\var{isRunning}.
Otherwise, the outgoing requests accumulate in the ouput buffer until the
@@ -946,7 +1046,7 @@ This function also closes down the connection by calling \var{MpxRemoveChannel}
if \fun{Close} has been called before the connection ws actually established.
?*/
void
-UchTextService :: DoSend ()
+UchTextService :: Flush ()
{
if (StatusFlag == isRunning) {
Write (OutBuffer);
@@ -977,9 +1077,9 @@ UchTextService :: Init (UchBaseMultiplexer& mpx, const char* s, const char* h)
if (fork () != 0) {
// we are the parent process, and we become the agent manager
// *** how to have the agent manager survive the client ???
- Error (ErrLog, "TSERVICE::Init", "trying to run agentman");
+ ::Error (ErrLog, "TSERVICE::Init", "trying to run agentman");
if (execlp ("agentman", "agentman", 0) != 0)
- Error (ErrWarn, "TSERVICE::Init", "could not run agentman");
+ ::Error (ErrWarn, "TSERVICE::Init", "could not run agentman");
}
}
// delay retry
@@ -1017,7 +1117,7 @@ and then the connection will be closed.
void
UchTextService :: Close ()
{
- Closed = TRUE;
+ Closed = true;
if (StatusFlag == isRunning || OutBuffer.BufLength () == 0)
Mpx->Remove (*this);
}
@@ -1044,6 +1144,6 @@ TellServer (const char* sname, const char* host, const char* req)
serv->Init (sname, host);
serv->Send (req);
serv->Close ();
- return TRUE;
+ return true;
}
#endif