]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/curl/lib/easy.c
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / curl / lib / easy.c
1 /***************************************************************************
2  *                                  _   _ ____  _     
3  *  Project                     ___| | | |  _ \| |    
4  *                             / __| | | | |_) | |    
5  *                            | (__| |_| |  _ <| |___ 
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, 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 http://curl.haxx.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  * $Id: easy.c,v 1.49 2004/03/15 16:28:36 bagder Exp $
22  ***************************************************************************/
23
24 #include "setup.h"
25
26 /* -- WIN32 approved -- */
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 #include <errno.h>
36
37 #include "strequal.h"
38
39 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
40 #include <time.h>
41 #include <io.h>
42 #else
43 #ifdef HAVE_SYS_SOCKET_H
44 #include <sys/socket.h>
45 #endif
46 #include <netinet/in.h>
47 #include <sys/time.h>
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51 #include <netdb.h>
52 #ifdef HAVE_ARPA_INET_H
53 #include <arpa/inet.h>
54 #endif
55 #ifdef HAVE_NET_IF_H
56 #include <net/if.h>
57 #endif
58 #include <sys/ioctl.h>
59 #include <signal.h>
60
61 #ifdef HAVE_SYS_PARAM_H
62 #include <sys/param.h>
63 #endif
64
65 #ifdef HAVE_SYS_SELECT_H
66 #include <sys/select.h>
67 #endif
68
69 #endif
70
71 #include "urldata.h"
72 #include <curl/curl.h>
73 #include "transfer.h"
74 #include "ssluse.h"
75 #include "url.h"
76 #include "getinfo.h"
77 #include "hostip.h"
78 #include "share.h"
79
80 #define _MPRINTF_REPLACE /* use our functions only */
81 #include <curl/mprintf.h>
82
83 /* The last #include file should be: */
84 #ifdef CURLDEBUG
85 #include "memdebug.h"
86 #endif
87
88 /* Silly win32 socket initialization functions */
89
90 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
91 static void win32_cleanup(void)
92 {
93   WSACleanup();
94 }
95
96 static CURLcode win32_init(void)
97 {
98   WORD wVersionRequested;  
99   WSADATA wsaData; 
100   int err; 
101
102 #ifdef ENABLE_IPV6
103   wVersionRequested = MAKEWORD(2, 0);
104 #else
105   wVersionRequested = MAKEWORD(1, 1);
106 #endif
107     
108   err = WSAStartup(wVersionRequested, &wsaData); 
109     
110   if (err != 0) 
111     /* Tell the user that we couldn't find a useable */ 
112     /* winsock.dll.     */ 
113     return CURLE_FAILED_INIT; 
114     
115   /* Confirm that the Windows Sockets DLL supports what we need.*/ 
116   /* Note that if the DLL supports versions greater */ 
117   /* than wVersionRequested, it will still return */ 
118   /* wVersionRequested in wVersion. wHighVersion contains the */
119   /* highest supported version. */
120
121   if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || 
122        HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { 
123     /* Tell the user that we couldn't find a useable */ 
124
125     /* winsock.dll. */ 
126     WSACleanup(); 
127     return CURLE_FAILED_INIT; 
128   }
129   return CURLE_OK;
130 }
131 /* The Windows Sockets DLL is acceptable. Proceed. */ 
132 #else
133 /* These functions exist merely to prevent compiler warnings */
134 static CURLcode win32_init(void) { return CURLE_OK; }
135 static void win32_cleanup(void) { }
136 #endif
137
138
139 /* true globals -- for curl_global_init() and curl_global_cleanup() */
140 static unsigned int  initialized = 0;
141 static long          init_flags  = 0;
142
143 /**
144  * Globally initializes cURL given a bitwise set of 
145  * the different features to initialize.
146  */
147 CURLcode curl_global_init(long flags)
148 {
149   if (initialized)
150     return CURLE_OK;
151
152   if (flags & CURL_GLOBAL_SSL)
153     Curl_SSL_init();
154
155   if (flags & CURL_GLOBAL_WIN32)
156     if (win32_init() != CURLE_OK)
157       return CURLE_FAILED_INIT;
158
159 #ifdef _AMIGASF
160   if(!amiga_init())
161     return CURLE_FAILED_INIT;
162 #endif
163
164   initialized = 1;
165   init_flags  = flags;
166   
167   return CURLE_OK;
168 }
169
170 /**
171  * Globally cleanup cURL, uses the value of "init_flags" to determine
172  * what needs to be cleaned up and what doesn't
173  */
174 void curl_global_cleanup(void)
175 {
176   if (!initialized)
177     return;
178
179   Curl_global_host_cache_dtor();
180
181   if (init_flags & CURL_GLOBAL_SSL)
182     Curl_SSL_cleanup();
183
184   if (init_flags & CURL_GLOBAL_WIN32)
185     win32_cleanup();
186
187 #ifdef _AMIGASF
188   amiga_cleanup();
189 #endif
190
191   initialized = 0;
192   init_flags  = 0;
193 }
194
195 CURL *curl_easy_init(void)
196 {
197   CURLcode res;
198   struct SessionHandle *data;
199
200   /* Make sure we inited the global SSL stuff */
201   if (!initialized) {
202     res = curl_global_init(CURL_GLOBAL_DEFAULT);
203     if(res)
204       /* something in the global init failed, return nothing */
205       return NULL;
206   }
207
208   /* We use curl_open() with undefined URL so far */
209   res = Curl_open(&data);
210   if(res != CURLE_OK)
211     return NULL;
212
213   return data;
214 }
215
216 typedef int (*func_T)(void);
217 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
218 {
219   va_list arg;
220   func_T param_func = (func_T)0;
221   long param_long = 0;
222   void *param_obj = NULL;
223   curl_off_t param_offset = 0;
224   struct SessionHandle *data = curl;
225   CURLcode ret=CURLE_FAILED_INIT;
226
227   va_start(arg, tag);
228
229   /* PORTING NOTE:
230      Object pointers can't necessarily be casted to function pointers and
231      therefore we need to know what type it is and read the correct type
232      at once. This should also correct problems with different sizes of
233      the types.
234   */
235
236   if(tag < CURLOPTTYPE_OBJECTPOINT) {
237     /* This is a LONG type */
238     param_long = va_arg(arg, long);
239     ret = Curl_setopt(data, tag, param_long);
240   }
241   else if(tag < CURLOPTTYPE_FUNCTIONPOINT) {
242     /* This is a object pointer type */
243     param_obj = va_arg(arg, void *);
244     ret = Curl_setopt(data, tag, param_obj);
245   }
246   else if(tag < CURLOPTTYPE_OFF_T) {
247     /* This is a function pointer type */
248     param_func = va_arg(arg, func_T );
249     ret = Curl_setopt(data, tag, param_func);
250   } else {
251     /* This is a curl_off_t type */
252     param_offset = va_arg(arg, curl_off_t);
253     ret = Curl_setopt(data, tag, param_offset);
254   }
255
256   va_end(arg);
257   return ret;
258 }
259
260 CURLcode curl_easy_perform(CURL *curl)
261 {
262   struct SessionHandle *data = (struct SessionHandle *)curl;
263
264   if ( ! (data->share && data->share->hostcache) ) {
265
266     if (Curl_global_host_cache_use(data) &&
267         data->hostcache != Curl_global_host_cache_get()) {
268       if (data->hostcache)
269         Curl_hash_destroy(data->hostcache);
270       data->hostcache = Curl_global_host_cache_get();
271     }
272
273     if (!data->hostcache) {
274       data->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);
275
276       if(!data->hostcache)
277         /* While we possibly could survive and do good without a host cache,
278            the fact that creating it failed indicates that things are truly
279            screwed up and we should bail out! */
280         return CURLE_OUT_OF_MEMORY;
281     }
282     
283   }
284   
285   return Curl_perform(data);
286 }
287
288 void curl_easy_cleanup(CURL *curl)
289 {
290   struct SessionHandle *data = (struct SessionHandle *)curl;
291   if ( ! (data->share && data->share->hostcache) ) {
292     if ( !Curl_global_host_cache_use(data)) {
293       Curl_hash_destroy(data->hostcache);
294     }
295   }
296   Curl_close(data);
297 }
298
299 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
300 {
301   va_list arg;
302   void *paramp;
303   struct SessionHandle *data = (struct SessionHandle *)curl;
304
305   va_start(arg, info);
306   paramp = va_arg(arg, void *);
307
308   return Curl_getinfo(data, info, paramp);
309 }
310
311 CURL *curl_easy_duphandle(CURL *incurl)
312 {
313   struct SessionHandle *data=(struct SessionHandle *)incurl;
314
315   struct SessionHandle *outcurl = (struct SessionHandle *)
316     malloc(sizeof(struct SessionHandle));
317
318   if(NULL == outcurl)
319     return NULL; /* failure */
320
321   /* start with clearing the entire new struct */
322   memset(outcurl, 0, sizeof(struct SessionHandle));
323
324   /*
325    * We setup a few buffers we need. We should probably make them
326    * get setup on-demand in the code, as that would probably decrease
327    * the likeliness of us forgetting to init a buffer here in the future.
328    */
329   outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
330   if(!outcurl->state.headerbuff) {
331     free(outcurl); /* free the memory again */
332     return NULL;
333   }
334   outcurl->state.headersize=HEADERSIZE;
335
336   /* copy all userdefined values */
337   outcurl->set = data->set;
338   outcurl->state.numconnects = data->state.numconnects;
339   outcurl->state.connects = (struct connectdata **)
340       malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
341
342   if(!outcurl->state.connects) {
343     free(outcurl->state.headerbuff);
344     free(outcurl);
345     return NULL;
346   }
347   memset(outcurl->state.connects, 0,
348          sizeof(struct connectdata *)*outcurl->state.numconnects);
349
350   outcurl->progress.flags    = data->progress.flags;
351   outcurl->progress.callback = data->progress.callback;
352
353   if(data->cookies)
354     /* If cookies are enabled in the parent handle, we enable them
355        in the clone as well! */
356     outcurl->cookies = Curl_cookie_init(data,
357                                         data->cookies->filename,
358                                         outcurl->cookies,
359                                         data->set.cookiesession);
360
361   /* duplicate all values in 'change' */
362   if(data->change.url) {
363     outcurl->change.url = strdup(data->change.url);
364     outcurl->change.url_alloc = TRUE;
365   }
366   if(data->change.proxy) {
367     outcurl->change.proxy = strdup(data->change.proxy);
368     outcurl->change.proxy_alloc = TRUE;
369   }
370   if(data->change.referer) {
371     outcurl->change.referer = strdup(data->change.referer);
372     outcurl->change.referer_alloc = TRUE;
373   }
374
375   return outcurl;
376 }