Switched to PES recording

This commit is contained in:
Klaus Schmidinger 2000-12-08 16:23:32 +01:00
parent c8a1be81af
commit 6b0658a977
15 changed files with 406 additions and 575 deletions

View File

@ -312,8 +312,15 @@ Video Disk Recorder Revision History
an early state and may still cause some problems, but it appears to work nice an early state and may still cause some problems, but it appears to work nice
already. already.
2000-12-01: Version 0.69 2000-12-08: Version 0.70
- VDR now requires driver version 0.80 or higher.
- Recordings are now saved in PES mode. Note that you now need to install the
driver *WITHOUT* 'outstream=0'! This is the default when you 'make insmod' in
the DVB/driver directory.
Old recordings (in AV_PES mode) can still be replayed (as long as the driver
still supports replaying AV_PES files). The only limitation with this is that
in fast forward/back mode the picture may be slightly distorted.
- The EPG data is now dumped into the file /video/epg.data every ten minutes. - The EPG data is now dumped into the file /video/epg.data every ten minutes.
Use the Perl script 'epg2html.pl' to convert the raw EPG data into a simple Use the Perl script 'epg2html.pl' to convert the raw EPG data into a simple
HTML programme listing. HTML programme listing.

12
INSTALL
View File

@ -15,13 +15,11 @@ If you have the DVB driver source in a different location
you will have to change the definition of DVBDIR in the you will have to change the definition of DVBDIR in the
Makefile. Makefile.
This program requires the card driver version 0.71 or higher This program requires the card driver version 0.80 or higher
to work properly. Currently you need to load the dvb.o module with to work properly. You need to load the dvb.o module *without* option
option outstream=0, so your insmod statement should read 'outstream=0' (previous versions of VDR required this option to have
'insmod dvb.o outstream=0'. This is necessary because 'vdr' works the driver supply the data in AV_PES format; as of version 0.70 VDR
with AV_PES data and will change once it has been modified to work works with PES format).
directly with MPEG2. You also need to apply the patch 'dvb.c.071.diff'
for the On Screen Display to work properly.
After extracting the package, change into the VDR directory After extracting the package, change into the VDR directory
and type 'make'. This should produce an executable file and type 'make'. This should produce an executable file

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 1.16 2000/11/18 14:58:10 kls Exp $ # $Id: Makefile 1.17 2000/12/03 15:24:20 kls Exp $
DVBDIR = ../DVB DVBDIR = ../DVB
@ -39,7 +39,7 @@ font: genfontfile fontfix.c fontosd.c
config.o : config.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h config.o : config.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h videodir.h dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h videodir.h
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
eit.o : eit.c eit.h thread.h tools.h eit.o : eit.c config.h dvbapi.h dvbosd.h eit.h font.h thread.h tools.h videodir.h
font.o : font.c font.h fontfix.c fontosd.c tools.h font.o : font.c font.h fontfix.c fontosd.c tools.h
i18n.o : i18n.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h thread.h tools.h i18n.o : i18n.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h thread.h tools.h
interface.o: interface.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h interface.o: interface.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
@ -48,7 +48,7 @@ osd.o : osd.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h os
recording.o: recording.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h recording.o: recording.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
remote.o : remote.c config.h dvbapi.h dvbosd.h eit.h font.h remote.h thread.h tools.h remote.o : remote.c config.h dvbapi.h dvbosd.h eit.h font.h remote.h thread.h tools.h
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h
thread.o : thread.c thread.h thread.o : thread.c thread.h tools.h
tools.o : tools.c tools.h tools.o : tools.c tools.h
vdr.o : vdr.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h vdr.o : vdr.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
videodir.o : videodir.c tools.h videodir.h videodir.o : videodir.c tools.h videodir.h

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.h 1.34 2000/11/18 13:25:53 kls Exp $ * $Id: config.h 1.35 2000/12/08 13:57:23 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -18,7 +18,7 @@
#include "eit.h" #include "eit.h"
#include "tools.h" #include "tools.h"
#define VDRVERSION "0.68" #define VDRVERSION "0.70"
#define MaxBuffer 10000 #define MaxBuffer 10000

709
dvbapi.c

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.h 1.26 2000/11/19 14:09:41 kls Exp $ * $Id: dvbapi.h 1.27 2000/12/03 13:44:28 kls Exp $
*/ */
#ifndef __DVBAPI_H #ifndef __DVBAPI_H
@ -42,6 +42,8 @@ public:
bool Save(int Index); bool Save(int Index);
}; };
class cRecordBuffer;
class cReplayBuffer;
class cTransferBuffer; class cTransferBuffer;
class cDvbApi { class cDvbApi {
@ -171,20 +173,10 @@ private:
// Record/Replay facilities // Record/Replay facilities
private: private:
enum { dvbStop = 1, // let's not have 0 as a command cRecordBuffer *recordBuffer;
dvbPause, cReplayBuffer *replayBuffer;
dvbPlay,
dvbForward,
dvbBackward,
dvbSkip,
dvbGetIndex,
};
pid_t pidRecord, pidReplay;
int fromRecord, toRecord;
int fromReplay, toReplay;
int ca; int ca;
int priority; int priority;
void SetReplayMode(int Mode);
protected: protected:
int Ca(void) { return ca; } int Ca(void) { return ca; }
// Returns the ca of the current recording session (0..MAXDVBAPI). // Returns the ca of the current recording session (0..MAXDVBAPI).
@ -214,7 +206,7 @@ public:
// If there is already a replay session active, it will be stopped // If there is already a replay session active, it will be stopped
// and the new file will be played back. // and the new file will be played back.
// If provided Title will be used in the progress display. // If provided Title will be used in the progress display.
void Stop(void); void StopReplay(void);
// Stops the current replay session (if any). // Stops the current replay session (if any).
void Pause(void); void Pause(void);
// Pauses the current replay session, or resumes a paused session. // Pauses the current replay session, or resumes a paused session.
@ -229,7 +221,7 @@ public:
// The sign of 'Seconds' determines the direction in which to skip. // The sign of 'Seconds' determines the direction in which to skip.
// Use a very large negative value to go all the way back to the // Use a very large negative value to go all the way back to the
// beginning of the recording. // beginning of the recording.
bool GetIndex(int *Current, int *Total = NULL); bool GetIndex(int &Current, int &Total);
}; };
class cEITScanner { class cEITScanner {

6
eit.c
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: eit.c 1.10 2000/11/25 12:51:06 kls Exp $ * $Id: eit.c 1.11 2000/12/03 15:33:37 kls Exp $
***************************************************************************/ ***************************************************************************/
#include "eit.h" #include "eit.h"
@ -131,7 +131,7 @@ bool cMJD::SetSystemTime()
isyslog(LOG_INFO, "System Time = %s (%ld)\n", ctime(&loctim), loctim); isyslog(LOG_INFO, "System Time = %s (%ld)\n", ctime(&loctim), loctim);
isyslog(LOG_INFO, "Local Time = %s (%ld)\n", ctime(&mjdtime), mjdtime); isyslog(LOG_INFO, "Local Time = %s (%ld)\n", ctime(&mjdtime), mjdtime);
if (stime(&mjdtime) < 0) if (stime(&mjdtime) < 0)
esyslog(LOG_ERR, "ERROR while setting system time: %s", strerror(errno)); esyslog(LOG_ERR, "ERROR while setting system time: %m");
return true; return true;
} }
@ -1117,7 +1117,7 @@ cSIProcessor::~cSIProcessor()
{ {
if (fsvbi >= 0) if (fsvbi >= 0)
{ {
Stop(); Cancel();
ShutDownFilters(); ShutDownFilters();
delete filters; delete filters;
if (!--numSIProcessors) // the last one deletes it if (!--numSIProcessors) // the last one deletes it

6
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.53 2000/11/26 16:15:30 kls Exp $ * $Id: menu.c 1.54 2000/12/03 11:43:35 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -2009,7 +2009,7 @@ cReplayControl::cReplayControl(void)
cReplayControl::~cReplayControl() cReplayControl::~cReplayControl()
{ {
Hide(); Hide();
dvbApi->Stop(); dvbApi->StopReplay();
} }
void cReplayControl::SetRecording(const char *FileName, const char *Title) void cReplayControl::SetRecording(const char *FileName, const char *Title)
@ -2060,7 +2060,7 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
case kUp: dvbApi->Play(); break; case kUp: dvbApi->Play(); break;
case kDown: dvbApi->Pause(); break; case kDown: dvbApi->Pause(); break;
case kBlue: Hide(); case kBlue: Hide();
dvbApi->Stop(); dvbApi->StopReplay();
return osEnd; return osEnd;
case kLeft: dvbApi->Backward(); break; case kLeft: dvbApi->Backward(); break;
case kRight: dvbApi->Forward(); break; case kRight: dvbApi->Forward(); break;

View File

@ -6,7 +6,7 @@
* *
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16. * Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
* *
* $Id: remote.c 1.19 2000/11/11 11:22:22 kls Exp $ * $Id: remote.c 1.20 2000/12/03 11:55:06 kls Exp $
*/ */
#include "remote.h" #include "remote.h"
@ -115,7 +115,7 @@ cRcIoRCU::cRcIoRCU(char *DeviceName)
cRcIoRCU::~cRcIoRCU() cRcIoRCU::~cRcIoRCU()
{ {
Stop(); Cancel();
} }
void cRcIoRCU::Action(void) void cRcIoRCU::Action(void)
@ -420,7 +420,7 @@ cRcIoLIRC::cRcIoLIRC(char *DeviceName)
cRcIoLIRC::~cRcIoLIRC() cRcIoLIRC::~cRcIoLIRC()
{ {
Stop(); Cancel();
} }
void cRcIoLIRC::Action(void) void cRcIoLIRC::Action(void)

View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * graphical interface that sits on top of an SVDRP connection.
* *
* $Id: svdrp.c 1.12 2000/11/05 13:44:42 kls Exp $ * $Id: svdrp.c 1.13 2000/12/03 15:34:35 kls Exp $
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
@ -18,6 +18,7 @@
#include "svdrp.h" #include "svdrp.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdarg.h> #include <stdarg.h>

View File

@ -4,12 +4,15 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.c 1.5 2000/11/22 17:11:04 kls Exp $ * $Id: thread.c 1.6 2000/12/03 15:35:02 kls Exp $
*/ */
#include "thread.h" #include "thread.h"
#include <errno.h>
#include <signal.h> #include <signal.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include "tools.h"
// --- cThread --------------------------------------------------------------- // --- cThread ---------------------------------------------------------------
@ -25,7 +28,7 @@ cThread::cThread(void)
signalHandlerInstalled = true; signalHandlerInstalled = true;
} }
running = false; running = false;
parentPid = lockingPid = 0; parentPid = threadPid = lockingPid = 0;
locked = 0; locked = 0;
} }
@ -40,6 +43,7 @@ void cThread::SignalHandler(int signum)
void *cThread::StartThread(cThread *Thread) void *cThread::StartThread(cThread *Thread)
{ {
Thread->threadPid = getpid();
Thread->Action(); Thread->Action();
return NULL; return NULL;
} }
@ -54,8 +58,31 @@ bool cThread::Start(void)
return true; //XXX return value of pthread_create()??? return true; //XXX return value of pthread_create()???
} }
void cThread::Stop(void) bool cThread::Active(void)
{ {
if (threadPid) {
if (kill(threadPid, SIGIO) < 0) { // couldn't find another way of checking whether the thread is still running - any ideas?
if (errno == ESRCH)
threadPid = 0;
else
LOG_ERROR;
}
else
return true;
}
return false;
}
void cThread::Cancel(int WaitSeconds)
{
if (WaitSeconds > 0) {
for (time_t t0 = time(NULL) + WaitSeconds; time(NULL) < t0; ) {
if (!Active())
return;
usleep(10000);
}
esyslog(LOG_ERR, "ERROR: thread %d won't end (waited %d seconds) - cancelling it...", threadPid, WaitSeconds);
}
pthread_cancel(thread); pthread_cancel(thread);
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.h 1.3 2000/11/14 18:38:11 kls Exp $ * $Id: thread.h 1.4 2000/12/03 11:18:37 kls Exp $
*/ */
#ifndef __THREAD_H #ifndef __THREAD_H
@ -28,7 +28,7 @@ class cThread {
private: private:
pthread_t thread; pthread_t thread;
cMutex Mutex; cMutex Mutex;
pid_t parentPid, lockingPid; pid_t parentPid, threadPid, lockingPid;
int locked; int locked;
bool running; bool running;
static bool signalHandlerInstalled; static bool signalHandlerInstalled;
@ -39,11 +39,12 @@ private:
protected: protected:
void WakeUp(void); void WakeUp(void);
virtual void Action(void) = 0; virtual void Action(void) = 0;
void Stop(void); void Cancel(int WaitSeconds = 0);
public: public:
cThread(void); cThread(void);
virtual ~cThread(); virtual ~cThread();
bool Start(void); bool Start(void);
bool Active(void);
}; };
// cThreadLock can be used to easily set a lock in a thread and make absolutely // cThreadLock can be used to easily set a lock in a thread and make absolutely

65
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 1.23 2000/11/11 15:17:12 kls Exp $ * $Id: tools.c 1.24 2000/12/03 15:39:11 kls Exp $
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
@ -15,10 +15,7 @@
#if defined(DEBUG_OSD) #if defined(DEBUG_OSD)
#include <ncurses.h> #include <ncurses.h>
#endif #endif
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#define MaxBuffer 1000 #define MaxBuffer 1000
@ -30,29 +27,6 @@ void writechar(int filedes, char c)
write(filedes, &c, sizeof(c)); write(filedes, &c, sizeof(c));
} }
void writeint(int filedes, int n)
{
write(filedes, &n, sizeof(n));
}
char readchar(int filedes)
{
char c;
read(filedes, &c, 1);
return c;
}
bool readint(int filedes, int &n)
{
return cFile::AnyFileReady(filedes, 0) && read(filedes, &n, sizeof(n)) == sizeof(n);
}
void purge(int filedes)
{
while (cFile::AnyFileReady(filedes, 0))
readchar(filedes);
}
char *readline(FILE *f) char *readline(FILE *f)
{ {
static char buffer[MaxBuffer]; static char buffer[MaxBuffer];
@ -205,7 +179,7 @@ bool MakeDirs(const char *FileName, bool IsDirectory)
if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) { if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
dsyslog(LOG_INFO, "creating directory %s", s); dsyslog(LOG_INFO, "creating directory %s", s);
if (mkdir(s, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) { if (mkdir(s, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) {
esyslog(LOG_ERR, "ERROR: %s: %s", s, strerror(errno)); LOG_ERROR_STR(s);
result = false; result = false;
break; break;
} }
@ -271,41 +245,6 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
return false; return false;
} }
bool CheckProcess(pid_t pid)
{
pid_t Pid2Check = pid;
int status;
pid = waitpid(Pid2Check, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return false;
}
return true;
}
void KillProcess(pid_t pid, int Timeout)
{
pid_t Pid2Wait4 = pid;
for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
int status;
pid_t pid = waitpid(Pid2Wait4, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return;
}
if (pid == Pid2Wait4)
return;
}
esyslog(LOG_ERR, "ERROR: process %d won't end (waited %d seconds) - terminating it...", Pid2Wait4, Timeout);
if (kill(Pid2Wait4, SIGTERM) < 0) {
esyslog(LOG_ERR, "ERROR: process %d won't terminate (%s) - killing it...", Pid2Wait4, strerror(errno));
if (kill(Pid2Wait4, SIGKILL) < 0)
esyslog(LOG_ERR, "ERROR: process %d won't die (%s) - giving up", Pid2Wait4, strerror(errno));
}
}
// --- cFile ----------------------------------------------------------------- // --- cFile -----------------------------------------------------------------
bool cFile::files[FD_SETSIZE] = { false }; bool cFile::files[FD_SETSIZE] = { false };

15
tools.h
View File

@ -4,13 +4,13 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.20 2000/11/12 15:27:06 kls Exp $ * $Id: tools.h 1.21 2000/12/03 15:32:54 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
#define __TOOLS_H #define __TOOLS_H
#include <errno.h> //#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -24,19 +24,14 @@ extern int SysLogLevel;
#define isyslog if (SysLogLevel > 1) syslog #define isyslog if (SysLogLevel > 1) syslog
#define dsyslog if (SysLogLevel > 2) syslog #define dsyslog if (SysLogLevel > 2) syslog
#define LOG_ERROR esyslog(LOG_ERR, "ERROR (%s,%d): %s", __FILE__, __LINE__, strerror(errno)) #define LOG_ERROR esyslog(LOG_ERR, "ERROR (%s,%d): %m", __FILE__, __LINE__)
#define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %s", s, strerror(errno)); #define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %m", s)
#define SECSINDAY 86400 #define SECSINDAY 86400
#define MAXPROCESSTIMEOUT 3 // seconds
#define DELETENULL(p) (delete (p), p = NULL) #define DELETENULL(p) (delete (p), p = NULL)
void writechar(int filedes, char c); void writechar(int filedes, char c);
void writeint(int filedes, int n);
char readchar(int filedes);
bool readint(int filedes, int &n);
void purge(int filedes);
char *readline(FILE *f); char *readline(FILE *f);
char *strn0cpy(char *dest, const char *src, size_t n); char *strn0cpy(char *dest, const char *src, size_t n);
char *strreplace(char *s, char c1, char c2); char *strreplace(char *s, char c1, char c2);
@ -51,8 +46,6 @@ uint FreeDiskSpaceMB(const char *Directory);
bool DirectoryOk(const char *DirName, bool LogErrors = false); bool DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = false); bool MakeDirs(const char *FileName, bool IsDirectory = false);
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false); bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
bool CheckProcess(pid_t pid);
void KillProcess(pid_t pid, int Timeout = MAXPROCESSTIMEOUT);
class cFile { class cFile {
private: private:

6
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/people/kls/vdr * The project's page is at http://www.cadsoft.de/people/kls/vdr
* *
* $Id: vdr.c 1.46 2000/11/18 13:46:56 kls Exp $ * $Id: vdr.c 1.47 2000/12/03 15:36:46 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -141,8 +141,8 @@ int main(int argc, char *argv[])
#if !defined(DEBUG_OSD) && !defined(REMOTE_KBD) #if !defined(DEBUG_OSD) && !defined(REMOTE_KBD)
pid_t pid = fork(); pid_t pid = fork();
if (pid < 0) { if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno)); fprintf(stderr, "%m\n");
esyslog(LOG_ERR, "ERROR: %s", strerror(errno)); esyslog(LOG_ERR, "ERROR: %m");
abort(); abort();
} }
if (pid != 0) if (pid != 0)