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
72static struct SocketIFace *__CurlISocket = NULL;
73static uint32 SocketFeatures = 0;
74
75#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
76#define HAVE_BSDSOCKET_GETADDRINFO 0x02
77
78CURLcode 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
108void 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 run-time,
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
127struct 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>
182int 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
198struct Library *SocketBase = NULL;
199extern int errno, h_errno;
200
201#ifdef __libnix__
202void __request(const char *msg);
203#else
204# define __request(msg) Printf(msg "\n\a")
205#endif
206
207void Curl_amiga_cleanup(void)
208{
209 if(SocketBase) {
210 CloseLibrary(SocketBase);
211 SocketBase = NULL;
212 }
213}
214
215CURLcode 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__
240ADD2EXIT(Curl_amiga_cleanup, -50);
241#endif
242
243#endif /* !USE_AMISSL */
244
245#endif /* HAVE_PROTO_BSDSOCKET_H */
246
247#endif /* __AMIGA__ */
248