summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS2
-rw-r--r--HISTORY12
-rw-r--r--PLUGINS/src/skincurses/HISTORY4
-rw-r--r--PLUGINS/src/sky/HISTORY4
-rw-r--r--PLUGINS/src/sky/sky.c6
-rw-r--r--channels.c11
-rw-r--r--keys.c5
-rw-r--r--osd.c5
-rw-r--r--plugin.c31
-rw-r--r--recording.c66
-rw-r--r--skinclassic.c10
-rw-r--r--skinsttng.c14
-rw-r--r--svdrp.c31
-rw-r--r--themes.c42
-rw-r--r--timers.c4
-rw-r--r--tools.c200
-rw-r--r--tools.h85
-rw-r--r--vdr.c45
18 files changed, 359 insertions, 218 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index d4c6385d..b62f8a32 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -348,6 +348,8 @@ Rainer Zocholl <vdrcontrib@zocki.toppoint.de>
for suggesting that VDR should stop if one of the configuration files can't be
read correctly at program startup
for reporting a possible race condition in generating the DVB device names
+ for pointing out that non-threadsafe functions should be replaced with their
+ threadsafe versions
Oleg Assovski <assen@bitcom.msk.ru>
for adding EPG scanning for another 4 days
diff --git a/HISTORY b/HISTORY
index 8d8dca2c..0f16486e 100644
--- a/HISTORY
+++ b/HISTORY
@@ -3209,3 +3209,15 @@ Video Disk Recorder Revision History
- Added 'channels.conf.terr' entries for Lübeck (thanks to Stefan Hußfeldt).
- Fixed a race condition in starting a thread (thanks to Reinhard Nissl for
reporting this one).
+- Replaced non-threadsafe library functions with their threadsafe versions (thanks
+ to Rainer Zocholl for pointing this out).
+- Other non-threadsafe functions have been replaced by threadsafe classes that hide
+ the actual buffering. In particular these are:
+ readdir() -> cReadDir
+ readline() -> cReadLine
+ strescape() -> cStrEscape
+ AddDirectory() -> cAddDirectory
+ ctime() -> cCtime
+ itoa() -> cItoa
+ WeekDayName() -> cWeekDayName
+ DayDateTime() -> cDayDateTime
diff --git a/PLUGINS/src/skincurses/HISTORY b/PLUGINS/src/skincurses/HISTORY
index df673583..057fb6f8 100644
--- a/PLUGINS/src/skincurses/HISTORY
+++ b/PLUGINS/src/skincurses/HISTORY
@@ -8,3 +8,7 @@ VDR Plugin 'skincurses' Revision History
2004-05-31: Version 0.0.2
- Fixed some default parameters.
+
+2004-12-26: Version 0.0.3
+
+- Made several functions threadsafe.
diff --git a/PLUGINS/src/sky/HISTORY b/PLUGINS/src/sky/HISTORY
index 490ee62b..f1f22a69 100644
--- a/PLUGINS/src/sky/HISTORY
+++ b/PLUGINS/src/sky/HISTORY
@@ -32,3 +32,7 @@ VDR Plugin 'sky' Revision History
2004-12-12: Version 0.3.2
- Changed Apid access in cChannel.
+
+2004-12-19: Version 0.3.3
+
+- Made several functions threadsafe.
diff --git a/PLUGINS/src/sky/sky.c b/PLUGINS/src/sky/sky.c
index 8936774e..49afea1d 100644
--- a/PLUGINS/src/sky/sky.c
+++ b/PLUGINS/src/sky/sky.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: sky.c 1.8 2004/12/12 14:27:33 kls Exp $
+ * $Id: sky.c 1.9 2004/12/19 15:33:47 kls Exp $
*/
#include <sys/socket.h>
@@ -14,7 +14,7 @@
#include <vdr/plugin.h>
#include <vdr/sources.h>
-static const char *VERSION = "0.3.2";
+static const char *VERSION = "0.3.3";
static const char *DESCRIPTION = "Sky Digibox interface";
// --- cDigiboxDevice --------------------------------------------------------
@@ -273,7 +273,7 @@ bool cPluginSky::Initialize(void)
// Initialize any background activities the plugin shall perform.
const char *ConfigDir = ConfigDirectory(Name());
if (ConfigDir) {
- if (SkyChannels.Load(AddDirectory(ConfigDir, "channels.conf.sky"), true)) {
+ if (SkyChannels.Load(*cAddDirectory(ConfigDir, "channels.conf.sky"), true)) {
new cDigiboxDevice;
return true;
}
diff --git a/channels.c b/channels.c
index 5d500ece..67949e24 100644
--- a/channels.c
+++ b/channels.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.c 1.31 2004/11/02 18:07:05 kls Exp $
+ * $Id: channels.c 1.32 2004/12/19 11:24:51 kls Exp $
*/
#include "channels.h"
@@ -705,7 +705,8 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
p = apidbuf;
char *q;
int NumApids = 0;
- while ((q = strtok(p, ",")) != NULL) {
+ char *strtok_next;
+ while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
if (NumApids < MAXAPIDS) {
char *l = strchr(q, '=');
if (l) {
@@ -725,7 +726,8 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
char *p = dpidbuf;
char *q;
int NumDpids = 0;
- while ((q = strtok(p, ",")) != NULL) {
+ char *strtok_next;
+ while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
if (NumDpids < MAXAPIDS) {
char *l = strchr(q, '=');
if (l) {
@@ -747,7 +749,8 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
char *p = caidbuf;
char *q;
int NumCaIds = 0;
- while ((q = strtok(p, ",")) != NULL) {
+ char *strtok_next;
+ while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
if (NumCaIds < MAXCAIDS) {
caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
if (NumCaIds == 1 && caids[0] <= 0x00FF)
diff --git a/keys.c b/keys.c
index 5529f323..aaeee97e 100644
--- a/keys.c
+++ b/keys.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: keys.c 1.5 2003/09/14 10:07:47 kls Exp $
+ * $Id: keys.c 1.6 2004/12/19 11:25:47 kls Exp $
*/
#include "keys.h"
@@ -195,7 +195,8 @@ bool cKeyMacro::Parse(char *s)
{
int n = 0;
char *p;
- while ((p = strtok(s, " \t")) != NULL) {
+ char *strtok_next;
+ while ((p = strtok_r(s, " \t", &strtok_next)) != NULL) {
if (n < MAXKEYSINMACRO) {
if (*p == '@') {
if (plugin) {
diff --git a/osd.c b/osd.c
index 6944e675..8b10f74f 100644
--- a/osd.c
+++ b/osd.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: osd.c 1.58 2004/10/16 10:31:34 kls Exp $
+ * $Id: osd.c 1.59 2004/12/19 12:27:38 kls Exp $
*/
#include "osd.h"
@@ -197,7 +197,8 @@ bool cBitmap::LoadXpm(const char *FileName)
int lines = 0;
int index = 0;
char *s;
- while ((s = readline(f)) != NULL) {
+ cReadLine ReadLine;
+ while ((s = ReadLine.Read(f)) != NULL) {
s = skipspace(s);
if (!isXpm) {
if (strcmp(s, "/* XPM */") != 0) {
diff --git a/plugin.c b/plugin.c
index 7f211b3c..a06d003c 100644
--- a/plugin.c
+++ b/plugin.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: plugin.c 1.11 2004/05/22 11:25:22 kls Exp $
+ * $Id: plugin.c 1.12 2004/12/19 12:05:28 kls Exp $
*/
#include "plugin.h"
@@ -256,26 +256,23 @@ void cPluginManager::SetDirectory(const char *Directory)
void cPluginManager::AddPlugin(const char *Args)
{
if (strcmp(Args, "*") == 0) {
- DIR *d = opendir(directory);
- if (d) {
- struct dirent *e;
- while ((e = readdir(d)) != NULL) {
- if (strstr(e->d_name, LIBVDR_PREFIX) == e->d_name) {
- char *p = strstr(e->d_name, SO_INDICATOR);
- if (p) {
- *p = 0;
- p += strlen(SO_INDICATOR);
- if (strcmp(p, VDRVERSION) == 0) {
- char *name = e->d_name + strlen(LIBVDR_PREFIX);
- if (strcmp(name, "*") != 0) { // let's not get into a loop!
- AddPlugin(e->d_name + strlen(LIBVDR_PREFIX));
- }
+ cReadDir d(directory);
+ struct dirent *e;
+ while ((e = d.Next()) != NULL) {
+ if (strstr(e->d_name, LIBVDR_PREFIX) == e->d_name) {
+ char *p = strstr(e->d_name, SO_INDICATOR);
+ if (p) {
+ *p = 0;
+ p += strlen(SO_INDICATOR);
+ if (strcmp(p, VDRVERSION) == 0) {
+ char *name = e->d_name + strlen(LIBVDR_PREFIX);
+ if (strcmp(name, "*") != 0) { // let's not get into a loop!
+ AddPlugin(e->d_name + strlen(LIBVDR_PREFIX));
}
}
}
}
- closedir(d);
- }
+ }
return;
}
char *s = strdup(skipspace(Args));
diff --git a/recording.c b/recording.c
index 5a703db2..aa9f6dcf 100644
--- a/recording.c
+++ b/recording.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.c 1.92 2004/11/01 14:04:47 kls Exp $
+ * $Id: recording.c 1.93 2004/12/19 15:44:42 kls Exp $
*/
#include "recording.h"
@@ -157,7 +157,7 @@ cResumeFile::cResumeFile(const char *FileName)
fileName = MALLOC(char, strlen(FileName) + strlen(RESUMEFILESUFFIX) + 1);
if (fileName) {
strcpy(fileName, FileName);
- sprintf(fileName + strlen(fileName), RESUMEFILESUFFIX, Setup.ResumeID ? "." : "", Setup.ResumeID ? itoa(Setup.ResumeID) : "");
+ sprintf(fileName + strlen(fileName), RESUMEFILESUFFIX, Setup.ResumeID ? "." : "", Setup.ResumeID ? *cItoa(Setup.ResumeID) : "");
}
else
esyslog("ERROR: can't allocate memory for resume file name");
@@ -628,47 +628,44 @@ cRecordings::cRecordings(bool Deleted)
void cRecordings::ScanVideoDir(const char *DirName)
{
- DIR *d = opendir(DirName);
- if (d) {
- struct dirent *e;
- while ((e = readdir(d)) != NULL) {
- if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
- char *buffer;
- asprintf(&buffer, "%s/%s", DirName, e->d_name);
- struct stat st;
- if (stat(buffer, &st) == 0) {
- if (S_ISLNK(st.st_mode)) {
+ cReadDir d(DirName);
+ struct dirent *e;
+ while ((e = d.Next()) != NULL) {
+ if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
+ char *buffer;
+ asprintf(&buffer, "%s/%s", DirName, e->d_name);
+ struct stat st;
+ if (stat(buffer, &st) == 0) {
+ if (S_ISLNK(st.st_mode)) {
+ free(buffer);
+ buffer = ReadLink(buffer);
+ if (!buffer)
+ continue;
+ if (stat(buffer, &st) != 0) {
free(buffer);
- buffer = ReadLink(buffer);
- if (!buffer)
- continue;
- if (stat(buffer, &st) != 0) {
- free(buffer);
- continue;
- }
+ continue;
}
- if (S_ISDIR(st.st_mode)) {
- if (endswith(buffer, deleted ? DELEXT : RECEXT)) {
- cRecording *r = new cRecording(buffer);
- if (r->Name())
- Add(r);
- else
- delete r;
- }
+ }
+ if (S_ISDIR(st.st_mode)) {
+ if (endswith(buffer, deleted ? DELEXT : RECEXT)) {
+ cRecording *r = new cRecording(buffer);
+ if (r->Name())
+ Add(r);
else
- ScanVideoDir(buffer);
+ delete r;
}
+ else
+ ScanVideoDir(buffer);
}
- free(buffer);
}
+ free(buffer);
}
- closedir(d);
- }
+ }
}
bool cRecordings::NeedsUpdate(void)
{
- return lastUpdate <= LastModifiedTime(AddDirectory(VideoDirectory, ".update"));
+ return lastUpdate <= LastModifiedTime(*cAddDirectory(VideoDirectory, ".update"));
}
bool cRecordings::Load(void)
@@ -750,8 +747,7 @@ bool cMark::Save(FILE *f)
bool cMarks::Load(const char *RecordingFileName)
{
- const char *MarksFile = AddDirectory(RecordingFileName, MARKSFILESUFFIX);
- if (cConfig<cMark>::Load(MarksFile)) {
+ if (cConfig<cMark>::Load(*cAddDirectory(RecordingFileName, MARKSFILESUFFIX))) {
Sort();
return true;
}
@@ -815,7 +811,7 @@ void cRecordingUserCommand::InvokeCommand(const char *State, const char *Recordi
{
if (command) {
char *cmd;
- asprintf(&cmd, "%s %s \"%s\"", command, State, strescape(RecordingFileName, "\"$"));
+ asprintf(&cmd, "%s %s \"%s\"", command, State, *cStrEscape(RecordingFileName, "\"$"));
isyslog("executing '%s'", cmd);
SystemExec(cmd);
free(cmd);
diff --git a/skinclassic.c b/skinclassic.c
index 9dd90942..3b9609f3 100644
--- a/skinclassic.c
+++ b/skinclassic.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: skinclassic.c 1.7 2004/05/31 14:09:00 kls Exp $
+ * $Id: skinclassic.c 1.8 2004/12/19 15:46:09 kls Exp $
*/
#include "skinclassic.h"
@@ -141,8 +141,8 @@ void cSkinClassicDisplayChannel::SetMessage(eMessageType Type, const char *Text)
void cSkinClassicDisplayChannel::Flush(void)
{
if (!message) {
- const char *date = DayDateTime();
- osd->DrawText(osd->Width() - cFont::GetFont(fontSml)->Width(date) - 2, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml));
+ cDayDateTime date;
+ osd->DrawText(osd->Width() - cFont::GetFont(fontSml)->Width(*date) - 2, 0, *date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml));
}
osd->Flush();
}
@@ -338,9 +338,9 @@ void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
void cSkinClassicDisplayMenu::Flush(void)
{
- const char *date = DayDateTime();
+ cDayDateTime date;
const cFont *font = cFont::GetFont(fontOsd);
- osd->DrawText(x1 - font->Width(date) - 2, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font);
+ osd->DrawText(x1 - font->Width(*date) - 2, y0, *date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font);
osd->Flush();
}
diff --git a/skinsttng.c b/skinsttng.c
index f1f79bf5..cf60ae14 100644
--- a/skinsttng.c
+++ b/skinsttng.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: skinsttng.c 1.7 2004/12/05 13:19:59 kls Exp $
+ * $Id: skinsttng.c 1.8 2004/12/19 15:48:55 kls Exp $
*/
// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
@@ -289,9 +289,9 @@ void cSkinSTTNGDisplayChannel::Flush(void)
{
if (withInfo) {
if (!message) {
- const char *date = DayDateTime();
+ cDayDateTime date;
const cFont *font = cFont::GetFont(fontSml);
- osd->DrawText(x4 - font->Width(date) - 2, y7 - font->Height(date), date, Theme.Color(clrChannelDate), frameColor, font);
+ osd->DrawText(x4 - font->Width(*date) - 2, y7 - font->Height(*date), *date, Theme.Color(clrChannelDate), frameColor, font);
}
int seen = 0;
@@ -456,11 +456,11 @@ void cSkinSTTNGDisplayMenu::SetTitle(const char *Title)
void cSkinSTTNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
{
- const char *date = DayDateTime();
+ cDayDateTime date;
const cFont *font = cFont::GetFont(fontSml);
int d = 10;
int d2 = d / 2;
- int t4 = x4 - font->Width(date) - 2;
+ int t4 = x4 - font->Width(*date) - 2;
int w = t4 - x3;
int t0 = x3 + d2;
int t1 = x3 + w / 4;
@@ -583,9 +583,9 @@ void cSkinSTTNGDisplayMenu::SetText(const char *Text, bool FixedFont)
void cSkinSTTNGDisplayMenu::Flush(void)
{
if (!message) {
- const char *date = DayDateTime();
+ cDayDateTime date;
const cFont *font = cFont::GetFont(fontSml);
- osd->DrawText(x4 - font->Width(date) - 2, y7 - font->Height(date), date, Theme.Color(clrMenuDate), frameColor, font);
+ osd->DrawText(x4 - font->Width(*date) - 2, y7 - font->Height(*date), *date, Theme.Color(clrMenuDate), frameColor, font);
}
osd->Flush();
}
diff --git a/svdrp.c b/svdrp.c
index eec6869c..365e4a36 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.65 2004/10/31 10:09:53 kls Exp $
+ * $Id: svdrp.c 1.66 2004/12/19 13:52:34 kls Exp $
*/
#include "svdrp.h"
@@ -555,8 +555,9 @@ void cSVDRP::CmdGRAB(const char *Option)
char buf[strlen(Option) + 1];
char *p = strcpy(buf, Option);
const char *delim = " \t";
- FileName = strtok(p, delim);
- if ((p = strtok(NULL, delim)) != NULL) {
+ char *strtok_next;
+ FileName = strtok_r(p, delim, &strtok_next);
+ if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
if (strcasecmp(p, "JPEG") == 0)
Jpeg = true;
else if (strcasecmp(p, "PNM") == 0)
@@ -566,7 +567,7 @@ void cSVDRP::CmdGRAB(const char *Option)
return;
}
}
- if ((p = strtok(NULL, delim)) != NULL) {
+ if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
if (isnumber(p))
Quality = atoi(p);
else {
@@ -574,14 +575,14 @@ void cSVDRP::CmdGRAB(const char *Option)
return;
}
}
- if ((p = strtok(NULL, delim)) != NULL) {
+ if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
if (isnumber(p))
SizeX = atoi(p);
else {
Reply(501, "Illegal sizex \"%s\"", p);
return;
}
- if ((p = strtok(NULL, delim)) != NULL) {
+ if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
if (isnumber(p))
SizeY = atoi(p);
else {
@@ -594,7 +595,7 @@ void cSVDRP::CmdGRAB(const char *Option)
return;
}
}
- if ((p = strtok(NULL, delim)) != NULL) {
+ if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
Reply(501, "Unexpected parameter \"%s\"", p);
return;
}
@@ -727,7 +728,8 @@ void cSVDRP::CmdLSTE(const char *Option)
char buf[strlen(Option) + 1];
strcpy(buf, Option);
const char *delim = " \t";
- char *p = strtok(buf, delim);
+ char *strtok_next;
+ char *p = strtok_r(buf, delim, &strtok_next);
while (p && DumpMode == dmAll) {
if (strcasecmp(p, "NOW") == 0)
DumpMode = dmPresent;
@@ -735,7 +737,7 @@ void cSVDRP::CmdLSTE(const char *Option)
DumpMode = dmFollowing;
else if (strcasecmp(p, "AT") == 0) {
DumpMode = dmAtTime;
- if ((p = strtok(NULL, delim)) != NULL) {
+ if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
if (isnumber(p))
AtTime = strtol(p, NULL, 10);
else {
@@ -770,7 +772,7 @@ void cSVDRP::CmdLSTE(const char *Option)
Reply(501, "Unknown option: \"%s\"", p);
return;
}
- p = strtok(NULL, delim);
+ p = strtok_r(NULL, delim, &strtok_next);
}
}
FILE *f = fdopen(file, "w");
@@ -995,11 +997,8 @@ void cSVDRP::CmdNEXT(const char *Option)
if (t) {
time_t Start = t->StartTime();
int Number = t->Index() + 1;
- if (!*Option) {
- char *s = ctime(&Start);
- s[strlen(s) - 1] = 0; // strip trailing newline
- Reply(250, "%d %s", Number, s);
- }
+ if (!*Option)
+ Reply(250, "%d %s", Number, *cCtime(Start));
else if (strcasecmp(Option, "ABS") == 0)
Reply(250, "%d %ld", Number, Start);
else if (strcasecmp(Option, "REL") == 0)
@@ -1152,7 +1151,7 @@ bool cSVDRP::Process(void)
char buffer[BUFSIZ];
gethostname(buffer, sizeof(buffer));
time_t now = time(NULL);
- Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now));
+ Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, *cCtime(now));
}
if (NewConnection)
lastActivity = time(NULL);
diff --git a/themes.c b/themes.c
index 0a9b951d..b4bffea3 100644
--- a/themes.c
+++ b/themes.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: themes.c 1.3 2004/06/18 15:05:07 kls Exp $
+ * $Id: themes.c 1.4 2004/12/19 15:49:49 kls Exp $
*/
#include "themes.h"
@@ -96,7 +96,8 @@ bool cTheme::Load(const char *FileName, bool OnlyDescriptions)
result = true;
char *s;
const char *error = NULL;
- while ((s = readline(f)) != NULL) {
+ cReadLine ReadLine;
+ while ((s = ReadLine.Read(f)) != NULL) {
line++;
char *p = strchr(s, '#');
if (p)
@@ -242,29 +243,26 @@ bool cThemes::Load(const char *SkinName)
{
Clear();
if (themesDirectory) {
- DIR *d = opendir(themesDirectory);
- if (d) {
- struct dirent *e;
- while ((e = readdir(d)) != NULL) {
- if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
- if (strstr(e->d_name, SkinName) == e->d_name && e->d_name[strlen(SkinName)] == '-') {
- const char *FileName = AddDirectory(themesDirectory, e->d_name);
- cTheme Theme;
- if (Theme.Load(FileName, true)) {
- names = (char **)realloc(names, (numThemes + 1) * sizeof(char *));
- names[numThemes] = strdup(Theme.Name());
- fileNames = (char **)realloc(fileNames, (numThemes + 1) * sizeof(char *));
- fileNames[numThemes] = strdup(FileName);
- descriptions = (char **)realloc(descriptions, (numThemes + 1) * sizeof(char *));
- descriptions[numThemes] = strdup(Theme.Description());
- numThemes++;
- }
+ cReadDir d(themesDirectory);
+ struct dirent *e;
+ while ((e = d.Next()) != NULL) {
+ if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
+ if (strstr(e->d_name, SkinName) == e->d_name && e->d_name[strlen(SkinName)] == '-') {
+ cAddDirectory FileName(themesDirectory, e->d_name);
+ cTheme Theme;
+ if (Theme.Load(*FileName, true)) {
+ names = (char **)realloc(names, (numThemes + 1) * sizeof(char *));
+ names[numThemes] = strdup(Theme.Name());
+ fileNames = (char **)realloc(fileNames, (numThemes + 1) * sizeof(char *));
+ fileNames[numThemes] = strdup(*FileName);
+ descriptions = (char **)realloc(descriptions, (numThemes + 1) * sizeof(char *));
+ descriptions[numThemes] = strdup(Theme.Description());
+ numThemes++;
}
}
}
- closedir(d);
- return numThemes > 0;
- }
+ }
+ return numThemes > 0;
}
return false;
}
diff --git a/timers.c b/timers.c
index 921a2256..5c6ba70e 100644
--- a/timers.c
+++ b/timers.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: timers.c 1.19 2004/11/22 16:49:15 kls Exp $
+ * $Id: timers.c 1.20 2004/12/19 14:11:29 kls Exp $
*/
#include "timers.h"
@@ -111,7 +111,7 @@ const char *cTimer::ToText(bool UseChannelID)
free(buffer);
strreplace(file, ':', '|');
strreplace(summary, '\n', '|');
- asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? Channel()->GetChannelID().ToString() : itoa(Channel()->Number()), PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : "");
+ asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? Channel()->GetChannelID().ToString() : *cItoa(Channel()->Number()), PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : "");
strreplace(summary, '|', '\n');
strreplace(file, '|', ':');
return buffer;
diff --git a/tools.c b/tools.c
index 41d0c725..111b18c2 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.82 2004/11/21 14:36:34 kls Exp $
+ * $Id: tools.c 1.83 2004/12/19 16:08:50 kls Exp $
*/
#include "tools.h"
@@ -65,18 +65,6 @@ void writechar(int filedes, char c)
safe_write(filedes, &c, sizeof(c));
}
-char *readline(FILE *f)
-{
- static char buffer[MAXPARSEBUFFER];
- if (fgets(buffer, sizeof(buffer), f) > 0) {
- int l = strlen(buffer) - 1;
- if (l >= 0 && buffer[l] == '\n')
- buffer[l] = 0;
- return buffer;
- }
- return NULL;
-}
-
char *strcpyrealloc(char *dest, const char *src)
{
if (src) {
@@ -167,29 +155,6 @@ char *compactspace(char *s)
return s;
}
-const char *strescape(const char *s, const char *chars)
-{
- static char *buffer = NULL;
- const char *p = s;
- char *t = NULL;
- while (*p) {
- if (strchr(chars, *p)) {
- if (!t) {
- buffer = (char *)realloc(buffer, 2 * strlen(s) + 1);
- t = buffer + (p - s);
- s = strcpy(buffer, s);
- }
- *t++ = '\\';
- }
- if (t)
- *t++ = *p;
- p++;
- }
- if (t)
- *t = 0;
- return s;
-}
-
bool startswith(const char *s, const char *p)
{
while (*p) {
@@ -253,21 +218,6 @@ bool isnumber(const char *s)
return true;
}
-const char *itoa(int n)
-{
- static char buf[16];
- snprintf(buf, sizeof(buf), "%d", n);
- return buf;
-}
-
-const char *AddDirectory(const char *DirName, const char *FileName)
-{
- static char *buf = NULL;
- free(buf);
- asprintf(&buf, "%s/%s", DirName && *DirName ? DirName : ".", FileName);
- return buf;
-}
-
int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
{
if (UsedMB)
@@ -336,10 +286,10 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
struct stat st;
if (stat(FileName, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
- DIR *d = opendir(FileName);
- if (d) {
+ cReadDir d(FileName);
+ if (d.Ok()) {
struct dirent *e;
- while ((e = readdir(d)) != NULL) {
+ while ((e = d.Next()) != NULL) {
if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
char *buffer;
asprintf(&buffer, "%s/%s", FileName, e->d_name);
@@ -367,7 +317,6 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
free(buffer);
}
}
- closedir(d);
}
else {
LOG_ERROR_STR(FileName);
@@ -389,11 +338,11 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis)
{
- DIR *d = opendir(DirName);
- if (d) {
+ cReadDir d(DirName);
+ if (d.Ok()) {
bool empty = true;
struct dirent *e;
- while ((e = readdir(d)) != NULL) {
+ while ((e = d.Next()) != NULL) {
if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) {
char *buffer;
asprintf(&buffer, "%s/%s", DirName, e->d_name);
@@ -414,7 +363,6 @@ bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis)
free(buffer);
}
}
- closedir(d);
if (RemoveThis && empty) {
dsyslog("removing %s", DirName);
if (remove(DirName) < 0) {
@@ -451,7 +399,7 @@ char *ReadLink(const char *FileName)
bool SpinUpDisk(const char *FileName)
{
- static char *buf = NULL;
+ char *buf = NULL;
for (int n = 0; n < 10; n++) {
free(buf);
if (DirectoryOk(FileName))
@@ -471,12 +419,14 @@ bool SpinUpDisk(const char *FileName)
double seconds = (((long long)tp2.tv_sec * 1000000 + tp2.tv_usec) - ((long long)tp1.tv_sec * 1000000 + tp1.tv_usec)) / 1000000.0;
if (seconds > 0.5)
dsyslog("SpinUpDisk took %.2f seconds\n", seconds);
+ free(buf);
return true;
}
else
LOG_ERROR_STR(buf);
}
}
+ free(buf);
esyslog("ERROR: SpinUpDisk failed");
return false;
}
@@ -489,35 +439,119 @@ time_t LastModifiedTime(const char *FileName)
return 0;
}
-const char *WeekDayName(int WeekDay)
+// --- cBufferedStringFunction -----------------------------------------------
+
+cBufferedStringFunction::cBufferedStringFunction(void)
+{
+ buffer = NULL;
+ result = ""; // makes sure dereferencing it doesn't hurt
+}
+
+cBufferedStringFunction::~cBufferedStringFunction()
+{
+ free(buffer);
+}
+
+// --- cAddDirectory ---------------------------------------------------------
+
+cAddDirectory::cAddDirectory(const char *DirName, const char *FileName)
+{
+ asprintf(&buffer, "%s/%s", DirName && *DirName ? DirName : ".", FileName);
+ result = buffer;
+}
+
+// --- cStrEscape ------------------------------------------------------------
+
+cStrEscape::cStrEscape(const char *s, const char *chars)
+{
+ buffer = NULL;
+ const char *p = s;
+ char *t = NULL;
+ while (*p) {
+ if (strchr(chars, *p)) {
+ if (!t) {
+ buffer = (char *)realloc(buffer, 2 * strlen(s) + 1);
+ t = buffer + (p - s);
+ s = strcpy(buffer, s);
+ }
+ *t++ = '\\';
+ }
+ if (t)
+ *t++ = *p;
+ p++;
+ }
+ if (t)
+ *t = 0;
+ result = s;
+}
+
+// --- cCtime ----------------------------------------------------------------
+
+cCtime::cCtime(time_t Time)
+{
+ if (ctime_r(&Time, buffer)) {
+ buffer[strlen(buffer) - 1] = 0; // strip trailing newline
+ result = buffer;
+ }
+}
+
+// --- cItoa -----------------------------------------------------------------
+
+cItoa::cItoa(int n)
+{
+ snprintf(buffer, sizeof(buffer), "%d", n);
+ result = buffer;
+}
+
+// --- cWeekDayName ----------------------------------------------------------
+
+cWeekDayName::cWeekDayName(int WeekDay)
+{
+ WeekDayName(WeekDay);
+}
+
+cWeekDayName::cWeekDayName(time_t t)
+{
+ struct tm tm_r;
+ WeekDayName(localtime_r(&t, &tm_r)->tm_wday);
+}
+
+void cWeekDayName::WeekDayName(int WeekDay)
{
- static char buffer[4];
WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with monday==0!
if (0 <= WeekDay && WeekDay <= 6) {
const char *day = tr("MonTueWedThuFriSatSun");
day += WeekDay * 3;
- strncpy(buffer, day, 3);
- return buffer;
+ strn0cpy(buffer, day, sizeof(buffer));
+ result = buffer;
}
else
- return "???";
+ result = "???";
}
-const char *WeekDayName(time_t t)
-{
- struct tm tm_r;
- return WeekDayName(localtime_r(&t, &tm_r)->tm_wday);
-}
+// --- cDayDateTime ----------------------------------------------------------
-const char *DayDateTime(time_t t)
+cDayDateTime::cDayDateTime(time_t t)
{
- static char buffer[32];
if (t == 0)
time(&t);
struct tm tm_r;
tm *tm = localtime_r(&t, &tm_r);
- snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d", WeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
- return buffer;
+ snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d", *cWeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
+ result = buffer;
+}
+
+// --- cReadLine -------------------------------------------------------------
+
+char *cReadLine::Read(FILE *f)
+{
+ if (fgets(buffer, sizeof(buffer), f) > 0) {
+ int l = strlen(buffer) - 1;
+ if (l >= 0 && buffer[l] == '\n')
+ buffer[l] = 0;
+ return buffer;
+ }
+ return NULL;
}
// --- cPoller ---------------------------------------------------------------
@@ -557,6 +591,24 @@ bool cPoller::Poll(int TimeoutMs)
return false;
}
+// --- cReadDir --------------------------------------------------------------
+
+cReadDir::cReadDir(const char *Directory)
+{
+ directory = opendir(Directory);
+}
+
+cReadDir::~cReadDir()
+{
+ if (directory)
+ closedir(directory);
+}
+
+struct dirent *cReadDir::Next(void)
+{
+ return directory && readdir_r(directory, &u.d, &result) == 0 ? result : NULL;
+}
+
// --- cFile -----------------------------------------------------------------
bool cFile::files[FD_SETSIZE] = { false };
diff --git a/tools.h b/tools.h
index 9e0abff4..bbbd5704 100644
--- a/tools.h
+++ b/tools.h
@@ -4,14 +4,16 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.h 1.58 2004/10/31 16:16:37 kls Exp $
+ * $Id: tools.h 1.59 2004/12/19 14:49:48 kls Exp $
*/
#ifndef __TOOLS_H
#define __TOOLS_H
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <objalloc.h>
#include <poll.h>
#include <stdio.h>
#include <string.h>
@@ -58,7 +60,6 @@ int BCD2INT(int x);
ssize_t safe_read(int filedes, void *buffer, size_t size);
ssize_t safe_write(int filedes, const void *buffer, size_t size);
void writechar(int filedes, char c);
-char *readline(FILE *f);
char *strcpyrealloc(char *dest, const char *src);
char *strn0cpy(char *dest, const char *src, size_t n);
char *strreplace(char *s, char c1, char c2);
@@ -66,7 +67,6 @@ char *strreplace(char *s, const char *s1, const char *s2); ///< re-allocates 's'
char *skipspace(const char *s);
char *stripspace(char *s);
char *compactspace(char *s);
-const char *strescape(const char *s, const char *chars); ///< \warning returns a statically allocated string!
bool startswith(const char *s, const char *p);
bool endswith(const char *s, const char *p);
bool isempty(const char *s);
@@ -74,8 +74,6 @@ int numdigits(int n);
int time_ms(void);
void delay_ms(int ms);
bool isnumber(const char *s);
-const char *itoa(int n); ///< \warning returns a statically allocated string!
-const char *AddDirectory(const char *DirName, const char *FileName); ///< \warning returns a statically allocated string!
int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL);
bool DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = false);
@@ -84,9 +82,65 @@ bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false);
char *ReadLink(const char *FileName);
bool SpinUpDisk(const char *FileName);
time_t LastModifiedTime(const char *FileName);
-const char *WeekDayName(int WeekDay); ///< \warning returns a statically allocated string!
-const char *WeekDayName(time_t t); ///< \warning returns a statically allocated string!
-const char *DayDateTime(time_t t = 0); ///< \warning returns a statically allocated string!
+
+class cBufferedStringFunction {
+protected:
+ char *buffer;
+ const char *result;
+public:
+ cBufferedStringFunction(void);
+ virtual ~cBufferedStringFunction();
+ const char * operator * () { return result; }
+ };
+
+template<int size> class cBufferedStringFunctionFix : public cBufferedStringFunction {
+protected:
+ char buffer[size];
+ const char *result;
+public:
+ cBufferedStringFunctionFix(void) { result = ""; } // makes sure dereferencing it doesn't hurt
+ const char * operator * () { return result; }
+ };
+
+class cAddDirectory : public cBufferedStringFunction {
+public:
+ cAddDirectory(const char *DirName, const char *FileName);
+ };
+
+class cStrEscape : public cBufferedStringFunction {
+public:
+ cStrEscape(const char *s, const char *chars);
+ };
+
+class cCtime : public cBufferedStringFunctionFix<32> {
+public:
+ cCtime(time_t Time);
+ };
+
+class cItoa : public cBufferedStringFunctionFix<16> {
+public:
+ cItoa(int n);
+ };
+
+class cWeekDayName : public cBufferedStringFunctionFix<4> {
+private:
+ void WeekDayName(int WeekDay);
+public:
+ cWeekDayName(int WeekDay);
+ cWeekDayName(time_t t);
+ };
+
+class cDayDateTime : public cBufferedStringFunctionFix<32> {
+public:
+ cDayDateTime(time_t t = 0);
+ };
+
+class cReadLine {
+private:
+ char buffer[MAXPARSEBUFFER];
+public:
+ char *Read(FILE *f);
+ };
class cPoller {
private:
@@ -99,6 +153,21 @@ public:
bool Poll(int TimeoutMs = 0);
};
+class cReadDir {
+private:
+ DIR *directory;
+ struct dirent *result;
+ union { // according to "The GNU C Library Reference Manual"
+ struct dirent d;
+ char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
+ } u;
+public:
+ cReadDir(const char *Directory);
+ ~cReadDir();
+ bool Ok(void) { return directory != NULL; }
+ struct dirent *Next(void);
+ };
+
class cFile {
private:
static bool files[];
diff --git a/vdr.c b/vdr.c
index 664cc7d3..2276e7e8 100644
--- a/vdr.c
+++ b/vdr.c
@@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/vdr
*
- * $Id: vdr.c 1.194 2004/12/05 13:20:29 kls Exp $
+ * $Id: vdr.c 1.195 2004/12/19 15:28:34 kls Exp $
*/
#include <getopt.h>
@@ -384,19 +384,19 @@ int main(int argc, char *argv[])
ConfigDirectory = VideoDirectory;
cPlugin::SetConfigDirectory(ConfigDirectory);
- cThemes::SetThemesDirectory(AddDirectory(ConfigDirectory, "themes"));
-
- Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
- if (!(Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true) &&
- Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC) &&
- Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true) &&
- Timers.Load(AddDirectory(ConfigDirectory, "timers.conf")) &&
- Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"), true) &&
- RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"), true) &&
- SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true) &&
- CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true) &&
- Keys.Load(AddDirectory(ConfigDirectory, "remote.conf")) &&
- KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true)
+ cThemes::SetThemesDirectory(*cAddDirectory(ConfigDirectory, "themes"));
+
+ Setup.Load(*cAddDirectory(ConfigDirectory, "setup.conf"));
+ if (!(Sources.Load(*cAddDirectory(ConfigDirectory, "sources.conf"), true, true) &&
+ Diseqcs.Load(*cAddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC) &&
+ Channels.Load(*cAddDirectory(ConfigDirectory, "channels.conf"), false, true) &&
+ Timers.Load(*cAddDirectory(ConfigDirectory, "timers.conf")) &&
+ Commands.Load(*cAddDirectory(ConfigDirectory, "commands.conf"), true) &&
+ RecordingCommands.Load(*cAddDirectory(ConfigDirectory, "reccmds.conf"), true) &&
+ SVDRPhosts.Load(*cAddDirectory(ConfigDirectory, "svdrphosts.conf"), true) &&
+ CaDefinitions.Load(*cAddDirectory(ConfigDirectory, "ca.conf"), true) &&
+ Keys.Load(*cAddDirectory(ConfigDirectory, "remote.conf")) &&
+ KeyMacros.Load(*cAddDirectory(ConfigDirectory, "keymacros.conf"), true)
))
EXIT(2);
@@ -405,13 +405,16 @@ int main(int argc, char *argv[])
// EPG data:
if (EpgDataFileName) {
- if (DirectoryOk(EpgDataFileName))
- EpgDataFileName = AddDirectory(EpgDataFileName, DEFAULTEPGDATAFILENAME);
+ const char *EpgDirectory = NULL;
+ if (DirectoryOk(EpgDataFileName)) {
+ EpgDirectory = EpgDataFileName;
+ EpgDataFileName = DEFAULTEPGDATAFILENAME;
+ }
else if (*EpgDataFileName != '/' && *EpgDataFileName != '.')
- EpgDataFileName = AddDirectory(VideoDirectory, EpgDataFileName);
+ EpgDirectory = VideoDirectory;
+ cSchedules::SetEpgDataFileName(*cAddDirectory(EpgDirectory, EpgDataFileName));
+ cSchedules::Read();
}
- cSchedules::SetEpgDataFileName(EpgDataFileName);
- cSchedules::Read();
// DVB interfaces:
@@ -867,7 +870,7 @@ int main(int argc, char *argv[])
if (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown) {
ForceShutdown = false;
if (timer)
- dsyslog("next timer event at %s", ctime(&Next));
+ dsyslog("next timer event at %s", *cCtime(Next));
if (WatchdogTimeout > 0)
signal(SIGALRM, SIG_IGN);
if (Interface->Confirm(tr("Press any key to cancel shutdown"), UserShutdown ? 5 : SHUTDOWNWAIT, true)) {
@@ -875,7 +878,7 @@ int main(int argc, char *argv[])
const char *File = timer ? timer->File() : "";
Delta = Next - time(NULL); // compensates for Confirm() timeout
char *cmd;
- asprintf(&cmd, "%s %ld %ld %d \"%s\" %d", Shutdown, Next, Delta, Channel, strescape(File, "\"$"), UserShutdown);
+ asprintf(&cmd, "%s %ld %ld %d \"%s\" %d", Shutdown, Next, Delta, Channel, *cStrEscape(File, "\"$"), UserShutdown);
isyslog("executing '%s'", cmd);
SystemExec(cmd);
free(cmd);