#include <winsock2.h>

#ifndef FILLIPV4ADDR
#define FILLIPV4ADDR(a,family,addr,port) \
                memset(&(a),0,sizeof(struct sockaddr_in)),\
                s.sin_family=family,\
                s.sin_addr.s_addr=addr,\
                s.sin_port=htons(port)
#endif

#ifndef SHUT_WR
#define SHUT_WR SD_SEND
#endif

#ifndef SHUT_RD
#define SHUT_RD SD_RECEIVE
#endif

#define close(s) closesocket(s)

int
win32_pipe(int fds[2])
{
        int serverfd,workfd,clientfd;
        struct sockaddr_in c,s;
        int sizes,sizec;
        FILLIPV4ADDR(s,AF_INET,htonl(INADDR_ANY),0);
        serverfd=workfd=clientfd=-1;
        if((serverfd=socket(AF_INET,SOCK_STREAM,0))==-1
          || bind(serverfd,(struct sockaddr *)&s,sizeof(s))!=0
          || listen(serverfd,1)==-1
          || (sizes=sizeof(s))!=sizeof(s)
          || getsockname(serverfd,(struct sockaddr *)&s,&sizes)==-1
          || memcpy(&c,&s,sizeof(c))==NULL
          || (clientfd=socket(AF_INET,SOCK_STREAM,0))==-1
          || connect(clientfd,(struct sockaddr *)&c,sizeof(c))==-1
          || (sizes=sizeof(s))!=sizeof(s)
          || (workfd=accept(serverfd,(struct sockaddr *)&s,&sizes))==-1
          || (sizec=sizeof(c))!=sizeof(c)
          || getsockname(workfd,(struct sockaddr *)&c,&sizec)==-1
          || memcmp(&c,&s,sizeof(c))!=0
        ) {
                if(serverfd!=-1)
                        close(serverfd),serverfd=-1;
                if(clientfd!=-1)
                        close(clientfd),clientfd=-1;
                if(workfd!=-1)
                        close(workfd),workfd=-1;
        }
        close(serverfd),serverfd=-1;
        shutdown(workfd,SHUT_WR);
        shutdown(clientfd,SHUT_RD);
        fds[0]=workfd,workfd=-1;
        fds[1]=clientfd,clientfd=-1;
        return(0);
}