From ab626eecd36217d15f9bee3e7e82100ca93c16d1 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 1 Apr 2001 14:13:42 +0200 Subject: SVDRP now also works with clients that don't do line buffering --- HISTORY | 3 +++ svdrp.c | 64 +++++++++++++++++++++++++++++++++++++++++++++------------------- svdrp.h | 6 +++++- tools.c | 23 +---------------------- tools.h | 3 +-- 5 files changed, 55 insertions(+), 44 deletions(-) diff --git a/HISTORY b/HISTORY index 18dac185..02260c47 100644 --- a/HISTORY +++ b/HISTORY @@ -447,3 +447,6 @@ Video Disk Recorder Revision History - Fixed a segfault that sometimes happened when killing VDR. - VDR now returns an exit status of '2' in case of an error at startup, instead of terminating with 'abort()' (which caused a core dump). +- SVDRP now also works with clients that don't do line buffering (like the + Windows 'telnet'). + diff --git a/svdrp.c b/svdrp.c index a01bce34..941685f0 100644 --- a/svdrp.c +++ b/svdrp.c @@ -10,7 +10,7 @@ * and interact with the Video Disk Recorder - or write a full featured * graphical interface that sits on top of an SVDRP connection. * - * $Id: svdrp.c 1.15 2001/03/02 22:59:37 kls Exp $ + * $Id: svdrp.c 1.16 2001/04/01 14:09:29 kls Exp $ */ #define _GNU_SOURCE @@ -113,7 +113,6 @@ int cSocket::Accept(void) // --- cSVDRP ---------------------------------------------------------------- -#define MAXCMDBUFFER 10000 #define MAXHELPTOPIC 10 const char *HelpPages[] = { @@ -234,6 +233,7 @@ const char *GetHelpPage(const char *Cmd) cSVDRP::cSVDRP(int Port) :socket(Port) { + numChars = 0; message = NULL; lastActivity = 0; isyslog(LOG_INFO, "SVDRP listening on port %d", Port); @@ -842,7 +842,8 @@ void cSVDRP::Execute(char *Cmd) char *s = Cmd; while (*s && !isspace(*s)) s++; - *s++ = 0; + if (*s) + *s++ = 0; if (CMD("CHAN")) CmdCHAN(s); else if (CMD("DELC")) CmdDELC(s); else if (CMD("DELT")) CmdDELT(s); @@ -864,8 +865,7 @@ void cSVDRP::Execute(char *Cmd) else if (CMD("OVLP")) CmdOVLP(s); else if (CMD("OVLO")) CmdOVLO(s); else if (CMD("UPDT")) CmdUPDT(s); - else if (CMD("QUIT") - || CMD("\x04")) Close(); + else if (CMD("QUIT")) Close(); else Reply(500, "Command unrecognized: \"%s\"", Cmd); } @@ -875,29 +875,55 @@ void cSVDRP::Process(void) bool SendGreeting = NewConnection; if (file.IsOpen() || file.Open(socket.Accept())) { - char buffer[MAXCMDBUFFER]; if (SendGreeting) { //TODO how can we get the *full* hostname? + char buffer[MAXCMDBUFFER]; gethostname(buffer, sizeof(buffer)); time_t now = time(NULL); Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now)); } if (NewConnection) lastActivity = time(NULL); - int rbytes = file.ReadString(buffer, sizeof(buffer) - 1); - if (rbytes > 0) { - //XXX overflow check??? - // strip trailing whitespace: - while (rbytes > 0 && strchr(" \t\r\n", buffer[rbytes - 1])) - buffer[--rbytes] = 0; - // make sure the string is terminated: - buffer[rbytes] = 0; - // showtime! - Execute(buffer); - lastActivity = time(NULL); + if (file.Ready(false)) { + unsigned char c; + int r = read(file, &c, 1); + if (r > 0) { + if (c == '\n' || c == 0x00) { + // strip trailing whitespace: + while (numChars > 0 && strchr(" \t\r\n", cmdLine[numChars - 1])) + cmdLine[--numChars] = 0; + // make sure the string is terminated: + cmdLine[numChars] = 0; + // showtime! + Execute(cmdLine); + numChars = 0; + } + else if (c == 0x04 && numChars == 0) { + // end of file (only at beginning of line) + Close(); + } + else if (c == 0x08 || c == 0x7F) { + // backspace or delete (last character) + if (numChars > 0) + numChars--; + } + else if (c <= 0x03 || c == 0x0D || 0xF0 <= c) { + // ignore control characters + } + else if (numChars < sizeof(cmdLine) - 1) { + cmdLine[numChars++] = c; + cmdLine[numChars] = 0; + } + else { + Reply(501, "Command line too long"); + esyslog(LOG_ERR, "SVDRP: command line too long: '%s'", cmdLine); + numChars = 0; + } + lastActivity = time(NULL); + } + else if (r < 0) + Close(); } - else if (rbytes < 0) - Close(); else if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) { isyslog(LOG_INFO, "timeout on SVDRP connection"); Close(true); diff --git a/svdrp.h b/svdrp.h index 62c1e753..794d8be2 100644 --- a/svdrp.h +++ b/svdrp.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: svdrp.h 1.7 2001/02/18 13:36:47 kls Exp $ + * $Id: svdrp.h 1.8 2001/04/01 14:10:33 kls Exp $ */ #ifndef __SVDRP_H @@ -26,11 +26,15 @@ public: int Accept(void); }; +#define MAXCMDBUFFER 1024 + class cSVDRP { private: cSocket socket; cFile file; CRect ovlClipRects[MAXCLIPRECTS]; + uint numChars; + char cmdLine[MAXCMDBUFFER]; char *message; time_t lastActivity; void Close(bool Timeout = false); diff --git a/tools.c b/tools.c index 67468452..c303a8ab 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 1.31 2001/03/03 13:25:00 kls Exp $ + * $Id: tools.c 1.32 2001/04/01 14:13:36 kls Exp $ */ #define _GNU_SOURCE @@ -369,27 +369,6 @@ void cFile::Close(void) } } -int cFile::ReadString(char *Buffer, int Size) -{ - int rbytes = 0; - bool wait = true; - - while (Ready(wait)) { - int n = read(f, Buffer + rbytes, 1); - if (n == 0) - break; // EOF - if (n < 0) { - LOG_ERROR; - return -1; - } - rbytes += n; - if (rbytes == Size || Buffer[rbytes - 1] == '\n') - break; - wait = false; - } - return rbytes; -} - bool cFile::Ready(bool Wait) { return f >= 0 && AnyFileReady(f, Wait ? 1000 : 0); diff --git a/tools.h b/tools.h index 96d09826..a9d61218 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 1.24 2001/02/11 13:39:40 kls Exp $ + * $Id: tools.h 1.25 2001/04/01 14:13:42 kls Exp $ */ #ifndef __TOOLS_H @@ -64,7 +64,6 @@ public: bool Open(int FileDes); void Close(void); bool IsOpen(void) { return f >= 0; } - int ReadString(char *Buffer, int Size); bool Ready(bool Wait = true); static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000); static bool FileReady(int FileDes, int TimeoutMs = 1000); -- cgit v1.2.3