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
70static struct SocketIFace *__CurlISocket = NULL;
71static uint32 SocketFeatures = 0;
72
73#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
74#define HAVE_BSDSOCKET_GETADDRINFO 0x02
75
76CURLcode 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
106void 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
125struct 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
179int 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
195struct Library *SocketBase = NULL;
196extern int errno, h_errno;
197
198#ifdef __libnix__
199void __request(const char *msg);
200#else
201# define __request(msg) Printf(msg "\n\a")
202#endif
203
204void Curl_amiga_cleanup(void)
205{
206 if(SocketBase) {
207 CloseLibrary(SocketBase);
208 SocketBase = NULL;
209 }
210}
211
212CURLcode 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__
237ADD2EXIT(Curl_amiga_cleanup, -50);
238#endif
239
240#endif /* !USE_AMISSL */
241
242#endif /* HAVE_PROTO_BSDSOCKET_H */
243
244#endif /* __AMIGA__ */
245