More Cygwin compatibility work -- now actually WORKS!

Always leave fds 0-2 defined; point them to /dev/null rather than
just closing them...
This commit is contained in:
hpa 2001-11-29 20:53:59 +00:00
parent 1a41c6ae7c
commit 5c5b5e8a0b
2 changed files with 56 additions and 21 deletions

View file

@ -93,6 +93,7 @@ AC_SEARCH_LIBS(gethostbyname, [nsl resolv], , [AC_MSG_ERROR(gethostbyname not fo
AC_SEARCH_LIBS(inet_aton, [nsl resolv], , [AC_MSG_ERROR(inet_aton not found)]) AC_SEARCH_LIBS(inet_aton, [nsl resolv], , [AC_MSG_ERROR(inet_aton not found)])
AC_SEARCH_LIBS(herror, [nsl resolv], , [AC_MSG_ERROR(herror not found)]) AC_SEARCH_LIBS(herror, [nsl resolv], , [AC_MSG_ERROR(herror not found)])
AC_CHECK_FUNCS(dup2)
AC_CHECK_FUNCS(fcntl) AC_CHECK_FUNCS(fcntl)
AC_CHECK_FUNCS(setsid) AC_CHECK_FUNCS(setsid)
AC_CHECK_FUNCS(recvmsg) AC_CHECK_FUNCS(recvmsg)

View file

@ -170,6 +170,25 @@ read_remap_rules(const char *file)
} }
#endif #endif
static inline void
set_socket_nonblock(int fd, int flag)
{
int err;
int flags;
#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
/* Posixly correct */
err = ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
(fcntl(fd, F_SETFL, flag ? flags|O_NONBLOCK : flags&~O_NONBLOCK) < 0);
#else
flags = flag ? 1 : 0;
err = (ioctl(fd, FIONBIO, &flags) < 0);
#endif
if ( err ) {
syslog(LOG_ERR, "Cannot set nonblock flag on socket: %m");
exit(EX_OSERR);
}
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -296,25 +315,10 @@ main(int argc, char **argv)
if ( spec_umask || !unixperms ) if ( spec_umask || !unixperms )
umask(my_umask); umask(my_umask);
#if defined(HAVE_FCNTL) && defined(O_NONBLOCK) /* Note: on Cygwin, select() on a nonblocking socket becomes
/* Posixly correct */ a nonblocking select. */
{ #ifndef __CYGWIN__
int flags; set_socket_nonblock(fd, 1);
if ( (flags = fcntl(fd, F_GETFL, 0) < 0) ||
(fcntl(fd, F_SETFL, flags|O_NONBLOCK)) ) {
syslog(LOG_ERR, "Cannot set nonblocking socket: %m");
exit(EX_OSERR);
}
}
#else
/* Old BSD version */
{
int on = 1;
if ( ioctl(fd, FIONBIO, &on) < 0 ) {
syslog(LOG_ERR, "Cannot set nonblocking socket: %m");
exit(EX_OSERR);
}
}
#endif #endif
#ifdef WITH_REGEX #ifdef WITH_REGEX
@ -376,15 +380,32 @@ main(int argc, char **argv)
/* Daemonize this process */ /* Daemonize this process */
{ {
pid_t f = fork(); pid_t f = fork();
int nfd;
if ( f > 0 ) if ( f > 0 )
exit(0); exit(0);
if ( f < 0 ) { if ( f < 0 ) {
syslog(LOG_ERR, "cannot fork: %m"); syslog(LOG_ERR, "cannot fork: %m");
exit(EX_OSERR); exit(EX_OSERR);
} }
nfd = open("/dev/null", O_RDWR);
if ( nfd >= 0 ) {
#ifdef HAVE_DUP2
dup2(nfd, 0);
dup2(nfd, 1);
dup2(nfd, 2);
#else
close(0); dup(nfd);
close(1); dup(nfd);
close(2); dup(nfd);
#endif
close(nfd);
} else {
close(0); close(1); close(2); close(0); close(1); close(2);
}
#ifdef HAVE_SETSID #ifdef HAVE_SETSID
#ifndef __CYGWIN__ /* Kills the process on Cygwin? */
setsid(); setsid();
#endif
#endif #endif
} }
} else { } else {
@ -429,6 +450,12 @@ main(int argc, char **argv)
tv_waittime.tv_sec = waittime; tv_waittime.tv_sec = waittime;
tv_waittime.tv_usec = 0; tv_waittime.tv_usec = 0;
#ifdef __CYGWIN__
/* On Cygwin, select() on a nonblocking socket returns immediately,
with a rv of 0! */
set_socket_nonblock(fd, 0);
#endif
/* Never time out if we're in standalone mode */ /* Never time out if we're in standalone mode */
rv = select(fd+1, &readset, NULL, NULL, standalone ? NULL : &tv_waittime); rv = select(fd+1, &readset, NULL, NULL, standalone ? NULL : &tv_waittime);
if ( rv == -1 && errno == EINTR ) if ( rv == -1 && errno == EINTR )
@ -440,6 +467,10 @@ main(int argc, char **argv)
exit(0); /* Timeout, return to inetd */ exit(0); /* Timeout, return to inetd */
} }
#ifdef __CYGWIN__
set_socket_nonblock(fd, 1);
#endif
fromlen = sizeof (from); fromlen = sizeof (from);
n = myrecvfrom(fd, buf, sizeof (buf), 0, n = myrecvfrom(fd, buf, sizeof (buf), 0,
(struct sockaddr *)&from, &fromlen, (struct sockaddr *)&from, &fromlen,
@ -454,7 +485,6 @@ main(int argc, char **argv)
} }
} }
if ( standalone && myaddr.sin_addr.s_addr == INADDR_ANY ) { if ( standalone && myaddr.sin_addr.s_addr == INADDR_ANY ) {
/* myrecvfrom() didn't capture the source address; but we might /* myrecvfrom() didn't capture the source address; but we might
have bound to a specific address, if so we should use it */ have bound to a specific address, if so we should use it */
@ -534,6 +564,10 @@ main(int argc, char **argv)
exit(EX_OSERR); exit(EX_OSERR);
} }
#ifdef __CYGWIN__
chdir("/"); /* Cygwin chroot() bug workaround */
#endif
#ifdef HAVE_SETREGID #ifdef HAVE_SETREGID
setrv = setregid(pw->pw_gid, pw->pw_gid); setrv = setregid(pw->pw_gid, pw->pw_gid);
#else #else