xref: /third_party/curl/lib/amigaos.c (revision 13498266)
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