1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2022, Daniel Stenberg, <[email protected]>, et al. |
9 | * |
10 | * This software is licensed as described in the file COPYING, which |
11 | * you should have received as part of this distribution. The terms |
12 | * are also available at https://curl.se/docs/copyright.html. |
13 | * |
14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
15 | * copies of the Software, and permit persons to whom the Software is |
16 | * furnished to do so, under the terms of the COPYING file. |
17 | * |
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
19 | * KIND, either express or implied. |
20 | * |
21 | * SPDX-License-Identifier: curl |
22 | * |
23 | ***************************************************************************/ |
24 | |
25 | #include "curl_setup.h" |
26 | |
27 | #ifdef __AMIGA__ |
28 | |
29 | #include "hostip.h" |
30 | #include "amigaos.h" |
31 | |
32 | #ifdef HAVE_PROTO_BSDSOCKET_H |
33 | # if defined(__amigaos4__) |
34 | # include <bsdsocket/socketbasetags.h> |
35 | # elif !defined(USE_AMISSL) |
36 | # include <amitcp/socketbasetags.h> |
37 | # endif |
38 | # ifdef __libnix__ |
39 | # include <stabs.h> |
40 | # endif |
41 | #endif |
42 | |
43 | /* The last #include files should be: */ |
44 | #include "curl_memory.h" |
45 | #include "memdebug.h" |
46 | |
47 | #ifdef HAVE_PROTO_BSDSOCKET_H |
48 | |
49 | #ifdef __amigaos4__ |
50 | /* |
51 | * AmigaOS 4.x specific code |
52 | */ |
53 | |
54 | /* |
55 | * hostip4.c - Curl_ipv4_resolve_r() replacement code |
56 | * |
57 | * Logic that needs to be considered are the following build cases: |
58 | * - newlib networking |
59 | * - clib2 networking |
60 | * - direct bsdsocket.library networking (usually AmiSSL builds) |
61 | * Each with the threaded resolver enabled or not. |
62 | * |
63 | * With the threaded resolver enabled, try to use gethostbyname_r() where |
64 | * available, otherwise (re)open bsdsocket.library and fallback to |
65 | * gethostbyname(). |
66 | */ |
67 | |
68 | #include <proto/bsdsocket.h> |
69 | |
70 | static struct SocketIFace *__CurlISocket = NULL; |
71 | static uint32 SocketFeatures = 0; |
72 | |
73 | #define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01 |
74 | #define HAVE_BSDSOCKET_GETADDRINFO 0x02 |
75 | |
76 | CURLcode Curl_amiga_init(void) |
77 | { |
78 | struct SocketIFace *ISocket; |
79 | struct Library *base = OpenLibrary("bsdsocket.library" , 4); |
80 | |
81 | if(base) { |
82 | ISocket = (struct SocketIFace *)GetInterface(base, "main" , 1, NULL); |
83 | if(ISocket) { |
84 | ULONG enabled = 0; |
85 | |
86 | SocketBaseTags(SBTM_SETVAL(SBTC_CAN_SHARE_LIBRARY_BASES), TRUE, |
87 | SBTM_GETREF(SBTC_HAVE_GETHOSTADDR_R_API), (ULONG)&enabled, |
88 | TAG_DONE); |
89 | |
90 | if(enabled) { |
91 | SocketFeatures |= HAVE_BSDSOCKET_GETHOSTBYNAME_R; |
92 | } |
93 | |
94 | __CurlISocket = ISocket; |
95 | |
96 | atexit(Curl_amiga_cleanup); |
97 | |
98 | return CURLE_OK; |
99 | } |
100 | CloseLibrary(base); |
101 | } |
102 | |
103 | return CURLE_FAILED_INIT; |
104 | } |
105 | |
106 | void Curl_amiga_cleanup(void) |
107 | { |
108 | if(__CurlISocket) { |
109 | struct Library *base = __CurlISocket->Data.LibBase; |
110 | DropInterface((struct Interface *)__CurlISocket); |
111 | CloseLibrary(base); |
112 | __CurlISocket = NULL; |
113 | } |
114 | } |
115 | |
116 | #ifdef CURLRES_AMIGA |
117 | /* |
118 | * Because we need to handle the different cases in hostip4.c at run-time, |
119 | * not at compile-time, based on what was detected in Curl_amiga_init(), |
120 | * we replace it completely with our own as to not complicate the baseline |
121 | * code. Assumes malloc/calloc/free are thread safe because Curl_he2ai() |
122 | * allocates memory also. |
123 | */ |
124 | |
125 | struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, |
126 | int port) |
127 | { |
128 | struct Curl_addrinfo *ai = NULL; |
129 | struct hostent *h; |
130 | struct SocketIFace *ISocket = __CurlISocket; |
131 | |
132 | if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) { |
133 | LONG h_errnop = 0; |
134 | struct hostent *buf; |
135 | |
136 | buf = calloc(1, CURL_HOSTENT_SIZE); |
137 | if(buf) { |
138 | h = gethostbyname_r((STRPTR)hostname, buf, |
139 | (char *)buf + sizeof(struct hostent), |
140 | CURL_HOSTENT_SIZE - sizeof(struct hostent), |
141 | &h_errnop); |
142 | if(h) { |
143 | ai = Curl_he2ai(h, port); |
144 | } |
145 | free(buf); |
146 | } |
147 | } |
148 | else { |
149 | #ifdef CURLRES_THREADED |
150 | /* gethostbyname() is not thread safe, so we need to reopen bsdsocket |
151 | * on the thread's context |
152 | */ |
153 | struct Library *base = OpenLibrary("bsdsocket.library" , 4); |
154 | if(base) { |
155 | ISocket = (struct SocketIFace *)GetInterface(base, "main" , 1, NULL); |
156 | if(ISocket) { |
157 | h = gethostbyname((STRPTR)hostname); |
158 | if(h) { |
159 | ai = Curl_he2ai(h, port); |
160 | } |
161 | DropInterface((struct Interface *)ISocket); |
162 | } |
163 | CloseLibrary(base); |
164 | } |
165 | #else |
166 | /* not using threaded resolver - safe to use this as-is */ |
167 | h = gethostbyname(hostname); |
168 | if(h) { |
169 | ai = Curl_he2ai(h, port); |
170 | } |
171 | #endif |
172 | } |
173 | |
174 | return ai; |
175 | } |
176 | #endif /* CURLRES_AMIGA */ |
177 | |
178 | #ifdef USE_AMISSL |
179 | int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds, |
180 | fd_set *errorfds, struct timeval *timeout) |
181 | { |
182 | int r = WaitSelect(nfds, readfds, writefds, errorfds, timeout, 0); |
183 | /* Ensure Ctrl-C signal is actioned */ |
184 | if((r == -1) && (SOCKERRNO == EINTR)) |
185 | raise(SIGINT); |
186 | return r; |
187 | } |
188 | #endif /* USE_AMISSL */ |
189 | |
190 | #elif !defined(USE_AMISSL) /* __amigaos4__ */ |
191 | /* |
192 | * Amiga OS3 specific code |
193 | */ |
194 | |
195 | struct Library *SocketBase = NULL; |
196 | extern int errno, h_errno; |
197 | |
198 | #ifdef __libnix__ |
199 | void __request(const char *msg); |
200 | #else |
201 | # define __request(msg) Printf(msg "\n\a") |
202 | #endif |
203 | |
204 | void Curl_amiga_cleanup(void) |
205 | { |
206 | if(SocketBase) { |
207 | CloseLibrary(SocketBase); |
208 | SocketBase = NULL; |
209 | } |
210 | } |
211 | |
212 | CURLcode Curl_amiga_init(void) |
213 | { |
214 | if(!SocketBase) |
215 | SocketBase = OpenLibrary("bsdsocket.library" , 4); |
216 | |
217 | if(!SocketBase) { |
218 | __request("No TCP/IP Stack running!" ); |
219 | return CURLE_FAILED_INIT; |
220 | } |
221 | |
222 | if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, |
223 | SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl" , |
224 | TAG_DONE)) { |
225 | __request("SocketBaseTags ERROR" ); |
226 | return CURLE_FAILED_INIT; |
227 | } |
228 | |
229 | #ifndef __libnix__ |
230 | atexit(Curl_amiga_cleanup); |
231 | #endif |
232 | |
233 | return CURLE_OK; |
234 | } |
235 | |
236 | #ifdef __libnix__ |
237 | ADD2EXIT(Curl_amiga_cleanup, -50); |
238 | #endif |
239 | |
240 | #endif /* !USE_AMISSL */ |
241 | |
242 | #endif /* HAVE_PROTO_BSDSOCKET_H */ |
243 | |
244 | #endif /* __AMIGA__ */ |
245 | |