From 610c5600df98b35226536ffe92b1fd231128c7d4 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 1 Apr 2001 18:00:00 +0200 Subject: =?UTF-8?q?Version=200.72=20-=20Fixed=20SVDRP=20commands=20LSTC=20?= =?UTF-8?q?and=20LSTT=20to=20make=20them=20return=20an=20error=20message?= =?UTF-8?q?=20if=20=20=20no=20channels=20or=20timers=20are=20defined.=20-?= =?UTF-8?q?=20Enhanced=20'channels.conf.cable'=20(thanks=20to=20Hans-Peter?= =?UTF-8?q?=20Raschke).=20-=20Fixed=20switching=20to=20another=20channel?= =?UTF-8?q?=20via=20the=20EPG=20while=20a=20recording=20is=20being=20=20?= =?UTF-8?q?=20replayed.=20-=20Fixed=20a=20memory=20leak=20in=20the=20EIT?= =?UTF-8?q?=20processor=20that=20happened=20when=20the=20system=20time=20?= =?UTF-8?q?=20=20was=20set.=20-=20Removed=20some=20redundant=20code=20from?= =?UTF-8?q?=20the=20cListBase=20destructor.=20-=20Fixed=20internationaliza?= =?UTF-8?q?tion=20of=20some=20Main=20menu=20texts.=20-=20Updated=20'channe?= =?UTF-8?q?ls.conf'=20after=20the=20recent=20changes=20of=20Premiere=20Wor?= =?UTF-8?q?ld=20(thanks=20=20=20to=20Axel=20Gruber).=20-=20Redesigned=20th?= =?UTF-8?q?e=20ring=20buffer=20to=20make=20it=20work=20with=20two=20separa?= =?UTF-8?q?te=20threads=20for=20=20=20input=20and=20output=20(also=20prepa?= =?UTF-8?q?red=20for=20using=20a=20remultiplexer).=20-=20Fixed=20setting?= =?UTF-8?q?=20system=20time=20from=20transponders.=20-=20Fixed=20a=20segfa?= =?UTF-8?q?ult=20in=20the=20Schedule=20menu=20in=20case=20there=20is=20no?= =?UTF-8?q?=20EPG=20information.=20-=20The=20'runvdr'=20script=20now=20kil?= =?UTF-8?q?ls=20any=20leftover=20vdr=20threads=20before=20restarting=20it.?= =?UTF-8?q?=20-=20Fixed=20a=20problem=20with=20Daylight=20Saving=20Time=20?= =?UTF-8?q?when=20displaying=20the=20times=20of=20=20=20recordings.=20-=20?= =?UTF-8?q?Added=20Dutch=20language=20texts=20(thanks=20to=20Arnold=20Nies?= =?UTF-8?q?sen).=20-=20The=20new=20command=20line=20option=20-t=20can=20be?= =?UTF-8?q?=20used=20to=20set=20the=20controlling=20terminal=20=20=20(than?= =?UTF-8?q?ks=20to=20J=FCrgen=20Sauer).=20This=20is=20especially=20useful?= =?UTF-8?q?=20when=20starting=20VDR=20through=20=20=20an=20entry=20in=20/e?= =?UTF-8?q?tc/inittab=20(see=20INSTALL).=20-=20Since=20the=20CAM=20module?= =?UTF-8?q?=20only=20works=20if=20it=20is=20installed=20in=20the=20"highes?= =?UTF-8?q?t"=20DVB=20card,=20=20=20recordings=20now=20search=20for=20a=20?= =?UTF-8?q?free=20DVB=20card=20from=20lowest=20to=20highest=20index=20(as?= =?UTF-8?q?=20=20=20opposed=20to=20the=20previous=20"highest=20to=20lowest?= =?UTF-8?q?"=20search)=20in=20order=20to=20not=20use=20the=20=20=20CAM=20c?= =?UTF-8?q?ard=20for=20FTA=20recordings=20unless=20necessary.=20This=20is?= =?UTF-8?q?=20only=20important=20for=20=20=20systems=20with=20three=20or?= =?UTF-8?q?=20more=20DVB=20cards.=20-=20Added=20the=20"statdvb2vdr"=20tool?= =?UTF-8?q?=20from=20Hans-Peter=20Raschke.=20-=20Fixed=20a=20segfault=20th?= =?UTF-8?q?at=20sometimes=20happened=20when=20killing=20VDR.=20-=20VDR=20n?= =?UTF-8?q?ow=20returns=20an=20exit=20status=20of=20'2'=20in=20case=20of?= =?UTF-8?q?=20an=20error=20at=20startup,=20instead=20=20=20of=20terminatin?= =?UTF-8?q?g=20with=20'abort()'=20(which=20caused=20a=20core=20dump).=20-?= =?UTF-8?q?=20SVDRP=20now=20also=20works=20with=20clients=20that=20don't?= =?UTF-8?q?=20do=20line=20buffering=20(like=20the=20=20=20Windows=20'telne?= =?UTF-8?q?t').=20-=20Empty=20lines=20in=20config=20files=20no=20longer=20?= =?UTF-8?q?cause=20error=20messages.=20-=20New=20SVDRP=20command=20LSTE=20?= =?UTF-8?q?to=20list=20the=20EPG=20data.=20-=20The=20SVDRP=20HELP=20comman?= =?UTF-8?q?d=20now=20prints=20the=20topics=20in=20several=20columns.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- svdrp.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 25 deletions(-) (limited to 'svdrp.c') diff --git a/svdrp.c b/svdrp.c index ffdac28..df4ffac 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.14 2001/02/18 14:18:13 kls Exp $ + * $Id: svdrp.c 1.18 2001/04/01 16:06:54 kls Exp $ */ #define _GNU_SOURCE @@ -113,7 +113,6 @@ int cSocket::Accept(void) // --- cSVDRP ---------------------------------------------------------------- -#define MAXCMDBUFFER 10000 #define MAXHELPTOPIC 10 const char *HelpPages[] = { @@ -138,6 +137,8 @@ const char *HelpPages[] = { " List channels. Without option, all channels are listed. Otherwise\n" " only the given channel is listed. If a name is given, all channels\n" " containing the given string as part of their name are listed.", + "LSTE\n" + " List EPG data.", "LSTT [ ]\n" " List timers. Without option, all timers are listed. Otherwise\n" " only the given timer is listed.", @@ -188,6 +189,7 @@ const char *HelpPages[] = { /* SVDRP Reply Codes: 214 Help message + 215 EPG data record 220 VDR service ready 221 VDR service closing transmission channel 250 Requested VDR action okay, completed @@ -234,6 +236,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); @@ -470,13 +473,24 @@ void cSVDRP::CmdHELP(const char *Option) Reply(-214, "This is VDR version %s", VDRVERSION); Reply(-214, "Topics:"); const char **hp = HelpPages; + int NumPages = 0; while (*hp) { - //TODO multi-column??? - const char *topic = GetHelpTopic(*hp); - if (topic) - Reply(-214, " %s", topic); + NumPages++; hp++; } + const int TopicsPerLine = 5; + int x = 0; + for (int y = 0; (y * TopicsPerLine + x) < NumPages; y++) { + char buffer[TopicsPerLine * (MAXHELPTOPIC + 5)]; + char *q = buffer; + for (x = 0; x < TopicsPerLine && (y * TopicsPerLine + x) < NumPages; x++) { + const char *topic = GetHelpTopic(HelpPages[(y * TopicsPerLine + x)]); + if (topic) + q += sprintf(q, " %s", topic); + } + x = 0; + Reply(-214, buffer); + } Reply(-214, "To report bugs in the implementation send email to"); Reply(-214, " vdr-bugs@cadsoft.de"); } @@ -535,7 +549,7 @@ void cSVDRP::CmdLSTC(const char *Option) Reply(250, "%d %s", next->number, next->ToText()); } } - else { + else if (Channels.MaxNumber() >= 1) { for (int i = 1; i <= Channels.MaxNumber(); i++) { cChannel *channel = Channels.GetByNumber(i); if (channel) @@ -544,6 +558,27 @@ void cSVDRP::CmdLSTC(const char *Option) Reply(501, "Channel \"%d\" not found", i); } } + else + Reply(550, "No channels defined"); +} + +void cSVDRP::CmdLSTE(const char *Option) +{ + cThreadLock ThreadLock; + const cSchedules *Schedules = cDvbApi::PrimaryDvbApi->Schedules(&ThreadLock); + if (Schedules) { + FILE *f = fdopen(file, "w"); + if (f) { + Schedules->Dump(f, "215-"); + fflush(f); + Reply(215, "End of EPG data"); + // don't 'fclose(f)' here! + } + else + Reply(451, "Can't open file connection"); + } + else + Reply(451, "Can't get EPG data"); } void cSVDRP::CmdLSTT(const char *Option) @@ -559,7 +594,7 @@ void cSVDRP::CmdLSTT(const char *Option) else Reply(501, "Error in timer number \"%s\"", Option); } - else { + else if (Timers.Count()) { for (int i = 0; i < Timers.Count(); i++) { cTimer *timer = Timers.Get(i); if (timer) @@ -568,6 +603,8 @@ void cSVDRP::CmdLSTT(const char *Option) Reply(501, "Timer \"%d\" not found", i + 1); } } + else + Reply(550, "No timers defined"); } void cSVDRP::CmdMESG(const char *Option) @@ -838,7 +875,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); @@ -846,6 +884,7 @@ void cSVDRP::Execute(char *Cmd) else if (CMD("HELP")) CmdHELP(s); else if (CMD("HITK")) CmdHITK(s); else if (CMD("LSTC")) CmdLSTC(s); + else if (CMD("LSTE")) CmdLSTE(s); else if (CMD("LSTT")) CmdLSTT(s); else if (CMD("MESG")) CmdMESG(s); else if (CMD("MODC")) CmdMODC(s); @@ -860,8 +899,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); } @@ -871,29 +909,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); -- cgit v1.2.3