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