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