/* $Id$ */ FIXME: Check and tidy it up first! #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc,char **argv) { int fdunix,fdtcp,fdtcplisten; struct sockaddr_un sockaddr_unix; struct sockaddr_in sockaddr_tcp; const char *pathnameunix,*nametcp; struct pollfd pollfds[2]; int fdi,fdo; socklen_t sockaddr_tcp_len; int setsockopt_SO_REUSEADDR_on; if (argc!=3) { fprintf(stderr,"%s: \n",argv[0]); exit(EXIT_FAILURE); } pathnameunix=argv[1]; nametcp=argv[2]; if (-1==(fdunix=socket(PF_UNIX,SOCK_STREAM,0))) { fprintf(stderr,"socket(PF_UNIX,SOCK_STREAM,0)=%d: %m\n",fdunix); exit(EXIT_FAILURE); } memset(&sockaddr_unix,0,sizeof(sockaddr_unix)); sockaddr_unix.sun_family=AF_UNIX; strncpy(sockaddr_unix.sun_path,pathnameunix,sizeof(sockaddr_unix.sun_path)); if (connect(fdunix,(const struct sockaddr *)&sockaddr_unix,sizeof(sockaddr_unix))) { fprintf(stderr,"connect(UNIX socket,\"%s\"): %m\n",pathnameunix); exit(EXIT_FAILURE); } if (-1==(fdtcplisten=socket(PF_INET,SOCK_STREAM,0))) { fprintf(stderr,"socket(PF_INET,SOCK_STREAM,0)=%d: %m\n",fdtcplisten); exit(EXIT_FAILURE); } setsockopt_SO_REUSEADDR_on=1; if (setsockopt(fdtcplisten,SOL_SOCKET,SO_REUSEADDR,&setsockopt_SO_REUSEADDR_on,sizeof(setsockopt_SO_REUSEADDR_on))) { fprintf(stderr,"setsockopt(TCP socket,SOL_SOCKET,SO_REUSEADDR,&1,sizeof(1)): %m\n"); exit(EXIT_FAILURE); } memset(&sockaddr_tcp,0,sizeof(sockaddr_tcp)); sockaddr_tcp.sin_family=AF_INET; sockaddr_tcp.sin_addr.s_addr=htonl(INADDR_LOOPBACK); sockaddr_tcp.sin_port=htons(atoi(nametcp)); if (bind(fdtcplisten,(const struct sockaddr *)&sockaddr_tcp,sizeof(sockaddr_tcp))) { fprintf(stderr,"bind(TCP socket,127.0.0.1:%s): %m\n",nametcp); exit(EXIT_FAILURE); } if (listen(fdtcplisten,1)) { fprintf(stderr,"listen(TCP socket,1): %m\n"); exit(EXIT_FAILURE); } sockaddr_tcp_len=sizeof(sockaddr_tcp); fprintf(stderr,"accept... "); if (-1==(fdtcp=accept(fdtcplisten,(struct sockaddr *)&sockaddr_tcp,&sockaddr_tcp_len))) { fprintf(stderr,"accept(TCP socket): %m\n"); exit(EXIT_FAILURE); } fprintf(stderr,"done\n"); if (close(fdtcplisten)) { fprintf(stderr,"close(TCP listen socket): %m\n"); exit(EXIT_FAILURE); } for (;;) { pollfds[0].fd=fdunix; pollfds[0].events=POLLIN; pollfds[1].fd=fdtcp; pollfds[1].events=POLLIN; if (0>=poll(pollfds,sizeof(pollfds)/sizeof(*pollfds),-1)) { fprintf(stderr,"poll(UNIX socket,PIPE socket): %m\n"); exit(EXIT_FAILURE); } if (pollfds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) { fprintf(stderr,"poll(UNIX socket): revents=0x%X\n",(unsigned)pollfds[0].revents); exit(EXIT_FAILURE); } if (pollfds[1].revents & (POLLERR|POLLHUP|POLLNVAL)) { fprintf(stderr,"poll(PIPE socket): revents=0x%X\n",(unsigned)pollfds[1].revents); exit(EXIT_FAILURE); } for (fdi=0;fdi"))); exit(EXIT_FAILURE); } got=read(pollfds[fdi].fd,buf,sizeof(buf)); if (got<0) { if (errno==EAGAIN) break; fprintf(stderr,"read(%s socket): %m\n", (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : ""))); exit(EXIT_FAILURE); } if (got==0) exit(EXIT_SUCCESS); for (fdo=0;fdo"))); exit(EXIT_FAILURE); } if (got!=write(pollfds[fdo].fd,buf,got)) { fprintf(stderr,"write(%s socket,%ld): %m\n", (fdo==0 ? "UNIX" : (fdo==1 ? "PIPE" : "")), (long)got); exit(EXIT_FAILURE); } } } } } return EXIT_SUCCESS; }