--- inetd.c.in Sun Jan 6 04:05:42 2002 +++ inetd.c Wed Apr 24 23:49:54 2002 @@ -590,6 +590,64 @@ SetServiceStatus(ssh, &ss); } +/* This is a part of a workaround for the following Microsft bug + on Win95/98/Me: + http://support.microsoft.com/default.aspx?scid=kb;en-us;Q198663 + http://support.microsoft.com/default.aspx?scid=kb;EN-US;q229658 + + msbug_close(pid, fd) is normally called twice. + The first time fd is >= 0. + On Win95/98/Me it then records the fd as belonging to the pid, + instead of closing it outright, and it sets the + "close on fork" flag to avoid further duplications. + The function is called again with fd < 0 when the pid exits. + It then closes the associated fd. + The two calls can safely be made in different threads. + + The function returns the value of the fcntl() or close() call + it makes, if any, else 0. +*/ +#include +#include +#define msbug_MAXFD 128 /* Plenty for small systems */ +static int msbug_close(pid_t pid, int fd) +{ + int i; + static struct { + pid_t pid; + int fd; + } info[msbug_MAXFD] = {}; + + if (GetVersion() < 0x80000000) { + if (fd >= 0) return close(fd); + else return 0; + } + if (fd >= 0) { + for (i = 0; i < msbug_MAXFD; i++){ + if (info[i].pid == 0) { + info[i].fd = fd; + info[i].pid = pid; /* Done last */ + return fcntl(fd, F_SETCF, 0); + } + } + return close(fd); /* Better now than never */ + } + else { + struct linger linger = {}; + for (i = 0; i < msbug_MAXFD; i++){ + if (info[i].pid == pid) { + fd = info[i].fd; + info[i].pid = 0; /* Done last */ + fcntl(fd, F_SETFL, 0); /* Blocking */ + setsockopt(fd, SOL_SOCKET, SO_LINGER, + &linger, sizeof(linger)); + return close(fd); + } + } + return 0; + } +} + void WINAPI service_main(DWORD argc, LPSTR *argv) #else @@ -920,7 +978,11 @@ } } if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) - close(ctrl); +#ifdef __CYGWIN__ + msbug_close(pid, ctrl); +#else + close(ctrl); +#endif } } } @@ -1061,6 +1123,9 @@ if (debug) fprintf(stderr, "%d reaped, status %#x\n", pid, status); +#ifdef __CYGWIN__ + msbug_close(pid, -1); +#endif for (sep = servtab; sep; sep = sep->se_next) if (sep->se_wait == pid) { if (status) @@ -1256,8 +1321,12 @@ } return; } - if (sep->se_socktype == SOCK_STREAM) + if (sep->se_socktype == SOCK_STREAM) { +#ifdef __CYGWIN__ + if (!sep->se_wait) fcntl(sep->se_fd, F_SETCF, 0); +#endif listen(sep->se_fd, 10); + } FD_SET(sep->se_fd, &allsock); nsock++; if (sep->se_fd > maxsock)