diff -Naur inetutils-1.9.2-orig/libinetutils/daemon.c inetutils-1.9.2/libinetutils/daemon.c --- inetutils-1.9.2-orig/libinetutils/daemon.c 2013-12-03 17:57:44.000000000 +0300 +++ inetutils-1.9.2/libinetutils/daemon.c 2014-12-12 11:55:11.043600000 +0300 @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -103,13 +104,87 @@ #define MAXFD 64 -void +/* copy signal stuff from inetd.c -- POSIX says that the various + signal interfaces should not be mixed in the same program. + Because inetd uses 'most recent signal interface' it can find, + we should too. +*/ + +#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) +#if defined(HAVE_SIGACTION) +# define SIGSTATUS sigset_t +# define sigstatus_empty(s) sigemptyset(&s) +#else +# define SIGSTATUS long +# define sigstatus_empty(s) s = 0 +#endif + +static void +signal_set_handler (int signo, RETSIGTYPE (*handler) ()) +{ +#if defined(HAVE_SIGACTION) + struct sigaction sa; + memset ((char *)&sa, 0, sizeof(sa)); + sigemptyset (&sa.sa_mask); + sigaddset (&sa.sa_mask, signo); +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif + sa.sa_handler = handler; + sigaction (signo, &sa, NULL); +#elif defined(HAVE_SIGVEC) + struct sigvec sv; + memset (&sv, 0, sizeof(sv)); + sv.sv_mask = SIGBLOCK; + sv.sv_handler = handler; + sigvec (signo, &sv, NULL); +#else /* !HAVE_SIGVEC */ + signal (signo, handler); +#endif /* HAVE_SIGACTION */ +} + +static void +signal_block (SIGSTATUS *old_status) +{ +#ifdef HAVE_SIGACTION + sigset_t sigs; + + sigemptyset (&sigs); + sigaddset (&sigs, SIGCHLD); + sigaddset (&sigs, SIGHUP); + sigaddset (&sigs, SIGALRM); + sigprocmask (SIG_BLOCK, &sigs, old_status); +#else + long omask = sigblock (SIGBLOCK); + if (old_status) + *old_status = omask; +#endif +} + +static void +signal_unblock (SIGSTATUS *status) +{ +#ifdef HAVE_SIGACTION + if (status) + sigprocmask (SIG_SETMASK, status, 0); + else + { + sigset_t empty; + sigemptyset (&empty); + sigprocmask (SIG_SETMASK, &empty, 0); + } +#else + sigsetmask (status ? *status : 0); +#endif +} + +RETSIGTYPE waitdaemon_timeout (int signo _GL_UNUSED_PARAMETER) { int left; left = alarm (0); - signal (SIGALRM, SIG_DFL); + signal_set_handler (SIGALRM, SIG_DFL); if (left == 0) error (EXIT_FAILURE, 0, "timed out waiting for child"); } @@ -138,9 +213,29 @@ default: /* In the parent. */ if (maxwait > 0) { - signal (SIGALRM, waitdaemon_timeout); + int status; + pid_t wpid; + + signal_unblock(NULL); + signal_set_handler (SIGALRM, waitdaemon_timeout); alarm (maxwait); - pause (); + do + { + wpid = waitpid(childpid, &status, WUNTRACED +#ifdef WCONTINUED /* Not all implementations support this */ + | WCONTINUED +#endif + ); + if (wpid == -1) + { + /* should't happen for timeouts, because the + SIGALRM handler will error (and exit). However, + we may recieve some OTHER signal... + */ + error (1, 0, "interrupted while waiting for child"); + } + } + while (!WIFEXITED(status) && !WIFSIGNALED(status)); } _exit (EXIT_SUCCESS); } @@ -152,7 +247,7 @@ then SIGHUP is sent to all process belonging to the same session, i.e., also to the second child. */ - signal (SIGHUP, SIG_IGN); + signal_set_handler (SIGHUP, SIG_IGN); switch (fork ()) { @@ -202,5 +297,9 @@ int daemon (int nochdir, int noclose) { +#ifdef __CYGWIN__ + return (waitdaemon (nochdir, noclose, 5) == -1) ? -1 : 0; +#else return (waitdaemon (nochdir, noclose, 0) == -1) ? -1 : 0; +#endif } diff -Naur inetutils-1.9.2-orig/libinetutils/logwtmp.c inetutils-1.9.2/libinetutils/logwtmp.c --- inetutils-1.9.2-orig/libinetutils/logwtmp.c 2013-09-26 12:36:38.000000000 +0300 +++ inetutils-1.9.2/libinetutils/logwtmp.c 2014-12-12 11:55:11.043600000 +0300 @@ -50,6 +50,10 @@ extern int errno; #endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + #ifdef HAVE_UTMPX_H static void _logwtmp (struct utmpx *ut) @@ -62,9 +66,9 @@ static int fd = -1; if (fd < 0) - fd = open (OUR_WTMP, O_WRONLY | O_APPEND, 0); + fd = open (OUR_WTMP, O_WRONLY | O_APPEND | O_BINARY, 0); #else - int fd = open (OUR_WTMP, O_WRONLY | O_APPEND, 0); + int fd = open (OUR_WTMP, O_WRONLY | O_APPEND | O_BINARY, 0); #endif if (fd >= 0) diff -Naur inetutils-1.9.2-orig/libinetutils/setsig.c inetutils-1.9.2/libinetutils/setsig.c --- inetutils-1.9.2-orig/libinetutils/setsig.c 2013-09-26 12:36:38.000000000 +0300 +++ inetutils-1.9.2/libinetutils/setsig.c 2014-12-12 11:55:11.059200000 +0300 @@ -26,6 +26,10 @@ #include +#ifdef __CYGWIN__ +typedef _sig_func_ptr sig_t; +#endif + /* This is exactly like the traditional signal function, but turns on the SA_RESTART bit where possible. */ sighandler_t