Added missing files and fixed stuff from the recent merged. I did only
[gpgme.git] / assuan / assuan-socket.c
1 /* assuan-socket.c
2  * Copyright (C) 2004 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20 #include <config.h>
21 #include <stdio.h>
22 #ifdef HAVE_W32_SYSTEM
23 #include <windows.h>
24 #include <io.h>
25 #else
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #endif
29 #include "assuan-defs.h"
30
31 int
32 _assuan_close (int fd)
33 {
34 #ifndef HAVE_W32_SYSTEM
35   return close (fd);
36 #else
37   int rc = closesocket (fd);
38   if (rc && WSAGetLastError () == WSAENOTSOCK)
39       rc = close (fd);
40   return rc;
41 #endif
42 }
43
44
45 int
46 _assuan_sock_new (int domain, int type, int proto)
47 {
48 #ifndef HAVE_W32_SYSTEM
49   return socket (domain, type, proto);
50 #else
51   if (domain == AF_UNIX || domain == AF_LOCAL)
52     domain = AF_INET;
53   return socket (domain, type, proto);
54 #endif
55 }
56
57
58 int
59 _assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
60 {
61 #ifndef HAVE_W32_SYSTEM
62   return connect (sockfd, addr, addrlen);
63 #else
64   struct sockaddr_in myaddr;
65   struct sockaddr_un * unaddr;
66   FILE * fp;
67   int port = 0;
68   
69   unaddr = (struct sockaddr_un *)addr;
70   fp = fopen (unaddr->sun_path, "rb");
71   if (!fp)
72       return -1;
73   fscanf (fp, "%d", &port);
74   fclose (fp);
75   /* XXX: set errno in this case */
76   if (port < 0 || port > 65535)
77       return -1;
78   
79   myaddr.sin_family = AF_INET;
80   myaddr.sin_port = port; 
81   myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
82
83   /* we need this later. */
84   unaddr->sun_family = myaddr.sin_family;
85   unaddr->sun_port = myaddr.sin_port;
86   unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
87   
88   return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr);
89 #endif
90 }
91
92
93 int
94 _assuan_sock_bind (int sockfd, struct sockaddr * addr, int addrlen)
95 {
96 #ifndef HAVE_W32_SYSTEM
97   return bind (sockfd, addr, addrlen);
98 #else
99   if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
100     {
101       struct sockaddr_in myaddr;
102       struct sockaddr_un * unaddr;
103       FILE * fp;
104       int len = sizeof myaddr;
105       int rc;
106
107       myaddr.sin_port = 0;
108       myaddr.sin_family = AF_INET;
109       myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
110
111       rc = bind (sockfd, (struct sockaddr *)&myaddr, len);
112       if (rc)
113         return rc;
114       rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
115       if (rc)
116         return rc;
117       unaddr = (struct sockaddr_un *)addr;
118       fp = fopen (unaddr->sun_path, "wb");
119       if (!fp)
120         return -1;
121       fprintf (fp, "%d", myaddr.sin_port);
122       fclose (fp);
123
124       /* we need this later. */
125       unaddr->sun_family = myaddr.sin_family;
126       unaddr->sun_port = myaddr.sin_port;
127       unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
128       
129       return 0;
130     }
131   return bind (sockfd, addr, addrlen);
132 #endif
133 }
134