dcce423c726d1466e28093359602d01960a5bee3
[gnupg.git] / jnlib / w32-afunix.c
1 /* w32-afunix.c - AF_UNIX emulation for Windows.
2  * Copyright (C) 2004, 2006 g10 Code GmbH
3  *
4  * This file is part of JNLIB.
5  *
6  * JNLIB is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * JNLIB is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21
22 #ifdef _WIN32
23 #include <stdio.h>
24 #include <windows.h>
25 #include <io.h>
26 #include <errno.h>
27
28 #include "w32-afunix.h"
29
30 int
31 _w32_close (int fd)
32 {
33   int rc = closesocket (fd);
34   if (rc && WSAGetLastError () == WSAENOTSOCK)
35       rc = close (fd);
36   return rc;
37 }
38
39
40 int
41 _w32_sock_new (int domain, int type, int proto)
42 {
43   if (domain == AF_UNIX || domain == AF_LOCAL)
44     domain = AF_INET;
45   return socket (domain, type, proto);
46 }
47
48
49 int
50 _w32_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
51 {
52   struct sockaddr_in myaddr;
53   struct sockaddr_un * unaddr;
54   FILE * fp;
55   int port;
56   
57   unaddr = (struct sockaddr_un *)addr;
58   fp = fopen (unaddr->sun_path, "rb");
59   if (!fp)
60     return -1;
61   fscanf (fp, "%d", &port);
62   fclose (fp);
63
64   if (port < 0 || port > 65535)
65     {
66       errno = EINVAL;
67       return -1;
68     }
69   
70   myaddr.sin_family = AF_INET;
71   myaddr.sin_port = port; 
72   myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
73
74   /* we need this later. */
75   unaddr->sun_family = myaddr.sin_family;
76   unaddr->sun_port = myaddr.sin_port;
77   unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
78   
79   return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr);
80 }
81
82
83 int
84 _w32_sock_bind (int sockfd, struct sockaddr * addr, int addrlen)
85 {
86   if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
87     {
88       struct sockaddr_in myaddr;
89       struct sockaddr_un * unaddr;
90       FILE * fp;
91       int len = sizeof myaddr;
92       int rc;
93
94       myaddr.sin_port = 0;
95       myaddr.sin_family = AF_INET;
96       myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
97
98       rc = bind (sockfd, (struct sockaddr *)&myaddr, len);
99       if (rc)
100         return rc;
101       rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
102       if (rc)
103         return rc;
104       unaddr = (struct sockaddr_un *)addr;
105       fp = fopen (unaddr->sun_path, "wb");
106       if (!fp)
107         return -1;
108       fprintf (fp, "%d", myaddr.sin_port);
109       fclose (fp);
110
111       /* we need this later. */
112       unaddr->sun_family = myaddr.sin_family;
113       unaddr->sun_port = myaddr.sin_port;
114       unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
115       
116       return 0;
117     }
118   return bind (sockfd, addr, addrlen);
119 }
120
121 #endif /*_WIN32*/