+make
[nethome.git] / src / unixtcp.c
1 /* $Id$ */
2
3 FIXME: Check and tidy it up first!
4
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <sys/un.h>
11 #include <sys/poll.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <errno.h>
16 #include <netinet/in.h>
17 #include <string.h>
18
19
20 int main(int argc,char **argv)
21 {
22 int fdunix,fdtcp,fdtcplisten;
23 struct sockaddr_un sockaddr_unix;
24 struct sockaddr_in sockaddr_tcp;
25 const char *pathnameunix,*nametcp;
26 struct pollfd pollfds[2];
27 int fdi,fdo;
28 socklen_t sockaddr_tcp_len;
29 int setsockopt_SO_REUSEADDR_on;
30
31         if (argc!=3) {
32                 fprintf(stderr,"%s: <pathname UNIX socket> <name TCP>\n",argv[0]);
33                 exit(EXIT_FAILURE);
34                 }
35         pathnameunix=argv[1];
36         nametcp=argv[2];
37
38         if (-1==(fdunix=socket(PF_UNIX,SOCK_STREAM,0))) {
39                 fprintf(stderr,"socket(PF_UNIX,SOCK_STREAM,0)=%d: %m\n",fdunix);
40                 exit(EXIT_FAILURE);
41                 }
42         memset(&sockaddr_unix,0,sizeof(sockaddr_unix));
43         sockaddr_unix.sun_family=AF_UNIX;
44         strncpy(sockaddr_unix.sun_path,pathnameunix,sizeof(sockaddr_unix.sun_path));
45         if (connect(fdunix,(const struct sockaddr *)&sockaddr_unix,sizeof(sockaddr_unix))) {
46                 fprintf(stderr,"connect(UNIX socket,\"%s\"): %m\n",pathnameunix);
47                 exit(EXIT_FAILURE);
48                 }
49
50         if (-1==(fdtcplisten=socket(PF_INET,SOCK_STREAM,0))) {
51                 fprintf(stderr,"socket(PF_INET,SOCK_STREAM,0)=%d: %m\n",fdtcplisten);
52                 exit(EXIT_FAILURE);
53                 }
54         setsockopt_SO_REUSEADDR_on=1;
55         if (setsockopt(fdtcplisten,SOL_SOCKET,SO_REUSEADDR,&setsockopt_SO_REUSEADDR_on,sizeof(setsockopt_SO_REUSEADDR_on))) {
56                 fprintf(stderr,"setsockopt(TCP socket,SOL_SOCKET,SO_REUSEADDR,&1,sizeof(1)): %m\n");
57                 exit(EXIT_FAILURE);
58                 }
59         memset(&sockaddr_tcp,0,sizeof(sockaddr_tcp));
60         sockaddr_tcp.sin_family=AF_INET;
61         sockaddr_tcp.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
62         sockaddr_tcp.sin_port=htons(atoi(nametcp));
63         if (bind(fdtcplisten,(const struct sockaddr *)&sockaddr_tcp,sizeof(sockaddr_tcp))) {
64                 fprintf(stderr,"bind(TCP socket,127.0.0.1:%s): %m\n",nametcp);
65                 exit(EXIT_FAILURE);
66                 }
67         if (listen(fdtcplisten,1)) {
68                 fprintf(stderr,"listen(TCP socket,1): %m\n");
69                 exit(EXIT_FAILURE);
70                 }
71         sockaddr_tcp_len=sizeof(sockaddr_tcp);
72         fprintf(stderr,"accept... ");
73         if (-1==(fdtcp=accept(fdtcplisten,(struct sockaddr *)&sockaddr_tcp,&sockaddr_tcp_len))) {
74                 fprintf(stderr,"accept(TCP socket): %m\n");
75                 exit(EXIT_FAILURE);
76                 }
77         fprintf(stderr,"done\n");
78         if (close(fdtcplisten)) {
79                 fprintf(stderr,"close(TCP listen socket): %m\n");
80                 exit(EXIT_FAILURE);
81                 }
82
83         for (;;) {
84                 pollfds[0].fd=fdunix;
85                 pollfds[0].events=POLLIN;
86                 pollfds[1].fd=fdtcp;
87                 pollfds[1].events=POLLIN;
88                 if (0>=poll(pollfds,sizeof(pollfds)/sizeof(*pollfds),-1)) {
89                         fprintf(stderr,"poll(UNIX socket,PIPE socket): %m\n");
90                         exit(EXIT_FAILURE);
91                         }
92                 if (pollfds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) {
93                         fprintf(stderr,"poll(UNIX socket): revents=0x%X\n",(unsigned)pollfds[0].revents);
94                         exit(EXIT_FAILURE);
95                         }
96                 if (pollfds[1].revents & (POLLERR|POLLHUP|POLLNVAL)) {
97                         fprintf(stderr,"poll(PIPE socket): revents=0x%X\n",(unsigned)pollfds[1].revents);
98                         exit(EXIT_FAILURE);
99                         }
100                 for (fdi=0;fdi<sizeof(pollfds)/sizeof(*pollfds);fdi++) {
101                         for (;;) {
102                                 ssize_t got;
103                                 char buf[0x1000];
104
105                                 if (fcntl(pollfds[fdi].fd,F_SETFL,O_NONBLOCK)) {
106                                         fprintf(stderr,"fcntl(%s socket,F_SETFL,O_NONBLOCK): %m\n",
107                                                         (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : "<UNKNOWN>")));
108                                         exit(EXIT_FAILURE);
109                                         }
110                                 got=read(pollfds[fdi].fd,buf,sizeof(buf));
111                                 if (got<0) {
112                                         if (errno==EAGAIN)
113                                                 break;
114                                         fprintf(stderr,"read(%s socket): %m\n",
115                                                         (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : "<UNKNOWN>")));
116                                         exit(EXIT_FAILURE);
117                                         }
118                                 if (got==0)
119                                         exit(EXIT_SUCCESS);
120                                 for (fdo=0;fdo<sizeof(pollfds)/sizeof(*pollfds);fdo++) {
121                                         if (fdi==fdo)
122                                                 continue;
123                                         if (fcntl(pollfds[fdo].fd,F_SETFL,0 /* !O_NONBLOCK */)) {
124                                                 fprintf(stderr,"fcntl(%s socket,F_SETFL,0 /* !O_NONBLOCK */): %m\n",
125                                                                 (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : "<UNKNOWN>")));
126                                                 exit(EXIT_FAILURE);
127                                                 }
128                                         if (got!=write(pollfds[fdo].fd,buf,got)) {
129                                                 fprintf(stderr,"write(%s socket,%ld): %m\n",
130                                                                 (fdo==0 ? "UNIX" : (fdo==1 ? "PIPE" : "<UNKNOWN>")),
131                                                                 (long)got);
132                                                 exit(EXIT_FAILURE);
133                                                 }
134                                         }
135                                 }
136                         }
137                 }
138         return EXIT_SUCCESS;
139 }