diff --git a/ChangeLog b/ChangeLog index 9ed6f384b..4be9a63a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ +2003-08-31 Adam Fedor + + * Tools/gdnc.m (main): Close any open file descriptors so we can + be a proper daemon. + Fixes #4938. + 2003-08-29 Adam Fedor - * config/procfs.m4: Disalbe procfs for solaris + * config/procfs.m4: Disable procfs for solaris 2003-08-26 Adam Fedor diff --git a/Tools/gdnc.m b/Tools/gdnc.m index 3f48dab8d..442cd97fb 100644 --- a/Tools/gdnc.m +++ b/Tools/gdnc.m @@ -28,12 +28,77 @@ #include "process.h" #endif +#include +#ifdef HAVE_SYSLOG_H +#include +#endif + #include #ifndef NSIG #define NSIG 32 #endif +static int is_daemon = 0; /* Currently running as daemon. */ +static char ebuf[2048]; + +#ifdef HAVE_SYSLOG + +static int log_priority; + +static void +gdnc_log (int prio) +{ + if (is_daemon) + { + syslog (log_priority | prio, ebuf); + } + else if (prio == LOG_INFO) + { + write (1, ebuf, strlen (ebuf)); + write (1, "\n", 1); + } + else + { + write (2, ebuf, strlen (ebuf)); + write (2, "\n", 1); + } + + if (prio == LOG_CRIT) + { + if (is_daemon) + { + syslog (LOG_CRIT, "exiting."); + } + else + { + fprintf (stderr, "exiting.\n"); + fflush (stderr); + } + exit(EXIT_FAILURE); + } +} +#else + +#define LOG_CRIT 2 +#define LOG_DEBUG 0 +#define LOG_ERR 1 +#define LOG_INFO 0 +#define LOG_WARNING 0 +void +gdnc_log (int prio) +{ + write (2, ebuf, strlen (ebuf)); + write (2, "\n", 1); + if (prio == LOG_CRIT) + { + fprintf (stderr, "exiting.\n"); + fflush (stderr); + exit(EXIT_FAILURE); + } +} +#endif + static void ihandler(int sig) { @@ -909,6 +974,7 @@ ihandler(int sig) int main(int argc, char** argv, char** env) { + int c; GDNCServer *server; NSString *str; BOOL shouldFork = YES; @@ -948,6 +1014,7 @@ main(int argc, char** argv, char** env) #else if (shouldFork) { + is_daemon = 1; switch (fork()) { case -1: @@ -971,6 +1038,41 @@ main(int argc, char** argv, char** env) } #endif /* !MINGW */ + /* + * Ensure we don't have any open file descriptors which may refer + * to sockets bound to ports we may try to use. + * + * Use '/dev/null' for stdin and stdout. + */ + for (c = 0; c < FD_SETSIZE; c++) + { + if (is_daemon || (c != 2)) + { + (void)close(c); + } + } + if (open("/dev/null", O_RDONLY) != 0) + { + sprintf(ebuf, "failed to open stdin from /dev/null (%s)\n", + strerror(errno)); + gdnc_log(LOG_CRIT); + exit(EXIT_FAILURE); + } + if (open("/dev/null", O_WRONLY) != 1) + { + sprintf(ebuf, "failed to open stdout from /dev/null (%s)\n", + strerror(errno)); + gdnc_log(LOG_CRIT); + exit(EXIT_FAILURE); + } + if (is_daemon && open("/dev/null", O_WRONLY) != 2) + { + sprintf(ebuf, "failed to open stderr from /dev/null (%s)\n", + strerror(errno)); + gdnc_log(LOG_CRIT); + exit(EXIT_FAILURE); + } + { #if GS_WITH_GC == 0 CREATE_AUTORELEASE_POOL(pool);